Data Structures | |
struct | SPI_REGISTERS_T |
the struct we use so we can address registers using field names More... | |
struct | tr_hal_spi_settings_t |
Typedefs | |
typedef void(* | tr_hal_spi_receive_callback_t) (uint8_t num_received_bytes, uint8_t *byte_buffer) |
typedef void(* | tr_hal_spi_event_callback_t) (tr_hal_spi_id_t spi_id, uint32_t event_bitmask) |
Enumerations | |
enum | tr_hal_spi_id_t { SPI_0_ID = 0 , SPI_1_ID = 1 } |
enum | tr_hal_spi_mode_t { TR_HAL_SPI_MODE_NORMAL = 0 , TR_HAL_SPI_MODE_DUAL = 2 , TR_HAL_SPI_MODE_QUAD = 3 } |
Normal SPI vs Dual SPI vs Quad SPI modes. More... | |
enum | tr_hal_spi_bit_size_t { TR_HAL_SPI_BIT_SIZE_8 = 0x10 , TR_HAL_SPI_BIT_SIZE_32 = 0x70 } |
enum | tr_hal_spi_rx_watermark_level_t { TR_HAL_SPI_RX_WATERMARK_LEVEL_8 = 0x1000 , TR_HAL_SPI_RX_WATERMARK_LEVEL_16 = 0x2000 , TR_HAL_SPI_RX_WATERMARK_LEVEL_24 = 0x3000 } |
enum | tr_hal_spi_tx_watermark_level_t { TR_HAL_SPI_TX_WATERMARK_LEVEL_8 = 0x4000 , TR_HAL_SPI_TX_WATERMARK_LEVEL_16 = 0x8000 , TR_HAL_SPI_TX_WATERMARK_LEVEL_24 = 0xC000 } |
enum | tr_hal_spi_clock_rate_t { SPI_CTRL_CLOCK_32_MHZ = 0x000 , SPI_CTRL_CLOCK_16_MHZ = 0x100 , SPI_CTRL_CLOCK_8_MHZ = 0x101 , SPI_CTRL_CLOCK_4_MHZ = 0x103 , SPI_CTRL_CLOCK_2_MHZ = 0x107 , SPI_CTRL_CLOCK_1_MHZ = 0x10F , SPI_CTRL_CLOCK_500_KHZ = 0x11F , SPI_CTRL_CLOCK_250_KHZ = 0x13F , SPI_CTRL_CLOCK_125_KHZ = 0x17F } |
Functions | |
SPI_REGISTERS_T * | tr_hal_spi_get_register_address (tr_hal_spi_id_t spi_id) |
tr_hal_status_t | tr_hal_spi_power_off (tr_hal_spi_id_t spi_id) |
tr_hal_status_t | tr_hal_spi_power_on (tr_hal_spi_id_t spi_id) |
tr_hal_status_t | tr_hal_spi_set_standard_pins (tr_hal_spi_id_t spi_id, tr_hal_gpio_pin_t clk_pin, tr_hal_gpio_pin_t chip_select_0_pin, tr_hal_gpio_pin_t sdo_pin, tr_hal_gpio_pin_t sdi_pin) |
tr_hal_status_t | tr_hal_spi_set_addl_cs_pins (tr_hal_spi_id_t spi_id, uint8_t num_chip_select, tr_hal_gpio_pin_t chip_select_1_pin, tr_hal_gpio_pin_t chip_select_2_pin, tr_hal_gpio_pin_t chip_select_3_pin) |
tr_hal_status_t | tr_hal_spi_read_stats (tr_hal_spi_id_t spi_id, uint32_t *transmit_started, uint32_t *transmit_completed, uint32_t *bytes_received) |
tr_hal_status_t | tr_hal_spi_clear_tx_busy (tr_hal_spi_id_t spi_id) |
#define CHIP_MEMORY_MAP_SPI0_BASE (0xB0000000UL) |
chip register addresses section 3.1 of the data sheet explains the Memory map. this gives the base address for how to write the chip registers the chip registers are how the software interacts and configures the SPI peripherals. We create a struct below that addresses the individual registers. This makes it so we can use this base address and a struct field to read or write a chip register
#define CHIP_MEMORY_MAP_SPI1_BASE (0x80000000UL) |
#define SPI0_CLK_BIT 20 |
#define SPI0_CLK_ENABLE_VALUE 0x100000 |
#define SPI0_CLK_PIN_OPTION1 6 |
#define SPI0_CLK_PIN_OPTION2 28 |
#define SPI0_CS0_PIN_OPTION1 7 |
#define SPI0_CS0_PIN_OPTION2 29 |
#define SPI0_CS1_PIN_OPTION1 1 |
#define SPI0_CS1_PIN_OPTION2 2 |
#define SPI0_CS1_PIN_OPTION3 3 |
#define SPI0_CS1_PIN_OPTION4 4 |
#define SPI0_CS2_PIN_OPTION1 1 |
#define SPI0_CS2_PIN_OPTION2 2 |
#define SPI0_CS2_PIN_OPTION3 3 |
#define SPI0_CS2_PIN_OPTION4 4 |
#define SPI0_CS3_PIN_OPTION1 1 |
#define SPI0_CS3_PIN_OPTION2 2 |
#define SPI0_CS3_PIN_OPTION3 3 |
#define SPI0_CS3_PIN_OPTION4 4 |
#define SPI0_IO0_PIN_OPTION1 8 |
#define SPI0_IO0_PIN_OPTION2 30 |
#define SPI0_IO1_PIN_OPTION1 9 |
#define SPI0_IO1_PIN_OPTION2 31 |
#define SPI0_IO2_PIN_OPTION1 4 |
#define SPI0_IO2_PIN_OPTION2 14 |
#define SPI0_IO3_PIN_OPTION1 5 |
#define SPI0_IO3_PIN_OPTION2 15 |
#define SPI0_MAX_CHIP_SELECT_PINS 4 |
#define SPI0_REGISTERS ((SPI_REGISTERS_T *) CHIP_MEMORY_MAP_SPI0_BASE) |
#define SPI1_CLK_BIT 21 |
#define SPI1_CLK_ENABLE_VALUE 0x200000 |
#define SPI1_CLK_PIN_OPTION1 28 |
valid pins for SPI1 - this chip has 2 SPI peripherals note that pins 10-13, 18-19, and 24-27 are not available and are not included below
SPI1
only one Chip select CS - GPIO 29 => set to GPIO MODE 5 SCLK - GPIO 28 => set to GPIO MODE 5 SDO == IO0 - GPIO 30 => set to GPIO MODE 5 SDI == IO1 - GPIO 31 => set to GPIO MODE 5
#define SPI1_CS0_PIN_OPTION1 29 |
#define SPI1_IO0_PIN_OPTION1 30 |
#define SPI1_IO1_PIN_OPTION1 31 |
#define SPI1_MAX_CHIP_SELECT_PINS 1 |
#define SPI1_REGISTERS ((SPI_REGISTERS_T *) CHIP_MEMORY_MAP_SPI1_BASE) |
#define SPI_AUX_CTRL_REG_BITSIZE_MASK 0x70 |
#define SPI_AUX_CTRL_REG_MODE_MASK 0x03 |
#define SPI_AUX_CTRL_REG_PREVENT_RX_BIT 0x08 |
#define SPI_AUX_CTRL_REG_PREVENT_TX_BIT 0x04 |
#define SPI_AUX_CTRL_REG_TRANSFER_EXTEND 0x80 |
#define SPI_CONFIG_CONTROLLER_NORMAL_MODE |
initializer macros for default SPI settings
it is common to send most significant bit first, so these are set for most_significant_bit_first = true
as far as clock polarity and phase SPI mode 0 is most common, which is CPOL = 0 and CPHA = 0, which is why cpol_bit and cpha_bit are set to 0 in the defaults
SPI settings for normal mode (4 wire) and as a SPI Controller, single CS this represents the most common settings for SPI set run_as_controller=false to run as a SPI Peripheral set num_chip_select_pins and chip_select_X to use more than one CS can adjust controller_clock_rate to be faster if the other SPI device can handle that
#define SPI_CONTROL_REG_BYTE_SWAP 0x02 |
#define SPI_CONTROL_REG_CONTINUOUS_TRANSFER 0x01 |
#define SPI_CONTROL_REG_CPHA_HIGH 0x08 |
#define SPI_CONTROL_REG_CPHA_LOW 0x00 |
#define SPI_CONTROL_REG_CPOL_HIGH 0x10 |
#define SPI_CONTROL_REG_CPOL_LOW 0x00 |
#define SPI_CONTROL_REG_ENABLE_CONTROLLER_DELAY 0x800 |
#define SPI_CONTROL_REG_MSB_FIRST 0x04 |
#define SPI_CONTROL_REG_RX_WMARK_MASK 0x3000 |
#define SPI_CONTROL_REG_SDATA_FOR_CROSSED 0x40 |
#define SPI_CONTROL_REG_SET_AS_CONTROLLER 0x20 |
#define SPI_CONTROL_REG_SET_AS_PERIPHERAL 0x00 |
#define SPI_CONTROL_REG_TX_WMARK_MASK 0xC000 |
#define SPI_DISABLE 0x00 |
#define SPI_DMA_DISABLE 0x00 |
#define SPI_DMA_ENABLE 0x01 |
#define SPI_DMA_INTERRUPTS_DISABLE 0x00 |
#define SPI_DMA_RX_BUFF_MINIMUM_SIZE 16 |
#define SPI_DMA_RX_INTERRUPT_ACTIVE 0x01 |
#define SPI_DMA_RX_INTERRUPT_ENABLE 0x01 |
#define SPI_DMA_TX_INTERRUPT_ACTIVE 0x02 |
#define SPI_DMA_TX_INTERRUPT_ENABLE 0x02 |
#define SPI_ENABLE 0x01 |
#define SPI_INTERRUPT_ALL 0x3F |
#define SPI_INTERRUPT_NONE 0x00 |
#define SPI_INTERRUPT_RX_FULL 0x08 |
#define SPI_INTERRUPT_RX_NOT_EMPTY 0x20 |
#define SPI_INTERRUPT_RX_WATERMARK 0x04 |
#define SPI_INTERRUPT_TRANSFER_DONE 0x10 |
#define SPI_INTERRUPT_TX_EMPTY 0x01 |
#define SPI_INTERRUPT_TX_WATERMARK 0x02 |
#define SPI_INVALID_PIN 0xFF |
valid pins for SPI0 - this chip has 2 SPI peripherals note that pins 10-13, 18-19, and 24-27 are not available and are not included below
SPI0
Chip select can be multiple (for multiple peripheral devices) Chip Select 0 - GPIO 7 or GPIO 29 => set to GPIO MODE 1 Chip Select 1 - GPIO 0, or GPIO 1, or GPIO 2, or GPIO 3 => set to GPIO MODE 2 Chip Select 2 - GPIO 0, or GPIO 1, or GPIO 2, or GPIO 3 => set to GPIO MODE 3 Chip Select 3 - GPIO 0, or GPIO 1, or GPIO 2, or GPIO 3 => set to GPIO MODE 6
SCLK - GPIO 6 or GPIO 28 => set to GPIO MODE 1
SDO == IO0 - GPIO 8 or GPIO 30 => set to GPIO MODE 1 SDI == IO1 - GPIO 9 or GPIO 31 => set to GPIO MODE 1 IO2 - GPIO 4 or GPIO 14 => set to GPIO MODE 1 IO4 - GPIO 5 or GPIO 15 => set to GPIO MODE 1
#define SPI_PERIPH_SELECT_0 0x01 |
#define SPI_PERIPH_SELECT_1 0x02 |
#define SPI_PERIPH_SELECT_2 0x04 |
#define SPI_PERIPH_SELECT_3 0x08 |
#define SPI_PERIPH_SELECT_CONTROLLER_ACTIVE_HIGH 0x0F |
#define SPI_PERIPH_SELECT_CONTROLLER_ACTIVE_LOW 0x00 |
#define SPI_PERIPH_SELECT_NONE 0x00 |
#define SPI_STATUS_RX_FIFO_EMPTY 0x20 |
#define SPI_STATUS_RX_FIFO_FULL 0x80 |
#define SPI_STATUS_RX_FIFO_WMARK 0x40 |
#define SPI_STATUS_TX_FIFO_EMPTY 0x04 |
#define SPI_STATUS_TX_FIFO_FULL 0x10 |
#define SPI_STATUS_TX_FIFO_WMARK 0x08 |
#define SPI_STATUS_TX_IN_PROGRESS 0x01 |
#define TR_HAL_NUM_SPI 2 |
#define TR_HAL_SPI_EVENT_DMA_RX_READY 0x00000200 |
#define TR_HAL_SPI_EVENT_DMA_RX_TO_USER_FX 0x00000100 |
#define TR_HAL_SPI_EVENT_DMA_TX_COMPLETE 0x00000400 |
#define TR_HAL_SPI_EVENT_RX_FULL 0x00000008 |
#define TR_HAL_SPI_EVENT_RX_HAS_MORE_DATA 0x00000010 |
#define TR_HAL_SPI_EVENT_RX_READY 0x00000080 |
#define TR_HAL_SPI_EVENT_RX_TO_USER_FX 0x00000040 |
#define TR_HAL_SPI_EVENT_RX_WMARK 0x00000004 |
#define TR_HAL_SPI_EVENT_TRANSFER_DONE 0x00000020 |
#define TR_HAL_SPI_EVENT_TX_EMPTY 0x00000001 |
these are the EVENTS that can be received into the SPI event handler functions. These are BITMASKs since we can have more than 1 in an event these are what the APP needs to handle in its event_handler_fx
#define TR_HAL_SPI_EVENT_TX_WMARK 0x00000002 |
#define TR_HAL_SPI_RX_FIFO_SIZE 32 |
#define TR_HAL_SPI_TX_FIFO_SIZE 32 |
typedef void(* tr_hal_spi_event_callback_t) (tr_hal_spi_id_t spi_id, uint32_t event_bitmask) |
typedef void(* tr_hal_spi_receive_callback_t) (uint8_t num_received_bytes, uint8_t *byte_buffer) |
callbacks from the Trident HAL to the App
enum tr_hal_spi_id_t |
enum tr_hal_spi_mode_t |
Normal SPI vs Dual SPI vs Quad SPI modes.
Normal SPI aka Standard SPI
SPI is used for synchronous serial communication, between a Controller (device that controls which device uses the bus) and a number of Peripherals, devices that use the bus. SPI uses at least 4 wires: CS = chip select, active low, to allow a peripheral to communicate SCLK = clock signal, from Controller SDO = serial data out / PICO = periperal in, controller out (data goes from Controller to Peripheral) SDI = serial data in / POCI = peripheral out, controller in (data goes from Peripheral to Controller) one device is the Controller, it has at least one Peripheral if there is more than 1 peripheral there should be a different CS line for each peripheral, but common bus for the other 3 pins. This way the Controller can pull the CS line low to a particular peripheral and only that peripheral will use the bus
Dual SPI
Dual SPI is a mode of operation that can double the transfer rate by using both the SDO and SDI data pins to send two bits per clock cycle (instead of just one), which is twice as fast as normal SPI. The SDO line is now called IO0 and the SDI line is called IO1.
Quad SPI
Quad SPI is a mode of operation that quadruples the throughput by using both SDO (now IO0) and SDI (now IO1) lines and two additional data lines. The additional data lines are called IO2, and IO3.
Enumerator | |
---|---|
TR_HAL_SPI_MODE_NORMAL | |
TR_HAL_SPI_MODE_DUAL | |
TR_HAL_SPI_MODE_QUAD |
tr_hal_status_t tr_hal_spi_clear_tx_busy | ( | tr_hal_spi_id_t | spi_id | ) |
SPI_REGISTERS_T * tr_hal_spi_get_register_address | ( | tr_hal_spi_id_t | spi_id | ) |
if the app wants to directly interface with the chip registers, this is a convenience function for getting the address/struct of a particular SPI so the chip registers can be accessed.
tr_hal_status_t tr_hal_spi_power_off | ( | tr_hal_spi_id_t | spi_id | ) |
these functions are used by the init/uninit function and should not be needed if the init and uninit functions are used to setup the SPI peripherals
tr_hal_status_t tr_hal_spi_power_on | ( | tr_hal_spi_id_t | spi_id | ) |
tr_hal_status_t tr_hal_spi_read_stats | ( | tr_hal_spi_id_t | spi_id, |
uint32_t * | transmit_started, | ||
uint32_t * | transmit_completed, | ||
uint32_t * | bytes_received ) |
these are development tools they were used to diagnose and fix an issue. They remain in case they are useful in the future
tr_hal_status_t tr_hal_spi_set_addl_cs_pins | ( | tr_hal_spi_id_t | spi_id, |
uint8_t | num_chip_select, | ||
tr_hal_gpio_pin_t | chip_select_1_pin, | ||
tr_hal_gpio_pin_t | chip_select_2_pin, | ||
tr_hal_gpio_pin_t | chip_select_3_pin ) |
tr_hal_status_t tr_hal_spi_set_standard_pins | ( | tr_hal_spi_id_t | spi_id, |
tr_hal_gpio_pin_t | clk_pin, | ||
tr_hal_gpio_pin_t | chip_select_0_pin, | ||
tr_hal_gpio_pin_t | sdo_pin, | ||
tr_hal_gpio_pin_t | sdi_pin ) |
these pin functions are used by the init function and should not be needed if the init functions is used to setup the SPI peripherals