diff options
| author | Victor Mignot <victor@vmignot.fr> | 2026-02-02 20:20:08 +0100 |
|---|---|---|
| committer | Victor Mignot <victor@vmignot.fr> | 2026-02-06 14:50:37 +0100 |
| commit | 719538162cd390963b3ac8f2965a3e6546162b3b (patch) | |
| tree | 6a291ffdb67cb530ce42b2c3af0d5f4e67cd8dc8 | |
| parent | f19ca61f48710fab019f39bb87bf6fb15f4ae7da (diff) | |
| download | nanji-719538162cd390963b3ac8f2965a3e6546162b3b.tar.gz | |
[WIP] nrf52832: add interface for SPI Master devices
| -rw-r--r-- | src/spi.c | 125 | ||||
| -rw-r--r-- | src/spi.h | 45 |
2 files changed, 170 insertions, 0 deletions
diff --git a/src/spi.c b/src/spi.c new file mode 100644 index 0000000..8acbf19 --- /dev/null +++ b/src/spi.c @@ -0,0 +1,125 @@ +#include "spi.h" +#include "gpio.h" +#include "register.h" + +#define WRITE_SPI_REG(spi, reg, value) (WRITE_REGISTER(spi_base_addresses[spi], reg, value)) +#define READ_SPI_REG(spi, reg) (READ_REGISTER(spi_base_addresses[spi], reg)) + +enum spi_register { + TASKS_START = 0x10, + TASKS_STOP = 0x14, + TASKS_SUSPEND = 0x1c, + TASKS_RESUME = 0x20, + EVENTS_STOPPED = 0x104, + EVENTS_ENDRX = 0x110, + EVENTS_END = 0x118, + EVENTS_ENDTX = 0x120, + EVENTS_STARTED = 0x14c, + SHORTS = 0x200, + INTENSET = 0x304, + INTENCLR = 0x308, + ENABLE = 0x500, + PSEL_SCK = 0x508, + PSEL_MOSI = 0x50c, + PSEL_MISO = 0x510, + FREQUENCY = 0x524, + RXD_PTR = 0x534, + RXD_MAXCNT = 0x538, + RXD_AMOUNT = 0x53c, + RXD_LIST = 0x540, + TXD_PTR = 0x544, + TXD_MAXCNT = 0x548, + TXD_AMOUNT = 0x54c, + TXD_LIST = 0x550, + CONFIG = 0x544, + ORC = 0x5c0, +}; + +static const hwaddr spi_base_addresses[] = { + [SPI_0] = 0x40003000, + [SPI_1] = 0x40004000, + [SPI_2] = 0x40023000, +}; + +static const u32 frequency_register_values[] = { + [K125] = 0x02000000, + [K250] = 0x04000000, + [K500] = 0x08000000, + [M1] = 0x10000000, + [M2] = 0x20000000, + [M4] = 0x40000000, + [M8] = 0x80000000, +}; + +void spi_master_init(enum spi_interface spi, enum gpio_pin clock, enum gpio_pin mosi, enum gpio_pin miso, enum spi_bits_order order, enum spi_clock_polarity polarity, enum spi_clock_phase phase, enum spi_frequency frequency, char overread_char) { + /* Setup GPIO pins */ + gpio_output_pin_init(clock, S0S1); + WRITE_SPI_REG(spi, PSEL_SCK, (0xffffffff >> 1) & (0xffffffe0 | clock)); + gpio_output_pin_init(mosi, S0S1); + WRITE_SPI_REG(spi, PSEL_MOSI, (0xffffffff >> 1) & (0xffffffe0 | mosi)); + gpio_input_pin_init(miso, PULL_DOWN, HIGH); + WRITE_SPI_REG(spi, PSEL_MISO, (0xffffffff >> 1) & (0xffffffe0 | miso)); + + /* Configure communication behaviour */ + u32 spi_config = 0x0; + spi_config |= order; + spi_config |= phase << 1; + spi_config |= polarity << 2; + WRITE_SPI_REG(spi, CONFIG, spi_config); + + WRITE_SPI_REG(spi, RXD_MAXCNT, MAX_TRANSFER_SIZE); + WRITE_SPI_REG(spi, TXD_MAXCNT, MAX_TRANSFER_SIZE); + WRITE_SPI_REG(spi, FREQUENCY, frequency_register_values[frequency]); + WRITE_SPI_REG(spi, ORC, overread_char); + + /* Enable SPI Master */ + WRITE_SPI_REG(spi, ENABLE, 0x7); +} + +u8 spi_master_transfer(enum spi_interface spi, u8 tx_size, u8 tx[], u8 rx_size, u8 rx[]) { + u32 events_started_reg = 0; + u32 events_end_reg = 0; + + WRITE_SPI_REG(spi, RXD_MAXCNT, rx_size & 0xff); + WRITE_SPI_REG(spi, TXD_MAXCNT, tx_size & 0xff); + WRITE_SPI_REG(spi, RXD_PTR, (hwaddr) rx); + WRITE_SPI_REG(spi, TXD_PTR, (hwaddr) tx); + + WRITE_SPI_REG(spi, TASKS_START, 0x1); + do { + events_started_reg = READ_SPI_REG(spi, EVENTS_STARTED); + } while (events_started_reg == 0); + + do { + events_end_reg = READ_SPI_REG(spi, EVENTS_END); + } while (events_end_reg == 0); + + return 0; +} + +void spi_master_stop(enum spi_interface spi, enum gpio_pin clock, enum gpio_pin mosi, enum gpio_pin miso) { + u32 events_stopped_reg = 0; + + WRITE_SPI_REG(spi, TASKS_STOP, 0x1); + do { + events_stopped_reg = READ_SPI_REG(spi, EVENTS_STOPPED); + } while (events_stopped_reg == 0); + + /* Disable SPI*/ + WRITE_SPI_REG(spi, ENABLE, 0x0); + + /* Set configuration registers to reset values */ + WRITE_SPI_REG(spi, CONFIG, 0x0); + WRITE_SPI_REG(spi, RXD_MAXCNT, 0x0); + WRITE_SPI_REG(spi, TXD_MAXCNT, 0x0); + WRITE_SPI_REG(spi, FREQUENCY, frequency_register_values[K250]); + WRITE_SPI_REG(spi, ORC, 0x0); + + /* Free GPIO pins */ + WRITE_SPI_REG(spi, PSEL_SCK, 0xffffffff); + gpio_pin_disable(clock); + WRITE_SPI_REG(spi, PSEL_MOSI, 0xffffffff); + gpio_pin_disable(mosi); + WRITE_SPI_REG(spi, PSEL_MISO, 0xffffffff); + gpio_pin_disable(miso); +} diff --git a/src/spi.h b/src/spi.h new file mode 100644 index 0000000..b076bcb --- /dev/null +++ b/src/spi.h @@ -0,0 +1,45 @@ +#ifndef SPI_H +#define SPI_H + +#include "gpio.h" + +#define MAX_TRANSFER_SIZE 256 + +enum spi_interface { + SPI_0, + SPI_1, + SPI_2, +}; + +enum spi_frequency { + K125, + K250, + K500, + M1, + M2, + M4, + M8, +}; + +enum spi_clock_polarity { + ACTIVE_HIGH = 0, + ACTIVE_LOW = 1, +}; + +enum spi_clock_phase { + LEADING = 0, + TRAILING = 1, +}; + +enum spi_bits_order { + MSB_FIRST = 0, + LSB_FIRST = 0, +}; + +void spi_master_init(enum spi_interface spi, enum gpio_pin clock, enum gpio_pin mosi, enum gpio_pin miso, enum spi_bits_order order, enum spi_clock_polarity polarity, enum spi_clock_phase phase, enum spi_frequency frequency, char overread_char); + +u8 spi_master_transfer(enum spi_interface spi, u8 tx_size, u8 tx[], u8 rx_size, u8 rx[]); + +void spi_master_stop(enum spi_interface spi, enum gpio_pin clock, enum gpio_pin mosi, enum gpio_pin miso); + +#endif |
