Start enabling the LTDC

This commit is contained in:
Romain Goyet
2015-05-09 18:25:38 +02:00
parent e4bbd86719
commit 32c094570b
10 changed files with 546 additions and 318 deletions

View File

@@ -18,7 +18,8 @@ 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
objs += platform/stm32f429/boot/isr.o
#platform/stm32f429/registers/gpio.o platform/stm32f429/registers/rcc.o platform/stm32f429/registers/spi.o platform/stm32f429/registers/ltdc.o
objs += platform/stm32f429/init.o platform/stm32f429/init_lcd.o
objs += platform/ili9341/ili9341.o

View File

@@ -23,24 +23,16 @@
* That's wat ST says in stm32f429i_discovery_lcd.c.
*/
#include "registers/rcc.h"
/*#include "registers/rcc.h"
#include "registers/gpio.h"
#include "registers/spi.h"
#include "registers/ltdc.h"*/
#include "registers.h"
#include <platform/ili9341/ili9341.h>
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();
static void init_spi_interface();
static void init_rgb_interface();
static void init_panel();
void init_lcd() {
/* This routine is responsible for initializing the LCD panel.
@@ -48,107 +40,170 @@ void init_lcd() {
* 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();
init_spi_interface();
/* According to our GPIO config, we send commands to the LCD panel over SPI on
* port SPI5. Let's configure it. */
init_lcd_spi();
init_rgb_interface();
/* configure display */
init_lcd_panel();
/* Last but not least */
//TODO: init_lcd_dma();
init_panel();
}
#pragma mark - GPIO initialization
// SPI interface
static void init_spi_gpios();
static void init_spi_port();
static void init_spi_interface() {
init_spi_gpios();
init_spi_port();
}
static void init_spi_gpios() {
// The LCD panel is connected on GPIO pins. Let's configure them
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;
}
RCC_AHB1ENR |= (GPIOCEN | GPIODEN | GPIOFEN);
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;
REGISTER_SET_VALUE(GPIO_MODER(GPIOC), MODER(2), GPIO_MODE_OUTPUT);
REGISTER_SET_VALUE(GPIO_MODER(GPIOD), MODER(13), 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;
REGISTER_SET_VALUE(GPIO_MODER(GPIOF), MODER(7), GPIO_MODE_ALTERNATE_FUNCTION);
REGISTER_SET_VALUE(GPIO_MODER(GPIOF), MODER(9), 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
*/
REGISTER_SET_VALUE(GPIO_AFRL(GPIOF), AFR(7), 5); // Pin 7 is in the "low" register
REGISTER_SET_VALUE(GPIO_AFRH(GPIOF), AFR(9), 5); // 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() {
static void init_spi_port() {
// Enable the SPI5 clock (SPI5 lives on the APB2 bus)
RCC_APB2ENR->SPI5EN = 1;
RCC_APB2ENR |= SPI5EN;
// 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
};
SPI_CR1(SPI5) = (SPI_BIDIMODE | SPI_BIDIOE | SPI_MSTR | SPI_DFF_8_BITS | SPI_BR(SPI_BR_DIV_2) | SPI_SSM | SPI_SSI | SPI_SPE);
}
// RGB interface
static void init_rgb_gpios();
static void init_rgb_clocks();
static void init_rgb_interface() {
init_rgb_gpios();
init_rgb_clocks();
}
struct gpio_pin {
char group;
char number;
};
#define RGB_PIN_COUNT 77
struct gpio_pin rgb_pins[RGB_PIN_COUNT] = {
{GPIOA, 3}, {GPIOA, 4}, {GPIOA, 6}, {GPIOA, 8}, {GPIOA, 11}, {GPIOA, 12},
{GPIOB, 8}, {GPIOB, 9}, {GPIOB, 10}, {GPIOB, 11},
{GPIOC, 6}, {GPIOC, 7}, {GPIOC, 10},
{GPIOD, 3}, {GPIOD, 6}, {GPIOD, 10},
{GPIOE, 4}, {GPIOE, 5}, {GPIOE, 6}, {GPIOE, 11}, {GPIOE, 12}, {GPIOE, 13},
{GPIOE, 14}, {GPIOE, 15}, {GPIOF, 10},
{GPIOG, 6}, {GPIOG, 7}, {GPIOG, 10}, {GPIOG, 11}, {GPIOG, 12},
{GPIOH, 2}, {GPIOH, 3}, {GPIOH, 8}, {GPIOH, 9}, {GPIOH, 10}, {GPIOH, 11},
{GPIOH, 12}, {GPIOH, 13}, {GPIOH, 14}, {GPIOH, 15},
{GPIOI, 0}, {GPIOI, 1}, {GPIOI, 2}, {GPIOI, 4}, {GPIOI, 5}, {GPIOI, 6},
{GPIOI, 7}, {GPIOI, 9}, {GPIOI, 10}, {GPIOI, 12}, {GPIOI, 13}, {GPIOI, 14},
{GPIOI, 15},
{GPIOJ, 0}, {GPIOJ, 1}, {GPIOJ, 2}, {GPIOJ, 3}, {GPIOJ, 4}, {GPIOJ, 5},
{GPIOJ, 6}, {GPIOJ, 7}, {GPIOJ, 8}, {GPIOJ, 9}, {GPIOJ, 10}, {GPIOJ, 11},
{GPIOJ, 12}, {GPIOJ, 13}, {GPIOJ, 14}, {GPIOJ, 15}, {GPIOK, 0}, {GPIOK, 1},
{GPIOK, 2}, {GPIOK, 3}, {GPIOK, 4}, {GPIOK, 5}, {GPIOK, 6}, {GPIOK, 7}
};
static void init_rgb_gpios() {
// The RGB interface uses GPIO pins in all groups!
RCC_AHB1ENR |= (
GPIOAEN | GPIOBEN | GPIOCEN | GPIODEN |
GPIOEEN | GPIOFEN | GPIOGEN | GPIOHEN |
GPIOIEN | GPIOJEN | GPIOJEN
);
// The LTDC is always mapped to AF14
for (int i=0; i<RGB_PIN_COUNT; i++) {
struct gpio_pin * pin = rgb_pins+i;
if (pin->number > 7) {
REGISTER_SET_VALUE(GPIO_AFRL(pin->group), AFR(pin->number), 14);
} else {
REGISTER_SET_VALUE(GPIO_AFRH(pin->group), AFR(pin->number), 14);
}
}
//FIXME: Apprently DMA should be enabled?
RCC_AHB1ENR |= (DMA1EN | DMA2EN | DMA2DEN);
}
static void init_rgb_clocks() {
// STEP 1 : Enable the LTDC clock in the RCC register
//
// TFT-LCD lives on the APB2 bus, so we'll want to play with RCC_APB2ENR
// (RCC stands for "Reset and Clock Control)
RCC_APB2ENR |= LTDCEN;
// STEP 2 : Configure the required Pixel clock following the panel datasheet
//
// We're setting PLLSAIN = 192, PLLSAIR = 4, and PLLSAIDIVR = 0x2 meaning divide-by-8
// So with a f(PLLSAI clock input) = 1MHz
// we get f(VCO clock) = PLLSAIN * fPPLSAI = 192 MHz
// and f(PLL LCD clock) = fVCO / PLLSAIR = 48 MHz
// and eventually f(LCD_CLK) = fPLLLCD/8 = 6 MHz
int pllsain = 192;
int pllsair = 4;
int pllsaidivr = 0x2; // This value means "divide by 8"
//FIXME: A macro here
REGISTER_SET_VALUE(RCC_PLLSAICFGR, PLLSAIR, pllsair);
REGISTER_SET_VALUE(RCC_PLLSAICFGR, PLLSAIN, pllsain);
REGISTER_SET_VALUE(RCC_DCKCFGR, PLLSAIDIVR, pllsaidivr);
// Now let's enable the PLL/PLLSAI clocks
RCC_CR |= (PLLSAION | PLLON);
}
// Panel
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);
static ili9341_t panel = {
.chip_select_pin_write = gpio_c2_write,
.data_command_pin_write = gpio_d13_write,
.spi_write = spi_5_write
};
static void init_panel() {
ili9341_initialize(&panel);
}
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) {
while (SPI_SR(SPI5) & SPI_BSY) {
}
for (size_t i=0; i<size; i++) {
*spi_data_register = data[i];
while (spi_status->TXE == 0) {
SPI_DR(SPI5) = data[i];
while (!(SPI_SR(SPI5) & SPI_TXE)) {
}
}
while (spi_status->BSY != 0) {
while (SPI_SR(SPI5) & SPI_BSY) {
}
}
#pragma mark - Panel initialization
void init_lcd_panel() {
ili9341_initialize(&sPanel);
void gpio_c2_write(bool pin_state) {
REGISTER_SET_VALUE(GPIO_ODR(GPIOC), ODR(2), pin_state);
}
void gpio_d13_write(bool pin_state) {
REGISTER_SET_VALUE(GPIO_ODR(GPIOD), ODR(13), pin_state);
}

View File

@@ -0,0 +1,22 @@
#include <stdint.h>
/* Example usage:
*
* REGISTER_SET_VALUE(RCC_CR, HSITRIM, 37);
* RCC_CR = (HSION|HSITRIM_VALUE(15));
* if (RCC_CR & HSIRDY) { }
*/
#define BIT_MASK(high, low) ((((uint32_t)1<<((high)-(low)+1))-1)<<(low))
#define BIT_VALUE(value, high, low) (((value)<<(low))&BIT_MASK(high, low))
#include "registers/rcc.h"
#include "registers/gpio.h"
#include "registers/spi.h"
#define REGISTER_FIELD_MASK(field) (BIT_MASK(HIGH_BIT_##field,LOW_BIT_##field))
#define REGISTER_FIELD_VALUE(field, value) (BIT_VALUE(value,HIGH_BIT_##field,LOW_BIT_##field))
#define REGISTER_SET_VALUE(reg, field, value) (reg = ((reg&(~REGISTER_FIELD_MASK(field)))|REGISTER_FIELD_VALUE(field,value)))
//#define SET(reg, field) (reg |= field)
//#define CLEAR(reg, field) (reg &= ~field)

View File

@@ -1,74 +0,0 @@
#include "gpio.h"
#define GPIOA_BASE 0x40020000
#define GPIOB_BASE 0x40020400
#define GPIOC_BASE 0x40020800
#define GPIOD_BASE 0x40020C00
#define GPIOE_BASE 0x40021000
#define GPIOF_BASE 0x40021400
#define GPIOG_BASE 0x40021800
#define GPIOH_BASE 0x40021C00
#define GPIOI_BASE 0x40022000
#define GPIOJ_BASE 0x40022400
#define GPIOK_BASE 0x40022800
#define GPIO_MODER_OFFSET 0x00
#define GPIO_OTYPER_OFFSET 0x04
#define GPIO_OSPEEDR_OFFSET 0x08
#define GPIO_PUPDR_OFFSET 0x0C
#define GPIO_IDR_OFFSET 0x10
#define GPIO_ODR_OFFSET 0x14
#define GPIO_BSRR_OFFSET 0x18
#define GPIO_LCKR_OFFSET 0x1C
#define GPIO_AFRL_OFFSET 0x20
#define GPIO_AFRH_OFFSET 0x24
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,
(char *)GPIOG_BASE, (char *)GPIOH_BASE, (char *)GPIOI_BASE,
(char *)GPIOJ_BASE, (char *)GPIOK_BASE
};
return gpioBaseAddress[gpio_group] + registerOffset;
}
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(GPIO_GROUP_t gpio_group) {
return (GPIO_OTYPER_t *)GPIO_REGISTER_ADDRESS(gpio_group, GPIO_OTYPER_OFFSET);
}
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(GPIO_GROUP_t gpio_group) {
return (GPIO_PUPDR_t *)GPIO_REGISTER_ADDRESS(gpio_group, GPIO_PUPDR_OFFSET);
}
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(GPIO_GROUP_t gpio_group) {
return (GPIO_ODR_t *)GPIO_REGISTER_ADDRESS(gpio_group, GPIO_ODR_OFFSET);
}
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(GPIO_GROUP_t gpio_group) {
return (GPIO_LCKR_t *)GPIO_REGISTER_ADDRESS(gpio_group, GPIO_LCKR_OFFSET);
}
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(GPIO_GROUP_t gpio_group) {
return (GPIO_AFRH_t *)GPIO_REGISTER_ADDRESS(gpio_group, GPIO_AFRH_OFFSET);
}

View File

@@ -1,6 +1,93 @@
#ifndef STM32_REGISTERS_GPIO_H
#define STM32_REGISTERS_GPIO_H 1
#define GPIO_BASE 0x40020000
#define GPIOA 0
#define GPIOB 1
#define GPIOC 2
#define GPIOD 3
#define GPIOE 4
#define GPIOF 5
#define GPIOG 6
#define GPIOH 7
#define GPIOI 8
#define GPIOJ 9
#define GPIOK 10
#define GPIO_REGISTER_AT(gpio_group,offset) (*(volatile uint32_t *)(GPIO_BASE+(gpio_group*0x400)+offset))
/*
//DELEte me when implementing
#define GPIO_OTYPER_OFFSET 0x04
#define GPIO_OSPEEDR_OFFSET 0x08
#define GPIO_PUPDR_OFFSET 0x0C
#define GPIO_IDR_OFFSET 0x10
#define GPIO_ODR_OFFSET 0x14
#define GPIO_BSRR_OFFSET 0x18
#define GPIO_LCKR_OFFSET 0x1C
#define GPIO_AFRL_OFFSET 0x20
#define GPIO_AFRH_OFFSET 0x24
*/
// GPIO port mode registers
#define GPIO_MODER(gpio_group) GPIO_REGISTER_AT(gpio_group, 0x00)
#define GPIO_MODE_INPUT 0
#define GPIO_MODE_OUTPUT 1
#define GPIO_MODE_ALTERNATE_FUNCTION 2
#define GPIO_MODE_ANALOG 3
#define LOW_BIT_MODER(v) (2*v)
#define HIGH_BIT_MODER(v) (2*v+1)
// GPIO port output data registers
#define GPIO_ODR(gpio_group) GPIO_REGISTER_AT(gpio_group, 0x14)
#define LOW_BIT_ODR(v) (v)
#define HIGH_BIT_ODR(v) (v)
// GPIO port alternate function registers
#define GPIO_AFRL(gpio_group) GPIO_REGISTER_AT(gpio_group, 0x20)
#define GPIO_AFRH(gpio_group) GPIO_REGISTER_AT(gpio_group, 0x24)
#define LOW_BIT_AFR(v) (4*(v%8))
#define HIGH_BIT_AFR(v) (4*(v%8)+3)
#if 0
typedef struct {
GPIO_AF_t AFRL0:4;
GPIO_AF_t AFRL1:4;
GPIO_AF_t AFRL2:4;
GPIO_AF_t AFRL3:4;
GPIO_AF_t AFRL4:4;
GPIO_AF_t AFRL5:4;
GPIO_AF_t AFRL6:4;
GPIO_AF_t AFRL7:4;
} GPIO_AFRL_t;
typedef struct {
GPIO_AF_t AFRH8:4;
GPIO_AF_t AFRH9:4;
GPIO_AF_t AFRH10:4;
GPIO_AF_t AFRH11:4;
GPIO_AF_t AFRH12:4;
GPIO_AF_t AFRH13:4;
GPIO_AF_t AFRH14:4;
GPIO_AF_t AFRH15:4;
} GPIO_AFRH_t;
GPIO_AFRL_t * GPIO_AFRL(GPIO_GROUP_t gpio_group);
GPIO_AFRH_t * GPIO_AFRH(GPIO_GROUP_t gpio_group);
//
typedef enum {
GPIOA = 0,
GPIOB = 1,
@@ -15,6 +102,8 @@ typedef enum {
GPIOK = 10
} GPIO_GROUP_t;
#define
#pragma mark - GPIO port mode registers
typedef enum {
@@ -301,3 +390,5 @@ GPIO_AFRL_t * GPIO_AFRL(GPIO_GROUP_t gpio_group);
GPIO_AFRH_t * GPIO_AFRH(GPIO_GROUP_t gpio_group);
#endif
#endif

View File

@@ -0,0 +1,132 @@
#ifndef STM32_REGISTERS_LTDC_H
#define STM32_REGISTERS_LTDC_H 1
// LCD-TFT Controller
#define LTDC_BASE 0x40016800
#define LTDC_REGISTER_AT(offset) (*(volatile uint32_t *)(LTDC_BASE+offset))
// LTDC Synchronization size configuration register
#define LTDC_SSCR LTDC_REGISTER_AT(0x08)
#define LOW_BIT_VSH 0
#define HIGH_BIT_VSH 10
#define LOW_BIT_HSW 15
#define HIGH_BIT_HSW 27
// LTDC Back porch configuration register
#define LTDC_BPCR LTDC_REGISTER_AT(0x0C)
#define LOW_BIT_AVBP 0
#define HIGH_BIT_AVBP 10
#define LOW_BIT_AHBP 15
#define HIGH_BIT_AHBP 27
#if 0
extern LTDC_BPCR_t * LTDC_BPCR;
typedef struct {
unsigned int AAH:11;
unsigned int :5;
unsigned int AAW:12;
unsigned int :4;
} LTDC_AWCR_t;
extern LTDC_AWCR_t * LTDC_AWCR;
typedef struct {
unsigned int TOTALH:11;
unsigned int :5;
unsigned int TOTALW:12;
unsigned int :4;
} LTDC_TWCR_t;
extern LTDC_TWCR_t * LTDC_TWCR;
typedef struct {
unsigned int LTDCEN:1;
unsigned int :3;
unsigned int DBW:3;
unsigned int :1;
unsigned int DGW:3;
unsigned int :1;
unsigned int DRW:3;
unsigned int :1;
unsigned int DEN:1;
unsigned int :11;
unsigned int PCPOL:1;
unsigned int DEPOL:1;
unsigned int VSPOL:1;
unsigned int HPOL:1;
} LTDC_GCR_t;
extern LTDC_GCR_t * LTDC_GCR;
typedef struct {
unsigned int IMR:1;
unsigned int VBR:1;
unsigned int :30;
} LTDC_SRCR_t;
extern LTDC_SRCR_t * LTDC_SRCR;
typedef struct {
unsigned int BCBLUE:8;
unsigned int BCGREEN:8;
unsigned int BCRED:8;
unsigned int :8;
} LTDC_BCCR_t;
extern LTDC_BCCR_t * LTDC_BCCR;
typedef struct {
unsigned int LIE:1;
unsigned int FUIE:1;
unsigned int TERRIE:1;
unsigned int RRIE:1;
unsigned int :28;
} LTDC_IER_t;
extern LTDC_IER_t * LTDC_IER;
typedef struct {
unsigned int LIF:1;
unsigned int FUIF:1;
unsigned int TERRIF:1;
unsigned int RRIF:1;
unsigned int :28;
} LTDC_ISR_t;
extern LTDC_ISR_t * LTDC_ISR;
typedef struct {
unsigned int CLIF:1;
unsigned int CFUIF:1;
unsigned int CTERRIF:1;
unsigned int CRIF:1;
unsigned int :28;
} LTDC_ICR_t;
extern LTDC_ICR_t * LTDC_ICR;
typedef enum {
LAYER1 = 0,
LAYER2 = 1,
} LTDC_LAYER_t;
typedef struct {
unsigned int LEN:1;
unsigned int COLKEN:1;
unsigned int :2;
unsigned int CLUTEN:1;
unsigned int :27;
} LTDC_LCR_t;
LTDC_LCR_t * LTDC_LCR(LTDC_LAYER_t ltdc_layer);
#endif
#endif

View File

@@ -1,8 +0,0 @@
// The non-inclusion of rcc.h here is voluntary.
// Since we didn't define a type for RCC_AHB1ENR, we cannot implement it here
// If we don't include rcc.h, we declare a "new" symbol which will happen to match...
//#include <registers/rcc.h>
#define RCC_BASE 0x40023800
void * RCC_AHB1ENR = (void *)(RCC_BASE + 0x30);
void * RCC_APB2ENR = (void *)(RCC_BASE + 0x44);

View File

@@ -1,63 +1,112 @@
#ifndef STM32_REGISTERS_RCC_H
#define STM32_REGISTERS_RCC_H 1
/* Sample usage : "RCC_AHB1ENR->GPIOAEN = 1;" will enable the clock on GPIOA.*/
extern struct {
unsigned int GPIOAEN:1;
unsigned int GPIOBEN:1;
unsigned int GPIOCEN:1;
unsigned int GPIODEN:1;
unsigned int GPIOEEN:1;
unsigned int GPIOFEN:1;
unsigned int GPIOGEN:1;
unsigned int GPIOHEN:1;
unsigned int GPIOIEN:1;
unsigned int GPIOJEN:1;
unsigned int GPIOKEN:1;
unsigned int :1;
unsigned int CRCEN:1;
unsigned int :5;
unsigned int BKPSRAMEN:1;
unsigned int :1;
unsigned int CCMDATARAMEN:1;
unsigned int DMA1EN:1;
unsigned int DMA2EN:1;
unsigned int DMA2DEN:1;
unsigned int :1;
unsigned int ETHMACEN:1;
unsigned int ETHMACTXEN:1;
unsigned int ETHMACRXEN:1;
unsigned int ETHMACPTPEN:1;
unsigned int OTGHSEN:1;
unsigned int OTGHSULPIEN:1;
unsigned int :1;
} * RCC_AHB1ENR;
// Reset and clock control
extern struct {
unsigned int TIM1EN:1;
unsigned int TIM8EN:1;
unsigned int :2;
unsigned int USART1EN:1;
unsigned int USART6EN:1;
unsigned int :2;
unsigned int ADC1EN:1;
unsigned int ADC2EN:1;
unsigned int ADC3EN:1;
unsigned int SDIOEN:1;
unsigned int SPI1EN:1;
unsigned int SPI4EN:1;
unsigned int SYSCFGEN:1;
unsigned int :1;
unsigned int TIM9EN:1;
unsigned int TIM10EN:1;
unsigned int TIM11EN:1;
unsigned int :1;
unsigned int SPI5EN:1;
unsigned int SPI6EN:1;
unsigned int SAI1EN:1;
unsigned int :3;
unsigned int LTDCEN:1;
unsigned int :5;
} * RCC_APB2ENR;
#define RCC_BASE 0x40023800
#define RCC_REGISTER_AT(offset) (*(volatile uint32_t *)(RCC_BASE+offset))
// RCC clock control register
#define RCC_CR RCC_REGISTER_AT(0x00)
#define HSION (1<<0)
#define HSIRDY (1<<1)
#define LOW_BIT_HSITRIM 3
#define HIGH_BIT_HSITRIM 7
#define LOW_BIT_HSICAL 8
#define HIGH_BIT_HSICAL 15
#define HSEON (1<<16)
#define HSERDY (1<<17)
#define HSEBYP (1<<18)
#define CSSON (1<<19)
#define PLLON (1<<24)
#define PLLRDY (1<<25)
#define PLLI2SON (1<<26)
#define PLLI2SRDY (1<<27)
#define PLLSAION (1<<28)
#define PLLSAIRDY (1<<29)
// RCC AHB1 peripheral clock enable register
#define RCC_AHB1ENR RCC_REGISTER_AT(0x30)
#define GPIOAEN (1<<0)
#define GPIOBEN (1<<1)
#define GPIOCEN (1<<2)
#define GPIODEN (1<<3)
#define GPIOEEN (1<<4)
#define GPIOFEN (1<<5)
#define GPIOGEN (1<<6)
#define GPIOHEN (1<<7)
#define GPIOIEN (1<<8)
#define GPIOJEN (1<<9)
#define GPIOKEN (1<<10)
#define CRCEN (1<<12)
#define BKPSRAMEN (1<<18)
#define CCMDATARAMEN (1<<20)
#define DMA1EN (1<<21)
#define DMA2EN (1<<22)
#define DMA2DEN (1<<23)
#define ETHMACEN (1<<25)
#define ETHMACTXEN (1<<26)
#define ETHMACRXEN (1<<27)
#define ETHMACPTPEN (1<<28)
#define OTGHSEN (1<<29)
#define OTGHSULPIEN (1<<30)
// RCC APB2 peripheral clock enable register
#define RCC_APB2ENR RCC_REGISTER_AT(0x44)
#define TIM1EN (1<<0)
#define TIM8EN (1<<1)
#define USART1EN (1<<4)
#define USART6EN (1<<5)
#define ADC1 (1<<8)
#define ADC2 (1<<9)
#define ADC3 (1<<10)
#define SDIOEN (1<<11)
#define SPI1EN (1<<12)
#define SPI4EN (1<<13)
#define SYSCFGEN (1<<14)
#define TIM9EN (1<<16)
#define TIM10EN (1<<17)
#define TIM11EN (1<<18)
#define SPI5EN (1<<20)
#define SPI6EN (1<<21)
#define SAI1EN (1<<22)
#define LTDCEN (1<<26)
// RCC PLL configuration register
#define RCC_PLLSAICFGR RCC_REGISTER_AT(0x88)
#define LOW_BIT_PLLSAIN 6
#define HIGH_BIT_PLLSAIN 14
#define RCC_PLLSAIN(v) REGISTER_FIELD_VALUE(PLLSAIN, v)
#define LOW_BIT_PLLSAIQ 24
#define HIGH_BIT_PLLSAIQ 27
#define RCC_PLLSAIQ(v) REGISTER_FIELD_VALUE(PLLSAIQ, v)
#define LOW_BIT_PLLSAIR 28
#define HIGH_BIT_PLLSAIR 30
#define RCC_PLLSAIR(v) REGISTER_FIELD_VALUE(PLLSAIR, v)
// RCC dedicated clock configuration register
#define RCC_DCKCFGR RCC_REGISTER_AT(0x8C)
#define LOW_BIT_PLLIS2DIVQ 0
#define HIGH_BIT_PLLIS2DIVQ 4
#define LOW_BIT_PLLSAIDIVQ 8
#define HIGH_BIT_PLLSAIDIVQ 12
#define LOW_BIT_PLLSAIDIVR 16
#define HIGH_BIT_PLLSAIDIVR 17
#define LOW_BIT_SAI1ASRC 20
#define HIGH_BIT_SAI1ASRC 21
#define LOW_BIT_SAI1BSRC 22
#define HIGH_BIT_SAI1BSRC 23
#define TIMPRE (1<<24)
#endif

View File

@@ -1,32 +0,0 @@
#include "spi.h"
#define SPI1_BASE 0x40013000
#define SPI2_BASE 0x40003800
#define SPI3_BASE 0x40003C00
#define SPI4_BASE 0x40013400
#define SPI5_BASE 0x40015000
#define SPI6_BASE 0x40015400
#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] = {
(char *)SPI1_BASE, (char *)SPI2_BASE, (char *)SPI3_BASE,
(char *)SPI4_BASE, (char *)SPI5_BASE, (char *)SPI6_BASE
};
return spiBaseAddress[spi] + registerOffset;
}
SPI_CR1_t * SPI_CR1(SPI_t spi) {
return (SPI_CR1_t *)SPI_REGISTER_ADDRESS(spi, SPI_CR1_OFFSET);
}
volatile SPI_SR_t * SPI_SR(SPI_t spi) {
return (SPI_SR_t *)SPI_REGISTER_ADDRESS(spi, SPI_SR_OFFSET);
}
volatile SPI_DR_t * SPI_DR(SPI_t spi) {
return (SPI_DR_t *)SPI_REGISTER_ADDRESS(spi, SPI_DR_OFFSET);
}

View File

@@ -1,74 +1,66 @@
#ifndef STM32F429_REGISTERS_SPI_H
#define STM32F429_REGISTERS_SPI_H 1
#include <stdint.h>
// Serial Peripheral Interface registers
typedef enum {
SPI1 = 0,
SPI2 = 1,
SPI3 = 2,
SPI4 = 3,
SPI5 = 4,
SPI6 = 5
} SPI_t;
#define SPI1_BASE 0x40013000
#define SPI2_BASE 0x40003800
#define SPI3_BASE 0x40003C00
#define SPI4_BASE 0x40013400
#define SPI5_BASE 0x40015000
#define SPI6_BASE 0x40015400
#pragma mark - SPI control registers 1
#define SPI_REGISTER_AT(spi_port,offset) (*(volatile uint16_t *)(spi_port##_BASE+offset))
typedef enum {
SPI_BR_DIV_2 = 0,
SPI_BR_DIV_4 = 1,
SPI_BR_DIV_8 = 2,
SPI_BR_DIV_16 = 3,
SPI_BR_DIV_32 = 4,
SPI_BR_DIV_64 = 5,
SPI_BR_DIV_128 = 6,
SPI_BR_DIV_256 = 7
} SPI_BR_t;
// SPI control registers 1
typedef enum {
SPI_DFF_8_BITS = 0,
SPI_DFF_16_BITS = 1
} SPI_DFF_t;
#define SPI_CR1(spi_port) SPI_REGISTER_AT(spi_port, 0x00)
typedef struct {
unsigned int CPHA:1;
unsigned int CPOL:1;
unsigned int MSTR:1;
SPI_BR_t BR:3;
unsigned int SPE:1;
unsigned int LSBFIRST:1;
unsigned int SSI:1;
unsigned int SSM:1;
unsigned int RXONLY:1;
SPI_DFF_t DFF:1;
unsigned int CRCNEXT:1;
unsigned int CRCEN:1;
unsigned int BIDIOE:1;
unsigned int BIDIMODE:1;
} SPI_CR1_t;
#define SPI_BR_DIV_2 0
#define SPI_BR_DIV_4 1
#define SPI_BR_DIV_8 2
#define SPI_BR_DIV_16 3
#define SPI_BR_DIV_32 4
#define SPI_BR_DIV_64 5
#define SPI_BR_DIV_128 6
#define SPI_BR_DIV_256 7
SPI_CR1_t * SPI_CR1(SPI_t spi);
#define SPI_DFF_8_BITS 0
#define SPI_DFF_16_BITS 1
#pragma mark - SPI status registers
#define SPI_CPHA (1<<0)
#define SPI_CPOL (1<<1)
#define SPI_MSTR (1<<2)
#define LOW_BIT_SPI_BR 3
#define HIGH_BIT_SPI_BR 5
#define SPI_BR(v) REGISTER_FIELD_VALUE(SPI_BR, v)
#define SPI_SPE (1<<6)
#define SPI_LSBFIRST (1<<7)
#define SPI_SSI (1<<8)
#define SPI_SSM (1<<9)
#define SPI_RXONLY (1<<10)
#define SPI_DFF (1<<11)
#define SPI_CRCNEXT (1<<12)
#define SPI_CRCEN (1<<13)
#define SPI_BIDIOE (1<<14)
#define SPI_BIDIMODE (1<<15)
typedef struct {
unsigned int RXNE:1;
unsigned int TXE:1;
unsigned int CHSIDE:1;
unsigned int UDR:1;
unsigned int CRCERR:1;
unsigned int MODF:1;
unsigned int OVR:1;
unsigned int BSY:1;
unsigned int FRE:1;
unsigned int :7;
} SPI_SR_t;
// SPI status registers
volatile SPI_SR_t * SPI_SR(SPI_t spi);
#define SPI_SR(spi_port) SPI_REGISTER_AT(spi_port, 0x08)
#pragma mark - SPI data registers
#define SPI_RXNE (1<<0)
#define SPI_TXE (1<<1)
#define SPI_CHSIDE (1<<2)
#define SPI_UDR (1<<3)
#define SPI_CRCERR (1<<4)
#define SPI_MODF (1<<5)
#define SPI_OVR (1<<6)
#define SPI_BSY (1<<7)
#define SPI_FRE (1<<8)
typedef uint16_t SPI_DR_t;
volatile SPI_DR_t * SPI_DR(SPI_t spi);
// SPI data registers
#define SPI_DR(spi_port) SPI_REGISTER_AT(spi_port, 0x0C)
#endif