diff options
-rw-r--r-- | 02-usart/include/common.h | 3 | ||||
-rw-r--r-- | 02-usart/include/isr_vector.h | 8 | ||||
-rw-r--r-- | 02-usart/include/isrs.i | 112 | ||||
-rw-r--r-- | 02-usart/src/init.c | 45 | ||||
-rw-r--r-- | 02-usart/src/isr_vector.c | 216 | ||||
-rw-r--r-- | 02-usart/src/main.c | 115 |
6 files changed, 263 insertions, 236 deletions
diff --git a/02-usart/include/common.h b/02-usart/include/common.h index 8e0cb06..f9cbe06 100644 --- a/02-usart/include/common.h +++ b/02-usart/include/common.h @@ -5,6 +5,9 @@ #include <stddef.h> #include <assert.h> +#define WEAK __attribute__((weak)) +#define NORETURN __attribute__((noreturn)) + #ifndef static_assert #define static_assert(a, b) #endif diff --git a/02-usart/include/isr_vector.h b/02-usart/include/isr_vector.h index 3e55f52..7cb4596 100644 --- a/02-usart/include/isr_vector.h +++ b/02-usart/include/isr_vector.h @@ -1,6 +1,8 @@ #ifndef h__ISR_VECTOR_H__ #define h__ISR_VECTOR_H__ +#include <stdint.h> + /* * Include file for interrupt service routines. */ @@ -9,12 +11,14 @@ * The interrupt service routines. These link in the function `main` as the * main function. */ -extern const void* isr_vector[]; +extern const void* vectors[]; /* * Defines an error state. This loops forever and defines a distinct flashing * pattern to let the user know an unhandled ISR happened. */ -void unhandled_isr(); +void unhandled_isr(uint8_t val); + +void isr_simple_pin_on(); #endif /* h___ISR_VECTOR_H__ */ diff --git a/02-usart/include/isrs.i b/02-usart/include/isrs.i new file mode 100644 index 0000000..cdb3889 --- /dev/null +++ b/02-usart/include/isrs.i @@ -0,0 +1,112 @@ +/* + * The following is a list of interrupts listed in a way + * that makes it easy to macro-process them by defining + * macro definitions for IRQ and IRQ_RESERVED alike followed + * by including this file. + */ +IRQ(on_reset, 1) +IRQ(on_nmi, 2) +IRQ(on_hard_fault, 3) +IRQ(on_mem_manage, 4) +IRQ(on_bus_fault, 5) +IRQ(on_usage_fault, 6) +IRQ_RESERVED(7) +IRQ_RESERVED(8) +IRQ_RESERVED(9) +IRQ_RESERVED(10) +IRQ(on_svc, 11) +IRQ(on_debug_mon, 12) +IRQ_RESERVED(13) +IRQ(on_pendsv, 14) +IRQ(on_systick, 15) +IRQ(on_wwdg_irq, 16) +IRQ(on_pvd_irq, 17) +IRQ(on_tamper_stamp_irq, 18) +IRQ(on_rtc_wkup_irq, 19) +IRQ(on_flash_irq, 20) +IRQ(on_rcc_irq, 21) +IRQ(on_exti0_irq, 22) +IRQ(on_exti1_irq, 23) +IRQ(on_exti2_irq, 24) +IRQ(on_exti3_irq, 25) +IRQ(on_exti4_irq, 26) +IRQ(on_dma1_channel1_irq, 27) +IRQ(on_dma1_channel2_irq, 28) +IRQ(on_dma1_channel3_irq, 29) +IRQ(on_dma1_channel4_irq, 30) +IRQ(on_dma1_channel5_irq, 31) +IRQ(on_dma1_channel6_irq, 32) +IRQ(on_dma1_channel7_irq, 33) +IRQ(on_adc1_irq, 34) +IRQ(on_can1_tx, 35) +IRQ(on_can1_rx0, 36) +IRQ(on_can1_rx1, 37) +IRQ(on_can1_sce, 38) +IRQ(on_exti9_5, 39) +IRQ(on_tim1_brk, 40) +IRQ(on_tim1_up, 41) +IRQ(on_tim1_trg_com, 42) +IRQ(on_tim1_cc, 43) +IRQ(on_tim2, 44) +IRQ(on_tim3, 45) +IRQ(on_tim4, 46) +IRQ(on_i2c1_ev, 47) +IRQ(on_i2c1_er, 48) +IRQ(on_i2c2_ev, 49) +IRQ(on_i2c2_er, 50) +IRQ(on_spi1, 51) +IRQ(on_spi2, 52) +IRQ(on_usart1, 53) +IRQ(on_usart2, 54) +IRQ(on_usart3, 55) +IRQ(on_exti15_10, 56) +IRQ(on_rtc_alarm, 57) +IRQ(on_dfsdm1_flt3, 58) +IRQ(on_tim8_brk, 59) +IRQ(on_tim8_up, 60) +IRQ(on_tim8_trg_com, 61) +IRQ(on_tim8_cc, 62) +IRQ(on_adc3, 63) +IRQ(on_fmc, 64) +IRQ(on_sdmmc1, 65) +IRQ(on_tim5, 66) +IRQ(on_spi3, 67) +IRQ(on_uart4, 68) +IRQ(on_uart5, 69) +IRQ(on_tim6_dacunder, 70) +IRQ(on_tim7, 71) +IRQ(on_dma2_channel1, 72) +IRQ(on_dma2_channel2, 73) +IRQ(on_dma2_channel3, 74) +IRQ(on_dma2_channel4, 75) +IRQ(on_dma2_channel5, 76) +IRQ(on_dfsdm1_flt0, 77) +IRQ(on_dfsdm1_flt1, 78) +IRQ(on_dfsdm1_flt2, 79) +IRQ(on_comp, 80) +IRQ(on_lptim1, 81) +IRQ(on_lptim2, 82) +IRQ(on_otg_fs, 83) +IRQ(on_dma2_channel6, 84) +IRQ(on_dma2_channel7, 85) +IRQ(on_lpuart1, 86) +IRQ(on_quadspi, 87) +IRQ(on_i2c3_ev, 88) +IRQ(on_i2c3_er, 89) +IRQ(on_sai1, 90) +IRQ(on_sai2, 91) +IRQ(on_swpmi1, 92) +IRQ(on_tsc, 93) +IRQ(on_lcd, 94) +IRQ(on_aes, 95) +IRQ(on_rng, 96) +IRQ(on_fpu, 97) +IRQ(on_hash, 98) +IRQ(on_i2c4_ev, 99) +IRQ(on_i2c4_er, 100) +IRQ(on_dcmi, 101) +IRQ(on_can2_tx, 102) +IRQ(on_can2_rx0, 103) +IRQ(on_can2_rx1, 104) +IRQ(on_can2_sce, 105) +IRQ(on_dma2d, 106) diff --git a/02-usart/src/init.c b/02-usart/src/init.c new file mode 100644 index 0000000..70703aa --- /dev/null +++ b/02-usart/src/init.c @@ -0,0 +1,45 @@ +#include "arch.h" +#include "system.h" + +/* Forward-declare the main function. This is implemented in main.c. */ +void main(); + +/* These are defined in the linker script. */ +extern uint32_t INIT_DATA_VALUES; +extern uint32_t DATA_SEGMENT_START; +extern uint32_t DATA_SEGMENT_STOP; +extern uint32_t BSS_START; +extern uint32_t BSS_END; + +/* + * Runs before main. Initializes the data and bss segments by loading them + * into memory. + */ +_Noreturn void on_reset() +{ + uint32_t* src; + uint32_t* dest; + + src = &INIT_DATA_VALUES; + dest = &DATA_SEGMENT_START; + + /* Copy the values from flash into the data segment. */ + while (dest != &DATA_SEGMENT_STOP) { + *(dest++) = *(src++); + } + + /* Everything in the BSS segment is set to zero. */ + dest = &BSS_START; + while (dest != &BSS_END) { + *(dest++) = 0; + } + + /* Set the vector offset table to be at the start + * of FLASH memory. */ + SCB.vto_r = 0x08000000; + + /* Jump to main. */ + main(); + + for(;;); +} diff --git a/02-usart/src/isr_vector.c b/02-usart/src/isr_vector.c index 6d5128c..484f3c5 100644 --- a/02-usart/src/isr_vector.c +++ b/02-usart/src/isr_vector.c @@ -6,165 +6,101 @@ #ifdef ARCH_STM32L4 -/* Forward-declare the main function. This is implemented in main.c. */ -void main(); - -/* These are defined in the linker script. */ -extern uint32_t INIT_DATA_VALUES; -extern uint32_t DATA_SEGMENT_START; -extern uint32_t DATA_SEGMENT_STOP; -extern uint32_t BSS_START; -extern uint32_t BSS_END; - -/* - * Runs before main. Initializes the data and bss segments by loading them - * into memory. - */ -void init() +#define IRQ_RESERVED(n) +#define IRQ(name, n) \ + void WEAK name () { \ + unhandled_isr(n); \ + } +#include "isrs.i" +#undef IRQ_RESERVED +#undef IRQ + + +void isr_simple_pin_on() { - uint32_t* src; - uint32_t* dest; + __IO gpio_port_t* port_b = enable_gpio(GPIO_PORT_B); + gpio_output_pin_t pin3 = set_gpio_pin_output(port_b, PIN_3); - src = &INIT_DATA_VALUES; - dest = &DATA_SEGMENT_START; + pin_on(pin3); +} - /* Copy the values from flash into the data segment. */ - while (dest != &DATA_SEGMENT_STOP) { - *(dest++) = *(src++); +#define DEFINE_UNHANDLED_ISR(n) \ + int unhandled_isr_##n() \ + { \ + unhandled_isr(n); \ } - /* Everything in the BSS segment is set to zero. */ - dest = &BSS_START; - while (dest != &BSS_END) { - *(dest++) = 0; + +/* Flashes wildly. */ +void super_flash() +{ + static int pin_on = 0; + __IO gpio_port_t* port_b = enable_gpio(GPIO_PORT_B); + gpio_output_pin_t pin3 = set_gpio_pin_output(port_b, PIN_3); + + if (pin_on) { + pin_off(pin3); + } else { + pin_on(pin3); } - /* Jump to main. */ - main(); + pin_on = !pin_on; } +#define IRQ_RESERVED(n) 0, +#define IRQ(name, n) name, const void* vectors[] __attribute__((section(".vectors"))) = { (void*)0x2000c000, /* Top of stack at top of sram1. 48k */ - init, /* Reset handler */ - unhandled_isr, /* NMI */ - unhandled_isr, /* Hard Fault */ - unhandled_isr, /* MemManage */ - unhandled_isr, /* BusFault */ - unhandled_isr, /* UsageFault */ - unhandled_isr, /* Reserved */ - unhandled_isr, /* Reserved */ - unhandled_isr, /* Reserved */ - unhandled_isr, /* Reserved */ - unhandled_isr, /* SVCall */ - unhandled_isr, /* Debug */ - unhandled_isr, /* Reserved */ - unhandled_isr, /* PendSV */ - unhandled_isr, /* SysTick */ - - /* External interrupt handlers follow */ - unhandled_isr, /* 0 WWDG */ - unhandled_isr, /* 1 PVD */ - unhandled_isr, /* 2 TAMP_SAMP */ - unhandled_isr, /* 3 RTC_WKUP */ - unhandled_isr, /* 4 FLASH */ - unhandled_isr, /* 5 RCC */ - unhandled_isr, /* 6 EXTI0 */ - unhandled_isr, /* 7 EXTI1 */ - unhandled_isr, /* 8 EXTI2 */ - unhandled_isr, /* 9 EXTI3 */ - unhandled_isr, /* 10 EXTI4 */ - unhandled_isr, /* 11 DMA_CH1 */ - unhandled_isr, /* 12 DMA_CH2 */ - unhandled_isr, /* 13 DMA_CH3 */ - unhandled_isr, /* 14 DMA_CH4 */ - unhandled_isr, /* 15 DMA_CH5 */ - unhandled_isr, /* 16 DMA_CH6 */ - unhandled_isr, /* 17 DMA_CH7 */ - unhandled_isr, /* 18 ADC1 */ - unhandled_isr, /* 19 CAN_TX */ - unhandled_isr, /* 20 CAN_RX0 */ - unhandled_isr, /* 21 CAN_RX1 */ - unhandled_isr, /* 22 CAN_SCE */ - unhandled_isr, /* 23 EXTI9_5 */ - unhandled_isr, /* 24 TIM1_BRK/TIM15 */ - unhandled_isr, /* 25 TIM1_UP/TIM16 */ - unhandled_isr, /* 26 TIM1_TRG_COM */ - unhandled_isr, /* 27 TIM1_CC */ - unhandled_isr, /* 28 TIM2 */ - unhandled_isr, /* 29 Reserved */ - unhandled_isr, /* 30 Reserved */ - unhandled_isr, /* 31 I2C1_EV */ - unhandled_isr, /* 32 I2C1_ER */ - unhandled_isr, /* 33 I2C2_EV */ - unhandled_isr, /* 34 I2C2_ER */ - unhandled_isr, /* 35 SPI1 */ - unhandled_isr, /* 36 SPI2 */ - unhandled_isr, /* 37 USART1 */ - unhandled_isr, /* 38 USART2 */ - unhandled_isr, /* 39 USART3 */ - unhandled_isr, /* 40 EXTI15_10 */ - unhandled_isr, /* 41 RTCAlarm */ - unhandled_isr, /* 42 Reserved */ - unhandled_isr, /* 43 Reserved */ - unhandled_isr, /* 44 Reserved */ - unhandled_isr, /* 45 Reserved */ - unhandled_isr, /* 46 Reserved */ - unhandled_isr, /* 47 Reserved */ - unhandled_isr, /* 48 Reserved */ - unhandled_isr, /* 49 SDMMC1 */ - unhandled_isr, /* 50 Reserved */ - unhandled_isr, /* 51 SPI3 */ - unhandled_isr, /* 52 Reserved */ - unhandled_isr, /* 53 Reserved */ - unhandled_isr, /* 54 TIM6_DACUNDER */ - unhandled_isr, /* 55 TIM7 */ - unhandled_isr, /* 56 DMA2_CH1 */ - unhandled_isr, /* 57 DMA2_CH2 */ - unhandled_isr, /* 58 DMA2_CH3 */ - unhandled_isr, /* 59 DMA2_CH4 */ - unhandled_isr, /* 60 DMA2_CH5 */ - unhandled_isr, /* 61 Reserved */ - unhandled_isr, /* 62 Reserved */ - unhandled_isr, /* 63 Reserved*/ - unhandled_isr, /* 64 COMP */ - unhandled_isr, /* 65 LPTIM1 */ - unhandled_isr, /* 66 LPTIM2 */ - unhandled_isr, /* 67 USB_FS */ - unhandled_isr, /* 68 DMA_CH6 */ - unhandled_isr, /* 69 DMA_CH7 */ - unhandled_isr, /* 70 LPUART1 */ - unhandled_isr, /* 71 QUADSPI */ - unhandled_isr, /* 72 I2C3_EV */ - unhandled_isr, /* 73 I2C3_ER */ - unhandled_isr, /* 74 SAI1 */ - unhandled_isr, /* 75 Reserved */ - unhandled_isr, /* 76 SWPMI1 */ - unhandled_isr, /* 77 TSC */ - unhandled_isr, /* 78 Reserved */ - unhandled_isr, /* 79 AES */ - unhandled_isr, /* 80 RNG */ - unhandled_isr, /* 81 FPU */ - unhandled_isr /* 82 CRS */ +#include "isrs.i" }; +#undef IRQ_RESERVED +#undef IRQ -/* - * Does nothing ... forever. +/* Encodes the provided number as a series of flashes on the on-board + * LED. The flashes follow as such: + * + * Before the bits of the code are flashed, a rapid succession of 20 flashes + * followed by a pause will occur indicating that the next 8 flashes indicate + * the bits of the provided code. + * + * The next eight flashes are indicate either a 1 or 0 depending on the length + * of the light being on. The first flash is the least-significant bit, the next + * the second least, the third third least, etc. + * + * - A quick flash followed by a long pause indicates a 0 bit. + * - A "long" flash followed by a equally long pause indicates a 1 bit. */ -void unhandled_isr() +void unhandled_isr(uint8_t number) { __IO gpio_port_t* port_b = enable_gpio(GPIO_PORT_B); gpio_output_pin_t pin3 = set_gpio_pin_output(port_b, PIN_3); for (;;) { - /* Flash in a distinct pattern to know that something went wrong. */ + for (int i = 0; i < 20; ++ i) { + pin_on(pin3); + delay(1000000); + pin_off(pin3); + delay(1000000); + } + delay(50000000); - pin_off(pin3); - delay(1000000); - pin_on(pin3); - delay(1000000); - pin_off(pin3); - delay(1000000); - pin_on(pin3); - delay(5000000); + int n = number; + for (int i = 0; i < 8; ++ i) { + if (n & 1) { + // LSB is a 1 + pin_on(pin3); + delay(15000000); + pin_off(pin3); + delay(15000000); + } else { + // LSB is a 0 + pin_on(pin3); + delay(1000000); + pin_off(pin3); + delay(29000000); + } + + n >>= 1; + } } } diff --git a/02-usart/src/main.c b/02-usart/src/main.c index b4f7dd7..b293202 100644 --- a/02-usart/src/main.c +++ b/02-usart/src/main.c @@ -1,4 +1,6 @@ +#include "isr_vector.h" +#include "lib.h" #include "string.h" #include "mem.h" #include "dma.h" @@ -8,117 +10,42 @@ #include "gpio.h" #include "spin.h" #include "usart.h" +#include "system.h" -volatile uint32_t delay_amt = 20000000 / 4; -int setup_usart2(uint32_t baud_rate) -{ - __IO gpio_port_t* port_a = enable_gpio(GPIO_PORT_A); - enable_hsi(&RCC, true); - - // Turn on the clock for the USART2 peripheral - set_usart2_clock_src(&RCC, USART_CLK_SRC_HSI16); - set_usart2_clock_enabled(&RCC, true); - - // Configure the I/O pins. Will use PA2 as TX and PA15 as RX so setup for - // alternate function - set_gpio_pin_mode(port_a, PIN_2, MODE_ALTERNATE); - set_gpio_pin_mode(port_a, PIN_15, MODE_ALTERNATE); - set_gpio_alternate_function(port_a, PIN_2, AFN_7); - set_gpio_alternate_function(port_a, PIN_15, AFN_3); - - // De-assert reset of USART2 - RCC.apb1rst1_r &= ~BIT(17); - - // Configure the USART - // disable USART first to allow setting of other control bits - // This also disables parity checking and enables 16 times oversampling - - USART2.c_r1 = 0; - USART2.c_r2 = 0; - USART2.c_r3 = 0; - - usart_set_divisor(&USART2, 16000000 / baud_rate); -} +#ifdef ARCH_STM32L4 -int enable_usart1(uint32_t baud_rate) +/** Overrides the default systick irq handler. */ +void on_systick() { - /* Enable the GPIO bus. */ - __IO gpio_port_t* port_b = enable_gpio(GPIO_PORT_B); - - /* Enable the USART clock. */ - RCC.apb2en_r |= BIT(14); - - /* == Configure the IO Pins. == */ - - /* GPIO D5 (Port B pin 6) is USART1 Tx, - * GPIO D6 (Port B pin 7) is USART1 Rx. */ - set_gpio_pin_mode(port_b, PIN_6, MODE_ALTERNATE); - set_gpio_pin_mode(port_b, PIN_7, MODE_ALTERNATE); - - /* Set the GPIO pins to use the USART alternate function. */ - set_gpio_alternate_function(port_b, PIN_6, AFN_7); - set_gpio_alternate_function(port_b, PIN_7, AFN_7); + static int is_on = 0; - RCC.apb2rst_r &= ~BIT(14); /* De-assert reset of USART1 */ - - uint32_t baud_rate_div = 80000000 / baud_rate; - USART1.c_r1 = 0; - USART1.c_r2 = 0; - USART1.c_r3 = 0; - USART1.br_r = baud_rate_div; + __IO gpio_port_t* port_b = enable_gpio(GPIO_PORT_B); + gpio_output_pin_t pin3 = set_gpio_pin_output(port_b, PIN_3); - USART1.c_r1 |= BIT(3) | BIT(2); - USART1.c_r1 |= BIT(0); + if (is_on) { + pin_off(pin3); + } else { + pin_on(pin3); + } - /* Enable the transmitter and the receiver. */ - usart_set_enabled(&USART1, USART_ENABLE_TX); - enable_interrupts(); + is_on = ! is_on; } -#ifdef ARCH_STM32L4 - /* Main function. This gets executed from the interrupt vector defined above. */ int main() { - /* Enable the GPIO port B. */ - - __IO gpio_port_t* port_b = enable_gpio(GPIO_PORT_B); - gpio_output_pin_t pin3 = set_gpio_pin_output(port_b, PIN_3); - gpio_output_pin_t pin1 = set_gpio_pin_output(port_b, PIN_1); - /* Enable a higher clock frequency. */ set_system_clock_MHz(80); - setup_usart2(115200); - - - char* into = (char*) (SRAM1_BASE + 50); - const char* hello = "Hello, Chester Cheeto!\r\n"; - int len = strlen(hello); - memcpy(into, hello, len + 1); - - usart_enable_dma(&USART2, USART_ENABLE_TX); - usart_set_enabled(&USART2, USART_ENABLE_TX | USART_ENABLE_RX); - - pin_on(pin3); - - RCC.ahb1en_bf.dma1en = 1; /* Enable DMA1 Clock. */ - DMA1.csel_bf.c7s = 0x2; /* Select USART2_TX for the sel. */ - DMA1.channel_config[6].cc_r = 0; - DMA1.channel_config[6].cc_bf.dir = READ_FROM_MEMORY; - DMA1.channel_config[6].cc_bf.minc = 1; - DMA1.channel_config[6].cc_bf.pl = DMA_PRIORITY_LEVEL_VERY_HIGH; - DMA1.channel_config[6].cndt_bf.ndt = len; - DMA1.channel_config[6].cpa_r = ptr2reg(&USART2.td_r); - DMA1.channel_config[6].cma_r = ptr2reg(into); + /* Set the countdown to start from 1,000,0000. */ + SCB.strv_r = 10000000; - USART2.ic_bf.tccf = 1; - DMA1.channel_config[6].cc_bf.en = 1; + /* Enable interrupts. */ + SCB.stcs_bf.tickint = 1; - pin_on(pin3); - // usart_transmit_str_sync(&USART2, into); - for(;;); + /* Start the systick. */ + SCB.stcs_bf.enable = 1; } #endif |