[CC2538-SPI] Implement SPI_FLUSH, spi mode, !CS
Because the CC2538 has a multi-byte SPI RX FIFO, flushing the buffer requires more than just a single read. This adds a loop that empties the entire RX buffer on a FLUSH(). Different SPI chips needs different SPI settings. This commit adds a function that allows chip drivers to configure the SPI peripheral before using it. The frame pin the driver was using as a chip select does not work as most devices expect it to. It toggles after every byte, and most chips interpret that as end of message. To make drivers more reliable, each chip driver should setup a GPIO and assert it as needed.
This commit is contained in:
parent
a96dc90250
commit
af27d2d252
4 changed files with 115 additions and 59 deletions
|
@ -41,27 +41,51 @@
|
|||
#ifndef SPI_ARCH_H_
|
||||
#define SPI_ARCH_H_
|
||||
|
||||
#include "contiki.h"
|
||||
#include "dev/ssi.h"
|
||||
|
||||
#define SPI_WAITFORTxREADY() do { \
|
||||
while(!(REG(SSI0_BASE + SSI_SR) & SSI_SR_TNF)); \
|
||||
} while (0)
|
||||
} while(0)
|
||||
|
||||
#define SPI_TXBUF REG(SSI0_BASE + SSI_DR)
|
||||
|
||||
#define SPI_RXBUF REG(SSI0_BASE + SSI_DR)
|
||||
|
||||
#define SPI_WAITFOREOTx() do { \
|
||||
while(REG(SSI0_BASE + SSI_SR) & SSI_SR_BSY); \
|
||||
} while (0)
|
||||
} while(0)
|
||||
|
||||
#define SPI_WAITFOREORx() do { \
|
||||
while(!(REG(SSI0_BASE + SSI_SR) & SSI_SR_RNE)); \
|
||||
} while (0)
|
||||
} while(0)
|
||||
|
||||
#ifdef SPI_FLUSH
|
||||
#error "You must include spi-arch.h before spi.h for the CC2538."
|
||||
#endif
|
||||
#define SPI_FLUSH() do { \
|
||||
SPI_WAITFOREORx(); \
|
||||
while (REG(SSI0_BASE + SSI_SR) & SSI_SR_RNE) { \
|
||||
SPI_RXBUF; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define SPI_CS_CLR(port, pin) do { \
|
||||
GPIO_CLR_PIN(GPIO_PORT_TO_BASE(port), GPIO_PIN_MASK(pin)); \
|
||||
} while(0)
|
||||
|
||||
#define SPI_CS_SET(port, pin) do { \
|
||||
GPIO_SET_PIN(GPIO_PORT_TO_BASE(port), GPIO_PIN_MASK(pin)); \
|
||||
} while(0)
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** \name Arch-specific SPI functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* \brief Configure a GPIO to be the chip select pin
|
||||
*/
|
||||
void spi_cs_init(uint8_t port, uint8_t pin);
|
||||
|
||||
/** \brief Enables the SPI peripheral
|
||||
*/
|
||||
void spi_enable(void);
|
||||
|
@ -71,6 +95,27 @@ void spi_enable(void);
|
|||
*/
|
||||
void spi_disable(void);
|
||||
|
||||
/**
|
||||
* \brief Configure the SPI data and clock polarity and the data size.
|
||||
*
|
||||
* This function configures the SSI peripheral to use a particular SPI
|
||||
* configuration that a slave device requires. It should always be called
|
||||
* before using the SPI bus as another driver could have changed the settings.
|
||||
*
|
||||
* See section 19.4.4 in the CC2538 user guide for more information.
|
||||
*
|
||||
* \param frame_format Set the SSI frame format. Use SSI_CR0_FRF_MOTOROLA,
|
||||
* SSI_CR0_FRF_TI, or SSI_CR0_FRF_MICROWIRE.
|
||||
* \param clock_polarity In Motorola mode, set whether the clock is high or low
|
||||
* when idle. Use SSI_CR0_SPO or 0.
|
||||
* \param clock_phase In Motorola mode, select whether data is valid on the
|
||||
* first or second edge of the clock. Use SSI_CR0_SPH or 0.
|
||||
* \param data_size The number of bits in each "byte" of data. Must be
|
||||
* between 4 and 16, inclusive.
|
||||
*/
|
||||
void spi_set_mode(uint32_t frame_format, uint32_t clock_polarity,
|
||||
uint32_t clock_phase, uint32_t data_size);
|
||||
|
||||
/** @} */
|
||||
|
||||
#endif /* SPI_ARCH_H_ */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue