From 661f4a0ae53637baa30933cf32c1be4fcbabd9da Mon Sep 17 00:00:00 2001 From: Steins7 Date: Thu, 27 Apr 2023 21:12:05 +0200 Subject: [PATCH] Implement nvic's control functions --- drivers/nvic.c | 87 ++++++++++++++++++++++++++++++++++ drivers/nvic.h | 125 +++++++++++++++++++++++++++++++++++++++++++++++++ startup.s | 113 ++++++++++++++++++++++++++++++++------------ 3 files changed, 294 insertions(+), 31 deletions(-) create mode 100644 drivers/nvic.c create mode 100644 drivers/nvic.h diff --git a/drivers/nvic.c b/drivers/nvic.c new file mode 100644 index 0000000..b4849e4 --- /dev/null +++ b/drivers/nvic.c @@ -0,0 +1,87 @@ +/** @file nvic.c + * Module handling the Nested Vector Interrupt Controller (NVIC) + * + * The module provides functions to configure the different interrupts and + * their priority suiing the NVIC's interface + */ + +//--includes-------------------------------------------------------------------- + +#include "nvic.h" +#include "nvic_regs.h" + + +//--local definitions----------------------------------------------------------- + +/** + * NVIC's register are only accessible by 32 bits words, and data is stored + * accors 3 consecutive registers. This macro sets the right bit from the + * right register based on the IRQ number + */ +#define set_bit(reg, irq) \ + do { \ + uint8_t n = irq / 32; \ + uint8_t r = irq - n * 32; \ + regs->reg[n] |= (0x1 << r); \ + } while (0) + +/** + * NVIC's register are only accessible by 32 bits words, and data is stored + * accors 3 consecutive registers. This macro fetches the right bit from the + * right register based on the IRQ number + */ +#define get_bit(reg, irq, res) \ + do { \ + uint8_t n = irq / 32; \ + uint8_t r = irq - n * 32; \ + res = 0 != (regs->reg[n] | (0x1 << r)); \ + } while (0) + + +//--local variables------------------------------------------------------------- + +static volatile struct NVIC1* regs = (struct NVIC1*)NVIC1_BASE_ADDRESS; + + +//--public functions------------------------------------------------------------ + +void nvic_enable(enum NvicIrq irq) +{ + set_bit(ISERX, irq); +} + +void nvic_disable(enum NvicIrq irq) +{ + set_bit(ICERX, irq); +} + +void nvic_clear_pending(enum NvicIrq irq) +{ + set_bit(ICPRX, irq); +} + +void nvic_set_priority(enum NvicIrq irq, uint8_t priority) +{ + uint8_t n = irq / 4; + uint8_t r = (irq - n * 4); //get the division's reminder + r *= 8; //mul by 8 since each 'slot' is 8 bits + r += 4; //add 4 since we only write to the upper 4 bits + regs->IPRX[n] &= ~(0x0F << r); + regs->IPRX[n] |= (priority & 0x0F) << r; +} + +void nvic_set_pending(enum NvicIrq irq) +{ + set_bit(ISPRX, irq); +} + +bool nvic_is_pending(enum NvicIrq irq) +{ + bool res = false; + get_bit(ISPRX, irq, res); + return res; +} + + +//--local functions------------------------------------------------------------- + diff --git a/drivers/nvic.h b/drivers/nvic.h new file mode 100644 index 0000000..38386b0 --- /dev/null +++ b/drivers/nvic.h @@ -0,0 +1,125 @@ +/** @file nvic.h + * Module handling the Nested Vector Interrupt Controller (NVIC) + * + * The module provides functions to configure the different interrupts and + * their priority suiing the NVIC's interface + */ + +#ifndef _NVIC_H_ +#define _NVIC_H_ + +//--includes-------------------------------------------------------------------- + +#include "stdint.h" +#include "stdbool.h" + + +//--type definitions------------------------------------------------------------ + +/** + * Available System IRQs. This does not include CPU's IRQs + */ +enum NvicIrq { + NVIC_IRQ_WWDG = 0, + NVIC_IRQ_PVD, + NVIC_IRQ_TAMPER, + NVIC_IRQ_RTC, + NVIC_IRQ_FLASH, + NVIC_IRQ_RCC, + NVIC_IRQ_EXTI0, + NVIC_IRQ_EXTI1, + NVIC_IRQ_EXTI2, + NVIC_IRQ_EXTI3, + NVIC_IRQ_EXTI4, + NVIC_IRQ_DMA1_CHANNEL1, + NVIC_IRQ_DMA1_CHANNEL2, + NVIC_IRQ_DMA1_CHANNEL3, + NVIC_IRQ_DMA1_CHANNEL4, + NVIC_IRQ_DMA1_CHANNEL5, + NVIC_IRQ_DMA1_CHANNEL6, + NVIC_IRQ_DMA1_CHANNEL7, + NVIC_IRQ_ADC1_2, + NVIC_IRQ_HP_CAN_TX, + NVIC_IRQ_LP_CAN_RX0, + NVIC_IRQ_CAN_RX1, + NVIC_IRQ_CAN_SCE, + NVIC_IRQ_EXTI9_5, + NVIC_IRQ_TIM1_BRK, + NVIC_IRQ_TIM1_UP, + NVIC_IRQ_TIM1_TRG_COM, + NVIC_IRQ_TIM1_CC, + NVIC_IRQ_TIM2, + NVIC_IRQ_TIM3, + NVIC_IRQ_TIM4, + NVIC_IRQ_I2C1_EVENT, + NVIC_IRQ_I2C1_ERROR, + NVIC_IRQ_I2C2_EVENT, + NVIC_IRQ_I2C2_ERROR, + NVIC_IRQ_SPI1, + NVIC_IRQ_SPI2, + NVIC_IRQ_USART1, + NVIC_IRQ_USART2, + NVIC_IRQ_USART3, + NVIC_IRQ_EXTI15_10, + NVIC_IRQ_RTC_ALARM, + NVIC_IRQ_USB_WAKEUP, + NVIC_IRQ_TIM8_BRK, + NVIC_IRQ_TIM8_UP, + NVIC_IRQ_TIM8_TRG_COM, + NVIC_IRQ_TIM8_CC, + NVIC_IRQ_ADC3, + NVIC_IRQ_FSMC, + NVIC_IRQ_SDIO, + NVIC_IRQ_TIM5, + NVIC_IRQ_SPI3, + NVIC_IRQ_UART4, + NVIC_IRQ_UART5, + NVIC_IRQ_TIM6, + NVIC_IRQ_TIM7, + NVIC_IRQ_DMA2_CHANNEL1, + NVIC_IRQ_DMA2_CHANNEL2, + NVIC_IRQ_DMA2_CHANNEL3, + NVIC_IRQ_DMA2_CHANNEL4_5, +}; + + +//--functions------------------------------------------------------------------- + +/** + * Enables the selected IRQ + */ +void nvic_enable(enum NvicIrq irq); + +/** + * Disables the selected IRQ + */ +void nvic_disable(enum NvicIrq irq); + +/** + * Clears the pending state of an IRQ. Should be called when reaching an IRQ + * handler so that the IRQ isn't triggered again when exiting the handler + */ +void nvic_clear_pending(enum NvicIrq irq); + +/** + * Sets the priority for the selected IRQ. The lower the priority value, the + * higher the effective priority. Valid priority values range from 0 to 15. Any + * higher value will be ignored. When multiple IRQs with the same priority are + * triggered, they will be serviced from the lowest ID to the highest + */ +void nvic_set_priority(enum NvicIrq irq, uint8_t priority); + +/** + * Sets the selected IRQ's pending state. If the IRQ is active, it will be + * triggered + */ +void nvic_set_pending(enum NvicIrq irq); + +/** + * Returns wether the selected IRQ is currently pending or not + */ +bool nvic_is_pending(enum NvicIrq irq); + + +#endif //_RCC_H_ + diff --git a/startup.s b/startup.s index 3d4080e..3a3b5a1 100644 --- a/startup.s +++ b/startup.s @@ -99,13 +99,13 @@ vector_table: .word hdr_exti2 .word hdr_exti3 .word hdr_exti4 - .word hdr_dma_channel1 - .word hdr_dma_channel2 - .word hdr_dma_channel3 - .word hdr_dma_channel4 - .word hdr_dma_channel5 - .word hdr_dma_channel6 - .word hdr_dma_channel7 + .word hdr_dma1_channel1 + .word hdr_dma1_channel2 + .word hdr_dma1_channel3 + .word hdr_dma1_channel4 + .word hdr_dma1_channel5 + .word hdr_dma1_channel6 + .word hdr_dma1_channel7 .word hdr_adc1_2 .word hdr_hp_can_tx .word hdr_lp_can_rx0 @@ -131,23 +131,23 @@ vector_table: .word hdr_exti15_10 .word hdr_rtc_alarm .word hdr_usb_wakeup - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 + .word hdr_tim8_brk + .word hdr_tim8_up + .word hdr_tim8_trg_com + .word hdr_tim8_cc + .word hdr_adc3 + .word hdr_fsmc + .word hdr_sdio + .word hdr_tim5 + .word hdr_spi3 + .word hdr_uart4 + .word hdr_uart5 + .word hdr_tim6 + .word hdr_tim7 + .word hdr_dma2_channel1 + .word hdr_dma2_channel2 + .word hdr_dma2_channel3 + .word hdr_dma2_channel4_5 //--Weak definitions------------------------------------------------------------ @@ -211,25 +211,25 @@ vector_table: .weak hdr_exti4 .thumb_set hdr_exti4, hdr_default - .weak hdr_dma_channel1 + .weak hdr_dma1_channel1 .thumb_set hdr_dma_channel1, hdr_default - .weak hdr_dma_channel2 + .weak hdr_dma1_channel2 .thumb_set hdr_dma_channel2, hdr_default - .weak hdr_dma_channel3 + .weak hdr_dma1_channel3 .thumb_set hdr_dma_channel3, hdr_default - .weak hdr_dma_channel4 + .weak hdr_dma1_channel4 .thumb_set hdr_dma_channel4, hdr_default - .weak hdr_dma_channel5 + .weak hdr_dma1_channel5 .thumb_set hdr_dma_channel5, hdr_default - .weak hdr_dma_channel6 + .weak hdr_dma1_channel6 .thumb_set hdr_dma_channel6, hdr_default - .weak hdr_dma_channel7 + .weak hdr_dma1_channel7 .thumb_set hdr_dma_channel7, hdr_default .weak hdr_adc1_2 @@ -307,3 +307,54 @@ vector_table: .weak hdr_usb_wakeup .thumb_set hdr_usb_wakeup, hdr_default + .weak hdr_tim8_brk + .thumb_set hdr_tim8_brk, hdr_default + + .weak hdr_tim8_up + .thumb_set hdr_tim8_up, hdr_default + + .weak hdr_tim8_trg_com + .thumb_set hdr_tim8_trg_com, hdr_default + + .weak hdr_tim8_cc + .thumb_set hdr_tim8_cc, hdr_default + + .weak hdr_adc3 + .thumb_set hdr_adc3, hdr_default + + .weak hdr_fsmc + .thumb_set hdr_fsmc, hdr_default + + .weak hdr_sdio + .thumb_set hdr_sdio, hdr_default + + .weak hdr_tim5 + .thumb_set hdr_tim5, hdr_default + + .weak hdr_spi3 + .thumb_set hdr_spi3, hdr_default + + .weak hdr_uart4 + .thumb_set hdr_uart4, hdr_default + + .weak hdr_uart5 + .thumb_set hdr_uart5, hdr_default + + .weak hdr_tim6 + .thumb_set hdr_tim6, hdr_default + + .weak hdr_tim7 + .thumb_set hdr_tim7, hdr_default + + .weak hdr_dma2_channel1 + .thumb_set hdr_dma_channel1, hdr_default + + .weak hdr_dma2_channel2 + .thumb_set hdr_dma_channel2, hdr_default + + .weak hdr_dma2_channel3 + .thumb_set hdr_dma_channel3, hdr_default + + .weak hdr_dma2_channel4_5 + .thumb_set hdr_dma_channel4_5, hdr_default +