PageRenderTime 58ms CodeModel.GetById 28ms RepoModel.GetById 1ms app.codeStats 0ms

/src/platform/stm32/platform_int.c

https://github.com/mwilbur/elua
C | 413 lines | 300 code | 80 blank | 33 comment | 53 complexity | 36e56155673e3743370e1ef9540f57d0 MD5 | raw file
  1. // STM32 interrupt support
  2. // Generic headers
  3. #include "platform.h"
  4. #include "platform_conf.h"
  5. #include "elua_int.h"
  6. #include "common.h"
  7. // Platform-specific headers
  8. #include "stm32f10x.h"
  9. #ifndef VTMR_TIMER_ID
  10. #define VTMR_TIMER_ID ( -1 )
  11. #endif
  12. // ****************************************************************************
  13. // Interrupt handlers
  14. extern USART_TypeDef *const stm32_usart[];
  15. static void all_usart_irqhandler( int resnum )
  16. {
  17. int temp;
  18. temp = USART_GetFlagStatus( stm32_usart[ resnum ], USART_FLAG_ORE );
  19. cmn_int_handler( INT_UART_RX, resnum );
  20. if( temp == SET )
  21. for( temp = 0; temp < 10; temp ++ )
  22. platform_s_uart_send( resnum, '@' );
  23. }
  24. void USART1_IRQHandler()
  25. {
  26. all_usart_irqhandler( 0 );
  27. }
  28. void USART2_IRQHandler()
  29. {
  30. all_usart_irqhandler( 1 );
  31. }
  32. void USART3_IRQHandler()
  33. {
  34. all_usart_irqhandler( 2 );
  35. }
  36. void UART4_IRQHandler()
  37. {
  38. all_usart_irqhandler( 3 );
  39. }
  40. void UART5_IRQHandler()
  41. {
  42. all_usart_irqhandler( 4 );
  43. }
  44. // ****************************************************************************
  45. // External interrupt handlers
  46. static const u32 exti_line[] = { EXTI_Line0, EXTI_Line1, EXTI_Line2, EXTI_Line3, EXTI_Line4, EXTI_Line5, EXTI_Line6, EXTI_Line7, EXTI_Line8, EXTI_Line9, EXTI_Line10, EXTI_Line12, EXTI_Line13, EXTI_Line14, EXTI_Line15 };
  47. static u16 exti_line_to_gpio( u32 line )
  48. {
  49. return PLATFORM_IO_ENCODE( ( AFIO->EXTICR[line >> 0x02] >> (0x04 * ( line & 0x03 ) ) ) & 0x07, line, PLATFORM_IO_ENC_PIN );
  50. }
  51. // Convert a GPIO ID to a EXINT number
  52. static int exint_gpio_to_src( pio_type piodata )
  53. {
  54. u16 pin = PLATFORM_IO_GET_PIN( piodata );
  55. return pin;
  56. }
  57. static void all_exti_irqhandler( int line )
  58. {
  59. u16 v, port, pin;
  60. v = exti_line_to_gpio( line );
  61. port = PLATFORM_IO_GET_PORT( v );
  62. pin = PLATFORM_IO_GET_PIN( v );
  63. if( EXTI->RTSR & (1 << line ) && platform_pio_op( port, 1 << pin, PLATFORM_IO_PIN_GET ) )
  64. cmn_int_handler( INT_GPIO_POSEDGE, v );
  65. if( EXTI->FTSR & (1 << line ) && ( platform_pio_op( port, 1 << pin, PLATFORM_IO_PIN_GET ) == 0 ) )
  66. cmn_int_handler( INT_GPIO_NEGEDGE, v );
  67. EXTI_ClearITPendingBit( exti_line[ line ] );
  68. }
  69. void EXTI0_IRQHandler()
  70. {
  71. all_exti_irqhandler( 0 );
  72. }
  73. void EXTI1_IRQHandler()
  74. {
  75. all_exti_irqhandler( 1 );
  76. }
  77. void EXTI2_IRQHandler()
  78. {
  79. all_exti_irqhandler( 2 );
  80. }
  81. void EXTI3_IRQHandler()
  82. {
  83. all_exti_irqhandler( 3 );
  84. }
  85. void EXTI4_IRQHandler()
  86. {
  87. all_exti_irqhandler( 4 );
  88. }
  89. void EXTI9_5_IRQHandler()
  90. {
  91. int i;
  92. for( i = 5; i < 10; i++ )
  93. {
  94. if( EXTI_GetITStatus( exti_line[ i ] ) != RESET )
  95. all_exti_irqhandler( i );
  96. }
  97. }
  98. void EXTI15_10_IRQHandler()
  99. {
  100. int i;
  101. for( i = 10; i < 16; i++ )
  102. {
  103. if( EXTI_GetITStatus( exti_line[ i ] ) != RESET )
  104. all_exti_irqhandler( i );
  105. }
  106. }
  107. // ----------------------------------------------------------------------------
  108. // Timer interrupt handlers
  109. const TIM_TypeDef * const timer[] = { TIM1, TIM2, TIM3, TIM4, TIM5 };
  110. extern u8 stm32_timer_int_periodic_flag[ NUM_PHYS_TIMER ];
  111. static void tmr_int_handler( int id )
  112. {
  113. TIM_TypeDef *base = ( TIM_TypeDef* )timer[ id ];
  114. if (TIM_GetITStatus( base, TIM_IT_CC1) != RESET)
  115. {
  116. TIM_ClearITPendingBit( base, TIM_IT_CC1 );
  117. if( id == VTMR_TIMER_ID )
  118. cmn_virtual_timer_cb();
  119. else
  120. cmn_int_handler( INT_TMR_MATCH, id );
  121. if( stm32_timer_int_periodic_flag[ id ] != PLATFORM_TIMER_INT_CYCLIC )
  122. TIM_ITConfig( base, TIM_IT_CC1, DISABLE );
  123. }
  124. }
  125. void TIM1_CC_IRQHandler(void)
  126. {
  127. tmr_int_handler( 0 );
  128. }
  129. void TIM2_IRQHandler(void)
  130. {
  131. tmr_int_handler( 1 );
  132. }
  133. void TIM3_IRQHandler(void)
  134. {
  135. tmr_int_handler( 2 );
  136. }
  137. void TIM4_IRQHandler(void)
  138. {
  139. tmr_int_handler( 3 );
  140. }
  141. void TIM5_IRQHandler(void)
  142. {
  143. tmr_int_handler( 4 );
  144. }
  145. void TIM8_CC_IRQHandler(void)
  146. {
  147. tmr_int_handler( 7 );
  148. }
  149. // ****************************************************************************
  150. // GPIO helper functions
  151. static int gpioh_get_int_status( elua_int_id id, elua_int_resnum resnum )
  152. {
  153. if ( EXTI->IMR & ( 1 << exint_gpio_to_src( resnum ) ) )
  154. return 1;
  155. else
  156. return 0;
  157. }
  158. static int gpioh_set_int_status( elua_int_id id, elua_int_resnum resnum, int status )
  159. {
  160. int prev = gpioh_get_int_status( id, resnum );
  161. u32 mask = 1 << exint_gpio_to_src( resnum );
  162. EXTI_InitTypeDef exti_init_struct;
  163. if( status == PLATFORM_CPU_ENABLE )
  164. {
  165. // Configure port for interrupt line
  166. GPIO_EXTILineConfig( PLATFORM_IO_GET_PORT( resnum ), PLATFORM_IO_GET_PIN( resnum ) );
  167. EXTI_StructInit(&exti_init_struct);
  168. exti_init_struct.EXTI_Line = exti_line[ exint_gpio_to_src( resnum ) ];
  169. exti_init_struct.EXTI_Mode = EXTI_Mode_Interrupt;
  170. if( ( ( ( EXTI->RTSR & mask ) != 0 ) && ( id == INT_GPIO_NEGEDGE ) ) ||
  171. ( ( ( EXTI->FTSR & mask ) != 0 ) && ( id == INT_GPIO_POSEDGE ) ) )
  172. exti_init_struct.EXTI_Trigger = EXTI_Trigger_Rising_Falling;
  173. else
  174. exti_init_struct.EXTI_Trigger = id == INT_GPIO_POSEDGE ? EXTI_Trigger_Rising : EXTI_Trigger_Falling;
  175. exti_init_struct.EXTI_LineCmd = ENABLE;
  176. EXTI_Init(&exti_init_struct);
  177. EXTI_ClearITPendingBit( exti_line[ exint_gpio_to_src( resnum ) ] );
  178. }
  179. else
  180. {
  181. //Disable edge
  182. if( id == INT_GPIO_POSEDGE )
  183. EXTI->RTSR &= ~mask;
  184. else
  185. EXTI->FTSR &= ~mask;
  186. //If no edges enabled, disable line interrupt
  187. if( ( ( EXTI->RTSR | EXTI->FTSR ) & mask ) == 0 )
  188. EXTI->IMR &= ~mask;
  189. }
  190. return prev;
  191. }
  192. static int gpioh_get_int_flag( elua_int_id id, elua_int_resnum resnum, int clear )
  193. {
  194. int flag = 0;
  195. u32 mask = 1 << exint_gpio_to_src( resnum );
  196. if( EXTI_GetFlagStatus( exti_line[ exint_gpio_to_src( resnum ) ] ) == SET )
  197. {
  198. if( id == INT_GPIO_POSEDGE )
  199. flag = ( EXTI->RTSR & mask ) != 0;
  200. else
  201. flag = ( EXTI->FTSR & mask ) != 0;
  202. }
  203. if( flag && clear )
  204. EXTI_ClearFlag( exti_line[ exint_gpio_to_src( resnum ) ] );
  205. return flag;
  206. }
  207. // ****************************************************************************
  208. // Interrupt: INT_GPIO_POSEDGE
  209. static int int_gpio_posedge_set_status( elua_int_resnum resnum, int status )
  210. {
  211. return gpioh_set_int_status( INT_GPIO_POSEDGE, resnum, status );
  212. }
  213. static int int_gpio_posedge_get_status( elua_int_resnum resnum )
  214. {
  215. return gpioh_get_int_status( INT_GPIO_POSEDGE, resnum );
  216. }
  217. static int int_gpio_posedge_get_flag( elua_int_resnum resnum, int clear )
  218. {
  219. return gpioh_get_int_flag( INT_GPIO_POSEDGE, resnum, clear );
  220. }
  221. // ****************************************************************************
  222. // Interrupt: INT_GPIO_NEGEDGE
  223. static int int_gpio_negedge_set_status( elua_int_resnum resnum, int status )
  224. {
  225. return gpioh_set_int_status( INT_GPIO_NEGEDGE, resnum, status );
  226. }
  227. static int int_gpio_negedge_get_status( elua_int_resnum resnum )
  228. {
  229. return gpioh_get_int_status( INT_GPIO_NEGEDGE, resnum );
  230. }
  231. static int int_gpio_negedge_get_flag( elua_int_resnum resnum, int clear )
  232. {
  233. return gpioh_get_int_flag( INT_GPIO_NEGEDGE, resnum, clear );
  234. }
  235. // ****************************************************************************
  236. // Interrupt: INT_TMR_MATCH
  237. static int int_tmr_match_get_status( elua_int_resnum resnum )
  238. {
  239. TIM_TypeDef *base = ( TIM_TypeDef* )timer[ resnum ];
  240. return ( base->DIER & TIM_IT_CC1 ) != 0;
  241. }
  242. static int int_tmr_match_set_status( elua_int_resnum resnum, int status )
  243. {
  244. int previous = int_tmr_match_get_status( resnum );
  245. TIM_TypeDef *base = ( TIM_TypeDef* )timer[ resnum ];
  246. TIM_ITConfig( base, TIM_IT_CC1, status == PLATFORM_CPU_ENABLE ? ENABLE : DISABLE );
  247. return previous;
  248. }
  249. static int int_tmr_match_get_flag( elua_int_resnum resnum, int clear )
  250. {
  251. TIM_TypeDef *base = ( TIM_TypeDef* )timer[ resnum ];
  252. int status = TIM_GetFlagStatus( base, TIM_FLAG_CC1 );
  253. if( clear )
  254. TIM_ClearFlag( base, TIM_FLAG_CC1 );
  255. return status;
  256. }
  257. // ****************************************************************************
  258. // Interrupt: INT_UART_RX
  259. static int int_uart_rx_get_status( elua_int_resnum resnum )
  260. {
  261. return USART_GetITStatus( stm32_usart[ resnum ], USART_IT_RXNE ) == SET ? 1 : 0;
  262. }
  263. static int int_uart_rx_set_status( elua_int_resnum resnum, int status )
  264. {
  265. int prev = int_uart_rx_get_status( resnum );
  266. USART_ITConfig( stm32_usart[ resnum ], USART_IT_RXNE, status == PLATFORM_CPU_ENABLE ? ENABLE : DISABLE );
  267. return prev;
  268. }
  269. static int int_uart_rx_get_flag( elua_int_resnum resnum, int clear )
  270. {
  271. int status = USART_GetFlagStatus( stm32_usart[ resnum ], USART_FLAG_RXNE ) == SET ? 1 : 0;
  272. if( clear )
  273. USART_ClearFlag( stm32_usart[ resnum ], USART_FLAG_RXNE );
  274. return status;
  275. }
  276. // ****************************************************************************
  277. // Initialize interrupt subsystem
  278. // UART IRQ table
  279. #if defined( STM32F10X_LD )
  280. static const u8 uart_irq_table[] = { USART1_IRQn, USART2_IRQn };
  281. #elseif defined( STM32F10X_MD )
  282. static const u8 uart_irq_table[] = { USART1_IRQn, USART2_IRQn, USART3_IRQn };
  283. #else // high density devices
  284. static const u8 uart_irq_table[] = { USART1_IRQn, USART2_IRQn, USART3_IRQn, UART4_IRQn, UART5_IRQn };
  285. #endif
  286. // EXTI IRQ table
  287. static const u8 exti_irq_table[] = { EXTI0_IRQn, EXTI1_IRQn, EXTI2_IRQn, EXTI3_IRQn, EXTI4_IRQn, EXTI9_5_IRQn, EXTI15_10_IRQn };
  288. // EXTI IRQ table
  289. #if defined( STM32F10X_LD )
  290. static const u8 timer_irq_table[] = { TIM1_CC_IRQn, TIM2_IRQn, TIM3_IRQn };
  291. #elseif defined( STM32F10X_MD )
  292. static const u8 timer_irq_table[] = { TIM1_CC_IRQn, TIM2_IRQn, TIM3_IRQn, TIM4_IRQn };
  293. #else
  294. static const u8 timer_irq_table[] = { TIM1_CC_IRQn, TIM2_IRQn, TIM3_IRQn, TIM4_IRQn, TIM5_IRQn };
  295. #endif
  296. void platform_int_init()
  297. {
  298. NVIC_InitTypeDef nvic_init_structure;
  299. unsigned i;
  300. // Enable all USART interrupts in the NVIC
  301. nvic_init_structure.NVIC_IRQChannelPreemptionPriority = 0;
  302. nvic_init_structure.NVIC_IRQChannelSubPriority = 0;
  303. nvic_init_structure.NVIC_IRQChannelCmd = ENABLE;
  304. for( i = 0; i < sizeof( uart_irq_table ) / sizeof( u8 ); i ++ )
  305. {
  306. nvic_init_structure.NVIC_IRQChannel = uart_irq_table[ i ];
  307. NVIC_Init( &nvic_init_structure );
  308. }
  309. // Enable all EXTI interrupts in the NVIC
  310. for( i = 0; i < sizeof( exti_irq_table ) / sizeof( u8 ); i ++ )
  311. {
  312. nvic_init_structure.NVIC_IRQChannel = exti_irq_table[ i ];
  313. NVIC_Init( &nvic_init_structure );
  314. }
  315. #ifdef INT_TMR_MATCH
  316. for( i = 0; i < sizeof( timer_irq_table ) / sizeof( u8 ); i ++ )
  317. {
  318. nvic_init_structure.NVIC_IRQChannel = timer_irq_table[ i ];
  319. nvic_init_structure.NVIC_IRQChannelSubPriority = 1;
  320. NVIC_Init( &nvic_init_structure );
  321. }
  322. #endif
  323. }
  324. // ****************************************************************************
  325. // Interrupt table
  326. // Must have a 1-to-1 correspondence with the interrupt enum in platform_conf.h!
  327. const elua_int_descriptor elua_int_table[ INT_ELUA_LAST ] =
  328. {
  329. { int_gpio_posedge_set_status, int_gpio_posedge_get_status, int_gpio_posedge_get_flag },
  330. { int_gpio_negedge_set_status, int_gpio_negedge_get_status, int_gpio_negedge_get_flag },
  331. { int_tmr_match_set_status, int_tmr_match_get_status, int_tmr_match_get_flag },
  332. { int_uart_rx_set_status, int_uart_rx_get_status, int_uart_rx_get_flag }
  333. };