port.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. /*
  2. * FreeRTOS Kernel <DEVELOPMENT BRANCH>
  3. * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  4. *
  5. * SPDX-License-Identifier: MIT
  6. *
  7. * Permission is hereby granted, free of charge, to any person obtaining a copy of
  8. * this software and associated documentation files (the "Software"), to deal in
  9. * the Software without restriction, including without limitation the rights to
  10. * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
  11. * the Software, and to permit persons to whom the Software is furnished to do so,
  12. * subject to the following conditions:
  13. *
  14. * The above copyright notice and this permission notice shall be included in all
  15. * copies or substantial portions of the Software.
  16. *
  17. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
  19. * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
  20. * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
  21. * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  22. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  23. *
  24. * https://www.FreeRTOS.org
  25. * https://github.com/FreeRTOS
  26. *
  27. */
  28. /*-----------------------------------------------------------
  29. * Implementation of functions defined in portable.h for the NIOS2 port.
  30. *----------------------------------------------------------*/
  31. /* Standard Includes. */
  32. #include <string.h>
  33. #include <errno.h>
  34. /* Altera includes. */
  35. #include "sys/alt_irq.h"
  36. #include "sys/alt_exceptions.h"
  37. #include "altera_avalon_timer_regs.h"
  38. #include "priv/alt_irq_table.h"
  39. /* Scheduler includes. */
  40. #include "FreeRTOS.h"
  41. #include "task.h"
  42. /* Interrupts are enabled. */
  43. #define portINITIAL_ESTATUS ( StackType_t ) 0x01
  44. int _alt_ic_isr_register( alt_u32 ic_id,
  45. alt_u32 irq,
  46. alt_isr_func isr,
  47. void * isr_context,
  48. void * flags );
  49. /*-----------------------------------------------------------*/
  50. /*
  51. * Setup the timer to generate the tick interrupts.
  52. */
  53. static void prvSetupTimerInterrupt( void );
  54. /*
  55. * Call back for the alarm function.
  56. */
  57. void vPortSysTickHandler( void * context );
  58. /*-----------------------------------------------------------*/
  59. static void prvReadGp( uint32_t * ulValue )
  60. {
  61. asm ( "stw gp, (%0)" ::"r" ( ulValue ) );
  62. }
  63. /*-----------------------------------------------------------*/
  64. /*
  65. * See header file for description.
  66. */
  67. StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
  68. TaskFunction_t pxCode,
  69. void * pvParameters )
  70. {
  71. StackType_t * pxFramePointer = pxTopOfStack - 1;
  72. StackType_t xGlobalPointer;
  73. prvReadGp( &xGlobalPointer );
  74. /* End of stack marker. */
  75. *pxTopOfStack = 0xdeadbeef;
  76. pxTopOfStack--;
  77. *pxTopOfStack = ( StackType_t ) pxFramePointer;
  78. pxTopOfStack--;
  79. *pxTopOfStack = xGlobalPointer;
  80. /* Space for R23 to R16. */
  81. pxTopOfStack -= 9;
  82. *pxTopOfStack = ( StackType_t ) pxCode;
  83. pxTopOfStack--;
  84. *pxTopOfStack = portINITIAL_ESTATUS;
  85. /* Space for R15 to R5. */
  86. pxTopOfStack -= 12;
  87. *pxTopOfStack = ( StackType_t ) pvParameters;
  88. /* Space for R3 to R1, muldiv and RA. */
  89. pxTopOfStack -= 5;
  90. return pxTopOfStack;
  91. }
  92. /*-----------------------------------------------------------*/
  93. /*
  94. * See header file for description.
  95. */
  96. BaseType_t xPortStartScheduler( void )
  97. {
  98. /* Start the timer that generates the tick ISR. Interrupts are disabled
  99. * here already. */
  100. prvSetupTimerInterrupt();
  101. /* Start the first task. */
  102. asm volatile ( " movia r2, restore_sp_from_pxCurrentTCB \n"
  103. " jmp r2 " );
  104. /* Should not get here! */
  105. return 0;
  106. }
  107. /*-----------------------------------------------------------*/
  108. void vPortEndScheduler( void )
  109. {
  110. /* It is unlikely that the NIOS2 port will require this function as there
  111. * is nothing to return to. */
  112. }
  113. /*-----------------------------------------------------------*/
  114. /*
  115. * Setup the systick timer to generate the tick interrupts at the required
  116. * frequency.
  117. */
  118. void prvSetupTimerInterrupt( void )
  119. {
  120. /* Try to register the interrupt handler. */
  121. if( -EINVAL == _alt_ic_isr_register( SYS_CLK_IRQ_INTERRUPT_CONTROLLER_ID, SYS_CLK_IRQ, vPortSysTickHandler, 0x0, 0x0 ) )
  122. {
  123. /* Failed to install the Interrupt Handler. */
  124. asm ( "break" );
  125. }
  126. else
  127. {
  128. /* Configure SysTick to interrupt at the requested rate. */
  129. IOWR_ALTERA_AVALON_TIMER_CONTROL( SYS_CLK_BASE, ALTERA_AVALON_TIMER_CONTROL_STOP_MSK );
  130. IOWR_ALTERA_AVALON_TIMER_PERIODL( SYS_CLK_BASE, ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) & 0xFFFF );
  131. IOWR_ALTERA_AVALON_TIMER_PERIODH( SYS_CLK_BASE, ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) >> 16 );
  132. IOWR_ALTERA_AVALON_TIMER_CONTROL( SYS_CLK_BASE, ALTERA_AVALON_TIMER_CONTROL_CONT_MSK | ALTERA_AVALON_TIMER_CONTROL_START_MSK | ALTERA_AVALON_TIMER_CONTROL_ITO_MSK );
  133. }
  134. /* Clear any already pending interrupts generated by the Timer. */
  135. IOWR_ALTERA_AVALON_TIMER_STATUS( SYS_CLK_BASE, ~ALTERA_AVALON_TIMER_STATUS_TO_MSK );
  136. }
  137. /*-----------------------------------------------------------*/
  138. void vPortSysTickHandler( void * context )
  139. {
  140. /* Increment the kernel tick. */
  141. if( xTaskIncrementTick() != pdFALSE )
  142. {
  143. vTaskSwitchContext();
  144. }
  145. /* Clear the interrupt. */
  146. IOWR_ALTERA_AVALON_TIMER_STATUS( SYS_CLK_BASE, ~ALTERA_AVALON_TIMER_STATUS_TO_MSK );
  147. }
  148. /*-----------------------------------------------------------*/
  149. /** This function is a re-implementation of the Altera provided function.
  150. * The function is re-implemented to prevent it from enabling an interrupt
  151. * when it is registered. Interrupts should only be enabled after the FreeRTOS.org
  152. * kernel has its scheduler started so that contexts are saved and switched
  153. * correctly.
  154. */
  155. int _alt_ic_isr_register( alt_u32 ic_id,
  156. alt_u32 irq,
  157. alt_isr_func isr,
  158. void * isr_context,
  159. void * flags )
  160. {
  161. int rc = -EINVAL;
  162. alt_irq_context status;
  163. int id = irq; /* IRQ interpreted as the interrupt ID. */
  164. if( id < ALT_NIRQ )
  165. {
  166. /*
  167. * interrupts are disabled while the handler tables are updated to ensure
  168. * that an interrupt doesn't occur while the tables are in an inconsistent
  169. * state.
  170. */
  171. status = alt_irq_disable_all();
  172. alt_irq[ id ].handler = isr;
  173. alt_irq[ id ].context = isr_context;
  174. rc = ( isr ) ? alt_ic_irq_enable( ic_id, id ) : alt_ic_irq_disable( ic_id, id );
  175. /* alt_irq_enable_all(status); This line is removed to prevent the interrupt from being immediately enabled. */
  176. }
  177. return rc;
  178. }
  179. /*-----------------------------------------------------------*/