diff --git a/Makefile b/Makefile index 5a9bd52e5..542010e96 100644 --- a/Makefile +++ b/Makefile @@ -14,11 +14,14 @@ CFLAGS += -target thumbv7em-unknown-eabi -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -ffre #CFLAGS += -Os -fdata-sections -ffunction-sections #LDFLAGS += --gc-sections -objs := boot/crt0.o +objs := platform/stm32f429/boot/crt0.o objs += external/freertos/tasks.o external/freertos/list.o external/freertos/queue.o external/freertos/portable/GCC/ARM_CM4F/port.o external/freertos/portable/MemMang/heap_1.o objs += external/newlib/libc/string/memset.o external/newlib/libc/string/memcpy.o -objs += platform/stm32f429/boot/isr.o platform/stm32f429/registers/gpio.o platform/stm32f429/registers/rcc.o platform/stm32f429/registers/spi.o platform/stm32f429/spi.o platform/stm32f429/pinmux.o +objs += platform/stm32f429/boot/isr.o platform/stm32f429/registers/gpio.o platform/stm32f429/registers/rcc.o platform/stm32f429/registers/spi.o + +objs += platform/stm32f429/init.o platform/stm32f429/init_lcd.o +objs += platform/ili9341/ili9341.o default: clean boot.elf @@ -39,9 +42,9 @@ boot.bin: boot.elf @echo "OBJCOPY $@" @$(OBJCOPY) -O binary boot.elf boot.bin -boot.elf: $(objs) src/lcd_spi.o +boot.elf: $(objs) @echo "LD $@" - @$(LD) -T platform/stm32f429/boot/flash.ld $(objs) src/lcd_spi.o -o $@ + @$(LD) -T platform/stm32f429/boot/flash.ld $(objs) -o $@ %.o: %.c @echo "CC $@" diff --git a/README_APPS.txt b/README_APPS.txt new file mode 100644 index 000000000..2249955eb --- /dev/null +++ b/README_APPS.txt @@ -0,0 +1,8 @@ +On what foundation do the apps rely? + + -> dynamic memory allocation -> Not obious, *maybe* a malloc implementation can be provided + -> direct access to a framebuffer + -> Use of a graphic library to write to the framebuffer (no "context") + -> A way to receive keyboard input. + +That's it! diff --git a/external/NEWLIB.txt b/external/NEWLIB.txt index f61308d58..b84900a08 100644 --- a/external/NEWLIB.txt +++ b/external/NEWLIB.txt @@ -1,2 +1,3 @@ - Using memcpy and memset - using , , and +- using for "bool" diff --git a/gdb_script.gdb b/gdb_script.gdb index 3d553d77e..9c1b66c64 100644 --- a/gdb_script.gdb +++ b/gdb_script.gdb @@ -7,6 +7,7 @@ load boot.elf # Tell OpenOCD to reset and halt monitor reset halt -break main +break init +break _halt continue diff --git a/platform/ili9341/ili9341.c b/platform/ili9341/ili9341.c new file mode 100644 index 000000000..7e2c888e9 --- /dev/null +++ b/platform/ili9341/ili9341.c @@ -0,0 +1,116 @@ +#include "ili9341.h" +#include +//#include //FIXME + +enum { + COMMAND_MODE = 0, + DATA_MODE = 1, + DELAY_MODE = 2 +}; + +enum { + NOP = 0x00, // No operation + SWRESET = 0x01, // Software reset + RDDIDIF = 0x04, // Read display identification information + RDDST = 0x09, // Read display status + RDDPM = 0x0A, // Read display power mode + SLPOUT = 0x11, // Sleep out + DISPOFF = 0x28, // Display off + DISPON = 0x29, // Display on + RAMWR = 0x2C, // Memory write + PIXSET = 0x3A, // Pixel format set + FRMCTR1 = 0xB1A // Frame rate control in normal/full-color mode +}; + +typedef struct { + char mode; + char payload; +} instruction_t; + +#define COMMAND(c) (instruction_t){.mode = (char)COMMAND_MODE, .payload = (char)c} +#define DATA(d) (instruction_t){.mode = (char)DATA_MODE, .payload = (char)d} +#define DELAY(m) (instruction_t){.mode = (char)DELAY_MODE, .payload = (char)m} + +static instruction_t initialisation_sequence[] = { + COMMAND(SWRESET), DELAY(5), // Software reset, then wait 5ms + COMMAND(DISPOFF), + + // FIXME: Ad-hoc skipping extended registers, we're not using it + + // Pixel format: 16bpp, both on RGB and SPI + COMMAND(PIXSET), DATA(0x55), + + /* FIXME: Useless: extended + // Framerate: + COMMAND(FRMCTR1), DATA(0x00), DATA(0x1B), + */ + + // Gamma + //FIXME + + // Display + // Entry mode set, skipped + COMMAND(SLPOUT), DELAY(100), + + COMMAND(DISPON), DELAY(20), + + COMMAND(NOP) // Used to mark the end of the init sequence +}; + +void perform_instruction(ili9341_t * c, instruction_t * instruction) { + if (instruction->mode == DELAY_MODE) { + // FIXME: Should sleep instruction->payload miliseconds + for (int i = 0; i < 800*instruction->payload; i++) { + } + } else { + c->data_command_pin_write(instruction->mode); + c->spi_write(&instruction->payload, 1); + } +} + +#define X 0xFFFF + uint16_t pattern[64] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, X, X, X, X, 0, 0, + 0, X, 0, 0, 0, 0, X, 0, + 0, 0, X, X, X, 0, X, 0, + 0, X, 0, 0, 0, X, 0, 0, + 0, X, 0, 0, 0, X, 0, 0, + 0, 0, X, X, X, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + }; +#undef X + +void ili9341_initialize(ili9341_t * c) { + // Falling edge on CSX + c->chip_select_pin_write(0); + + // Send all the initialisation_sequence + instruction_t * instruction = initialisation_sequence; + while (!(instruction->mode == COMMAND_MODE && instruction->payload == NOP)) { + perform_instruction(c, instruction++); + } + + perform_instruction(c, &COMMAND(RAMWR)); + + c->data_command_pin_write(DATA_MODE); + + for (int j=0;j<320;j++) { + for (int i =0;i<30;i++) { + c->spi_write(((char *)pattern + sizeof(uint16_t)*8*(j%8)), 8*sizeof(uint16_t)); + } + } + +/* + //FIXME + GPIO_MODER(GPIOF)->MODER9 = GPIO_MODE_INPUT; + + for (int i = 0; i<1000; i++) {} + + for (int i=0; i < 10; i++) { + send_data(c, 'A'); + }*/ +} + +void ili9341_set_gamma(ili9341_t * c) { +} diff --git a/platform/ili9341/ili9341.h b/platform/ili9341/ili9341.h new file mode 100644 index 000000000..14fb4dc89 --- /dev/null +++ b/platform/ili9341/ili9341.h @@ -0,0 +1,19 @@ +#ifndef PLATFORM_ILI9341_H +#define PLATFORM_ILI9341_H 1 + +#include +#include + +/* This is the ILI9341 driver + * + * It just needs to be pointed to a "write" function + */ +typedef struct { + void (*chip_select_pin_write)(bool pin_state); + void (*data_command_pin_write)(bool pin_state); + void (*spi_write)(char * data, size_t size); +} ili9341_t; + +void ili9341_initialize(ili9341_t * controller); +void ili9341_set_gamma(ili9341_t * controller); +#endif diff --git a/boot/crt0.c b/platform/stm32f429/boot/crt0.c similarity index 94% rename from boot/crt0.c rename to platform/stm32f429/boot/crt0.c index 0dccd5736..339282c14 100644 --- a/boot/crt0.c +++ b/platform/stm32f429/boot/crt0.c @@ -7,7 +7,12 @@ extern const void * _data_section_end_ram; extern const void * _bss_section_start_ram; extern const void * _bss_section_end_ram; -int main(int argc, char * argv[]); +void init(); + +void _halt() { + while (1) { + } +} void _start(void) { // This is where execution starts after reset. @@ -26,10 +31,7 @@ void _start(void) { size_t bssSectionLength = (char *)&_bss_section_end_ram - (char *)&_bss_section_start_ram; memset(&_bss_section_start_ram, 0, bssSectionLength); - main(0, 0x0); -} + init(); -void _halt(void) { - while (1) { - } + _halt(); } diff --git a/platform/stm32f429/gpio.h b/platform/stm32f429/gpio.h deleted file mode 100644 index d74def770..000000000 --- a/platform/stm32f429/gpio.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef STM32F429_GPIO_H -#define STM32F429_GPIO_H 1 - -typedef enum { - STM32_GPIO_GROUP_A = 0, - STM32_GPIO_GROUP_B = 1, - STM32_GPIO_GROUP_C = 2, - STM32_GPIO_GROUP_D = 3, - STM32_GPIO_GROUP_E = 4, - STM32_GPIO_GROUP_F = 5, - STM32_GPIO_GROUP_G = 6, - STM32_GPIO_GROUP_H = 7, - STM32_GPIO_GROUP_I = 8, - STM32_GPIO_GROUP_J = 9, - STM32_GPIO_GROUP_K = 10 -} stm32_gpio_group_t; - -typedef struct { - stm32_gpio_group_t group:4; - unsigned int number:4; -} stm32_pin_t; - -#define STM32_PIN(g,i) (stm32_pin_t){.group = STM32_GPIO_GROUP_##g, .number = i} - -#endif diff --git a/platform/stm32f429/init.c b/platform/stm32f429/init.c new file mode 100644 index 000000000..fbee6bda4 --- /dev/null +++ b/platform/stm32f429/init.c @@ -0,0 +1,5 @@ +#include "init_lcd.h" + +void init() { + init_lcd(); +} diff --git a/platform/stm32f429/init_lcd.c b/platform/stm32f429/init_lcd.c new file mode 100644 index 000000000..e2048efad --- /dev/null +++ b/platform/stm32f429/init_lcd.c @@ -0,0 +1,154 @@ +/* LCD Initialisation code + * + * The LCD panel is connected via two interfaces: RGB and SPI. The SPI interface + * is used to configure the panel, and can be used to send pixel data. + * For higher performances, the RGB interface can be used to send pixel data. + * + * Here is the connection this file assumes: + * + * LCD_SPI | STM32 | Role + * ---------+-------+----- + * RESET | NRST | + * CSX | PC2 | Chip enable input + * DCX | PD13 | Selects "command" or data mode + * SCL | PF7 | SPI clock + * SDI/SDO | PF9 | SPI data + * + * The entry point is init_lcd(); + * + * Some info regarding the built-in LCD panel of the STM32F429I Discovery: + * -> The pin EXTC of the ili9341 is not connected to Vdd. It reads as "0", and + * therefore extended registers are not available. Those are 0xB0-0xCF and 0xE0 + * - 0xFF. Apparently this means we cannot read the display ID (RDDIDIF). + * That's wat ST says in stm32f429i_discovery_lcd.c. + */ + +#include "registers/rcc.h" +#include "registers/gpio.h" +#include "registers/spi.h" +#include + +static void spi_5_write(char * data, size_t size); +static void gpio_c2_write(bool pin_state); +static void gpio_d13_write(bool pin_state); + +ili9341_t sPanel = { + .chip_select_pin_write = gpio_c2_write, + .data_command_pin_write = gpio_d13_write, + .spi_write = spi_5_write +}; + +static void init_lcd_gpio(); +static void init_lcd_spi(); +static void init_lcd_panel(); + +void init_lcd() { + /* This routine is responsible for initializing the LCD panel. + * Its interface with the outer world is the framebuffer: after execution of + * this routine, everyone can expect to write to the LCD by writing to the + * framebuffer. */ + + /* The LCD panel is connected on GPIO pins. Let's configure them. */ + init_lcd_gpio(); + + /* According to our GPIO config, we send commands to the LCD panel over SPI on + * port SPI5. Let's configure it. */ + init_lcd_spi(); + + /* configure display */ + init_lcd_panel(); + + /* Last but not least */ + //TODO: init_lcd_dma(); +} + +#pragma mark - GPIO initialization + +static void init_lcd_gpio_clocks() { + // We are using groups C, D, and F. Let's enable their clocks + RCC_AHB1ENR->GPIOCEN = 1; + RCC_AHB1ENR->GPIODEN = 1; + RCC_AHB1ENR->GPIOFEN = 1; +} + +static void init_lcd_gpio_modes() { + // PC2 and PD13 are controlled directly + GPIO_MODER(GPIOC)->MODER2 = GPIO_MODE_OUTPUT; + GPIO_MODER(GPIOD)->MODER13 = GPIO_MODE_OUTPUT; + + // PF7 and PF9 are used for an alternate function (in that case, SPI) + GPIO_MODER(GPIOF)->MODER7 = GPIO_MODE_ALTERNATE_FUNCTION; + GPIO_MODER(GPIOF)->MODER9 = GPIO_MODE_ALTERNATE_FUNCTION; + + // More precisely, PF7 and PF9 are doing SPI-SCL and SPI-SDO/SDO. + // This corresponds to Alternate Function 5 using SPI port 5 + // (See STM32F429 p78) + GPIO_AFRL(GPIOF)->AFRL7 = GPIO_AF_AF5; // Pin 7 is in the "low" register + GPIO_AFRH(GPIOF)->AFRH9 = GPIO_AF_AF5; // and pin 9 in the "high" one + + // For debug + /* + GPIO_MODER(GPIOF)->MODER6 = GPIO_MODE_ALTERNATE_FUNCTION; + GPIO_MODER(GPIOF)->MODER8 = GPIO_MODE_ALTERNATE_FUNCTION; + GPIO_AFRL(GPIOF)->AFRL6 = GPIO_AF_AF5; // and pin 9 in the "high" one + GPIO_AFRH(GPIOF)->AFRH8 = GPIO_AF_AF5; // and pin 9 in the "high" one + */ +} + +static void init_lcd_gpio() { + /* The LCD panel is connected on GPIO pins. Let's configure them. */ + init_lcd_gpio_clocks(); + init_lcd_gpio_modes(); +} + +void gpio_c2_write(bool pin_state) { + GPIO_ODR(GPIOC)->ODR2 = pin_state; +} + +void gpio_d13_write(bool pin_state) { + GPIO_ODR(GPIOD)->ODR13 = pin_state; +} + +#pragma mark - SPI initialization + +static void init_lcd_spi() { + // Enable the SPI5 clock (SPI5 lives on the APB2 bus) + 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_8_BITS, + .CPOL = 0, + .CPHA = 0, + .BR = SPI_BR_DIV_2, + .SSM = 1, + .SSI = 1, + .LSBFIRST = 0, // Send the most significant bit first + .SPE = 1 + }; +} + +static void spi_5_write(char * data, size_t size) { + volatile SPI_SR_t * spi_status = SPI_SR(SPI5); + volatile SPI_DR_t * spi_data_register = SPI_DR(SPI5); + + while (spi_status->BSY != 0) { + } + for (size_t i=0; iTXE == 0) { + } + } + while (spi_status->BSY != 0) { + } +} + +#pragma mark - Panel initialization + +void init_lcd_panel() { + ili9341_initialize(&sPanel); +} diff --git a/platform/stm32f429/init_lcd.h b/platform/stm32f429/init_lcd.h new file mode 100644 index 000000000..56de91d0d --- /dev/null +++ b/platform/stm32f429/init_lcd.h @@ -0,0 +1 @@ +void init_lcd(); diff --git a/platform/stm32f429/pinmux.c b/platform/stm32f429/pinmux.c deleted file mode 100644 index 30b25112b..000000000 --- a/platform/stm32f429/pinmux.c +++ /dev/null @@ -1,12 +0,0 @@ -#include "pinmux.h" - -void stm32_configure_pin(stm32_pin_t pin, stm32_pin_function_t function) { -// GPIOE = pin.group; -// high_or_low = pin.number > 8 ? high : low; - -// alt_fun_number = AlternateFunctions[pin][function]; - // Step 1 -> Figure the Alternate Function (1,2,3,4) - // Step 2 -> Grab the mode register -// GPIO_AFRH(GPIOE)->AFRH12 = GPIO_AF_AF5; -} - diff --git a/platform/stm32f429/pinmux.h b/platform/stm32f429/pinmux.h deleted file mode 100644 index 203bd51f1..000000000 --- a/platform/stm32f429/pinmux.h +++ /dev/null @@ -1,76 +0,0 @@ -#ifndef STM32F429_PINMUX_H -#define STM32F429_PINMUX_H 1 - -#include "gpio.h" - -/* How to use ? - * - * configure_pin(PB11, TIM2_CH4); - * That's it! - * Who uses this? - * platform/spi for example: - * spi_init(SPI2) - * -> NO. BAD IDEA. PINMUX has nothing to do with SPI per-se. */ - -/* Note that the table is pretty large - * Not using it in production might be an idea. - * Just don't use "stm32_configure_pin", but address registers manually - * and the linker will do its job. */ - -typedef enum { - STM32_BUS_SYS, - STM32_BUS_TIM1, - STM32_BUS_TIM2, - STM32_BUS_TIM3, - STM32_BUS_TIM4, - STM32_BUS_TIM5, - STM32_BUS_TIM8, - STM32_BUS_TIM9, - STM32_BUS_TIM10, - STM32_BUS_TIM11, - STM32_BUS_TIM12, - STM32_BUS_TIM13, - STM32_BUS_SPI1, - STM32_BUS_SPI2, - STM32_BUS_SPI3 -} stm32_bus_t; - -typedef enum { - SPI_WIRE_NSS = 0, - SPI_WIRE_SCK = 1, - SPI_WIRE_MISO = 2, - SPI_WIRE_MOSI = 3, - - USART_WIRE_CK = 0, - USART_WIRE_RX = 1, - USART_WIRE_TX = 2, - USART_WIRE_CTS = 3, - USART_WIRE_RTS = 4 -} stm32_wire_t; - -typedef struct { - stm32_bus_t bus:4; // SPI2 - stm32_wire_t wire:4; // MISO -} stm32_pin_function_t; - - -#define STM32_PIN_FUNCTION(b,i,r) (stm32_pin_function_t){.bus = STM32_BUS_##b##i, .wire = b##_WIRE_##r} -#define P(b,i,r) STM32_PIN_FUNCTION(b,i,r) - -stm32_pin_function_t AlternateFunctionMapping[11*16][16] = { - // This comes from the STM32F429 datasheet - // Page 73 to 83 - //{X, P(SPI2,MISO), X, X, X}, - //{{}, {}, {.bus = SPI2, .role = MOSI}}, - {{}, P(SPI,2,MISO),{}}, - {}, -}; - -#undef P - -// Sample call: -// stm32_configure_pin(STM32_PIN(A,10), STM32_PIN_FUNCTION(SPI,2,MISO)); - -void stm32_configure_pin(stm32_pin_t pin, stm32_pin_function_t function); - -#endif diff --git a/platform/stm32f429/registers.h b/platform/stm32f429/registers.h deleted file mode 100644 index 53d567fe8..000000000 --- a/platform/stm32f429/registers.h +++ /dev/null @@ -1,3 +0,0 @@ -#include "registers/gpio.h" -#include "registers/rcc.h" -#include "registers/spi.h" diff --git a/platform/stm32f429/registers/gpio.c b/platform/stm32f429/registers/gpio.c index 3dd52d9ed..26ed72822 100644 --- a/platform/stm32f429/registers/gpio.c +++ b/platform/stm32f429/registers/gpio.c @@ -23,7 +23,7 @@ #define GPIO_AFRL_OFFSET 0x20 #define GPIO_AFRH_OFFSET 0x24 -char * GPIO_REGISTER_ADDRESS(stm32_gpio_group_t gpio_group, int registerOffset) { +char * GPIO_REGISTER_ADDRESS(GPIO_GROUP_t gpio_group, int registerOffset) { char * gpioBaseAddress[11] = { (char *)GPIOA_BASE, (char *)GPIOB_BASE, (char *)GPIOC_BASE, (char *)GPIOD_BASE, (char *)GPIOE_BASE, (char *)GPIOF_BASE, @@ -33,42 +33,42 @@ char * GPIO_REGISTER_ADDRESS(stm32_gpio_group_t gpio_group, int registerOffset) return gpioBaseAddress[gpio_group] + registerOffset; } -GPIO_MODER_t * GPIO_MODER(stm32_gpio_group_t gpio_group) { +GPIO_MODER_t * GPIO_MODER(GPIO_GROUP_t gpio_group) { return (GPIO_MODER_t *)GPIO_REGISTER_ADDRESS(gpio_group, GPIO_MODER_OFFSET); } -GPIO_OTYPER_t * GPIO_OTYPER(stm32_gpio_group_t gpio_group) { +GPIO_OTYPER_t * GPIO_OTYPER(GPIO_GROUP_t gpio_group) { return (GPIO_OTYPER_t *)GPIO_REGISTER_ADDRESS(gpio_group, GPIO_OTYPER_OFFSET); } -GPIO_OSPEEDR_t * GPIO_OSPEEDR(stm32_gpio_group_t gpio_group) { +GPIO_OSPEEDR_t * GPIO_OSPEEDR(GPIO_GROUP_t gpio_group) { return (GPIO_OSPEEDR_t *)GPIO_REGISTER_ADDRESS(gpio_group, GPIO_OSPEEDR_OFFSET); } -GPIO_PUPDR_t * GPIO_PUPDR(stm32_gpio_group_t gpio_group) { +GPIO_PUPDR_t * GPIO_PUPDR(GPIO_GROUP_t gpio_group) { return (GPIO_PUPDR_t *)GPIO_REGISTER_ADDRESS(gpio_group, GPIO_PUPDR_OFFSET); } -GPIO_IDR_t * GPIO_IDR(stm32_gpio_group_t gpio_group) { +GPIO_IDR_t * GPIO_IDR(GPIO_GROUP_t gpio_group) { return (GPIO_IDR_t *)GPIO_REGISTER_ADDRESS(gpio_group, GPIO_IDR_OFFSET); } -GPIO_ODR_t * GPIO_ODR(stm32_gpio_group_t gpio_group) { +GPIO_ODR_t * GPIO_ODR(GPIO_GROUP_t gpio_group) { return (GPIO_ODR_t *)GPIO_REGISTER_ADDRESS(gpio_group, GPIO_ODR_OFFSET); } -GPIO_BSRR_t * GPIO_BSRR(stm32_gpio_group_t gpio_group) { +GPIO_BSRR_t * GPIO_BSRR(GPIO_GROUP_t gpio_group) { return (GPIO_BSRR_t *)GPIO_REGISTER_ADDRESS(gpio_group, GPIO_BSRR_OFFSET); } -GPIO_LCKR_t * GPIO_LCKR(stm32_gpio_group_t gpio_group) { +GPIO_LCKR_t * GPIO_LCKR(GPIO_GROUP_t gpio_group) { return (GPIO_LCKR_t *)GPIO_REGISTER_ADDRESS(gpio_group, GPIO_LCKR_OFFSET); } -GPIO_AFRL_t * GPIO_AFRL(stm32_gpio_group_t gpio_group) { +GPIO_AFRL_t * GPIO_AFRL(GPIO_GROUP_t gpio_group) { return (GPIO_AFRL_t *)GPIO_REGISTER_ADDRESS(gpio_group, GPIO_AFRL_OFFSET); } -GPIO_AFRH_t * GPIO_AFRH(stm32_gpio_group_t gpio_group) { +GPIO_AFRH_t * GPIO_AFRH(GPIO_GROUP_t gpio_group) { return (GPIO_AFRH_t *)GPIO_REGISTER_ADDRESS(gpio_group, GPIO_AFRH_OFFSET); } diff --git a/platform/stm32f429/registers/gpio.h b/platform/stm32f429/registers/gpio.h index 2a20e094b..593743437 100644 --- a/platform/stm32f429/registers/gpio.h +++ b/platform/stm32f429/registers/gpio.h @@ -1,7 +1,19 @@ #ifndef STM32_REGISTERS_GPIO_H #define STM32_REGISTERS_GPIO_H 1 -#include +typedef enum { + GPIOA = 0, + GPIOB = 1, + GPIOC = 2, + GPIOD = 3, + GPIOE = 4, + GPIOF = 5, + GPIOG = 6, + GPIOH = 7, + GPIOI = 8, + GPIOJ = 9, + GPIOK = 10 +} GPIO_GROUP_t; #pragma mark - GPIO port mode registers @@ -31,7 +43,7 @@ typedef struct { GPIO_MODE_t MODER15:2; } GPIO_MODER_t; -GPIO_MODER_t * GPIO_MODER(stm32_gpio_group_t gpio_group); +GPIO_MODER_t * GPIO_MODER(GPIO_GROUP_t gpio_group); #pragma mark - GPIO port output type registers @@ -60,7 +72,7 @@ typedef struct { unsigned int :16; } GPIO_OTYPER_t; -GPIO_OTYPER_t * GPIO_OTYPER(stm32_gpio_group_t gpio_group); +GPIO_OTYPER_t * GPIO_OTYPER(GPIO_GROUP_t gpio_group); #pragma mark - GPIO port output speed registers @@ -90,7 +102,7 @@ typedef struct { GPIO_OSPEED_t OSPEEDR15:2; } GPIO_OSPEEDR_t; -GPIO_OSPEEDR_t * GPIO_OSPEEDR(stm32_gpio_group_t gpio_group); +GPIO_OSPEEDR_t * GPIO_OSPEEDR(GPIO_GROUP_t gpio_group); #pragma mark - GPIO port pull-up/pull-down registers @@ -119,7 +131,7 @@ typedef struct { GPIO_PUPD_t PUPDR15:2; } GPIO_PUPDR_t; -GPIO_PUPDR_t * GPIO_PUPDR(stm32_gpio_group_t gpio_group); +GPIO_PUPDR_t * GPIO_PUPDR(GPIO_GROUP_t gpio_group); #pragma mark - GPIO port input data registers @@ -143,7 +155,7 @@ typedef struct { unsigned int :16; } GPIO_IDR_t; -GPIO_IDR_t * GPIO_IDR(stm32_gpio_group_t gpio_group); +GPIO_IDR_t * GPIO_IDR(GPIO_GROUP_t gpio_group); #pragma mark - GPIO port output data registers @@ -167,7 +179,7 @@ typedef struct { unsigned int :16; } GPIO_ODR_t; -GPIO_ODR_t * GPIO_ODR(stm32_gpio_group_t gpio_group); +GPIO_ODR_t * GPIO_ODR(GPIO_GROUP_t gpio_group); #pragma mark - GPIO port bit set/reset registers @@ -206,7 +218,7 @@ typedef struct { unsigned int BR15:1; } GPIO_BSRR_t; -GPIO_BSRR_t * GPIO_BSRR(stm32_gpio_group_t gpio_group); +GPIO_BSRR_t * GPIO_BSRR(GPIO_GROUP_t gpio_group); #pragma mark - GPIO port configuration lock registers @@ -240,7 +252,7 @@ typedef struct { GPIO_LCK_KEY_t LCKK:1; } GPIO_LCKR_t; -GPIO_LCKR_t * GPIO_LCKR(stm32_gpio_group_t gpio_group); +GPIO_LCKR_t * GPIO_LCKR(GPIO_GROUP_t gpio_group); #pragma mark - GPIO port alternate function registers @@ -285,7 +297,7 @@ typedef struct { GPIO_AF_t AFRH15:4; } GPIO_AFRH_t; -GPIO_AFRL_t * GPIO_AFRL(stm32_gpio_group_t gpio_group); -GPIO_AFRH_t * GPIO_AFRH(stm32_gpio_group_t gpio_group); +GPIO_AFRL_t * GPIO_AFRL(GPIO_GROUP_t gpio_group); +GPIO_AFRH_t * GPIO_AFRH(GPIO_GROUP_t gpio_group); #endif diff --git a/platform/stm32f429/registers/spi.c b/platform/stm32f429/registers/spi.c index 2e2f068ec..d8b46f56b 100644 --- a/platform/stm32f429/registers/spi.c +++ b/platform/stm32f429/registers/spi.c @@ -23,10 +23,10 @@ SPI_CR1_t * SPI_CR1(SPI_t spi) { return (SPI_CR1_t *)SPI_REGISTER_ADDRESS(spi, SPI_CR1_OFFSET); } -SPI_SR_t * SPI_SR(SPI_t spi) { +volatile 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) { +volatile SPI_DR_t * SPI_DR(SPI_t spi) { return (SPI_DR_t *)SPI_REGISTER_ADDRESS(spi, SPI_DR_OFFSET); } diff --git a/platform/stm32f429/registers/spi.h b/platform/stm32f429/registers/spi.h index 96c82880a..64832bace 100644 --- a/platform/stm32f429/registers/spi.h +++ b/platform/stm32f429/registers/spi.h @@ -64,11 +64,11 @@ typedef struct { unsigned int :7; } SPI_SR_t; -SPI_SR_t * SPI_SR(SPI_t spi); +volatile 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); +volatile SPI_DR_t * SPI_DR(SPI_t spi); #endif diff --git a/platform/stm32f429/spi.c b/platform/stm32f429/spi.c deleted file mode 100644 index becfd42b1..000000000 --- a/platform/stm32f429/spi.c +++ /dev/null @@ -1,13 +0,0 @@ -#include "spi.h" - -// pin mapping -// -// Give a port number: e.g. SPI2 -// and a pinmatch. e.g "SPI1_SCK -> PB3" -// and obtain an alternate function -// Actually, this should be done elsewhere... - - -void spi_init(spi_port_t * port) { - // Do shit! -} diff --git a/platform/stm32f429/spi.h b/platform/stm32f429/spi.h deleted file mode 100644 index fdbd0773f..000000000 --- a/platform/stm32f429/spi.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef STM32F429_SPI_H -#define STM32F429_SPI_H 1 - -#include -#include - -struct spi_port { - struct { - SPI_CR1_t controlRegister1; - // SPI_CR2_t controlRegister1; - } config; - struct { - int b; - } state; -}; - -#endif diff --git a/src/lcd_spi.c b/src/lcd_spi.c deleted file mode 100644 index 6c80d0dad..000000000 --- a/src/lcd_spi.c +++ /dev/null @@ -1,174 +0,0 @@ -#include -#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 Discovery board has the IM[0-3] pins of the LCD controller - * connected to low, high, high, low = 0b0110. (UM1670 p. 33). - * This tells the LCD controller to expect data this way: - * "4 wire, 8-bit serial, SDA = In/out" - * See ILI9341 p. 63 - * - * Now how are the LCD pins connected to the MCU ones? - * The Discovery board doc says this: - * MCU pin - 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); - } -} -/* -struct spi_port { - // Private data: - .config = { - }, - .state = { - } -}; - -// Public API, private impl. -spi_init(); -spi_write(); -*/ -int main(int argc, char * argv[]) { - - spi_port_t my_spi_port = { - .config = { - .controlRegister1 = { - .BIDIMODE = 1, - .BIDIOE = 1, - .MSTR = 1, - .DFF = SPI_DFF_16_BITS, - .CPOL = 0, - .BR = SPI_BR_DIV_256, - .SSM = 1, - .SSI = 1, - .SPE = 1 - } - } - }; - spi_init(&my_spi_port); - - /* - // Code we'd like to write: - - spi_port my_spi_port; - spi_init(&my_spi_port); - - ili9431 lcd_panel = { - .port = my_spi_port - }; - - ili9431_init(&lcd_panel); - lcd_panel.clear(); - lcd_panel.setGammaCurve(); - - char * fb = lcd_panel.framebuffer; - - for (int i=0;i<100;i++) { - *fb[i] = 1; - } - -*/ - - - - // 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 : Set the GPIO pin C2 as output - - RCC_AHB1ENR->GPIOCEN = 1; - GPIO_MODER(GPIOC)->MODER2 = GPIO_MODE_OUTPUT; - - RCC_AHB1ENR->GPIOCEN = 1; - GPIO_MODER(GPIOC)->MODER2 = GPIO_MODE_OUTPUT; - // From now on, we'll control pin C2 with - // GPIO_ODR(GPIOC)->ODR2 = desiredValue; - - // 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 - } -}