From cc98a1c0941e6f08a2c326d2e8afffde49bed5b5 Mon Sep 17 00:00:00 2001 From: Romain Goyet Date: Tue, 5 May 2015 12:33:13 +0200 Subject: [PATCH] SPI data registers --- Makefile | 4 +- arch/stm32f429/registers/spi.c | 5 ++ arch/stm32f429/registers/spi.h | 8 ++- src/lcd_spi.c | 101 +++++++++++++++++++++++++++++++++ src/spi.c | 49 ++++------------ 5 files changed, 127 insertions(+), 40 deletions(-) create mode 100644 src/lcd_spi.c diff --git a/Makefile b/Makefile index cfb68889d..7263a774b 100644 --- a/Makefile +++ b/Makefile @@ -35,9 +35,9 @@ boot.bin: boot.elf @echo "OBJCOPY $@" @$(OBJCOPY) -O binary boot.elf boot.bin -boot.elf: $(objs) src/spi.o +boot.elf: $(objs) src/lcd_spi.o @echo "LD $@" - @$(LD) -T boot/stm32f429.ld $(objs) src/spi.o -o $@ + @$(LD) -T boot/stm32f429.ld $(objs) src/lcd_spi.o -o $@ %.o: %.c @echo "CC $@" diff --git a/arch/stm32f429/registers/spi.c b/arch/stm32f429/registers/spi.c index 8abfb0b8c..376af9e05 100644 --- a/arch/stm32f429/registers/spi.c +++ b/arch/stm32f429/registers/spi.c @@ -9,6 +9,7 @@ #define SPI_CR1_OFFSET 0x00 #define SPI_SR_OFFSET 0x08 +#define SPI_DR_OFFSET 0x0C char * SPI_REGISTER_ADDRESS(SPI_t spi, int registerOffset) { char * spiBaseAddress[6] = { @@ -25,3 +26,7 @@ SPI_CR1_t * SPI_CR1(SPI_t spi) { SPI_SR_t * SPI_SR(SPI_t spi) { return (SPI_SR_t *)SPI_REGISTER_ADDRESS(spi, SPI_SR_OFFSET); } + +SPI_DR_t * SPI_DR(SPI_t spi) { + return (SPI_DR_t *)SPI_REGISTER_ADDRESS(spi, SPI_DR_OFFSET); +} diff --git a/arch/stm32f429/registers/spi.h b/arch/stm32f429/registers/spi.h index 39b6372f3..b331ec22f 100644 --- a/arch/stm32f429/registers/spi.h +++ b/arch/stm32f429/registers/spi.h @@ -1,3 +1,5 @@ +#include + typedef enum { SPI1 = 0, SPI2 = 1, @@ -25,7 +27,6 @@ typedef enum { SPI_DFF_16_BITS = 1 } SPI_DFF_t; - typedef struct { unsigned int CPHA:1; unsigned int CPOL:1; @@ -61,3 +62,8 @@ typedef struct { } SPI_SR_t; SPI_SR_t * SPI_SR(SPI_t spi); + +#pragma mark - SPI data registers + +typedef uint16_t SPI_DR_t; +SPI_DR_t * SPI_DR(SPI_t spi); diff --git a/src/lcd_spi.c b/src/lcd_spi.c new file mode 100644 index 000000000..cfa98f668 --- /dev/null +++ b/src/lcd_spi.c @@ -0,0 +1,101 @@ +#include +#include +#include +#include +#include + +/* This code sends data to the onboard LCD over SPI + * + * The LCD has two interfaces, SPI and direct RGB. + * We'll only use SPI in this one. + * + * The documentation gives the following mapping + * Pin name - LCD-SPI + * NRST - Reset + * PC2 - CSX // Chip select for LCD + * PD13 - DCX // Data/Command register + * PF7 - SCL // SPI Clock + * PF9 - SDI/SDO // MOSI + * + * See UM1670 p. 19 to 24. */ + +/* We'll need to figure out which GPIO pins this maps to, and in which + * Alternate Function mode. STM32F429 datasheet p78-79 says: + * PF6 in AF5 = SPI5_NSS + * PF7 in AF5 = SPI5_SCK + * PF8 in AF5 = SPI5_MISO + * PF9 in AF5 = SPI5_MOSI + */ + +/* In case we want to monitor this, here's a color-mapping + * + * PF6 - SPI5_NSS - Yellow + * PF7 - SPI5_SCK - Green + * PF8 - SPI5_MISO - Red + * PF9 - SPI5_MOSI - Blue + */ + +void SpiSend(void * pvParameters) { + uint16_t value = 0; + while(1) { + SPI_SR_t * spi_status = SPI_SR(SPI5); + SPI_DR_t * spi_data_register = SPI_DR(SPI5); + if (spi_status->BSY == 0) { + *spi_data_register = value++; + } + vTaskDelay(100/portTICK_PERIOD_MS); + } +} + +int main(int argc, char * argv[]) { + // We'll use GPIO pins F6-F9 to emit SPI data + // GPIO are grouped by letter. All GPIO groups live on the "AHB1" bus. + // (this is documented in the STM32F4 reference mnual, page 65) + + // Step 1 : Enable clock in RCC_AHBxENR + RCC_AHB1ENR->GPIOFEN = 1; + + // Step 2 : Configure the GPIO pin to "Alternate function number 5" + // This means "SPI5 on pins F6-F9", cf STM32F249 p78 + GPIO_MODER(GPIOF)->MODER6 = GPIO_MODE_ALTERNATE_FUNCTION; + GPIO_MODER(GPIOF)->MODER7 = GPIO_MODE_ALTERNATE_FUNCTION; + GPIO_MODER(GPIOF)->MODER8 = GPIO_MODE_ALTERNATE_FUNCTION; + GPIO_MODER(GPIOF)->MODER9 = GPIO_MODE_ALTERNATE_FUNCTION; + + // We're interested in pins 11-14, which are in the 8-16 range, so we + // have to deal with the "high" version of the AF register + GPIO_AFRL(GPIOF)->AFRL6 = GPIO_AF_AF5; + GPIO_AFRL(GPIOF)->AFRL7 = GPIO_AF_AF5; + GPIO_AFRH(GPIOF)->AFRH8 = GPIO_AF_AF5; + GPIO_AFRH(GPIOF)->AFRH9 = GPIO_AF_AF5; + + // Enable the SPI5 clock + RCC_APB2ENR->SPI5EN = 1; + + // Configure the SPI port + // Using a C99 compound litteral. C99 guarantees all non-set values are zero + *SPI_CR1(SPI5) = (SPI_CR1_t){ + .BIDIMODE = 1, + .BIDIOE = 1, + .MSTR = 1, + .DFF = SPI_DFF_16_BITS, + .CPOL = 0, + .BR = SPI_BR_DIV_256, + .SSM = 1, + .SSI = 1, + .SPE = 1 + }; + + BaseType_t success = xTaskCreate(SpiSend, + "SpiSnd", + 100, // Stack size + NULL, // Parameters + 2, + NULL); + + vTaskStartScheduler(); + + while (1) { + // We should never get here + } +} diff --git a/src/spi.c b/src/spi.c index 03570c1dd..db8aa735d 100644 --- a/src/spi.c +++ b/src/spi.c @@ -51,43 +51,18 @@ int main(int argc, char * argv[]) { RCC_APB2ENR->SPI4EN = 1; // Configure the SPI port - /* - SPI_InitStruct.SPI_Direction = SPI_Direction_2Lines_FullDuplex; - SPI_InitStruct.SPI_Mode = SPI_Mode_Master; - SPI_InitStruct.SPI_DataSize = SPI_DataSize_8b; - SPI_InitStruct.SPI_CPOL = SPI_CPOL_Low; - SPI_InitStruct.SPI_CPHA = SPI_CPHA_1Edge; - SPI_InitStruct.SPI_NSS = SPI_NSS_Soft | SPI_NSSInternalSoft_Set; - SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256; - SPI_InitStruct.SPI_FirstBit = SPI_FirstBit_MSB; - */ - SPI_CR1_t * SPI4_CR1 = SPI_CR1(SPI4); - /* - SPI4_CR1->BIDIMODE = 0; - SPI4_CR1->BIDIOE = 1; - SPI4_CR1->MSTR = 1; - SPI4_CR1->DFF = SPI_DFF_8_BITS; - SPI4_CR1->CPOL = 0; - SPI4_CR1->BR = SPI_BR_DIV_256; - SPI4_CR1->SSM = 1; - SPI4_CR1->SSI = 1; - SPI4_CR1->SPE = 1; - */ - - /* - 11 0 0 1 - 0 1 1 0 1 111 - 100 */ - - /* - * 1100 - * 1011 - * 0111 - * 1100 - */ - *(uint16_t *)SPI4_CR1 = 0xCB7C; - - SPI_CR1_t output = *SPI4_CR1; + // Using a C99 compound litteral + *SPI_CR1(SPI4) = (SPI_CR1_t){ + .BIDIMODE = 1, + .BIDIOE = 1, + .MSTR = 1, + .DFF = SPI_DFF_16_BITS, + .CPOL = 0, + .BR = SPI_BR_DIV_256, + .SSM = 1, + .SSI = 1, + .SPE = 1 + }; BaseType_t success = xTaskCreate(SpiSend, "SpiSnd",