aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosh Rahm <joshuarahm@gmail.com>2020-11-28 23:21:22 -0700
committerJosh Rahm <joshuarahm@gmail.com>2020-11-28 23:21:22 -0700
commitfd674424d19cf12c1186394606729cff236d5bdf (patch)
tree5ecd05faa96a32dbf86a94cec191954c14f1cb0f
parent654511788e24794c03ecb810a3b5907e95b8b55c (diff)
downloadstm32l4-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.inc14
-rw-r--r--include/arch/stm32l4xxx/peripherals/spi.h7
-rw-r--r--include/drv/ws2812B/ws2812b.h18
-rw-r--r--include/kern/dma/dma_manager.h287
-rw-r--r--src/drv/ws2812B/ws2812b.c55
-rw-r--r--src/kern/dma/dma_manager.c55
-rw-r--r--src/kern/main.c173
-rw-r--r--src/kern/mem.c18
-rw-r--r--src/kern/stdlibrepl.c15
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