From bc16cd48678f0e02ddf24379b0563e5265cf2d63 Mon Sep 17 00:00:00 2001 From: GeorgeKang Date: Thu, 26 Mar 2015 11:15:06 +0800 Subject: [PATCH 01/10] config: Add user interrupt configure options in Kconfig for stm32f4 --- include/platform/stm32f4/nvic_private.h | 328 ++++++++++++++++++++++- platform/Kconfig | 3 + platform/stm32f4/Kconfig | 330 ++++++++++++++++++++++++ 3 files changed, 660 insertions(+), 1 deletion(-) create mode 100644 platform/stm32f4/Kconfig diff --git a/include/platform/stm32f4/nvic_private.h b/include/platform/stm32f4/nvic_private.h index 1fbfe994..1f55ebbc 100644 --- a/include/platform/stm32f4/nvic_private.h +++ b/include/platform/stm32f4/nvic_private.h @@ -1,84 +1,410 @@ /* This header is only included internally. */ - +#if !defined(USER_INTERRUPT) || \ + (defined(USER_INTERRUPT) && defined(CONFIG_WWDG_USER_IRQ)) IRQ_VEC_N_OP(0) +#endif + +#if !defined(USER_INTERRUPT) || \ + (defined(USER_INTERRUPT) && defined(CONFIG_PVD_USER_IRQ)) IRQ_VEC_N_OP(1) +#endif + +#if !defined(USER_INTERRUPT) || \ + (defined(USER_INTERRUPT) && defined(CONFIG_TAMP_STAMP_USER_IRQ)) IRQ_VEC_N_OP(2) +#endif + +#if !defined(USER_INTERRUPT) || \ + (defined(USER_INTERRUPT) && defined(CONFIG_RTC_WKUP_USER_IRQ)) IRQ_VEC_N_OP(3) +#endif + +#if !defined(USER_INTERRUPT) || \ + (defined(USER_INTERRUPT) && defined(CONFIG_FLASH_USER_IRQ)) IRQ_VEC_N_OP(4) +#endif + +#if !defined(USER_INTERRUPT) || \ + (defined(USER_INTERRUPT) && defined(CONFIG_RCC_USER_IRQ)) IRQ_VEC_N_OP(5) +#endif + +#if !defined(USER_INTERRUPT) || \ + (defined(USER_INTERRUPT) && defined(CONFIG_EXTI0_USER_IRQ)) IRQ_VEC_N_OP(6) +#endif + +#if !defined(USER_INTERRUPT) || \ + (defined(USER_INTERRUPT) && defined(CONFIG_EXTI1_USER_IRQ)) IRQ_VEC_N_OP(7) +#endif + +#if !defined(USER_INTERRUPT) || \ + (defined(USER_INTERRUPT) && defined(CONFIG_EXTI2_USER_IRQ)) IRQ_VEC_N_OP(8) +#endif + +#if !defined(USER_INTERRUPT) || \ + (defined(USER_INTERRUPT) && defined(CONFIG_EXTI3_USER_IRQ)) IRQ_VEC_N_OP(9) +#endif + +#if !defined(USER_INTERRUPT) || \ + (defined(USER_INTERRUPT) && defined(CONFIG_EXTI4_USER_IRQ)) IRQ_VEC_N_OP(10) +#endif + +#if !defined(USER_INTERRUPT) || \ + (defined(USER_INTERRUPT) && defined(CONFIG_DMA1_Stream0_USER_IRQ)) IRQ_VEC_N_OP(11) +#endif + +#if !defined(USER_INTERRUPT) || \ + (defined(USER_INTERRUPT) && defined(CONFIG_DMA1_Stream1_USER_IRQ)) IRQ_VEC_N_OP(12) +#endif + +#if !defined(USER_INTERRUPT) || \ + (defined(USER_INTERRUPT) && defined(CONFIG_DMA1_Stream2_USER_IRQ)) IRQ_VEC_N_OP(13) +#endif + +#if !defined(USER_INTERRUPT) || \ + (defined(USER_INTERRUPT) && defined(CONFIG_DMA1_Stream3_USER_IRQ)) IRQ_VEC_N_OP(14) +#endif + +#if !defined(USER_INTERRUPT) || \ + (defined(USER_INTERRUPT) && defined(CONFIG_DMA1_Stream4_USER_IRQ)) IRQ_VEC_N_OP(15) +#endif + +#if !defined(USER_INTERRUPT) || \ + (defined(USER_INTERRUPT) && defined(CONFIG_DMA1_Stream5_USER_IRQ)) IRQ_VEC_N_OP(16) +#endif + +#if !defined(USER_INTERRUPT) || \ + (defined(USER_INTERRUPT) && defined(CONFIG_DMA1_Stream6_USER_IRQ)) IRQ_VEC_N_OP(17) +#endif + +#if !defined(USER_INTERRUPT) || \ + (defined(USER_INTERRUPT) && defined(CONFIG_ADC_USER_IRQ)) IRQ_VEC_N_OP(18) +#endif + +#if !defined(USER_INTERRUPT) || \ + (defined(USER_INTERRUPT) && defined(CONFIG_CAN1_TX_USER_IRQ)) IRQ_VEC_N_OP(19) +#endif + +#if !defined(USER_INTERRUPT) || \ + (defined(USER_INTERRUPT) && defined(CONFIG_CAN1_RX_USER_IRQ)) IRQ_VEC_N_OP(20) +#endif + +#if !defined(USER_INTERRUPT) || \ + (defined(USER_INTERRUPT) && defined(CONFIG_CAN1_RX1_USER_IRQ)) IRQ_VEC_N_OP(21) +#endif + +#if !defined(USER_INTERRUPT) || \ + (defined(USER_INTERRUPT) && defined(CONFIG_CAN1_SCE_USER_IRQ)) IRQ_VEC_N_OP(22) +#endif + +#if !defined(USER_INTERRUPT) || \ + (defined(USER_INTERRUPT) && defined(CONFIG_EXTI9_5_USER_IRQ)) IRQ_VEC_N_OP(23) +#endif + +#if !defined(USER_INTERRUPT) || \ + (defined(USER_INTERRUPT) && defined(CONFIG_TIM1_BRK_TIM9_USER_IRQ)) IRQ_VEC_N_OP(24) +#endif + +#if !defined(USER_INTERRUPT) || \ + (defined(USER_INTERRUPT) && defined(CONFIG_TIM1_UP_TIM10_USER_IRQ)) IRQ_VEC_N_OP(25) +#endif + +#if !defined(USER_INTERRUPT) || \ + (defined(USER_INTERRUPT) && defined(CONFIG_TIM1_TRG_COM_TIM11_USER_IRQ)) IRQ_VEC_N_OP(26) +#endif + +#if !defined(USER_INTERRUPT) || \ + (defined(USER_INTERRUPT) && defined(CONFIG_TIM1_CC_USER_IRQ)) IRQ_VEC_N_OP(27) +#endif + +#if !defined(USER_INTERRUPT) || \ + (defined(USER_INTERRUPT) && defined(CONFIG_TIM2_USER_IRQ)) IRQ_VEC_N_OP(28) +#endif + +#if !defined(USER_INTERRUPT) || \ + (defined(USER_INTERRUPT) && defined(CONFIG_TIM3_USER_IRQ)) IRQ_VEC_N_OP(29) +#endif + +#if !defined(USER_INTERRUPT) || \ + (defined(USER_INTERRUPT) && defined(CONFIG_TIM4_USER_IRQ)) IRQ_VEC_N_OP(30) +#endif + +#if !defined(USER_INTERRUPT) || \ + (defined(USER_INTERRUPT) && defined(CONFIG_I2C1_EV_USER_IRQ)) IRQ_VEC_N_OP(31) +#endif + +#if !defined(USER_INTERRUPT) || \ + (defined(USER_INTERRUPT) && defined(CONFIG_I2C1_ER_USER_IRQ)) IRQ_VEC_N_OP(32) +#endif + +#if !defined(USER_INTERRUPT) || \ + (defined(USER_INTERRUPT) && defined(CONFIG_I2C2_EV_USER_IRQ)) IRQ_VEC_N_OP(33) +#endif + +#if !defined(USER_INTERRUPT) || \ + (defined(USER_INTERRUPT) && defined(CONFIG_I2C2_ER_USER_IRQ)) IRQ_VEC_N_OP(34) +#endif + +#if !defined(USER_INTERRUPT) || \ + (defined(USER_INTERRUPT) && defined(CONFIG_SPI1_USER_IRQ)) IRQ_VEC_N_OP(35) +#endif + +#if !defined(USER_INTERRUPT) || \ + (defined(USER_INTERRUPT) && defined(CONFIG_SPI2_USER_IRQ)) IRQ_VEC_N_OP(36) +#endif + +#if !defined(USER_INTERRUPT) || \ + (defined(USER_INTERRUPT) && defined(CONFIG_USART1_USER_IRQ)) IRQ_VEC_N_OP(37) +#endif + +#if !defined(USER_INTERRUPT) || \ + (defined(USER_INTERRUPT) && defined(CONFIG_USART2_USER_IRQ)) IRQ_VEC_N_OP(38) +#endif + +#if !defined(USER_INTERRUPT) || \ + (defined(USER_INTERRUPT) && defined(CONFIG_USART3_USER_IRQ)) IRQ_VEC_N_OP(39) +#endif + +#if !defined(USER_INTERRUPT) || \ + (defined(USER_INTERRUPT) && defined(CONFIG_EXTI15_10_USER_IRQ)) IRQ_VEC_N_OP(40) +#endif + +#if !defined(USER_INTERRUPT) || \ + (defined(USER_INTERRUPT) && defined(CONFIG_RTC_Alarm_USER_IRQ)) IRQ_VEC_N_OP(41) +#endif + +#if !defined(USER_INTERRUPT) || \ + (defined(USER_INTERRUPT) && defined(CONFIG_OTG_FS_WKUP_USER_IRQ)) IRQ_VEC_N_OP(42) +#endif + +#if !defined(USER_INTERRUPT) || \ + (defined(USER_INTERRUPT) && defined(CONFIG_TIM8_BRK_TIM12_USER_IRQ)) IRQ_VEC_N_OP(43) +#endif + +#if !defined(USER_INTERRUPT) || \ + (defined(USER_INTERRUPT) && defined(CONFIG_TIM8_UP_TIM13_USER_IRQ)) IRQ_VEC_N_OP(44) +#endif + +#if !defined(USER_INTERRUPT) || \ + (defined(USER_INTERRUPT) && defined(CONFIG_TIM8_TRG_COM_TIM14_USER_IRQ)) IRQ_VEC_N_OP(45) +#endif + +#if !defined(USER_INTERRUPT) || \ + (defined(USER_INTERRUPT) && defined(CONFIG_TIM8_CC_USER_IRQ)) IRQ_VEC_N_OP(46) +#endif + +#if !defined(USER_INTERRUPT) || \ + (defined(USER_INTERRUPT) && defined(CONFIG_DMA1_Stream7_USER_IRQ)) IRQ_VEC_N_OP(47) +#endif + +#if !defined(USER_INTERRUPT) || \ + (defined(USER_INTERRUPT) && defined(CONFIG_FSMC_USER_IRQ)) IRQ_VEC_N_OP(48) +#endif + +#if !defined(USER_INTERRUPT) || \ + (defined(USER_INTERRUPT) && defined(CONFIG_SDIO_USER_IRQ)) IRQ_VEC_N_OP(49) +#endif + +#if !defined(USER_INTERRUPT) || \ + (defined(USER_INTERRUPT) && defined(CONFIG_TIM5_USER_IRQ)) IRQ_VEC_N_OP(50) +#endif + +#if !defined(USER_INTERRUPT) || \ + (defined(USER_INTERRUPT) && defined(CONFIG_SPI3_USER_IRQ)) IRQ_VEC_N_OP(51) +#endif + +#if !defined(USER_INTERRUPT) || \ + (defined(USER_INTERRUPT) && defined(CONFIG_UART4_USER_IRQ)) IRQ_VEC_N_OP(52) +#endif + +#if !defined(USER_INTERRUPT) || \ + (defined(USER_INTERRUPT) && defined(CONFIG_UART5_USER_IRQ)) IRQ_VEC_N_OP(53) +#endif + +#if !defined(USER_INTERRUPT) || \ + (defined(USER_INTERRUPT) && defined(CONFIG_TIM6_DAC_USER_IRQ)) IRQ_VEC_N_OP(54) +#endif + +#if !defined(USER_INTERRUPT) || \ + (defined(USER_INTERRUPT) && defined(CONFIG_TIM7_USER_IRQ)) IRQ_VEC_N_OP(55) +#endif + +#if !defined(USER_INTERRUPT) || \ + (defined(USER_INTERRUPT) && defined(CONFIG_DMA2_Stream0_USER_IRQ)) IRQ_VEC_N_OP(56) +#endif + +#if !defined(USER_INTERRUPT) || \ + (defined(USER_INTERRUPT) && defined(CONFIG_DMA2_Stream1_USER_IRQ)) IRQ_VEC_N_OP(57) +#endif + +#if !defined(USER_INTERRUPT) || \ + (defined(USER_INTERRUPT) && defined(CONFIG_DMA2_Stream2_USER_IRQ)) IRQ_VEC_N_OP(58) +#endif + +#if !defined(USER_INTERRUPT) || \ + (defined(USER_INTERRUPT) && defined(CONFIG_DMA2_Stream3_USER_IRQ)) IRQ_VEC_N_OP(59) +#endif + +#if !defined(USER_INTERRUPT) || \ + (defined(USER_INTERRUPT) && defined(CONFIG_DMA2_Stream4_USER_IRQ)) IRQ_VEC_N_OP(60) +#endif + +#if !defined(USER_INTERRUPT) || \ + (defined(USER_INTERRUPT) && defined(CONFIG_ETH_USER_IRQ)) IRQ_VEC_N_OP(61) +#endif + +#if !defined(USER_INTERRUPT) || \ + (defined(USER_INTERRUPT) && defined(CONFIG_ETH_WKUP_USER_IRQ)) IRQ_VEC_N_OP(62) +#endif + +#if !defined(USER_INTERRUPT) || \ + (defined(USER_INTERRUPT) && defined(CONFIG_CAN2_TX_USER_IRQ)) IRQ_VEC_N_OP(63) +#endif + +#if !defined(USER_INTERRUPT) || \ + (defined(USER_INTERRUPT) && defined(CONFIG_CAN2_RX0_USER_IRQ)) IRQ_VEC_N_OP(64) +#endif + +#if !defined(USER_INTERRUPT) || \ + (defined(USER_INTERRUPT) && defined(CONFIG_CAN2_RX1_USER_IRQ)) IRQ_VEC_N_OP(65) +#endif + +#if !defined(USER_INTERRUPT) || \ + (defined(USER_INTERRUPT) && defined(CONFIG_CAN2_SCE_USER_IRQ)) IRQ_VEC_N_OP(66) +#endif + +#if !defined(USER_INTERRUPT) || \ + (defined(USER_INTERRUPT) && defined(CONFIG_OTG_FS_USER_IRQ)) IRQ_VEC_N_OP(67) +#endif + +#if !defined(USER_INTERRUPT) || \ + (defined(USER_INTERRUPT) && defined(CONFIG_DMA2_Stream5_USER_IRQ)) IRQ_VEC_N_OP(68) +#endif + +#if !defined(USER_INTERRUPT) || \ + (defined(USER_INTERRUPT) && defined(CONFIG_DMA2_Stream6_USER_IRQ)) IRQ_VEC_N_OP(69) +#endif + +#if !defined(USER_INTERRUPT) || \ + (defined(USER_INTERRUPT) && defined(CONFIG_DMA2_Stream7_USER_IRQ)) IRQ_VEC_N_OP(70) +#endif + +#if !defined(USER_INTERRUPT) || \ + (defined(USER_INTERRUPT) && defined(CONFIG_USART6_USER_IRQ)) IRQ_VEC_N_OP(71) +#endif + +#if !defined(USER_INTERRUPT) || \ + (defined(USER_INTERRUPT) && defined(CONFIG_I2C3_EV_USER_IRQ)) IRQ_VEC_N_OP(72) +#endif + +#if !defined(USER_INTERRUPT) || \ + (defined(USER_INTERRUPT) && defined(CONFIG_I2C3_ER_USER_IRQ)) IRQ_VEC_N_OP(73) +#endif + +#if !defined(USER_INTERRUPT) || \ + (defined(USER_INTERRUPT) && defined(CONFIG_OTG_HS_EP1_OUT_USER_IRQ)) IRQ_VEC_N_OP(74) +#endif + +#if !defined(USER_INTERRUPT) || \ + (defined(USER_INTERRUPT) && defined(CONFIG_OTG_HS_EP1_IN_USER_IRQ)) IRQ_VEC_N_OP(75) +#endif + +#if !defined(USER_INTERRUPT) || \ + (defined(USER_INTERRUPT) && defined(CONFIG_OTG_HS_WKUP_USER_IRQ)) IRQ_VEC_N_OP(76) +#endif + +#if !defined(USER_INTERRUPT) || \ + (defined(USER_INTERRUPT) && defined(CONFIG_OTG_HS_USER_IRQ)) IRQ_VEC_N_OP(77) +#endif + +#if !defined(USER_INTERRUPT) || \ + (defined(USER_INTERRUPT) && defined(CONFIG_DCMI_USER_IRQ)) IRQ_VEC_N_OP(78) +#endif + +#if !defined(USER_INTERRUPT) || \ + (defined(USER_INTERRUPT) && defined(CONFIG_CRYP_USER_IRQ)) IRQ_VEC_N_OP(79) +#endif + +#if !defined(USER_INTERRUPT) || \ + (defined(USER_INTERRUPT) && defined(CONFIG_HASH_RNG_USER_IRQ)) IRQ_VEC_N_OP(80) +#endif + +#if !defined(USER_INTERRUPT) || (\ + defined(USER_INTERRUPT) && defined(CONFIG_FPU_USER_IRQ)) IRQ_VEC_N_OP(81) +#endif diff --git a/platform/Kconfig b/platform/Kconfig index 5e0a9e6a..40d58c62 100644 --- a/platform/Kconfig +++ b/platform/Kconfig @@ -62,4 +62,7 @@ config DBGPORT_USE_USART4 endchoice +if BOARD_STM32F4DISCOVERY +source platform/stm32f4/Kconfig +endif endmenu diff --git a/platform/stm32f4/Kconfig b/platform/stm32f4/Kconfig new file mode 100644 index 00000000..182ce1ac --- /dev/null +++ b/platform/stm32f4/Kconfig @@ -0,0 +1,330 @@ +menu "User Interrupt Config" + +config WWDG_USER_IRQ + bool "User WWDG IRQ" + default n + +config PVD_USER_IRQ + bool "User PVD IRQ" + default n + +config TAMP_STAMP_USER_IRQ + bool "User TAMP_STAMP IRQ" + default n + +config RTC_WKUP_USER_IRQ + bool "User RTC_WKUP IRQ" + default n + +config FLASH_USER_IRQ + bool "User FLASH_USER IRQ" + default n + +config RCC_USER_IRQ + bool "User RCC IRQ" + default n + +config EXTI0_USER_IRQ + bool "User EXTI0 IRQ" + default n + +config EXTI1_USER_IRQ + bool "User EXIT1 IRQ" + default n + +config EXTI2_USER_IRQ + bool "User EXIT2 IRQ" + default n + +config EXTI3_USER_IRQ + bool "User EXIT3 IRQ" + default n + +config EXTI4_USER_IRQ + bool "User EXIT4 IRQ" + default n + +config DMA1_Stream0_USER_IRQ + bool "User DMA1_Stream0 IRQ" + default n + +config DMA1_Stream1_USER_IRQ + bool "User DMA1_Stream1 IRQ" + default n + +config DMA1_Stream2_USER_IRQ + bool "User DMA1_Stream2 IRQ" + default n + +config DMA1_Stream3_USER_IRQ + bool "User DMA1_Stream3 IRQ" + default n + +config DMA1_Stream4_USER_IRQ + bool "User DMA1_Stream4 IRQ" + default n + +config DMA1_Stream5_USER_IRQ + bool "User DMA1_Stream5 IRQ" + default n + +config DMA1_Stream6_USER_IRQ + bool "User DMA1_Stream6 IRQ" + default n + +config ADC_USER_IRQ + bool "User ADC IRQ" + default n + +config CAN1_TX_USER_IRQ + bool "CAN1 TX User IRQ" + default n + +config CAN1_RX_USER_IRQ + bool "CAN1 RX User IRQ" + default n + +config CAN1_RX1_USER_IRQ + bool "CAN1 RX1 User IRQ" + default n + +config CAN1_SCE_USER_IRQ + bool "CAN1 SEC User IRQ" + default n + +config EXTI9_5_USER_IRQ + bool "EXTI9_5 User IRQ" + default n + +config TIM1_BRK_TIM9_USER_IRQ + bool "TIM1_BRK_TIM9 User IRQ" + default n + +config TIM1_UP_TIM10_USER_IRQ + bool "TIM1_UP_TIM10 User IRQ" + default n + +config TIM1_TRG_COM_TIM11_USER_IRQ + bool "TIM1_TRG_COM_TIM11 User IRQ" + default n + +config TIM1_CC_USER_IRQ + bool "TIM1_CC User IRQ" + default n + +config TIM2_USER_IRQ + bool "TIM2 User IRQ" + default n + +config TIM3_USER_IRQ + bool "TIM3 User IRQ" + default n + +config TIM4_USER_IRQ + bool "TIM4 User IRQ" + default n + +config I2C1_EV_USER_IRQ + bool "I2C1_EV User IRQ" + default n + +config I2C1_ER_USER_IRQ + bool "I2C1_ER User IRQ" + default n + +config I2C2_EV_USER_IRQ + bool "I2C2_EV User IRQ" + default n + +config I2C2_ER_USER_IRQ + bool "I2C2_ER User IRQ" + default n + +config SPI1_USER_IRQ + bool "SPI1 User IRQ" + default n + +config SPI2_USER_IRQ + bool "SPI2 User IRQ" + default n + +config USART1_USER_IRQ + bool "USART1 User IRQ" + default n + +config USART2_USER_IRQ + bool "USART2 User IRQ" + default n + +config USART3_USER_IRQ + bool "USART3 User IRQ" + default n + +config EXTI15_10_USER_IRQ + bool "EXTI15_10 User IRQ" + default n + +config RTC_Alarm_USER_IRQ + bool "RTC Alarm User IRQ" + default n + +config OTG_FS_WKUP_USER_IRQ + bool "OTG_FS_WKUP User IRQ" + default n + +config TIM8_BRK_TIM12_USER_IRQ + bool "TIM8_BRK_TIM12 User IRQ" + default n + +config TIM8_UP_TIM13_USER_IRQ + bool "TIM8_UP_TIM13 User IRQ" + default n + +config TIM8_TRG_COM_TIM14_USER_IRQ + bool "TIM8_TRG_COM_TIM14 User IRQ" + default n + +config TIM8_CC_USER_IRQ + bool "TIM8_CC User IRQ" + default n + +config DMA1_Stream7_USER_IRQ + bool "DMA1_Stream7 User IRQ" + default n + +config FSMC_USER_IRQ + bool "FSMC User IRQ" + default n + +config SDIO_USER_IRQ + bool "SDIO User IRQ" + default n + +config TIM5_USER_IRQ + bool "TIM5 User IRQ" + default n + +config SPI3_USER_IRQ + bool "SPI3 User IRQ" + default n + +config UART4_USER_IRQ + bool "UART4 User IRQ" + default n + +config UART5_USER_IRQ + bool "UART5 User IRQ" + default n + +config TIM6_DAC_USER_IRQ + bool "TIM6_DAC User IRQ" + default n + +config TIM7_USER_IRQ + bool "TIM7 User IRQ" + default n + +config DMA2_Stream0_USER_IRQ + bool "DMA2 Stream0 User IRQ" + default n + +config DMA2_Stream1_USER_IRQ + bool "DMA2 Stream1 User IRQ" + default n + +config DMA2_Stream2_USER_IRQ + bool "DMA2 Stream2 User IRQ" + default n + +config DMA2_Stream3_USER_IRQ + bool "DMA2 Stream3 User IRQ" + default n + +config DMA2_Stream4_USER_IRQ + bool "DMA2_Stream4 User IRQ" + default n + +config ETH_USER_IRQ + bool "ETH User IRQ" + default n + +config ETH_WKUP_USER_IRQ + bool "ETH WKUP User IRQ" + default n + +config CAN2_TX_USER_IRQ + bool "CAN2 TX User IRQ" + default n + +config CAN2_RX0_USER_IRQ + bool "CAN2 RX0 User IRQ" + default n + +config CAN2_RX1_USER_IRQ + bool "CAN2 RX1 User IRQ" + default n + +config CAN2_SCE_USER_IRQ + bool "CAN2 SCE User IRQ" + default n + +config OTG_FS_USER_IRQ + bool "OTG FS User IRQ" + default n + +config DMA2_Stream5_USER_IRQ + bool "DMA2 Stream5 User IRQ" + default n + +config DMA2_Stream6_USER_IRQ + bool "DMA2 Stream6 User IRQ" + default n + +config DMA2_Stream7_USER_IRQ + bool "DMA2 Stream7 User IRQ" + default n + +config USART6_USER_IRQ + bool "USART6 User IRQ" + default n + +config I2C3_EV_USER_IRQ + bool "I2C3 EV User IRQ" + default n + +config I2C3_ER_USER_IRQ + bool "I2C3 ER User IRQ" + default n + +config OTG_HS_EP1_OUT_USER_IRQ + bool "OTG_HS_EP1_OUT User IRQ" + default n + +config OTG_HS_EP1_IN_USER_IRQ + bool "OTG_HS_EP1_IN User IRQ" + default n + +config OTG_HS_WKUP_USER_IRQ + bool "OTG_HS_WKUP User IRQ" + default n + +config OTG_HS_USER_IRQ + bool "OTG_HS User IRQ" + default n + +config DCMI_USER_IRQ + bool "DCMI User IRQ" + default n + +config CRYP_USER_IRQ + bool "CRYP User IRQ" + default n + +config HASH_RNG_USER_IRQ + bool "HASH_RNG User IRQ" + default n + +config FPU_USER_IRQ + bool "FPU User IRQ" + default n +endmenu From 6284fa4fe8c8930cedc8570bdd1cab1c8afe0a5c Mon Sep 17 00:00:00 2001 From: GeorgeKang Date: Mon, 23 Mar 2015 19:54:33 +0800 Subject: [PATCH 02/10] ipc: Export ipc_read_mr() and ipc_write_mr() for using in kernel --- include/ipc.h | 3 +++ kernel/ipc.c | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/include/ipc.h b/include/ipc.h index d5268c43..8f96d977 100644 --- a/include/ipc.h +++ b/include/ipc.h @@ -12,4 +12,7 @@ void sys_ipc(uint32_t *param1); uint32_t ipc_deliver(void *data); +uint32_t ipc_read_mr(tcb_t *from, int i); +void ipc_write_mr(tcb_t *to, int i, uint32_t data); + #endif /* IPC_H_ */ diff --git a/kernel/ipc.c b/kernel/ipc.c index f5b8a95b..4282a497 100644 --- a/kernel/ipc.c +++ b/kernel/ipc.c @@ -22,14 +22,14 @@ extern tcb_t *caller; extern tcb_t *thread_map[]; extern int thread_count; -static uint32_t ipc_read_mr(tcb_t *from, int i) +uint32_t ipc_read_mr(tcb_t *from, int i) { if (i >= 8) return from->utcb->mr[i - 8]; return from->ctx.regs[i]; } -static void ipc_write_mr(tcb_t *to, int i, uint32_t data) +void ipc_write_mr(tcb_t *to, int i, uint32_t data) { if (i >= 8) to->utcb->mr[i - 8] = data; From dc00404136d291313f37b721c4ed05aba79d3a13 Mon Sep 17 00:00:00 2001 From: GeorgeKang Date: Mon, 23 Mar 2015 20:14:28 +0800 Subject: [PATCH 03/10] irq: Use the last element of IRQ emu as total irq number --- include/platform/stm32f1/nvic.h | 1 + include/platform/stm32f4/nvic.h | 1 + include/platform/stm32f429/nvic.h | 1 + 3 files changed, 3 insertions(+) diff --git a/include/platform/stm32f1/nvic.h b/include/platform/stm32f1/nvic.h index 663a7497..ce74f2dd 100644 --- a/include/platform/stm32f1/nvic.h +++ b/include/platform/stm32f1/nvic.h @@ -67,6 +67,7 @@ typedef enum IRQn { EXTI15_10_IRQn = 40, /*!< External Line[15:10] Interrupts */ RTC_Alarm_IRQn = 41, /*!< RTC Alarm (A and B) through EXTI Line Interrupt */ OTG_FS_WKUP_IRQn = 42, /*!< USB OTG FS Wakeup through EXTI line interrupt */ + IRQn_NUM, } IRQn_Type; #define MAX_IRQn FPU_IRQn diff --git a/include/platform/stm32f4/nvic.h b/include/platform/stm32f4/nvic.h index 73650bb9..f192d5a5 100644 --- a/include/platform/stm32f4/nvic.h +++ b/include/platform/stm32f4/nvic.h @@ -106,6 +106,7 @@ typedef enum IRQn { CRYP_IRQn = 79, /*!< CRYP crypto global interrupt */ HASH_RNG_IRQn = 80, /*!< Hash and Rng global interrupt */ FPU_IRQn = 81, /*!< FPU global interrupt */ + IRQn_NUM, } IRQn_Type; #define MAX_IRQn FPU_IRQn diff --git a/include/platform/stm32f429/nvic.h b/include/platform/stm32f429/nvic.h index 431639f8..4936a291 100644 --- a/include/platform/stm32f429/nvic.h +++ b/include/platform/stm32f429/nvic.h @@ -106,6 +106,7 @@ typedef enum IRQn { CRYP_IRQn = 79, /*!< CRYP crypto global interrupt */ HASH_RNG_IRQn = 80, /*!< Hash and Rng global interrupt */ FPU_IRQn = 81, /*!< FPU global interrupt */ + IRQn_NUM, } IRQn_Type; #define MAX_IRQn FPU_IRQn From ec452f60d95ac3fd9b905dbe75cb7a5f5834b19b Mon Sep 17 00:00:00 2001 From: GeorgeKang Date: Tue, 24 Mar 2015 10:59:55 +0800 Subject: [PATCH 04/10] nvic: check function to identify if irq handler is default By default, irq handler is _undefined_handler. Therefore, for an irq, we can compare _undefined_handler and its value of vector table to identify if there is specific handler for this irq. --- include/platform/stm32f4/nvic.h | 1 + platform/stm32-common/nvic.c | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/include/platform/stm32f4/nvic.h b/include/platform/stm32f4/nvic.h index f192d5a5..d27acbc6 100644 --- a/include/platform/stm32f4/nvic.h +++ b/include/platform/stm32f4/nvic.h @@ -269,4 +269,5 @@ inline static uint32_t NVIC_GetActive(IRQn_Type IRQn) (1 << ((uint32_t)(IRQn) & 0x1F))) ? 1 : 0); } +int nvic_is_setup(int irq); #endif /* __PLATFORM_STM32F4_NVIC_H__ */ diff --git a/platform/stm32-common/nvic.c b/platform/stm32-common/nvic.c index 13b2bb61..bdd20820 100644 --- a/platform/stm32-common/nvic.c +++ b/platform/stm32-common/nvic.c @@ -28,6 +28,12 @@ void _undefined_handler(void) #include "platform/stm32f4/nvic_private.h" #undef IRQ_VEC_N_OP +extern void (* const g_pfnVectors[])(void); +int nvic_is_setup(int irq) +{ + return !(g_pfnVectors[irq + 16] == _undefined_handler); +} + void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup) { if (!(NVIC_PriorityGroup == NVIC_PriorityGroup_0 || From a9ec7c7f89c1c375e7a952f2fef0c0b9a3fc82d9 Mon Sep 17 00:00:00 2001 From: GeorgeKang Date: Tue, 24 Mar 2015 11:35:51 +0800 Subject: [PATCH 05/10] irq: support user threaded irq handler in kernel Interrupt handler now could be defined as thread in user space. Kernel provides ipc to register handler thread and notify this handler when interrupt happens. --- include/interrupt.h | 15 ++ include/interrupt_ipc.h | 24 +++ include/thread.h | 2 + kernel/build.mk | 7 +- kernel/interrupt.c | 359 ++++++++++++++++++++++++++++++++++++++++ kernel/ipc.c | 21 ++- 6 files changed, 426 insertions(+), 2 deletions(-) create mode 100644 include/interrupt.h create mode 100644 include/interrupt_ipc.h create mode 100644 kernel/interrupt.c diff --git a/include/interrupt.h b/include/interrupt.h new file mode 100644 index 00000000..c4ead034 --- /dev/null +++ b/include/interrupt.h @@ -0,0 +1,15 @@ +#ifndef INTERRUPT_H_ +#define INTERRUPT_H_ + +#define DEFAULT_PRIORITY 1 + +void user_interrupt_config(tcb_t *from); +void user_interrupt_handler_update(tcb_t *thr); + +/* Platform depended */ +void user_irq_enable(int irq); +void user_irq_disable(int irq); +void user_irq_set_pending(int irq); +void user_irq_clear_pending(int irq); + +#endif diff --git a/include/interrupt_ipc.h b/include/interrupt_ipc.h new file mode 100644 index 00000000..2d8de9ba --- /dev/null +++ b/include/interrupt_ipc.h @@ -0,0 +1,24 @@ +#ifndef INTERRUPT_IPC_H_ +#define INTERRUPT_IPC_H_ + +/* interrupt ipc message */ +enum { + IRQ_IPC_IRQN = 0, + IRQ_IPC_TID = 1, + IRQ_IPC_HANDLER = 2, + IRQ_IPC_ACTION = 3, + IRQ_IPC_PRIORITY = 4 +}; + +#define IRQ_IPC_MSG_NUM IRQ_IPC_PRIORITY + +/* irq actions */ +enum { + USER_IRQ_ENABLE = 0, + USER_IRQ_DISABLE = 1, + USER_IRQ_FREE = 2 +}; + +#define USER_INTERRUPT_LABEL 0x928 + +#endif diff --git a/include/thread.h b/include/thread.h index 2e87c307..9346ee89 100644 --- a/include/thread.h +++ b/include/thread.h @@ -42,6 +42,8 @@ typedef enum { THREAD_IDLE, THREAD_KERNEL, THREAD_ROOT, + THREAD_INTERRUPT, + THREAD_IRQ_REQUEST, THREAD_LOG, THREAD_SYS = 16, /* Systembase */ THREAD_USER = CONFIG_INTR_THREAD_MAX /* Userbase */ diff --git a/kernel/build.mk b/kernel/build.mk index b7e04a19..35388702 100644 --- a/kernel/build.mk +++ b/kernel/build.mk @@ -17,7 +17,12 @@ kernel-y = \ syscall.o \ systhread.o \ thread.o \ - user-log.o \ + user-log.o + +ifdef CONFIG_BOARD_STM32F4DISCOVERY +kernel-y += \ + interrupt.o +endif KDB-$(CONFIG_KDB) = \ kdb.o diff --git a/kernel/interrupt.c b/kernel/interrupt.c new file mode 100644 index 00000000..6a158251 --- /dev/null +++ b/kernel/interrupt.c @@ -0,0 +1,359 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include INC_PLAT(nvic.h) + +void __interrupt_handler(int n); + +/* user interrupt vector */ +#define USER_IRQ_VEC(n) \ + void nvic_handler##n(void) __NAKED; \ + void nvic_handler##n(void) \ + { \ + irq_enter(); \ + __interrupt_handler(n); \ + request_schedule(); \ + irq_return(); \ + } + +#undef USER_INTERRUPT_USED +#define USER_INTERRUPT +#define IRQ_VEC_N_OP USER_IRQ_VEC +#include INC_PLAT(nvic_private.h) +#undef IRQ_VEC_N_OP +#undef USER_INTERRUPT + +typedef void (*irq_handler_t)(void); + +#define INVALID_IDX IRQn_NUM +#define INVALID_IRQ_NUM IRQn_NUM + +#define IS_VALID_IRQ_NUM(irq) ((irq) < INVALID_IRQ_NUM) + +struct user_irq { + tcb_t *thr; + int irq; + uint16_t action; + uint16_t priority; + irq_handler_t handler; + struct user_irq *next; +}; + +static struct user_irq *user_irqs[IRQn_NUM]; + +DECLARE_KTABLE(struct user_irq, user_irq_table, IRQn_NUM); + +struct user_irq_queue { + struct user_irq *head; + struct user_irq *tail; +}; + +static struct user_irq_queue user_irq_queue; + +static int user_irq_queue_is_empty(void) +{ + return (user_irq_queue.head == NULL); +} + +static void user_irq_queue_push(struct user_irq *uirq) +{ + if (user_irq_queue_is_empty()) { + user_irq_queue.head = user_irq_queue.tail = uirq; + } else { + user_irq_queue.tail->next = uirq; + user_irq_queue.tail = uirq; + } +} + +static struct user_irq *user_irq_queue_pop(void) +{ + struct user_irq *uirq; + if (user_irq_queue_is_empty()) + return NULL; + + uirq = user_irq_queue.head; + user_irq_queue.head = uirq->next; + uirq->next = NULL; + + return uirq; +} + +static void user_irq_queue_delete(int irq) +{ + struct user_irq **iter, *uirq; + + uirq = user_irqs[irq]; + for (iter = &user_irq_queue.head ; *iter != NULL ; iter = &(*iter)->next) { + if (*iter == uirq) { + *iter = uirq->next; + break; + } + } +} + +static inline void user_irq_reset_all(void) +{ + int i; + for (i = 0 ; i < IRQn_NUM ; i++) + user_irqs[i] = NULL; +} + +static struct user_irq *user_irq_create_default(int irq) +{ + if (IS_VALID_IRQ_NUM(irq)) { + struct user_irq *uirq; + + uirq = (struct user_irq *)ktable_alloc(&user_irq_table); + uirq->thr = NULL; + uirq->irq = irq; + uirq->action = 0; + uirq->priority = 0; + uirq->handler = NULL; + uirq->next = NULL; + + return uirq; + } + return NULL; +} + +static inline struct user_irq *user_irq_fetch(int irq) +{ + if (!user_irqs[irq]) + user_irqs[irq] = user_irq_create_default(irq); + return user_irqs[irq]; +} + +static void user_irq_release(int irq) +{ + if (IS_VALID_IRQ_NUM(irq)) { + struct user_irq *uirq = user_irqs[irq]; + + if (uirq != NULL) { + ktable_free(&user_irq_table, uirq); + user_irqs[irq] = NULL; + } + } +} + +static void irq_handler_ipc(struct user_irq *uirq) +{ + tcb_t *thr; + ipc_msg_tag_t tag; + + if (uirq == NULL || uirq->thr == NULL) + return; + + /* Prepare ipc for user interrupt thread */ + thr = uirq->thr; + tag.s.label = USER_INTERRUPT_LABEL; + tag.s.n_untyped = IRQ_IPC_MSG_NUM; + ipc_write_mr(thr, 0, tag.raw); + ipc_write_mr(thr, IRQ_IPC_IRQN + 1, (uint32_t)uirq->irq); + ipc_write_mr(thr, IRQ_IPC_HANDLER + 1, (uint32_t)uirq->handler); + ipc_write_mr(thr, IRQ_IPC_ACTION + 1, (uint32_t)uirq->action); + thr->utcb->sender = TID_TO_GLOBALID(THREAD_INTERRUPT); + thr->ipc_from = L4_NILTHREAD; +} + +static int irq_handler_enable(int irq) +{ + tcb_t *thr; + struct user_irq *uirq = user_irqs[irq]; + + assert(uirq != NULL); + + if (uirq->thr == NULL) + return -1; + + thr = uirq->thr; + + if (thr->state != T_RECV_BLOCKED) + return -1; + + irq_handler_ipc(uirq); + + return 0; +} + +/* +* Push n to irq queue. +* Select the first one in queue to run. +*/ +static void irq_schedule(int irq) +{ + struct user_irq *uirq; + + uirq = user_irq_fetch(irq); + irq_disable(); + user_irq_queue_push(uirq); + irq_enable(); + + irq_handler_enable(irq); +} + +static tcb_t *irq_handler_sched(struct sched_slot *slot) +{ + struct user_irq *uirq; + tcb_t *thr = NULL; + + irq_disable(); + uirq = user_irq_queue_pop(); + + if (uirq != NULL && (thr = uirq->thr) != NULL && + thr->state == T_RECV_BLOCKED) { + thr->state = T_RUNNABLE; + sched_slot_dispatch(SSI_INTR_THREAD, thr); + } + + irq_enable(); + + return thr; +} + +void __interrupt_handler(int irq) +{ + struct user_irq *uirq; + + uirq = user_irq_fetch(irq); + + if (uirq == NULL || + uirq->thr == NULL || + uirq->handler == NULL || + uirq->action != USER_IRQ_ENABLE) { + return; + } + + user_irq_disable(irq); /* No re-entry interrupt */ + irq_schedule(irq); +} + +void interrupt_init(void) +{ + user_irq_reset_all(); + sched_slot_set_handler(SSI_INTR_THREAD, irq_handler_sched); +} + +INIT_HOOK(interrupt_init, INIT_LEVEL_KERNEL_EARLY); + +void user_interrupt_config(tcb_t *from) +{ + ipc_msg_tag_t tag; + l4_thread_t tid; + struct user_irq *uirq; + int irq; + int action, priority; + irq_handler_t handler; + + tag.raw = ipc_read_mr(from, 0); + + if (tag.s.label != USER_INTERRUPT_LABEL) + return; + + irq = (uint16_t)from->ctx.regs[IRQ_IPC_IRQN + 1]; + tid = (l4_thread_t)from->ctx.regs[IRQ_IPC_TID + 1]; + action = (uint16_t)from->ctx.regs[IRQ_IPC_ACTION + 1]; + handler = (irq_handler_t)from->ctx.regs[IRQ_IPC_HANDLER + 1]; + priority = (uint16_t)from->ctx.regs[IRQ_IPC_PRIORITY + 1]; + + + user_irq_disable(irq); + + if (!IS_VALID_IRQ_NUM(irq)) + return; + + uirq = user_irq_fetch(irq); + + if (uirq == NULL) + return; + + /* update user irq config */ + if (tid != L4_NILTHREAD) + uirq->thr = thread_by_globalid(tid); + + uirq->action = (uint16_t)action; + + if (handler != NULL) + uirq->handler = handler; + + if (priority > 0) + uirq->priority = (uint16_t)priority; +} + +void user_interrupt_handler_update(tcb_t *thr) +{ + int irq; + + if (thr == NULL) + return; + + for (irq = 0 ; irq < IRQn_NUM ; irq++) { + struct user_irq *uirq; + uirq = user_irq_fetch(irq); + + if (uirq == NULL) + continue; + + if (uirq->thr == thr) { + /* make sure irq is cleared */ + /* clear pending bit */ + user_irq_clear_pending(irq); + switch (uirq->action) { + case USER_IRQ_ENABLE: + user_irq_enable(irq); + break; + case USER_IRQ_DISABLE: + irq_disable(); + user_irq_queue_delete(irq); + irq_enable(); + user_irq_disable(irq); + break; + case USER_IRQ_FREE: + irq_disable(); + user_irq_queue_delete(irq); + user_irq_release(irq); + irq_enable(); + /* reply ipc immediately */ + irq_handler_ipc(uirq); + thr->state = T_RUNNABLE; + break; + } + break; + } + } +} + +void user_irq_enable(int irq) +{ + if (nvic_is_setup(irq)) { + NVIC_EnableIRQ(irq); + } +} + +void user_irq_disable(int irq) +{ + if (nvic_is_setup(irq)) { + NVIC_ClearPendingIRQ(irq); + NVIC_DisableIRQ(irq); + } +} + +void user_irq_set_pending(int irq) +{ + if (nvic_is_setup(irq)) { + NVIC_SetPendingIRQ(irq); + } +} + +void user_irq_clear_pending(int irq) +{ + if (nvic_is_setup(irq)) { + NVIC_ClearPendingIRQ(irq); + } +} diff --git a/kernel/ipc.c b/kernel/ipc.c index 4282a497..b5f62c43 100644 --- a/kernel/ipc.c +++ b/kernel/ipc.c @@ -15,6 +15,7 @@ #include #include #include +#include extern tcb_t *caller; @@ -225,6 +226,12 @@ void sys_ipc(uint32_t *param1) user_log(caller); caller->state = T_RUNNABLE; return; +#ifdef CONFIG_BOARD_STM32F4DISCOVERY + } else if (to_tid == TID_TO_GLOBALID(THREAD_IRQ_REQUEST)) { + user_interrupt_config(caller); + caller->state = T_RUNNABLE; + return; +#endif } else if ((to_thr && to_thr->state == T_RECV_BLOCKED) || to_tid == caller->t_globalid) { /* To thread who is waiting for us or sends to myself */ @@ -292,7 +299,11 @@ void sys_ipc(uint32_t *param1) return; } } +#ifdef CONFIG_BOARD_STM32F4DISCOVERY + } else if (from_tid != TID_TO_GLOBALID(THREAD_INTERRUPT)) { +#else } else { +#endif thr = thread_by_globalid(from_tid); if (thr->state == T_SEND_BLOCKED && @@ -306,6 +317,13 @@ void sys_ipc(uint32_t *param1) caller->state = T_RECV_BLOCKED; caller->ipc_from = from_tid; +#ifdef CONFIG_BOARD_STM32F4DISCOVERY + if (from_tid == TID_TO_GLOBALID(THREAD_INTERRUPT)) { + /* Threaded interrupt is ready */ + user_interrupt_handler_update(caller); + } +#endif + if (timeout) sys_ipc_timeout(timeout); @@ -328,7 +346,8 @@ uint32_t ipc_deliver(void *data) switch (thr->state) { case T_RECV_BLOCKED: if (thr->ipc_from != L4_NILTHREAD && - thr->ipc_from != L4_ANYTHREAD) { + thr->ipc_from != L4_ANYTHREAD && + thr->ipc_from != TID_TO_GLOBALID(THREAD_INTERRUPT)) { from_thr = thread_by_globalid(thr->ipc_from); if (from_thr->state == T_SEND_BLOCKED) do_ipc(from_thr, thr); From 6d2213d88245d56733a8887e33ad30a423cccac6 Mon Sep 17 00:00:00 2001 From: GeorgeKang Date: Tue, 24 Mar 2015 11:56:17 +0800 Subject: [PATCH 06/10] user irq: wrapper function to manipulate interrupt in user space --- user/include/user_interrupt.h | 29 ++++++++ user/lib/io/build.mk | 3 +- user/lib/io/user_interrupt.c | 120 ++++++++++++++++++++++++++++++++++ 3 files changed, 151 insertions(+), 1 deletion(-) create mode 100644 user/include/user_interrupt.h create mode 100644 user/lib/io/user_interrupt.c diff --git a/user/include/user_interrupt.h b/user/include/user_interrupt.h new file mode 100644 index 00000000..eca05ace --- /dev/null +++ b/user/include/user_interrupt.h @@ -0,0 +1,29 @@ +#ifndef _USER_INTERRUPT_H_ +#define _USER_INTERRUPT_H_ +#include INC_PLAT(nvic.h) + +#include +#include +#include +#include +#include +#include +#include + +#define IRQ_STACK_SIZE 512 + +typedef void (*irq_handler_t)(void); + +__USER_TEXT +L4_Word_t request_irq(int irq, irq_handler_t handler, uint16_t priority); + +__USER_TEXT +L4_Word_t enable_irq(int irq); + +__USER_TEXT +L4_Word_t disable_irq(int irq); + +__USER_TEXT +L4_Word_t free_irq(int irq); + +#endif diff --git a/user/lib/io/build.mk b/user/lib/io/build.mk index 586cd175..983f4ee2 100644 --- a/user/lib/io/build.mk +++ b/user/lib/io/build.mk @@ -3,7 +3,8 @@ # found in the LICENSE file. user-lib-io-y = \ - l4io.o + l4io.o \ + user_interrupt.o ifeq "$(CONFIG_SEMIHOST)" "y" user-lib-io-y += \ diff --git a/user/lib/io/user_interrupt.c b/user/lib/io/user_interrupt.c new file mode 100644 index 00000000..4676af89 --- /dev/null +++ b/user/lib/io/user_interrupt.c @@ -0,0 +1,120 @@ +/* Copyright (c) 2015 The F9 Microkernel Project. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ +#include +#include +#include +#include +#include +#include + +__USER_TEXT +static void *__interrupt_handler_thread(void *arg) +{ + do { + L4_Msg_t msg; + L4_MsgTag_t tag; + irq_handler_t handler; + L4_Word_t action; + L4_ThreadId_t recv_tid = { + .raw = TID_TO_GLOBALID(THREAD_INTERRUPT)}; + + tag = L4_Receive(recv_tid); + + L4_MsgStore(tag, &msg); + handler = (irq_handler_t)L4_MsgWord(&msg, IRQ_IPC_HANDLER); + action = L4_MsgWord(&msg, IRQ_IPC_ACTION); + + switch (action) { + case USER_IRQ_ENABLE: + handler(); + break; + case USER_IRQ_FREE: + return NULL; + } + } while(1); + +} + +__USER_TEXT +static void __irq_msg( + L4_Msg_t *out_msg, L4_ThreadId_t tid, + unsigned int irq, irq_handler_t handler, + L4_Word_t action, uint16_t priority) +{ + L4_Word_t irq_data[IRQ_IPC_MSG_NUM]; + + L4_MsgClear(out_msg); + + irq_data[IRQ_IPC_IRQN] = (L4_Word_t)irq; + irq_data[IRQ_IPC_TID] = (L4_Word_t)tid.raw; + irq_data[IRQ_IPC_HANDLER] = (L4_Word_t)handler; + irq_data[IRQ_IPC_ACTION] = (L4_Word_t)action; + irq_data[IRQ_IPC_PRIORITY] = (L4_Word_t)priority; + + /* Create msg for irq request */ + L4_MsgPut(out_msg, USER_INTERRUPT_LABEL, + IRQ_IPC_MSG_NUM, irq_data, 0, NULL); +} + +__USER_TEXT +static L4_Word_t __request_irq(L4_Msg_t *msg) +{ + L4_MsgTag_t ret; + L4_ThreadId_t send_tid = { + .raw = TID_TO_GLOBALID(THREAD_IRQ_REQUEST)}; + + /* Load msg to registers */ + L4_MsgLoad(msg); + + /* register irq in kernel */ + ret = L4_Send(send_tid); + + return ret.raw; +} + +__USER_TEXT +L4_Word_t request_irq(int irq, irq_handler_t handler, uint16_t priority) +{ + L4_Msg_t msg; + L4_ThreadId_t tid; + + /* Create thread for interrupt handler */ + tid = pager_create_thread(); + pager_start_thread(tid, __interrupt_handler_thread, NULL); + __irq_msg(&msg, tid, irq, handler, USER_IRQ_ENABLE, priority); + + return __request_irq(&msg); +} + +__USER_TEXT +L4_Word_t enable_irq(int irq) +{ + L4_Msg_t msg; + + __irq_msg(&msg, L4_nilthread, irq, NULL, USER_IRQ_ENABLE, -1); + + return __request_irq(&msg); +} + +__USER_TEXT +L4_Word_t disable_irq(int irq) +{ + L4_Msg_t msg; + + __irq_msg(&msg, L4_nilthread, irq, NULL, USER_IRQ_DISABLE, -1); + + return __request_irq(&msg); +} + +__USER_TEXT +L4_Word_t free_irq(int irq) +{ + L4_Msg_t msg; + + __irq_msg(&msg, L4_nilthread, irq, NULL, USER_IRQ_FREE, -1); + + return __request_irq(&msg); +} + From a3c74dfbd2c347a1a1576087f7c3cfc2bafed078 Mon Sep 17 00:00:00 2001 From: GeorgeKang Date: Tue, 24 Mar 2015 21:04:40 +0800 Subject: [PATCH 07/10] user irq: user irq test case by EXTI interrupt EXTI interrupt could be controlled by software. Therefore, it is very suitable to demo and test user thread irq. --- Makefile | 3 +- include/platform/stm32f4/exti.h | 28 ++++++++++++++ user/Kconfig | 11 ++++++ user/apps/build.mk | 6 +++ user/apps/irq_test/build.mk | 7 ++++ user/apps/irq_test/main.c | 62 ++++++++++++++++++++++++++++++ user/apps/irq_test/user_exti.c | 68 +++++++++++++++++++++++++++++++++ user/apps/irq_test/user_exti.h | 21 ++++++++++ 8 files changed, 205 insertions(+), 1 deletion(-) create mode 100644 include/platform/stm32f4/exti.h create mode 100644 user/Kconfig create mode 100644 user/apps/irq_test/build.mk create mode 100644 user/apps/irq_test/main.c create mode 100644 user/apps/irq_test/user_exti.c create mode 100644 user/apps/irq_test/user_exti.h diff --git a/Makefile b/Makefile index ce4564ba..d75d1aef 100644 --- a/Makefile +++ b/Makefile @@ -52,7 +52,8 @@ $(eval BOARD_$(BOARD)=y) KCONFIG_FILES = \ platform/Kconfig \ kernel/Kconfig \ - loader/Kconfig + loader/Kconfig \ + user/Kconfig # Read configurations about system features and characteristics include mk/config.mk diff --git a/include/platform/stm32f4/exti.h b/include/platform/stm32f4/exti.h new file mode 100644 index 00000000..4d24628c --- /dev/null +++ b/include/platform/stm32f4/exti.h @@ -0,0 +1,28 @@ +#ifndef PLATFORM_STM32F4_EXTI_H_ +#define PLATFORM_STM32F4_EXTI_H_ + +#include +#include + +/* EXTI mode */ +#define EXTI_INTERRUPT_MODE 0x0 +#define EXTI_EVENT_MODE 0x4 + +/* EXTI trigger type */ +#define EXTI_RISING_TRIGGER 0x8 +#define EXTI_FALLING_TRIGGER 0xc +#define EXTI_RISING_FALLING_TRIGGER 0x10 + +#define EXTI_LINE(x) ((uint32_t)0x1 << x) + +struct exti_regs { + volatile uint32_t IMR; + volatile uint32_t EMR; + volatile uint32_t RTSR; + volatile uint32_t FTSR; + volatile uint32_t SWIER; + volatile uint32_t PR; +}; + + +#endif diff --git a/user/Kconfig b/user/Kconfig new file mode 100644 index 00000000..055e6d3e --- /dev/null +++ b/user/Kconfig @@ -0,0 +1,11 @@ +# Copyright (c) 2015 The F9 Microkernel Project. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +menu "Test Case" +config EXTI_INTERRUPT_TEST + bool "EXTI interrupt test case" + default n + depends on EXTI0_USER_IRQ && EXTI1_USER_IRQ + +endmenu diff --git a/user/apps/build.mk b/user/apps/build.mk index a623963b..a4e714a0 100644 --- a/user/apps/build.mk +++ b/user/apps/build.mk @@ -6,6 +6,12 @@ user-apps-dirs = \ l4test \ pingpong + +ifdef CONFIG_EXTI_INTERRUPT_TEST +user-apps-dirs += \ + irq_test +endif + ifdef CONFIG_BOARD_STM32F429DISCOVERY user-apps-dirs += \ lcd_test diff --git a/user/apps/irq_test/build.mk b/user/apps/irq_test/build.mk new file mode 100644 index 00000000..eb26f6f0 --- /dev/null +++ b/user/apps/irq_test/build.mk @@ -0,0 +1,7 @@ +# Copyright (c) 2013 The F9 Microkernel Project. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +user-apps-irq_test-y = \ + user_exti.o \ + main.o \ diff --git a/user/apps/irq_test/main.c b/user/apps/irq_test/main.c new file mode 100644 index 00000000..88348f4d --- /dev/null +++ b/user/apps/irq_test/main.c @@ -0,0 +1,62 @@ +#include INC_PLAT(nvic.h) +#include INC_PLAT(registers.h) +#include INC_PLAT(exti.h) + +#include +#include +#include +#include +#include "user_exti.h" + +__USER_BSS +static uint32_t exti0_interrupt_num = 0; + +__USER_BSS +static uint32_t exti1_interrupt_num = 0; + +__USER_TEXT +void exti0_interrupt_handler(void) +{ + exti_clear(0); + L4_Sleep(L4_TimePeriod(500 * 1000)); + exti0_interrupt_num++; + exti_launch_sw_interrupt(1); + printf("%d: %s\n", L4_MyGlobalId(), __func__); +} + +__USER_TEXT +void exti1_interrupt_handler(void) +{ + exti_clear(1); + L4_Sleep(L4_TimePeriod(500 * 1000)); + exti1_interrupt_num++; + exti_launch_sw_interrupt(0); + printf("%d: %s\n", L4_MyGlobalId(), __func__); +} + +__USER_TEXT +static void *main(void *user) +{ + request_irq(EXTI0_IRQn, exti0_interrupt_handler, 1); + request_irq(EXTI1_IRQn, exti1_interrupt_handler, 1); + exti_config(0, EXTI_INTERRUPT_MODE, EXTI_RISING_TRIGGER); + exti_config(1, EXTI_INTERRUPT_MODE, EXTI_RISING_TRIGGER); + + exti_launch_sw_interrupt(0); + + /* Sleep 10s */ + L4_Sleep(L4_TimePeriod(10000000)); + free_irq(EXTI0_IRQn); + free_irq(EXTI1_IRQn); + + return 0; +} + +DECLARE_USER( + 128, + irq_test, + main, + DECLARE_FPAGE(0x0, 4 * (UTCB_SIZE + IRQ_STACK_SIZE)) + DECLARE_FPAGE(0x0, 512) + DECLARE_FPAGE(0x40010000, 0x4000) +); diff --git a/user/apps/irq_test/user_exti.c b/user/apps/irq_test/user_exti.c new file mode 100644 index 00000000..364626a7 --- /dev/null +++ b/user/apps/irq_test/user_exti.c @@ -0,0 +1,68 @@ +#include INC_PLAT(registers.h) +#include INC_PLAT(exti.h) +#include "user_exti.h" + +__USER_TEXT +void exti_config(uint32_t line, uint32_t mode, uint32_t trigger_type) +{ + struct exti_regs *exti_regs = (struct exti_regs *)EXTI_BASE; + + /* Clear EXTI mask */ + exti_regs->IMR &= ~EXTI_LINE(line); + exti_regs->EMR &= ~EXTI_LINE(line); + + *((volatile uint32_t *)(EXTI_BASE + mode)) |= EXTI_LINE(line); + + if (trigger_type == EXTI_RISING_FALLING_TRIGGER) { + exti_regs->RTSR |= EXTI_LINE(line); + exti_regs->FTSR |= EXTI_LINE(line); + } else { + *((volatile uint32_t *)(EXTI_BASE + mode)) |= EXTI_LINE(line); + } +} + +__USER_TEXT + void exti_enable(uint32_t line, uint32_t mode) +{ + *((volatile uint32_t *)(EXTI_BASE + mode)) |= EXTI_LINE(line); +} + +__USER_TEXT +void exti_disable(uint32_t line) +{ + struct exti_regs *exti_regs = (struct exti_regs *)EXTI_BASE; + + /* Clear EXTI mask */ + exti_regs->IMR &= ~EXTI_LINE(line); + exti_regs->EMR &= ~EXTI_LINE(line); +} + +__USER_TEXT +void exti_launch_sw_interrupt(uint32_t line) +{ + struct exti_regs *exti_regs = (struct exti_regs *)EXTI_BASE; + + exti_regs->SWIER |= EXTI_LINE(line); +} + +__USER_TEXT +void exti_clear(uint32_t line) +{ + struct exti_regs *exti_regs = (struct exti_regs *)EXTI_BASE; + + exti_regs->PR = EXTI_LINE(line); +} + +__USER_TEXT +int exti_interrupt_status(uint32_t line) +{ + struct exti_regs *exti_regs = (struct exti_regs *)EXTI_BASE; + + return (exti_regs->PR & EXTI_LINE(line)) && (exti_regs->IMR & EXTI_LINE(line)); +} + +__USER_TEXT +void exti_interrupt_status_clear(uint32_t line) +{ + exti_clear(line); +} diff --git a/user/apps/irq_test/user_exti.h b/user/apps/irq_test/user_exti.h new file mode 100644 index 00000000..dfac41fe --- /dev/null +++ b/user/apps/irq_test/user_exti.h @@ -0,0 +1,21 @@ +#ifndef USER_EXTI_H_ +#define USER_EXTI_H_ + +#include + +__USER_TEXT +void exti_config(uint32_t line, uint32_t mode, uint32_t trigger_type); + +__USER_TEXT +void exti_enable(uint32_t line, uint32_t mode); + +__USER_TEXT +void exti_disable(uint32_t line); + +__USER_TEXT +void exti_launch_sw_interrupt(uint32_t line); + +__USER_TEXT +void exti_clear(uint32_t line); + +#endif From 4df2192dc033c78491c0d76f56f0f47e12555a9e Mon Sep 17 00:00:00 2001 From: GeorgeKang Date: Tue, 24 Mar 2015 21:19:00 +0800 Subject: [PATCH 08/10] memory: fix end address of APB2_1DEV section RM0090 Reference manual STM32F405xx, STM32F407xx, STM32F415xx and STM32F417xx advanced ARM-based 32-bit MCUs page.65 --- kernel/memory.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/memory.c b/kernel/memory.c index d621b99b..a6136a9f 100644 --- a/kernel/memory.c +++ b/kernel/memory.c @@ -74,7 +74,7 @@ static mempool_t memmap[] = { #endif DECLARE_MEMPOOL("APB1DEV", 0x40000000, 0x40007800, MP_UR | MP_UW | MP_DEVICES, MPT_DEVICES), - DECLARE_MEMPOOL("APB2_1DEV", 0x40010000, 0x40013400, + DECLARE_MEMPOOL("APB2_1DEV", 0x40010000, 0x40014c00, MP_UR | MP_UW | MP_DEVICES, MPT_DEVICES), DECLARE_MEMPOOL("APB2_2DEV", 0x40014000, 0x40014c00, MP_UR | MP_UW | MP_DEVICES, MPT_DEVICES), From e126f44f14f9737a19d36990dfcf40357ea9c6c6 Mon Sep 17 00:00:00 2001 From: GeorgeKang Date: Tue, 24 Mar 2015 21:28:26 +0800 Subject: [PATCH 09/10] user app: add sleep in pong thread to avoid starvation The schedule priority of ipc is higher than thread creation. If ipc is too busy like ping-pong test, there is no chance to do thread creation. Therefore, we should add sleep funtion in pong thread to avoid this starvation. --- user/apps/pingpong/main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/user/apps/pingpong/main.c b/user/apps/pingpong/main.c index 9456a9d4..c719b628 100644 --- a/user/apps/pingpong/main.c +++ b/user/apps/pingpong/main.c @@ -52,6 +52,7 @@ void *pong_thread(void *arg) printf("%p: recv ipc fails\n", L4_MyGlobalId()); printf("%p: ErrorCode = 0x%x\n", L4_MyGlobalId(), L4_ErrorCode()); } + L4_Sleep(L4_TimePeriod(500 * 1000)); } } From 98e069122e3660ec06cde37e8eec217129d5ff85 Mon Sep 17 00:00:00 2001 From: GeorgeKang Date: Tue, 31 Mar 2015 22:41:18 +0800 Subject: [PATCH 10/10] config: Update default config for user irq --- board/discoveryf4/defconfig | 86 +++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) diff --git a/board/discoveryf4/defconfig b/board/discoveryf4/defconfig index 5c75ccda..61659c01 100644 --- a/board/discoveryf4/defconfig +++ b/board/discoveryf4/defconfig @@ -62,3 +62,89 @@ CONFIG_KPROBES=y CONFIG_SYMMAP=y CONFIG_PANIC_DUMP_STACK=y # CONFIG_LOADER is not set + +# +# User IRQ +# +# CONFIG_WWDG_USER_IRQ is not set +# CONFIG_PVD_USER_IRQ is not set +# CONFIG_TAMP_STAMP_USER_IRQ is not set +# CONFIG_RTC_WKUP_USER_IRQ is not set +# CONFIG_FLASH_USER_IRQ is not set +# CONFIG_RCC_USER_IRQ is not set +# CONFIG_EXTI0_USER_IRQ is not set +# CONFIG_EXTI1_USER_IRQ is not set +# CONFIG_EXTI2_USER_IRQ is not set +# CONFIG_EXTI3_USER_IRQ is not set +# CONFIG_EXTI4_USER_IRQ is not set +# CONFIG_DMA1_Stream0_USER_IRQ is not set +# CONFIG_DMA1_Stream1_USER_IRQ is not set +# CONFIG_DMA1_Stream2_USER_IRQ is not set +# CONFIG_DMA1_Stream3_USER_IRQ is not set +# CONFIG_DMA1_Stream4_USER_IRQ is not set +# CONFIG_DMA1_Stream5_USER_IRQ is not set +# CONFIG_DMA1_Stream6_USER_IRQ is not set +# CONFIG_ADC_USER_IRQ is not set +# CONFIG_CAN1_TX_USER_IRQ is not set +# CONFIG_CAN1_RX_USER_IRQ is not set +# CONFIG_CAN1_RX1_USER_IRQ is not set +# CONFIG_CAN1_SCE_USER_IRQ is not set +# CONFIG_EXTI9_5_USER_IRQ is not set +# CONFIG_TIM1_BRK_TIM9_USER_IRQ is not set +# CONFIG_TIM1_UP_TIM10_USER_IRQ is not set +# CONFIG_TIM1_TRG_COM_TIM11_USER_IRQ is not set +# CONFIG_TIM1_CC_USER_IRQ is not set +# CONFIG_TIM2_USER_IRQ is not set +# CONFIG_TIM3_USER_IRQ is not set +# CONFIG_TIM4_USER_IRQ is not set +# CONFIG_I2C1_EV_USER_IRQ is not set +# CONFIG_I2C1_ER_USER_IRQ is not set +# CONFIG_I2C2_EV_USER_IRQ is not set +# CONFIG_I2C2_ER_USER_IRQ is not set +# CONFIG_SPI1_USER_IRQ is not set +# CONFIG_SPI2_USER_IRQ is not set +# CONFIG_USART1_USER_IRQ is not set +# CONFIG_USART2_USER_IRQ is not set +# CONFIG_USART3_USER_IRQ is not set +# CONFIG_EXTI15_10_USER_IRQ is not set +# CONFIG_RTC_Alarm_USER_IRQ is not set +# CONFIG_OTG_FS_WKUP_USER_IRQ is not set +# CONFIG_TIM8_BRK_TIM12_USER_IRQ is not set +# CONFIG_TIM8_UP_TIM13_USER_IRQ is not set +# CONFIG_TIM8_TRG_COM_TIM14_USER_IRQ is not set +# CONFIG_TIM8_CC_USER_IRQ is not set +# CONFIG_DMA1_Stream7_USER_IRQ is not set +# CONFIG_FSMC_USER_IRQ is not set +# CONFIG_SDIO_USER_IRQ is not set +# CONFIG_TIM5_USER_IRQ is not set +# CONFIG_SPI3_USER_IRQ is not set +# CONFIG_UART4_USER_IRQ is not set +# CONFIG_UART5_USER_IRQ is not set +# CONFIG_TIM6_DAC_USER_IRQ is not set +# CONFIG_TIM7_USER_IRQ is not set +# CONFIG_DMA2_Stream0_USER_IRQ is not set +# CONFIG_DMA2_Stream1_USER_IRQ is not set +# CONFIG_DMA2_Stream2_USER_IRQ is not set +# CONFIG_DMA2_Stream3_USER_IRQ is not set +# CONFIG_DMA2_Stream4_USER_IRQ is not set +# CONFIG_ETH_USER_IRQ is not set +# CONFIG_ETH_WKUP_USER_IRQ is not set +# CONFIG_CAN2_TX_USER_IRQ is not set +# CONFIG_CAN2_RX0_USER_IRQ is not set +# CONFIG_CAN2_RX1_USER_IRQ is not set +# CONFIG_CAN2_SCE_USER_IRQ is not set +# CONFIG_OTG_FS_USER_IRQ is not set +# CONFIG_DMA2_Stream5_USER_IRQ is not set +# CONFIG_DMA2_Stream6_USER_IRQ is not set +# CONFIG_DMA2_Stream7_USER_IRQ is not set +# CONFIG_USART6_USER_IRQ is not set +# CONFIG_I2C3_EV_USER_IRQ is not set +# CONFIG_I2C3_ER_USER_IRQ is not set +# CONFIG_OTG_HS_EP1_OUT_USER_IRQ is not set +# CONFIG_OTG_HS_EP1_IN_USER_IRQ is not set +# CONFIG_OTG_HS_WKUP_USER_IRQ is not set +# CONFIG_OTG_HS_USER_IRQ is not set +# CONFIG_DCMI_USER_IRQ is not set +# CONFIG_CRYP_USER_IRQ is not set +# CONFIG_HASH_RNG_USER_IRQ is not set +# CONFIG_FPU_USER_IRQ is not set