lpc176x: Add support for ssp1 (#2393)

Signed-off-by: Andrey Kovalev <aka@pxe.ru>
This commit is contained in:
akatik 2020-01-15 07:06:29 +04:00 committed by KevinOConnor
parent b70416167b
commit b3c3b61387
3 changed files with 39 additions and 22 deletions

View File

@ -30,6 +30,7 @@ uint16_t gpio_adc_read(struct gpio_adc g);
void gpio_adc_cancel_sample(struct gpio_adc g); void gpio_adc_cancel_sample(struct gpio_adc g);
struct spi_config { struct spi_config {
void *spi;
uint32_t cr0, cpsr; uint32_t cr0, cpsr;
}; };
struct spi_config spi_setup(uint32_t bus, uint8_t mode, uint32_t rate); struct spi_config spi_setup(uint32_t bus, uint8_t mode, uint32_t rate);

View File

@ -10,6 +10,7 @@
#define PCLK_TIMER0 1 #define PCLK_TIMER0 1
#define PCLK_UART0 3 #define PCLK_UART0 3
#define PCLK_SSP1 10
#define PCLK_ADC 12 #define PCLK_ADC 12
#define PCLK_I2C1 19 #define PCLK_I2C1 19
#define PCLK_SSP0 21 #define PCLK_SSP0 21

View File

@ -9,42 +9,55 @@
#include "internal.h" // gpio_peripheral #include "internal.h" // gpio_peripheral
#include "sched.h" // sched_shutdown #include "sched.h" // sched_shutdown
struct spi_info {
LPC_SSP_TypeDef *spi;
uint8_t miso_pin, mosi_pin, sck_pin, pclk;
};
DECL_ENUMERATION("spi_bus", "ssp0", 0); DECL_ENUMERATION("spi_bus", "ssp0", 0);
DECL_CONSTANT_STR("BUS_PINS_ssp0", "P0.17,P0.18,P0.15"); DECL_CONSTANT_STR("BUS_PINS_ssp0", "P0.17,P0.18,P0.15");
DECL_ENUMERATION("spi_bus", "ssp1", 1);
DECL_CONSTANT_STR("BUS_PINS_ssp1", "P0.8,P0.9,P0.7");
static const struct spi_info spi_bus[] = {
{ LPC_SSP0, GPIO(0, 17), GPIO(0, 18), GPIO(0, 15), PCLK_SSP0 },
{ LPC_SSP1, GPIO(0, 8), GPIO(0, 9), GPIO(0, 7), PCLK_SSP1 },
};
static void static void
spi_init(void) spi_init(uint32_t bus)
{ {
static int have_run_init; static int have_run_init[ARRAY_SIZE(spi_bus)];
if (have_run_init) if (have_run_init[bus])
return; return;
have_run_init = 1; have_run_init[bus] = 1;
// Configure MISO0, MOSI0, SCK0 pins // Configure MISO0, MOSI0, SCK0 pins
gpio_peripheral(GPIO(0, 17), 2, 0); gpio_peripheral(spi_bus[bus].miso_pin, 2, 0);
gpio_peripheral(GPIO(0, 18), 2, 0); gpio_peripheral(spi_bus[bus].mosi_pin, 2, 0);
gpio_peripheral(GPIO(0, 15), 2, 0); gpio_peripheral(spi_bus[bus].sck_pin, 2, 0);
// Setup clock // Setup clock
enable_pclock(PCLK_SSP0); enable_pclock(spi_bus[bus].pclk);
// Set initial registers // Set initial registers
LPC_SSP0->CR0 = 0x07; LPC_SSP_TypeDef *spi = spi_bus[bus].spi;
LPC_SSP0->CPSR = 254; spi->CR0 = 0x07;
LPC_SSP0->CR1 = 1<<1; spi->CPSR = 254;
spi->CR1 = 1<<1;
} }
struct spi_config struct spi_config
spi_setup(uint32_t bus, uint8_t mode, uint32_t rate) spi_setup(uint32_t bus, uint8_t mode, uint32_t rate)
{ {
if (bus) if (bus >= ARRAY_SIZE(spi_bus))
shutdown("Invalid spi_setup parameters"); shutdown("Invalid spi_setup parameters");
// Make sure bus is enabled // Make sure bus is enabled
spi_init(); spi_init(bus);
// Setup clock rate and mode // Setup clock rate and mode
struct spi_config res = {0, 0}; struct spi_config res = {spi_bus[bus].spi, 0, 0};
uint32_t pclk = SystemCoreClock; uint32_t pclk = SystemCoreClock;
uint32_t div = DIV_ROUND_UP(pclk/2, rate) << 1; uint32_t div = DIV_ROUND_UP(pclk/2, rate) << 1;
res.cpsr = div < 2 ? 2 : (div > 254 ? 254 : div); res.cpsr = div < 2 ? 2 : (div > 254 ? 254 : div);
@ -56,31 +69,33 @@ spi_setup(uint32_t bus, uint8_t mode, uint32_t rate)
void void
spi_prepare(struct spi_config config) spi_prepare(struct spi_config config)
{ {
LPC_SSP0->CR0 = config.cr0; LPC_SSP_TypeDef *spi = config.spi;
LPC_SSP0->CPSR = config.cpsr; spi->CR0 = config.cr0;
spi->CPSR = config.cpsr;
} }
void void
spi_transfer(struct spi_config config, uint8_t receive_data spi_transfer(struct spi_config config, uint8_t receive_data
, uint8_t len, uint8_t *data) , uint8_t len, uint8_t *data)
{ {
LPC_SSP_TypeDef *spi = config.spi;
if (receive_data) { if (receive_data) {
while (len--) { while (len--) {
LPC_SSP0->DR = *data; spi->DR = *data;
// wait for read data to be ready // wait for read data to be ready
while (!(LPC_SSP0->SR & (1<<2))) while (!(spi->SR & (1<<2)))
; ;
// get data // get data
*data++ = LPC_SSP0->DR; *data++ = spi->DR;
} }
} else { } else {
while (len--) { while (len--) {
LPC_SSP0->DR = *data++; spi->DR = *data++;
// wait for read data to be ready // wait for read data to be ready
while (!(LPC_SSP0->SR & (1<<2))) while (!(spi->SR & (1<<2)))
; ;
// read data (to clear receive fifo) // read data (to clear receive fifo)
LPC_SSP0->DR; spi->DR;
} }
} }
} }