port.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. /*
  2. * FreeRTOS Kernel V10.4.6
  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 "altera_avalon_timer_regs.h"
  37. #include "priv/alt_irq_table.h"
  38. /* Scheduler includes. */
  39. #include "FreeRTOS.h"
  40. #include "task.h"
  41. /* Interrupts are enabled. */
  42. #define portINITIAL_ESTATUS ( StackType_t ) 0x01
  43. /*-----------------------------------------------------------*/
  44. /*
  45. * Setup the timer to generate the tick interrupts.
  46. */
  47. static void prvSetupTimerInterrupt( void );
  48. /*
  49. * Call back for the alarm function.
  50. */
  51. void vPortSysTickHandler( void * context, alt_u32 id );
  52. /*-----------------------------------------------------------*/
  53. static void prvReadGp( uint32_t *ulValue )
  54. {
  55. asm( "stw gp, (%0)" :: "r"(ulValue) );
  56. }
  57. /*-----------------------------------------------------------*/
  58. /*
  59. * See header file for description.
  60. */
  61. StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
  62. {
  63. StackType_t *pxFramePointer = pxTopOfStack - 1;
  64. StackType_t xGlobalPointer;
  65. prvReadGp( &xGlobalPointer );
  66. /* End of stack marker. */
  67. *pxTopOfStack = 0xdeadbeef;
  68. pxTopOfStack--;
  69. *pxTopOfStack = ( StackType_t ) pxFramePointer;
  70. pxTopOfStack--;
  71. *pxTopOfStack = xGlobalPointer;
  72. /* Space for R23 to R16. */
  73. pxTopOfStack -= 9;
  74. *pxTopOfStack = ( StackType_t ) pxCode;
  75. pxTopOfStack--;
  76. *pxTopOfStack = portINITIAL_ESTATUS;
  77. /* Space for R15 to R5. */
  78. pxTopOfStack -= 12;
  79. *pxTopOfStack = ( StackType_t ) pvParameters;
  80. /* Space for R3 to R1, muldiv and RA. */
  81. pxTopOfStack -= 5;
  82. return pxTopOfStack;
  83. }
  84. /*-----------------------------------------------------------*/
  85. /*
  86. * See header file for description.
  87. */
  88. BaseType_t xPortStartScheduler( void )
  89. {
  90. /* Start the timer that generates the tick ISR. Interrupts are disabled
  91. here already. */
  92. prvSetupTimerInterrupt();
  93. /* Start the first task. */
  94. asm volatile ( " movia r2, restore_sp_from_pxCurrentTCB \n"
  95. " jmp r2 " );
  96. /* Should not get here! */
  97. return 0;
  98. }
  99. /*-----------------------------------------------------------*/
  100. void vPortEndScheduler( void )
  101. {
  102. /* It is unlikely that the NIOS2 port will require this function as there
  103. is nothing to return to. */
  104. }
  105. /*-----------------------------------------------------------*/
  106. /*
  107. * Setup the systick timer to generate the tick interrupts at the required
  108. * frequency.
  109. */
  110. void prvSetupTimerInterrupt( void )
  111. {
  112. /* Try to register the interrupt handler. */
  113. if ( -EINVAL == alt_irq_register( SYS_CLK_IRQ, 0x0, vPortSysTickHandler ) )
  114. {
  115. /* Failed to install the Interrupt Handler. */
  116. asm( "break" );
  117. }
  118. else
  119. {
  120. /* Configure SysTick to interrupt at the requested rate. */
  121. IOWR_ALTERA_AVALON_TIMER_CONTROL( SYS_CLK_BASE, ALTERA_AVALON_TIMER_CONTROL_STOP_MSK );
  122. IOWR_ALTERA_AVALON_TIMER_PERIODL( SYS_CLK_BASE, ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) & 0xFFFF );
  123. IOWR_ALTERA_AVALON_TIMER_PERIODH( SYS_CLK_BASE, ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) >> 16 );
  124. 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 );
  125. }
  126. /* Clear any already pending interrupts generated by the Timer. */
  127. IOWR_ALTERA_AVALON_TIMER_STATUS( SYS_CLK_BASE, ~ALTERA_AVALON_TIMER_STATUS_TO_MSK );
  128. }
  129. /*-----------------------------------------------------------*/
  130. void vPortSysTickHandler( void * context, alt_u32 id )
  131. {
  132. /* Increment the kernel tick. */
  133. if( xTaskIncrementTick() != pdFALSE )
  134. {
  135. vTaskSwitchContext();
  136. }
  137. /* Clear the interrupt. */
  138. IOWR_ALTERA_AVALON_TIMER_STATUS( SYS_CLK_BASE, ~ALTERA_AVALON_TIMER_STATUS_TO_MSK );
  139. }
  140. /*-----------------------------------------------------------*/
  141. /** This function is a re-implementation of the Altera provided function.
  142. * The function is re-implemented to prevent it from enabling an interrupt
  143. * when it is registered. Interrupts should only be enabled after the FreeRTOS.org
  144. * kernel has its scheduler started so that contexts are saved and switched
  145. * correctly.
  146. */
  147. int alt_irq_register( alt_u32 id, void* context, void (*handler)(void*, alt_u32) )
  148. {
  149. int rc = -EINVAL;
  150. alt_irq_context status;
  151. if (id < ALT_NIRQ)
  152. {
  153. /*
  154. * interrupts are disabled while the handler tables are updated to ensure
  155. * that an interrupt doesn't occur while the tables are in an inconsistent
  156. * state.
  157. */
  158. status = alt_irq_disable_all ();
  159. alt_irq[id].handler = handler;
  160. alt_irq[id].context = context;
  161. rc = (handler) ? alt_irq_enable (id): alt_irq_disable (id);
  162. /* alt_irq_enable_all(status); This line is removed to prevent the interrupt from being immediately enabled. */
  163. }
  164. return rc;
  165. }
  166. /*-----------------------------------------------------------*/