diff options
author | Josh Rahm <joshuarahm@gmail.com> | 2020-11-28 23:21:22 -0700 |
---|---|---|
committer | Josh Rahm <joshuarahm@gmail.com> | 2020-11-28 23:21:22 -0700 |
commit | fd674424d19cf12c1186394606729cff236d5bdf (patch) | |
tree | 5ecd05faa96a32dbf86a94cec191954c14f1cb0f | |
parent | 654511788e24794c03ecb810a3b5907e95b8b55c (diff) | |
download | stm32l4-fd674424d19cf12c1186394606729cff236d5bdf.tar.gz stm32l4-fd674424d19cf12c1186394606729cff236d5bdf.tar.bz2 stm32l4-fd674424d19cf12c1186394606729cff236d5bdf.zip |
Some LED lights working. Not great. WIP
-rw-r--r-- | include/arch/stm32l4xxx/peripherals/isrs.inc | 14 | ||||
-rw-r--r-- | include/arch/stm32l4xxx/peripherals/spi.h | 7 | ||||
-rw-r--r-- | include/drv/ws2812B/ws2812b.h | 18 | ||||
-rw-r--r-- | include/kern/dma/dma_manager.h | 287 | ||||
-rw-r--r-- | src/drv/ws2812B/ws2812b.c | 55 | ||||
-rw-r--r-- | src/kern/dma/dma_manager.c | 55 | ||||
-rw-r--r-- | src/kern/main.c | 173 | ||||
-rw-r--r-- | src/kern/mem.c | 18 | ||||
-rw-r--r-- | src/kern/stdlibrepl.c | 15 |
9 files changed, 455 insertions, 187 deletions
diff --git a/include/arch/stm32l4xxx/peripherals/isrs.inc b/include/arch/stm32l4xxx/peripherals/isrs.inc index 0682238..32f9779 100644 --- a/include/arch/stm32l4xxx/peripherals/isrs.inc +++ b/include/arch/stm32l4xxx/peripherals/isrs.inc @@ -30,13 +30,13 @@ IRQ(on_exti1_irq, EXTI1_IRQ, 23) IRQ(on_exti2_irq, EXTI2_IRQ, 24) IRQ(on_exti3_irq, EXTI3_IRQ, 25) IRQ(on_exti4_irq, EXTI4_IRQ, 26) -IRQ(on_dma1_channel1_irq, DMA1_CHANNEL1_IRQ, 27) -IRQ(on_dma1_channel2_irq, DMA1_CHANNEL2_IRQ, 28) -IRQ(on_dma1_channel3_irq, DMA1_CHANNEL3_IRQ, 29) -IRQ(on_dma1_channel4_irq, DMA1_CHANNEL4_IRQ, 30) -IRQ(on_dma1_channel5_irq, DMA1_CHANNEL5_IRQ, 31) -IRQ(on_dma1_channel6_irq, DMA1_CHANNEL6_IRQ, 32) -IRQ(on_dma1_channel7_irq, DMA1_CHANNEL7_IRQ, 33) +IRQ(on_dma1_channel1, DMA1_CHANNEL1_IRQ, 27) +IRQ(on_dma1_channel2, DMA1_CHANNEL2_IRQ, 28) +IRQ(on_dma1_channel3, DMA1_CHANNEL3_IRQ, 29) +IRQ(on_dma1_channel4, DMA1_CHANNEL4_IRQ, 30) +IRQ(on_dma1_channel5, DMA1_CHANNEL5_IRQ, 31) +IRQ(on_dma1_channel6, DMA1_CHANNEL6_IRQ, 32) +IRQ(on_dma1_channel7, DMA1_CHANNEL7_IRQ, 33) IRQ(on_adc1_irq, ADC1_IRQ, 34) IRQ(on_can1_tx, CAN1_TX, 35) IRQ(on_can1_rx0, CAN1_RX0, 36) diff --git a/include/arch/stm32l4xxx/peripherals/spi.h b/include/arch/stm32l4xxx/peripherals/spi.h index a39a0bb..e5b44fe 100644 --- a/include/arch/stm32l4xxx/peripherals/spi.h +++ b/include/arch/stm32l4xxx/peripherals/spi.h @@ -37,6 +37,13 @@ typedef enum { SPI_DATA_SIZE_16_BITS = 15, } spi_data_size_t; +typedef enum { + SPI_FIFO_STATUS_EMPTY = 0, + SPI_FIFO_STATUS_QUARTER = 1, + SPI_FIFO_STATUS_HALF = 2, + SPI_FIFO_STATUS_FULL = 3, +} spi_fifo_status_t; + typedef __IO struct { /* spi control register. */ #define spi_bidimode (1 << 15) /* Bidirectional data mode enable. */ diff --git a/include/drv/ws2812B/ws2812b.h b/include/drv/ws2812B/ws2812b.h new file mode 100644 index 0000000..cdbb41a --- /dev/null +++ b/include/drv/ws2812B/ws2812b.h @@ -0,0 +1,18 @@ +#ifndef WS2812B_H_ +#define WS2812B_H_ + +#include "kern/common.h" + +typedef struct { + /* why is it out of order? Don't know! That's the way the hardware was + * designed! */ + uint8_t g; + uint8_t r; + uint8_t b; +} PACKED rgb_t; + +static_assert(sizeof(rgb_t) == 3, "Sizeof rgb_t should be 3."); + +uint8_t* ws2812b_compile_rgb(rgb_t* out, size_t arr_len); + +#endif /* WS2812B_H_ */ diff --git a/include/kern/dma/dma_manager.h b/include/kern/dma/dma_manager.h index 0d17bd5..055bbb2 100644 --- a/include/kern/dma/dma_manager.h +++ b/include/kern/dma/dma_manager.h @@ -1,15 +1,15 @@ #ifndef PERI_DMA_H_ #define PERI_DMA_H_ -#include "kern/common.h" #include "arch/stm32l4xxx/peripherals/dma.h" /* Access to the DMA registers. */ #include "arch/stm32l4xxx/peripherals/irq.h" +#include "kern/common.h" #define DMA_ERROR_CHANNEL_IN_USE 1 -#define CAT2(x, y) x ## y +#define CAT2(x, y) x##y #define CAT1(v, c) CAT2(v, c) -#define DMA_RESERVED(dma) CAT1(dma ## _PERIPH_RESERVED, __COUNTER__) +#define DMA_RESERVED(dma) CAT1(dma##_PERIPH_RESERVED, __COUNTER__) #define ALTERNATE0 0x0000 #define ALTERNATE1 0x0100 @@ -18,23 +18,23 @@ #define DMA_N_CHANNELS 7 typedef enum { - DMA1_PERIPH_ADC1 = 0, - DMA1_PERIPH_ADC2 = 1, - DMA1_PERIPH_ADC3 = 2, + DMA1_PERIPH_ADC1 = 0, + DMA1_PERIPH_ADC2 = 1, + DMA1_PERIPH_ADC3 = 2, DMA1_PERIPH_DFSDM1_FLT0 = 3, DMA1_PERIPH_DFSDM1_FLT1 = 4, DMA1_PERIPH_DFSDM1_FLT2 = 5, DMA1_PERIPH_DFSDM1_FLT3 = 6, - DMA_RESERVED(DMA1) = 7, + DMA_RESERVED(DMA1) = 7, DMA1_PERIPH_SPI1_RX = 8, DMA1_PERIPH_SPI1_TX = 9, DMA1_PERIPH_SPI2_RX = 10, DMA1_PERIPH_SPI2_TX = 11, - DMA1_PERIPH_SAI2_A = 12, - DMA1_PERIPH_SAI2_B = 13, + DMA1_PERIPH_SAI2_A = 12, + DMA1_PERIPH_SAI2_B = 13, - DMA_RESERVED(DMA1) = 14, + DMA_RESERVED(DMA1) = 14, DMA1_PERIPH_USART3_TX = 15, DMA1_PERIPH_USART3_RX = 16, DMA1_PERIPH_USART1_TX = 17, @@ -42,7 +42,7 @@ typedef enum { DMA1_PERIPH_USART2_RX = 19, DMA1_PERIPH_USART2_TX = 20, - DMA_RESERVED(DMA1) = 21, + DMA_RESERVED(DMA1) = 21, DMA1_PERIPH_I2C3_TX = 22, DMA1_PERIPH_I2C3_RX = 23, DMA1_PERIPH_I2C2_TX = 24, @@ -50,139 +50,134 @@ typedef enum { DMA1_PERIPH_I2C1_TX = 26, DMA1_PERIPH_I2C1_RX = 27, - DMA1_PERIPH_TIM2_CH3 = 28, - DMA1_PERIPH_TIM2_UP = 29, + DMA1_PERIPH_TIM2_CH3 = 28, + DMA1_PERIPH_TIM2_UP = 29, DMA1_PERIPH_TIM16_CH1_1 = 30 | ALTERNATE0, - DMA1_PERIPH_TIM16_UP_1 = 30 | ALTERNATE1, /* Same as TIM16_CH1. */ - DMA_RESERVED(DMA1) = 31, - DMA1_PERIPH_TIM2_CH1 = 32, + DMA1_PERIPH_TIM16_UP_1 = 30 | ALTERNATE1, /* Same as TIM16_CH1. */ + DMA_RESERVED(DMA1) = 31, + DMA1_PERIPH_TIM2_CH1 = 32, DMA1_PERIPH_TIM16_CH1_2 = 33, - DMA1_PERIPH_TIM16_UP_2 = 33 | ALTERNATE1, /* Same as TIM16_CH1. */ - DMA1_PERIPH_TIM2_CH2 = 34, - DMA1_PERIPH_TIM2_CH4 = 34 | ALTERNATE1, /* Same as TIM2_CH2. */ - - - DMA1_PERIPH_TIM17_CH1_1 = 35, - DMA1_PERIPH_TIM17_UP_1 = 35 | ALTERNATE1, /* Same as TIM17_CH1 */ - DMA1_PERIPH_TIM3_CH3 = 36, - DMA1_PERIPH_TIM3_CH4 = 37, - DMA1_PERIPH_TIM3_UP = 37 | ALTERNATE1, /* Same as TIM3_CH4 */ - DMA1_PERIPH_TIM7_UP = 38, - DMA1_PERIPH_DAC_CH2 = 38 | ALTERNATE1, /* Same as TIM7_UP */ - DMA1_PERIPH_QUADSPI = 39, - DMA1_PERIPH_TIM3_CH1 = 40, - DMA1_PERIPH_TIM3_TRIG = 40 | ALTERNATE1, /* Same as TIM3_CH1 */ - DMA1_PERIPH_TIM17_CH1_2 = 41, - DMA1_PERIPH_TIM17_UP_2 = 41 | ALTERNATE1, /* Same as TIM17_CH1 */ + DMA1_PERIPH_TIM16_UP_2 = 33 | ALTERNATE1, /* Same as TIM16_CH1. */ + DMA1_PERIPH_TIM2_CH2 = 34, + DMA1_PERIPH_TIM2_CH4 = 34 | ALTERNATE1, /* Same as TIM2_CH2. */ + + DMA1_PERIPH_TIM17_CH1_1 = 35, + DMA1_PERIPH_TIM17_UP_1 = 35 | ALTERNATE1, /* Same as TIM17_CH1 */ + DMA1_PERIPH_TIM3_CH3 = 36, + DMA1_PERIPH_TIM3_CH4 = 37, + DMA1_PERIPH_TIM3_UP = 37 | ALTERNATE1, /* Same as TIM3_CH4 */ + DMA1_PERIPH_TIM7_UP = 38, + DMA1_PERIPH_DAC_CH2 = 38 | ALTERNATE1, /* Same as TIM7_UP */ + DMA1_PERIPH_QUADSPI = 39, + DMA1_PERIPH_TIM3_CH1 = 40, + DMA1_PERIPH_TIM3_TRIG = 40 | ALTERNATE1, /* Same as TIM3_CH1 */ + DMA1_PERIPH_TIM17_CH1_2 = 41, + DMA1_PERIPH_TIM17_UP_2 = 41 | ALTERNATE1, /* Same as TIM17_CH1 */ DMA1_PERIPH_TIM4_CH1 = 42, - DMA_RESERVED(DMA1) = 43, - DMA1_PERIPH_TIM6_UP = 44, - DMA1_PERIPH_DAC_CH1 = 44 | ALTERNATE1, /* Same as TIM6_UP */ + DMA_RESERVED(DMA1) = 43, + DMA1_PERIPH_TIM6_UP = 44, + DMA1_PERIPH_DAC_CH1 = 44 | ALTERNATE1, /* Same as TIM6_UP */ DMA1_PERIPH_TIM4_CH2 = 45, DMA1_PERIPH_TIM4_CH3 = 46, - DMA_RESERVED(DMA1) = 47, - DMA1_PERIPH_TIM4_UP = 48, - - DMA_DMA1_PERIHP_RESERVED5 = 49, - DMA1_PERIPH_TIM1_CH1 = 50, - DMA1_PERIPH_TIM1_CH2 = 51, - DMA1_PERIPH_TIM1_CH4 = 52, - DMA1_PERIPH_TIM1_TRIG = 52 | ALTERNATE1, /* Same as TIM1_TRIG */ - DMA1_PERIPH_TIM1_COM = 52 | ALTERNATE2, /* Same as TIM1_TRIG */ - DMA1_PERIPH_TIM15_CH1 = 53, - DMA1_PERIPH_TIM15_UP = 53 | ALTERNATE1, /* Same as TIM15_CH1 */ + DMA_RESERVED(DMA1) = 47, + DMA1_PERIPH_TIM4_UP = 48, + + DMA_DMA1_PERIHP_RESERVED5 = 49, + DMA1_PERIPH_TIM1_CH1 = 50, + DMA1_PERIPH_TIM1_CH2 = 51, + DMA1_PERIPH_TIM1_CH4 = 52, + DMA1_PERIPH_TIM1_TRIG = 52 | ALTERNATE1, /* Same as TIM1_TRIG */ + DMA1_PERIPH_TIM1_COM = 52 | ALTERNATE2, /* Same as TIM1_TRIG */ + DMA1_PERIPH_TIM15_CH1 = 53, + DMA1_PERIPH_TIM15_UP = 53 | ALTERNATE1, /* Same as TIM15_CH1 */ DMA1_PERIPH_TIM15_TRIG = 53 | ALTERNATE2, /* Same as TIM15_CH1 */ - DMA1_PERIPH_TIM15_COM = 53 | ALTERNATE3, /* Same as TIM15_CH1 */ - DMA1_PERIPH_TIM1_UP = 54, - DMA1_PERIPH_TIM1_CH3 = 55, - - DMA2_DMA1_SWITCH__ = 56, - - DMA2_PERIPH_I2C4_RX = 56, - DMA2_PERIPH_I2C4_TX = 57, - DMA2_PERIPH_ADC1 = 58, - DMA2_PERIPH_ADC2 = 59, - DMA2_PERIPH_ADC3 = 60, - DMA2_PERIPH_DCMI_1 = 61, - DMA_RESERVED(DMA2) = 62, - - DMA2_PERIPH_SAI1_A_1 = 63, - DMA2_PERIPH_SAI1_B_1 = 64, - DMA2_PERIPH_SAI2_A = 65, - DMA2_PERIPH_SAI2_B = 66, - DMA_RESERVED(DMA2) = 67, - DMA2_PERIPH_SAI1_A_2 = 68, - DMA2_PERIPH_SAI1_B_2 = 69, - - DMA2_PERIPH_UART5_TX = 70, - DMA2_PERIPH_UART5_RX = 71, - DMA2_PERIPH_UART4_TX = 72, - DMA_RESERVED(DMA2) = 73, - DMA2_PERIPH_UART4_RX = 74, - DMA2_PERIPH_USART1_TX = 75, - DMA2_PERIPH_USART1_RX = 76, - - DMA2_PERIPH_SPI3_RX = 77, - DMA2_PERIPH_SPI3_TX = 78, - DMA_RESERVED(DMA2) = 79, - DMA2_PERIPH_TIM6_UP = 80, - DMA2_PERIPH_DAC_CH1 = 80 | ALTERNATE1, /* Same as TIM6_UP */ - DMA2_PERIPH_TIM7_UP = 81, - DMA2_PERIPH_DAC_CH2 = 81 | ALTERNATE1, /* Same as TIM7_UP */ - DMA_RESERVED(DMA2) = 82, - DMA2_PERIPH_QUADSPI = 83, - - DMA2_PERIPH_SWPMI1_RX = 84, - DMA2_PERIPH_SWPMI1_TX = 85, - DMA2_PERIPH_SPI1_RX = 86, - DMA2_PERIPH_SPI1_TX = 87, - DMA2_PERIPH_DCMI_2 = 88, + DMA1_PERIPH_TIM15_COM = 53 | ALTERNATE3, /* Same as TIM15_CH1 */ + DMA1_PERIPH_TIM1_UP = 54, + DMA1_PERIPH_TIM1_CH3 = 55, + + DMA2_DMA1_SWITCH__ = 56, + + DMA2_PERIPH_I2C4_RX = 56, + DMA2_PERIPH_I2C4_TX = 57, + DMA2_PERIPH_ADC1 = 58, + DMA2_PERIPH_ADC2 = 59, + DMA2_PERIPH_ADC3 = 60, + DMA2_PERIPH_DCMI_1 = 61, + DMA_RESERVED(DMA2) = 62, + + DMA2_PERIPH_SAI1_A_1 = 63, + DMA2_PERIPH_SAI1_B_1 = 64, + DMA2_PERIPH_SAI2_A = 65, + DMA2_PERIPH_SAI2_B = 66, + DMA_RESERVED(DMA2) = 67, + DMA2_PERIPH_SAI1_A_2 = 68, + DMA2_PERIPH_SAI1_B_2 = 69, + + DMA2_PERIPH_UART5_TX = 70, + DMA2_PERIPH_UART5_RX = 71, + DMA2_PERIPH_UART4_TX = 72, + DMA_RESERVED(DMA2) = 73, + DMA2_PERIPH_UART4_RX = 74, + DMA2_PERIPH_USART1_TX = 75, + DMA2_PERIPH_USART1_RX = 76, + + DMA2_PERIPH_SPI3_RX = 77, + DMA2_PERIPH_SPI3_TX = 78, + DMA_RESERVED(DMA2) = 79, + DMA2_PERIPH_TIM6_UP = 80, + DMA2_PERIPH_DAC_CH1 = 80 | ALTERNATE1, /* Same as TIM6_UP */ + DMA2_PERIPH_TIM7_UP = 81, + DMA2_PERIPH_DAC_CH2 = 81 | ALTERNATE1, /* Same as TIM7_UP */ + DMA_RESERVED(DMA2) = 82, + DMA2_PERIPH_QUADSPI = 83, + + DMA2_PERIPH_SWPMI1_RX = 84, + DMA2_PERIPH_SWPMI1_TX = 85, + DMA2_PERIPH_SPI1_RX = 86, + DMA2_PERIPH_SPI1_TX = 87, + DMA2_PERIPH_DCMI_2 = 88, DMA2_PERIPH_LPUART1_TX = 89, DMA2_PERIPH_LPUART1_RX = 90, - - DMA2_PERIPH_TIM5_CH4 = 91, - DMA2_PERIPH_TIM5_TRIG = 91 | ALTERNATE1, /* Same as TIM5_CH4 */ - DMA2_PERIPH_TIM5_CH3 = 92, - DMA2_PERIPH_TIM5_UP = 92 | ALTERNATE1, /* Same as TIM5_CH3 */ - DMA_RESERVED(DMA2) = 93, - DMA2_PERIPH_TIM5_CH2 = 94, - DMA2_PERIPH_TIM5_CH1 = 95, - DMA2_PERIPH_I2C1_RX = 96, - DMA2_PERIPH_I2C1_TX = 97, - - DMA2_PERIPH_AES_IN_1 = 98, - DMA2_PERIPH_AES_OUT_1 = 99, - DMA2_PERIPH_AES_OUT_2 = 100, - DMA_RESERVED(DMA2) = 101, - DMA2_PERIPH_AES_IN_2 = 102, - DMA_RESERVED(DMA2) = 103, - DMA2_PERIPH_HASH_IN = 104, - - DMA2_PERIPH_TIM8_CH3 = 105, - DMA2_PERIPH_TIM8_UP = 105 | ALTERNATE1, /* Same as TIM8_CH3 */ - DMA2_PERIPH_TIM8_CH4 = 106, - DMA2_PERIPH_TIM8_TRIG = 106 | ALTERNATE1, /* Same as TIM8_CH4 */ - DMA2_PERIPH_TIM8_COM = 106 | ALTERNATE2, /* Same as TIM8_CH4 */ - DMA_RESERVED(DMA2) = 107, - DMA2_PERIPH_SDMMC1_1 = 108, - DMA2_PERIPH_SDMMC1_2 = 109, - DMA2_PERIPH_TIM8_CH1 = 110, - DMA2_PERIPH_TIM8_CH2 = 111, - + DMA2_PERIPH_TIM5_CH4 = 91, + DMA2_PERIPH_TIM5_TRIG = 91 | ALTERNATE1, /* Same as TIM5_CH4 */ + DMA2_PERIPH_TIM5_CH3 = 92, + DMA2_PERIPH_TIM5_UP = 92 | ALTERNATE1, /* Same as TIM5_CH3 */ + DMA_RESERVED(DMA2) = 93, + DMA2_PERIPH_TIM5_CH2 = 94, + DMA2_PERIPH_TIM5_CH1 = 95, + DMA2_PERIPH_I2C1_RX = 96, + DMA2_PERIPH_I2C1_TX = 97, + + DMA2_PERIPH_AES_IN_1 = 98, + DMA2_PERIPH_AES_OUT_1 = 99, + DMA2_PERIPH_AES_OUT_2 = 100, + DMA_RESERVED(DMA2) = 101, + DMA2_PERIPH_AES_IN_2 = 102, + DMA_RESERVED(DMA2) = 103, + DMA2_PERIPH_HASH_IN = 104, + + DMA2_PERIPH_TIM8_CH3 = 105, + DMA2_PERIPH_TIM8_UP = 105 | ALTERNATE1, /* Same as TIM8_CH3 */ + DMA2_PERIPH_TIM8_CH4 = 106, + DMA2_PERIPH_TIM8_TRIG = 106 | ALTERNATE1, /* Same as TIM8_CH4 */ + DMA2_PERIPH_TIM8_COM = 106 | ALTERNATE2, /* Same as TIM8_CH4 */ + DMA_RESERVED(DMA2) = 107, + DMA2_PERIPH_SDMMC1_1 = 108, + DMA2_PERIPH_SDMMC1_2 = 109, + DMA2_PERIPH_TIM8_CH1 = 110, + DMA2_PERIPH_TIM8_CH2 = 111, DMA_PERIPH_SENTINEL, } dma_peripheral_t; - /* Defines a DMA channel. */ typedef struct { - uint8_t dma; /* 0 = DMA1, 1 = DMA2 */ + uint8_t dma; /* 0 = DMA1, 1 = DMA2 */ uint8_t chan; /* 0 - 6 */ } dma_channel_t; - /* * Defines a DMA channel allocated for memory-to-peripheral transfers. This * structure is only nominally different from dma_channel_t in order to provide @@ -209,7 +204,7 @@ typedef struct { dma_channel_t c_; } dma_mem2mem_channel_t; -#define DMA_CHAN_ERROR ((dma_channel_t) { .dma = 0xff, .chan = 0xff }) +#define DMA_CHAN_ERROR ((dma_channel_t){.dma = 0xff, .chan = 0xff}) typedef struct { bool transfer_complete_interrupt_enable; @@ -226,39 +221,34 @@ typedef struct { dma_priority_level_t priority; } dma_opts_t; -#define DEFAULT_DMA_OPTS \ - ((dma_opts_t) { .memory_increment = 1, \ - .peripheral_increment = 0, \ - .transfer_complete_interrupt_enable = 0, \ - .half_transfer_interrupt_enable = 0, \ - .transfer_error_interrupt_enable = 0, \ - .circular_mode = 0, \ - .peripheral_block_size = DMA_SIZE_8_BITS, \ - .memory_block_size = DMA_SIZE_8_BITS, \ - .priority = DMA_PRIORITY_LEVEL_MEDIUM }) +#define DEFAULT_DMA_OPTS \ + ((dma_opts_t){ \ + .memory_increment = 1, \ + .peripheral_increment = 0, \ + .transfer_complete_interrupt_enable = 0, \ + .half_transfer_interrupt_enable = 0, \ + .transfer_error_interrupt_enable = 0, \ + .circular_mode = 0, \ + .peripheral_block_size = DMA_SIZE_8_BITS, \ + .memory_block_size = DMA_SIZE_8_BITS, \ + .priority = DMA_PRIORITY_LEVEL_MEDIUM}) dma_p2mem_channel_t select_dma_channel_p2mem( - dma_peripheral_t peripheral, - dma_opts_t* opts_in, - int* error); + dma_peripheral_t peripheral, dma_opts_t* opts_in, int* error); dma_mem2p_channel_t select_dma_channel_mem2p( - dma_peripheral_t peripheral, - dma_opts_t* opts_in, - int* error); + dma_peripheral_t peripheral, dma_opts_t* opts_in, int* error); /* Returns a dma channel used for memory-to-memory transfers. * * channel - the channel this dma should use. The channel should * be on the range [0-13]. The channels [0-6] refer to the 7 channels * on DMA1, where channels [7-13] refer to the 7 channels on DMA2. - * + * * If `channel` is -1, then the highest unused dma channel is selected. */ dma_mem2mem_channel_t select_dma_channel_mem2mem( - int channel, - dma_opts_t* opts, - int* error_out); + int channel, dma_opts_t* opts, int* error_out); void dma_mem2p_initiate_transfer( dma_mem2p_channel_t chan, const void* from_loc, uint16_t nblocks); @@ -276,4 +266,9 @@ void release_dma_channel(dma_channel_t chan); interrupt_t dma_channel_get_interrupt(dma_channel_t chan); +void dma_chan_set_callback( + dma_channel_t chan, void (*callback)(void*), void* arg); + +void dma_channel_interrupt_enable(dma_channel_t chan, bool enabled); + #endif diff --git a/src/drv/ws2812B/ws2812b.c b/src/drv/ws2812B/ws2812b.c new file mode 100644 index 0000000..e1e9309 --- /dev/null +++ b/src/drv/ws2812B/ws2812b.c @@ -0,0 +1,55 @@ +#include "drv/ws2812B/ws2812b.h" + +#include "kern/mem.h" +#include "kern/panic.h" +#include "kern/dma/dma_manager.h" +#include "arch/stm32l4xxx/peripherals/spi.h" + +uint8_t* ws2812b_compile_rgb(rgb_t* out_, size_t arr_len) +{ + uint8_t* out = (uint8_t*) out_; + uint8_t* spi_out = kalloc(arr_len * 9); + + if (!spi_out) { + panic("Unable to allocate spi_out\n"); + } + + size_t i; + size_t j; + + for (i = 0, j = 0; i < arr_len * 3; ++i, j += 3) { + // stuff + uint8_t c = out[i]; + spi_out[j] = 0 + | (1 << 7) + | ((c & (1 << 7)) << 6) + | (0 << 5) + | (1 << 4) + | ((c & (1 << 6)) << 3) + | (0 << 2) + | (1 << 1) + | ((c & (1 << 5)) << 0); + + spi_out[j + 1] = 0 + | (0 << 7) + | (1 << 6) + | ((c & (1 << 4)) << 5) + | (0 << 4) + | (1 << 3) + | ((c & (1 << 3)) << 2) + | (0 << 1) + | (1 << 0); + + spi_out[j + 2] = 0 + | ((c & (1 << 2)) << 7) + | (0 << 6) + | (1 << 5) + | ((c & (1 << 1)) << 4) + | (0 << 3) + | (1 << 2) + | ((c & (1 << 0)) << 1) + | (0 << 0); + } + + return spi_out; +} diff --git a/src/kern/dma/dma_manager.c b/src/kern/dma/dma_manager.c index 9ffa795..39ae9a3 100644 --- a/src/kern/dma/dma_manager.c +++ b/src/kern/dma/dma_manager.c @@ -2,10 +2,38 @@ #include "arch/stm32l4xxx/peripherals/dma.h" #include "arch/stm32l4xxx/peripherals/rcc.h" +#include "arch/stm32l4xxx/peripherals/spi.h" #include "arch/stm32l4xxx/peripherals/usart.h" /* Bitmask of DMA2 channels in use. */ -static uint8_t dma_inuse[2]; +uint8_t dma_inuse[2]; + +void (*dma_channel_callbacks[14])(void*); +void* callback_args[14]; + +#define ON_DMA(dma, chan) \ + void on_dma##dma##_channel##chan() \ + { \ + if (dma_channel_callbacks[(dma - 1) * 7 + (chan - 1)]) { \ + dma_channel_callbacks[(dma - 1) * 7 + (chan - 1)]( \ + callback_args[(dma - 1) * 7 + (chan - 1)]); \ + } \ + } + +ON_DMA(1, 1); +ON_DMA(1, 2); +ON_DMA(1, 3); +ON_DMA(1, 4); +ON_DMA(1, 5); +ON_DMA(1, 6); +ON_DMA(1, 7); +ON_DMA(2, 1); +ON_DMA(2, 2); +ON_DMA(2, 3); +ON_DMA(2, 4); +ON_DMA(2, 5); +ON_DMA(2, 6); +ON_DMA(2, 7); static inline dma_t* get_dma(int dma) { @@ -37,6 +65,12 @@ static uint32_t get_periph_location(dma_peripheral_t operipheral) CASE(DMA1_PERIPH_USART1_TX, &USART1.td_r) CASE(DMA1_PERIPH_USART2_RX, &USART2.rd_r) CASE(DMA1_PERIPH_USART2_TX, &USART2.td_r) + CASE(DMA2_PERIPH_SPI1_RX, &SPI1.d_r) + CASE(DMA2_PERIPH_SPI1_TX, &SPI1.d_r) + CASE(DMA1_PERIPH_SPI1_RX, &SPI1.d_r) + CASE(DMA1_PERIPH_SPI1_TX, &SPI1.d_r) + CASE(DMA2_PERIPH_SPI3_RX, &SPI3.d_r) + CASE(DMA2_PERIPH_SPI3_TX, &SPI3.d_r) default: return 0; @@ -280,6 +314,25 @@ void dma_p2mem_initiate_transfer( regset(config->cc_r, dma_cc_en, 1); } +void dma_chan_set_callback( + dma_channel_t chan, void (*callback)(void*), void* arg) +{ + dma_channel_callbacks[chan.dma * 7 + chan.chan] = callback; + callback_args[chan.dma * 7 + chan.chan] = arg; + enable_interrupt(dma_channel_get_interrupt(chan)); +} + +void dma_channel_interrupt_enable(dma_channel_t chan, bool enabled) +{ + dma_channel_config_t* config = get_raw_channel_config(chan); + regset(config->cc_r, dma_cc_tcie, !!enabled); + if (enabled) { + enable_interrupt(dma_channel_get_interrupt(chan)); + } else { + disable_interrupt(dma_channel_get_interrupt(chan)); + } +} + interrupt_t dma_channel_get_interrupt(dma_channel_t chan) { if (chan.dma == 0) { diff --git a/src/kern/main.c b/src/kern/main.c index d4393f3..3dcadf6 100644 --- a/src/kern/main.c +++ b/src/kern/main.c @@ -1,17 +1,61 @@ #include "arch.h" #include "arch/arm/cortex-m4/mpu.h" #include "arch/stm32l4xxx/peripherals/clock.h" +#include "arch/stm32l4xxx/peripherals/dma.h" #include "arch/stm32l4xxx/peripherals/rcc.h" +#include "arch/stm32l4xxx/peripherals/irq.h" #include "arch/stm32l4xxx/peripherals/spi.h" #include "arch/stm32l4xxx/peripherals/system.h" #include "kern/gpio/gpio_manager.h" +#include "kern/dma/dma_manager.h" #include "kern/init.h" #include "kern/log.h" #include "kern/mem.h" #include "kern/mpu/mpu_manager.h" #include "kern/panic.h" +#include "kern/delay.h" #include "kern/priv.h" +#include "kern/gpio/sysled.h" +#include "arch/stm32l4xxx/peripherals/clock.h" #include "user/syscall.h" +#include "drv/ws2812B/ws2812b.h" + + +gpio_reserved_pin_t sysl; +int syslon; +int n; +uint16_t my_short; +extern uint16_t dma_inuse; + +void on_spi1() +{ + SPI1.d_r = ~my_short; + if (n++ == 10000) { + if (syslon) { + set_gpio_pin_low(sysl); + } else { + set_gpio_pin_high(sysl); + } + + syslon = !syslon; + n = 0; + } +} + +inline void spi_write_byte(uint8_t byte) +{ + // volatile uint32_t read; + + //delay(5); + //while (regget(SPI1.s_r, spi_rxne)) { + // read = SPI1.d_r; + //} + //delay(5); + + //delay(5); + while (regget(SPI1.s_r, spi_ftlvl) > SPI_FIFO_STATUS_HALF); + SPI1.d_r = (byte << 8) | byte; +} void on_hard_fault() { @@ -20,7 +64,9 @@ void on_hard_fault() void on_systick() /* Overrides weak-symbol on_systick. */ { - klogf("Systick\n"); + // klogf("systick\n"); + if (my_short == 0) my_short = 0xffff; + my_short >>=1; } void configure_mpu() @@ -32,14 +78,92 @@ void configure_mpu() mpu_set_enabled(1); } +static void dma_callback(void* arg) +{ + klogf("Dma callback\n"); + dma_channel_t* chan = arg; + + release_dma_channel(*chan); + dma_channel_interrupt_enable(*chan, 0); + + regset(SPI1.c_r1, spi_spe, 0); + + DMA2.ifc_r |= 0xffffffff; + DMA1.ifc_r |= 0xffffffff; + regset(DMA2.channel_config[3].cc_r, dma_cc_en, 0); +} + #ifdef ARCH_STM32L4 /* Main function. This gets executed from the interrupt vector defined above. */ int main() { - configure_mpu(); + int ec = 0; + + size_t size = 20; + rgb_t arr[] = { + {0x00, 0x00, 0xff}, + {0x00, 0xff, 0x00}, + {0xff, 0x00, 0x00}, + + {0xff, 0x80, 0x80}, + {0x80, 0xff, 0x80}, + {0x80, 0x80, 0xff}, - int ec; + {0xff, 0xff, 0xff}, + {0xff, 0xff, 0xff}, + {0xff, 0xff, 0xff}, + + {0xff, 0xff, 0xff}, + {0xff, 0xff, 0xff}, + {0xff, 0xff, 0xff}, + + {0xff, 0xff, 0xff}, + {0xff, 0xff, 0xff}, + {0xff, 0xff, 0xff}, + + {0xff, 0xff, 0xff}, + {0xff, 0xff, 0xff}, + {0xff, 0xff, 0xff}, + + {0xff, 0xff, 0xff}, + {0xff, 0xff, 0xff}, + {0xff, 0xff, 0xff}, + + {0xff, 0xff, 0xff}, + {0xff, 0xff, 0xff}, + {0xff, 0xff, 0xff}, + + {0xff, 0xff, 0xff}, + {0xff, 0xff, 0xff}, + {0xff, 0xff, 0xff}, + + {0xff, 0xff, 0xff}, + {0xff, 0xff, 0xff}, + {0xff, 0xff, 0xff}, + }; + uint8_t* dataptr = ws2812b_compile_rgb(arr, size); + + klogf("Heap start: %p\n", &HEAP_START); + klogf("Heap end: %p\n", &HEAP_STOP); + klogf("Dataptr start: %p\n", dataptr); + klogf("Dataptr end: %p\n", (dataptr + size)); + + dma_opts_t opts = DEFAULT_DMA_OPTS; + opts.transfer_complete_interrupt_enable = 1; + opts.circular_mode = 0; + dma_mem2p_channel_t dma_chan = + select_dma_channel_mem2p(DMA2_PERIPH_SPI1_TX, &opts, &ec); + dma_chan_set_callback(dma_chan.c_, dma_callback, &dma_chan); + + if (ec) { + panic("Unable to allocate dma channel: %d\n", ec); + } + + my_short = 0xff; + klogf("This is weird.\n"); + // configure_mpu(); + sysl = get_sysled(); // gpio_enable_alternate_function( // GPIO_ALTERNATE_FUNCTION_SPI1_MISO, GPIO_PIN_PA6, &ec); @@ -62,8 +186,19 @@ int main() klogf("Unable to set pin PA5 (ec=%d)\n", ec); } + /* Set the countdown to start from 10,000,0000. */ + SCB.strv_r = 1000000; + + /* Enable interrupts. */ + regset(SCB.stcs_r, scb_tickint, 1); + + /* Start the systick. */ + regset(SCB.stcs_r, scb_enable, 1); + regset(RCC.apb2en_r, rcc_spi1en, 1); + enable_interrupt(IRQ_SPI1); + uint32_t reg = 0; regset(reg, spi_ldma_tx, 0); regset(reg, spi_ldma_rx, 0); @@ -75,7 +210,7 @@ int main() regset(reg, spi_frf, 0); regset(reg, spi_nssp, 0); regset(reg, spi_ssoe, 0); - regset(reg, spi_txdmaen, 0); + regset(reg, spi_txdmaen, 1); regset(reg, spi_rxdmaen, 0); SPI1.c_r2 = reg; @@ -89,34 +224,18 @@ int main() regset(reg, spi_ssi, 1); regset(reg, spi_lsbfirst, 0); regset(reg, spi_spe, 1); - regset(reg, spi_br, SPI_BAUD_FPCLK_DIV_256); + regset(reg, spi_br, SPI_BAUD_FPCLK_DIV_32); regset(reg, spi_mstr, 1); regset(reg, spi_cpol, 0); regset(reg, spi_cpha, 0); SPI1.c_r1 = reg; - uint8_t val = 0xf0; - SPI1.d_r = val; - SPI1.d_r = val; - SPI1.d_r = val; - SPI1.d_r = val; - SPI1.d_r = val; - SPI1.d_r = val; - SPI1.d_r = val; - SPI1.d_r = val; - SPI1.d_r = val; - SPI1.d_r = val; - SPI1.d_r = val; - klogf("4 Spi Status %p\n", SPI1.s_r); - - for (;;) SPI1.d_r = val; - // for (;;) { - // klogf("Spi Status %p\n", SPI1.s_r); - // // while (!regget(SPI1.s_r, spi_txe)) - // // ; - // // klogf("Write\n"); - // // SPI1.d_r = val; - // } + klogf("Initiate xfer\n"); + dma_mem2p_initiate_transfer(dma_chan, dataptr, size * 9); + klogf("Post\n"); + + // for (;;); } + #endif diff --git a/src/kern/mem.c b/src/kern/mem.c index 31756e5..aa221ff 100644 --- a/src/kern/mem.c +++ b/src/kern/mem.c @@ -44,16 +44,19 @@ typedef struct KALLOC_NODE { uint8_t mem[]; /* The memory to use. */ } PACKED kalloc_node_t; -kalloc_node_t* kalloc_start; +#ifdef ARCH_PC +typedef uint64_t ptrint_t; +#else +typedef uint32_t ptrint_t; +#endif -#define CANARY 0xdeadbeee +#define CANARY ((uint32_t) 0xdeadbeee) #define kalloc_node_in_use(node) ((node)->used_and_canary & 1) #define kalloc_node_get_canary(node) ((node)->used_and_canary & (~1)) #define WORD_SIZE (sizeof(uint32_t)) #define SIZEOF_KALLOC_NODE_WORDS (sizeof(kalloc_node_t) / WORD_SIZE) -#define HEAP_START_ADDR ((ptrdiff_t)&HEAP_START) -#define REAL_HEAP_START \ - (*((unsigned char*)((HEAP_START_ADDR & (~3)) + (HEAP_START_ADDR % 4 != 0)))) +#define HEAP_START_ADDR ((ptrint_t)&HEAP_START) +#define REAL_HEAP_START *(uint8_t*)(HEAP_START_ADDR + (4 - HEAP_START_ADDR % 4)) #define MAX_HEAP_SIZE ((&HEAP_STOP - &REAL_HEAP_START)) #define MAX_HEAP_SIZE_WORDS (MAX_HEAP_SIZE / WORD_SIZE) #define kalloc_node_out_of_range(node) ((void*)(node) >= (void*)&HEAP_STOP) @@ -74,6 +77,8 @@ kalloc_node_t* kalloc_start; #define size_for(n) (((n) / 4) + ((n) % 4 != 0)) +kalloc_node_t* kalloc_start; + void kalloc_init() { kalloc_start = (kalloc_node_t*)&REAL_HEAP_START; @@ -158,7 +163,8 @@ static void coalesce(kalloc_node_t* cur) next_used->prev = kalloc_node_get_off(last_freed); } - last_freed->size_words = ((uint8_t*)next_used - (last_freed->mem)) / WORD_SIZE; + last_freed->size_words = + ((uint8_t*)next_used - (last_freed->mem)) / WORD_SIZE; } void kfree(void* mem) diff --git a/src/kern/stdlibrepl.c b/src/kern/stdlibrepl.c index 98142e2..588191b 100644 --- a/src/kern/stdlibrepl.c +++ b/src/kern/stdlibrepl.c @@ -1,3 +1,4 @@ +#include "arch.h" /* * Replacement for common stdlib functions that don't exist * on the ARM bare-metal compilation environment. @@ -11,3 +12,17 @@ size_t strlen(char* ch) while (*(ch++) != 0) ++ret; return ret; } + +#ifdef ARCH_STM32L4 + +void memcpy(void* dest, void* src, size_t size) +{ + uint8_t* dest_ = dest; + uint8_t* src_ = src; + + while(size --) { + *(dest_++) = *(src_++); + } +} + +#endif |