diff options
author | Damien George <damien.p.george@gmail.com> | 2015-06-10 14:25:54 +0100 |
---|---|---|
committer | Damien George <damien.p.george@gmail.com> | 2015-12-22 21:00:20 +0000 |
commit | 401af50dc081faa421e7caef18fde2beb15632e4 (patch) | |
tree | 3af529bf86743dddf182c632849edf2a9ecf5f6a | |
parent | abd0fcfc86c413d7de58f0c927ca6f598ee12950 (diff) | |
download | micropython-401af50dc081faa421e7caef18fde2beb15632e4.tar.gz micropython-401af50dc081faa421e7caef18fde2beb15632e4.zip |
stmhal: Add pyb.irq_stats() to get statistics about IRQ calls.
Adds a lot of code, makes IRQs a bit less efficient, but is very useful
for debugging. Usage: pyb.irq_stats() returns a memory view that can be
read and written, eg:
list(pyb.irq_stats())
pyb.irq_stats()[0]
pyb.irq_stats()[0] = 0
The patch provides general IRQ_ENTER() and IRQ_EXIT() macros that can be
modified to provide further IRQ statistics if desired.
-rw-r--r-- | stmhal/dma.c | 32 | ||||
-rw-r--r-- | stmhal/irq.c | 12 | ||||
-rw-r--r-- | stmhal/irq.h | 14 | ||||
-rw-r--r-- | stmhal/modpyb.c | 3 | ||||
-rw-r--r-- | stmhal/qstrdefsport.h | 1 | ||||
-rw-r--r-- | stmhal/sdcard.c | 2 | ||||
-rw-r--r-- | stmhal/stm32_it.c | 79 |
7 files changed, 127 insertions, 16 deletions
diff --git a/stmhal/dma.c b/stmhal/dma.c index 2b344141e9..2255e51601 100644 --- a/stmhal/dma.c +++ b/stmhal/dma.c @@ -86,22 +86,22 @@ volatile dma_idle_count_t dma_idle; #define DMA_CHANNEL_AS_UINT8(dma_channel) (((dma_channel) & DMA_SxCR_CHSEL) >> 24) -void DMA1_Stream0_IRQHandler(void) { if (dma_handle[0] != NULL) { HAL_DMA_IRQHandler(dma_handle[0]); } } -void DMA1_Stream1_IRQHandler(void) { if (dma_handle[1] != NULL) { HAL_DMA_IRQHandler(dma_handle[1]); } } -void DMA1_Stream2_IRQHandler(void) { if (dma_handle[2] != NULL) { HAL_DMA_IRQHandler(dma_handle[2]); } } -void DMA1_Stream3_IRQHandler(void) { if (dma_handle[3] != NULL) { HAL_DMA_IRQHandler(dma_handle[3]); } } -void DMA1_Stream4_IRQHandler(void) { if (dma_handle[4] != NULL) { HAL_DMA_IRQHandler(dma_handle[4]); } } -void DMA1_Stream5_IRQHandler(void) { if (dma_handle[5] != NULL) { HAL_DMA_IRQHandler(dma_handle[5]); } } -void DMA1_Stream6_IRQHandler(void) { if (dma_handle[6] != NULL) { HAL_DMA_IRQHandler(dma_handle[6]); } } -void DMA1_Stream7_IRQHandler(void) { if (dma_handle[7] != NULL) { HAL_DMA_IRQHandler(dma_handle[7]); } } -void DMA2_Stream0_IRQHandler(void) { if (dma_handle[8] != NULL) { HAL_DMA_IRQHandler(dma_handle[8]); } } -void DMA2_Stream1_IRQHandler(void) { if (dma_handle[9] != NULL) { HAL_DMA_IRQHandler(dma_handle[9]); } } -void DMA2_Stream2_IRQHandler(void) { if (dma_handle[10] != NULL) { HAL_DMA_IRQHandler(dma_handle[10]); } } -void DMA2_Stream3_IRQHandler(void) { if (dma_handle[11] != NULL) { HAL_DMA_IRQHandler(dma_handle[11]); } } -void DMA2_Stream4_IRQHandler(void) { if (dma_handle[12] != NULL) { HAL_DMA_IRQHandler(dma_handle[12]); } } -void DMA2_Stream5_IRQHandler(void) { if (dma_handle[13] != NULL) { HAL_DMA_IRQHandler(dma_handle[13]); } } -void DMA2_Stream6_IRQHandler(void) { if (dma_handle[14] != NULL) { HAL_DMA_IRQHandler(dma_handle[14]); } } -void DMA2_Stream7_IRQHandler(void) { if (dma_handle[15] != NULL) { HAL_DMA_IRQHandler(dma_handle[15]); } } +void DMA1_Stream0_IRQHandler(void) { IRQ_ENTER(DMA1_Stream0_IRQn); if (dma_handle[0] != NULL) { HAL_DMA_IRQHandler(dma_handle[0]); } IRQ_EXIT(DMA1_Stream0_IRQn); } +void DMA1_Stream1_IRQHandler(void) { IRQ_ENTER(DMA1_Stream1_IRQn); if (dma_handle[1] != NULL) { HAL_DMA_IRQHandler(dma_handle[1]); } IRQ_EXIT(DMA1_Stream1_IRQn); } +void DMA1_Stream2_IRQHandler(void) { IRQ_ENTER(DMA1_Stream2_IRQn); if (dma_handle[2] != NULL) { HAL_DMA_IRQHandler(dma_handle[2]); } IRQ_EXIT(DMA1_Stream2_IRQn); } +void DMA1_Stream3_IRQHandler(void) { IRQ_ENTER(DMA1_Stream3_IRQn); if (dma_handle[3] != NULL) { HAL_DMA_IRQHandler(dma_handle[3]); } IRQ_EXIT(DMA1_Stream3_IRQn); } +void DMA1_Stream4_IRQHandler(void) { IRQ_ENTER(DMA1_Stream4_IRQn); if (dma_handle[4] != NULL) { HAL_DMA_IRQHandler(dma_handle[4]); } IRQ_EXIT(DMA1_Stream4_IRQn); } +void DMA1_Stream5_IRQHandler(void) { IRQ_ENTER(DMA1_Stream5_IRQn); if (dma_handle[5] != NULL) { HAL_DMA_IRQHandler(dma_handle[5]); } IRQ_EXIT(DMA1_Stream5_IRQn); } +void DMA1_Stream6_IRQHandler(void) { IRQ_ENTER(DMA1_Stream6_IRQn); if (dma_handle[6] != NULL) { HAL_DMA_IRQHandler(dma_handle[6]); } IRQ_EXIT(DMA1_Stream6_IRQn); } +void DMA1_Stream7_IRQHandler(void) { IRQ_ENTER(DMA1_Stream7_IRQn); if (dma_handle[7] != NULL) { HAL_DMA_IRQHandler(dma_handle[7]); } IRQ_EXIT(DMA1_Stream7_IRQn); } +void DMA2_Stream0_IRQHandler(void) { IRQ_ENTER(DMA2_Stream0_IRQn); if (dma_handle[8] != NULL) { HAL_DMA_IRQHandler(dma_handle[8]); } IRQ_EXIT(DMA2_Stream0_IRQn); } +void DMA2_Stream1_IRQHandler(void) { IRQ_ENTER(DMA2_Stream1_IRQn); if (dma_handle[9] != NULL) { HAL_DMA_IRQHandler(dma_handle[9]); } IRQ_EXIT(DMA2_Stream1_IRQn); } +void DMA2_Stream2_IRQHandler(void) { IRQ_ENTER(DMA2_Stream2_IRQn); if (dma_handle[10] != NULL) { HAL_DMA_IRQHandler(dma_handle[10]); } IRQ_EXIT(DMA2_Stream2_IRQn); } +void DMA2_Stream3_IRQHandler(void) { IRQ_ENTER(DMA2_Stream3_IRQn); if (dma_handle[11] != NULL) { HAL_DMA_IRQHandler(dma_handle[11]); } IRQ_EXIT(DMA2_Stream3_IRQn); } +void DMA2_Stream4_IRQHandler(void) { IRQ_ENTER(DMA2_Stream4_IRQn); if (dma_handle[12] != NULL) { HAL_DMA_IRQHandler(dma_handle[12]); } IRQ_EXIT(DMA2_Stream4_IRQn); } +void DMA2_Stream5_IRQHandler(void) { IRQ_ENTER(DMA2_Stream5_IRQn); if (dma_handle[13] != NULL) { HAL_DMA_IRQHandler(dma_handle[13]); } IRQ_EXIT(DMA2_Stream5_IRQn); } +void DMA2_Stream6_IRQHandler(void) { IRQ_ENTER(DMA2_Stream6_IRQn); if (dma_handle[14] != NULL) { HAL_DMA_IRQHandler(dma_handle[14]); } IRQ_EXIT(DMA2_Stream6_IRQn); } +void DMA2_Stream7_IRQHandler(void) { IRQ_ENTER(DMA2_Stream7_IRQn); if (dma_handle[15] != NULL) { HAL_DMA_IRQHandler(dma_handle[15]); } IRQ_EXIT(DMA2_Stream7_IRQn); } #define DMA1_IS_CLK_ENABLED() ((RCC->AHB1ENR & RCC_AHB1ENR_DMA1EN) != 0) #define DMA2_IS_CLK_ENABLED() ((RCC->AHB1ENR & RCC_AHB1ENR_DMA2EN) != 0) diff --git a/stmhal/irq.c b/stmhal/irq.c index 749e4813c3..44758e11bc 100644 --- a/stmhal/irq.c +++ b/stmhal/irq.c @@ -31,6 +31,10 @@ /// \moduleref pyb +#if IRQ_ENABLE_STATS +uint32_t irq_stats[FPU_IRQn + 1] = {0}; +#endif + /// \function wfi() /// Wait for an interrupt. /// This executies a `wfi` instruction which reduces power consumption @@ -62,3 +66,11 @@ STATIC mp_obj_t pyb_enable_irq(uint n_args, const mp_obj_t *arg) { return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_enable_irq_obj, 0, 1, pyb_enable_irq); + +#if IRQ_ENABLE_STATS +// return a memoryview of the irq statistics array +STATIC mp_obj_t pyb_irq_stats(void) { + return mp_obj_new_memoryview(0x80 | 'I', MP_ARRAY_SIZE(irq_stats), &irq_stats[0]); +} +MP_DEFINE_CONST_FUN_OBJ_0(pyb_irq_stats_obj, pyb_irq_stats); +#endif diff --git a/stmhal/irq.h b/stmhal/irq.h index bf8c1fcd98..f3a8a2cc9e 100644 --- a/stmhal/irq.h +++ b/stmhal/irq.h @@ -28,6 +28,19 @@ #define IRQ_STATE_DISABLED (0x00000001) #define IRQ_STATE_ENABLED (0x00000000) +// Enable this to get a count for the number of times each irq handler is called, +// accessible via pyb.irq_stats(). +#define IRQ_ENABLE_STATS (0) + +#if IRQ_ENABLE_STATS +extern uint32_t irq_stats[FPU_IRQn + 1]; +#define IRQ_ENTER(irq) ++irq_stats[irq] +#define IRQ_EXIT(irq) +#else +#define IRQ_ENTER(irq) +#define IRQ_EXIT(irq) +#endif + static inline mp_uint_t query_irq(void) { return __get_PRIMASK(); } @@ -60,6 +73,7 @@ static inline void restore_irq_pri(uint32_t basepri) { MP_DECLARE_CONST_FUN_OBJ(pyb_wfi_obj); MP_DECLARE_CONST_FUN_OBJ(pyb_disable_irq_obj); MP_DECLARE_CONST_FUN_OBJ(pyb_enable_irq_obj); +MP_DECLARE_CONST_FUN_OBJ(pyb_irq_stats_obj); // IRQ priority definitions. // diff --git a/stmhal/modpyb.c b/stmhal/modpyb.c index be71f3f80e..0f18b04ed6 100644 --- a/stmhal/modpyb.c +++ b/stmhal/modpyb.c @@ -139,6 +139,9 @@ STATIC const mp_map_elem_t pyb_module_globals_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR_wfi), (mp_obj_t)&pyb_wfi_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_disable_irq), (mp_obj_t)&pyb_disable_irq_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_enable_irq), (mp_obj_t)&pyb_enable_irq_obj }, + #if IRQ_ENABLE_STATS + { MP_OBJ_NEW_QSTR(MP_QSTR_irq_stats), (mp_obj_t)&pyb_irq_stats_obj }, + #endif { MP_OBJ_NEW_QSTR(MP_QSTR_stop), (mp_obj_t)&machine_sleep_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_standby), (mp_obj_t)&machine_deepsleep_obj }, diff --git a/stmhal/qstrdefsport.h b/stmhal/qstrdefsport.h index 4f7499fe83..0c0b40773c 100644 --- a/stmhal/qstrdefsport.h +++ b/stmhal/qstrdefsport.h @@ -40,6 +40,7 @@ Q(wfi) Q(disable_irq) Q(enable_irq) Q(reset) +Q(irq_stats) Q(stop) Q(standby) Q(idle) diff --git a/stmhal/sdcard.c b/stmhal/sdcard.c index 2adbaf1468..ae18525196 100644 --- a/stmhal/sdcard.c +++ b/stmhal/sdcard.c @@ -196,7 +196,9 @@ uint64_t sdcard_get_capacity_in_bytes(void) { } void SDIO_IRQHandler(void) { + IRQ_ENTER(SDIO_IRQn); HAL_SD_IRQHandler(&sd_handle); + IRQ_EXIT(SDIO_IRQn); } mp_uint_t sdcard_read_blocks(uint8_t *dest, uint32_t block_num, uint32_t num_blocks) { diff --git a/stmhal/stm32_it.c b/stmhal/stm32_it.c index fec663ea74..abef2ca79f 100644 --- a/stmhal/stm32_it.c +++ b/stmhal/stm32_it.c @@ -72,6 +72,7 @@ #include "py/obj.h" #include "pendsv.h" +#include "irq.h" #include "extint.h" #include "timer.h" #include "uart.h" @@ -306,12 +307,16 @@ void SysTick_Handler(void) { */ #if defined(USE_USB_FS) void OTG_FS_IRQHandler(void) { + IRQ_ENTER(OTG_FS_IRQn); HAL_PCD_IRQHandler(&pcd_fs_handle); + IRQ_EXIT(OTG_FS_IRQn); } #endif #if defined(USE_USB_HS) void OTG_HS_IRQHandler(void) { + IRQ_ENTER(OTG_HS_IRQn); HAL_PCD_IRQHandler(&pcd_hs_handle); + IRQ_EXIT(OTG_HS_IRQn); } #endif @@ -363,12 +368,14 @@ STATIC void OTG_CMD_WKUP_Handler(PCD_HandleTypeDef *pcd_handle) { * @retval None */ void OTG_FS_WKUP_IRQHandler(void) { + IRQ_ENTER(OTG_FS_WKUP_IRQn); OTG_CMD_WKUP_Handler(&pcd_fs_handle); /* Clear EXTI pending Bit*/ __HAL_USB_FS_EXTI_CLEAR_FLAG(); + IRQ_EXIT(OTG_FS_WKUP_IRQn); } #endif @@ -379,12 +386,14 @@ void OTG_FS_WKUP_IRQHandler(void) { * @retval None */ void OTG_HS_WKUP_IRQHandler(void) { + IRQ_ENTER(OTG_HS_WKUP_IRQn); OTG_CMD_WKUP_Handler(&pcd_hs_handle); /* Clear EXTI pending Bit*/ __HAL_USB_HS_EXTI_CLEAR_FLAG(); + IRQ_EXIT(OTG_HS_WKUP_IRQn); } #endif @@ -399,6 +408,7 @@ void OTG_HS_WKUP_IRQHandler(void) { // Handle a flash (erase/program) interrupt. void FLASH_IRQHandler(void) { + IRQ_ENTER(FLASH_IRQn); // This calls the real flash IRQ handler, if needed /* uint32_t flash_cr = FLASH->CR; @@ -408,6 +418,7 @@ void FLASH_IRQHandler(void) { */ // This call the storage IRQ handler, to check if the flash cache needs flushing storage_irq_handler(); + IRQ_EXIT(FLASH_IRQn); } /** @@ -416,163 +427,231 @@ void FLASH_IRQHandler(void) { * @retval None */ void EXTI0_IRQHandler(void) { + IRQ_ENTER(EXTI0_IRQn); Handle_EXTI_Irq(0); + IRQ_EXIT(EXTI0_IRQn); } void EXTI1_IRQHandler(void) { + IRQ_ENTER(EXTI1_IRQn); Handle_EXTI_Irq(1); + IRQ_EXIT(EXTI1_IRQn); } void EXTI2_IRQHandler(void) { + IRQ_ENTER(EXTI2_IRQn); Handle_EXTI_Irq(2); + IRQ_EXIT(EXTI2_IRQn); } void EXTI3_IRQHandler(void) { + IRQ_ENTER(EXTI3_IRQn); Handle_EXTI_Irq(3); + IRQ_EXIT(EXTI3_IRQn); } void EXTI4_IRQHandler(void) { + IRQ_ENTER(EXTI4_IRQn); Handle_EXTI_Irq(4); + IRQ_EXIT(EXTI4_IRQn); } void EXTI9_5_IRQHandler(void) { + IRQ_ENTER(EXTI9_5_IRQn); Handle_EXTI_Irq(5); Handle_EXTI_Irq(6); Handle_EXTI_Irq(7); Handle_EXTI_Irq(8); Handle_EXTI_Irq(9); + IRQ_EXIT(EXTI9_5_IRQn); } void EXTI15_10_IRQHandler(void) { + IRQ_ENTER(EXTI15_10_IRQn); Handle_EXTI_Irq(10); Handle_EXTI_Irq(11); Handle_EXTI_Irq(12); Handle_EXTI_Irq(13); Handle_EXTI_Irq(14); Handle_EXTI_Irq(15); + IRQ_EXIT(EXTI15_10_IRQn); } void PVD_IRQHandler(void) { + IRQ_ENTER(PVD_IRQn); #if defined(MICROPY_HW_USE_ALT_IRQ_FOR_CDC) extern void USBD_CDC_HAL_TIM_PeriodElapsedCallback(void); USBD_CDC_HAL_TIM_PeriodElapsedCallback(); #endif Handle_EXTI_Irq(EXTI_PVD_OUTPUT); + IRQ_EXIT(PVD_IRQn); } void RTC_Alarm_IRQHandler(void) { + IRQ_ENTER(RTC_Alarm_IRQn); Handle_EXTI_Irq(EXTI_RTC_ALARM); + IRQ_EXIT(RTC_Alarm_IRQn); } #if defined(ETH) // The 407 has ETH, the 405 doesn't void ETH_WKUP_IRQHandler(void) { + IRQ_ENTER(ETH_WKUP_IRQn); Handle_EXTI_Irq(EXTI_ETH_WAKEUP); + IRQ_EXIT(ETH_WKUP_IRQn); } #endif void TAMP_STAMP_IRQHandler(void) { + IRQ_ENTER(TAMP_STAMP_IRQn); Handle_EXTI_Irq(EXTI_RTC_TIMESTAMP); + IRQ_EXIT(TAMP_STAMP_IRQn); } void RTC_WKUP_IRQHandler(void) { + IRQ_ENTER(RTC_WKUP_IRQn); RTC->ISR &= ~(1 << 10); // clear wakeup interrupt flag Handle_EXTI_Irq(EXTI_RTC_WAKEUP); // clear EXTI flag and execute optional callback + IRQ_EXIT(RTC_WKUP_IRQn); } void TIM1_BRK_TIM9_IRQHandler(void) { + IRQ_ENTER(TIM1_BRK_TIM9_IRQn); timer_irq_handler(9); + IRQ_EXIT(TIM1_BRK_TIM9_IRQn); } void TIM1_UP_TIM10_IRQHandler(void) { + IRQ_ENTER(TIM1_UP_TIM10_IRQn); timer_irq_handler(1); timer_irq_handler(10); + IRQ_EXIT(TIM1_UP_TIM10_IRQn); } void TIM1_TRG_COM_TIM11_IRQHandler(void) { + IRQ_ENTER(TIM1_TRG_COM_TIM11_IRQn); timer_irq_handler(11); + IRQ_EXIT(TIM1_TRG_COM_TIM11_IRQn); } void TIM2_IRQHandler(void) { + IRQ_ENTER(TIM2_IRQn); timer_irq_handler(2); + IRQ_EXIT(TIM2_IRQn); } void TIM3_IRQHandler(void) { + IRQ_ENTER(TIM3_IRQn); #if defined(MICROPY_HW_USE_ALT_IRQ_FOR_CDC) timer_irq_handler(3); #else HAL_TIM_IRQHandler(&TIM3_Handle); #endif + IRQ_EXIT(TIM3_IRQn); } void TIM4_IRQHandler(void) { + IRQ_ENTER(TIM4_IRQn); timer_irq_handler(4); + IRQ_EXIT(TIM4_IRQn); } void TIM5_IRQHandler(void) { + IRQ_ENTER(TIM5_IRQn); timer_irq_handler(5); HAL_TIM_IRQHandler(&TIM5_Handle); + IRQ_EXIT(TIM5_IRQn); } void TIM6_DAC_IRQHandler(void) { + IRQ_ENTER(TIM6_DAC_IRQn); timer_irq_handler(6); + IRQ_EXIT(TIM6_DAC_IRQn); } void TIM7_IRQHandler(void) { + IRQ_ENTER(TIM7_IRQn); timer_irq_handler(7); + IRQ_EXIT(TIM7_IRQn); } void TIM8_BRK_TIM12_IRQHandler(void) { + IRQ_ENTER(TIM8_BRK_TIM12_IRQn); timer_irq_handler(12); + IRQ_EXIT(TIM8_BRK_TIM12_IRQn); } void TIM8_UP_TIM13_IRQHandler(void) { + IRQ_ENTER(TIM8_UP_TIM13_IRQn); timer_irq_handler(8); timer_irq_handler(13); + IRQ_EXIT(TIM8_UP_TIM13_IRQn); } void TIM8_TRG_COM_TIM14_IRQHandler(void) { + IRQ_ENTER(TIM8_TRG_COM_TIM14_IRQn); timer_irq_handler(14); + IRQ_EXIT(TIM8_TRG_COM_TIM14_IRQn); } // UART/USART IRQ handlers void USART1_IRQHandler(void) { + IRQ_ENTER(USART1_IRQn); uart_irq_handler(1); + IRQ_EXIT(USART1_IRQn); } void USART2_IRQHandler(void) { + IRQ_ENTER(USART2_IRQn); uart_irq_handler(2); + IRQ_EXIT(USART2_IRQn); } void USART3_IRQHandler(void) { + IRQ_ENTER(USART3_IRQn); uart_irq_handler(3); + IRQ_EXIT(USART3_IRQn); } void UART4_IRQHandler(void) { + IRQ_ENTER(UART4_IRQn); uart_irq_handler(4); + IRQ_EXIT(UART4_IRQn); } void UART5_IRQHandler(void) { + IRQ_ENTER(UART5_IRQn); uart_irq_handler(5); + IRQ_EXIT(UART5_IRQn); } void USART6_IRQHandler(void) { + IRQ_ENTER(USART6_IRQn); uart_irq_handler(6); + IRQ_EXIT(USART6_IRQn); } #if MICROPY_HW_ENABLE_CAN void CAN1_RX0_IRQHandler(void) { + IRQ_ENTER(CAN1_RX0_IRQn); can_rx_irq_handler(PYB_CAN_1, CAN_FIFO0); + IRQ_EXIT(CAN1_RX0_IRQn); } void CAN1_RX1_IRQHandler(void) { + IRQ_ENTER(CAN1_RX1_IRQn); can_rx_irq_handler(PYB_CAN_1, CAN_FIFO1); + IRQ_EXIT(CAN1_RX1_IRQn); } void CAN2_RX0_IRQHandler(void) { + IRQ_ENTER(CAN2_RX0_IRQn); can_rx_irq_handler(PYB_CAN_2, CAN_FIFO0); + IRQ_EXIT(CAN2_RX0_IRQn); } void CAN2_RX1_IRQHandler(void) { + IRQ_ENTER(CAN2_RX1_IRQn); can_rx_irq_handler(PYB_CAN_2, CAN_FIFO1); + IRQ_EXIT(CAN2_RX1_IRQn); } #endif // MICROPY_HW_ENABLE_CAN |