Open Model Railroad Network (OpenMRN)
Loading...
Searching...
No Matches
TivaSPI.hxx
Go to the documentation of this file.
1
34#ifndef _FREERTOS_DRIVERS_TI_TIVASPI_HXX_
35#define _FREERTOS_DRIVERS_TI_TIVASPI_HXX_
36
37
38#include "SPI.hxx"
39#include "driverlib/ssi.h"
40#include "inc/hw_ssi.h"
41#include "inc/hw_types.h"
42#include "driverlib/udma.h"
43
44class TivaSPI : public SPI
45{
46public:
62 TivaSPI(const char *name, unsigned long base, uint32_t interrupt,
63 ChipSelectMethod cs_assert, ChipSelectMethod cs_deassert,
64 OSMutex *bus_lock = nullptr,
65 size_t dma_threshold = DEFAULT_DMA_THRESHOLD_BYTES,
66 uint32_t dma_channel_index_tx = UDMA_CH11_SSI0TX,
67 uint32_t dma_channel_index_rx = UDMA_CH10_SSI0RX);
68
70 ~TivaSPI();
71
73 void interrupt_handler();
74
82 {
83 return &lock_;
84 }
85
86private:
89 static constexpr size_t DEFAULT_DMA_THRESHOLD_BYTES = 0;
90
92 static constexpr size_t MAX_DMA_TRANSFER_AMOUNT = 1024;
93
99 static constexpr uint32_t dmaRxConfig_[] =
100 {
101 UDMA_SIZE_8 | UDMA_SRC_INC_NONE | UDMA_DST_INC_8 | UDMA_ARB_1,
102 UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_1,
103 };
104
110 static constexpr uint32_t dmaTxConfig_[] =
111 {
112 UDMA_SIZE_8 | UDMA_SRC_INC_8 | UDMA_DST_INC_NONE | UDMA_ARB_1,
113 UDMA_SIZE_16 | UDMA_SRC_INC_16 | UDMA_DST_INC_NONE | UDMA_ARB_1,
114 };
115
121 static constexpr uint32_t dmaNullConfig_[] =
122 {
123 UDMA_SIZE_8 | UDMA_SRC_INC_NONE | UDMA_DST_INC_NONE | UDMA_ARB_1,
124 UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_NONE | UDMA_ARB_1,
125 };
126
129 void enable() override;
130
133 void disable() override;
134
138 int update_configuration() override;
139
143 __attribute__((optimize("-O3")))
144 int transfer(struct spi_ioc_transfer *msg) override
145 {
146 return transfer_polled(msg);
147#if 0
149 if (LIKELY(msg->len < dmaThreshold_))
150 {
151 return transfer_polled(msg);
152 }
153 else
154 {
155 /* use DMA */
156 config_dma(msg);
157 }
158
159 return msg->len;
160#endif
161 }
162
167 template<typename T>
168 __attribute__((optimize("-O3")))
169 int transfer_polled(struct spi_ioc_transfer *msg)
170 {
171 T dummy = 0;
172
173 /* we are assuming that at least one byte will be transferred, and
174 * we want to start tranfering data as soon as possible
175 */
176 data_put(msg->tx_buf ? *((T*)msg->tx_buf) : 0xFFFFFFFF);
177
178 T *tx_buf = msg->tx_buf ? ((T*)msg->tx_buf) + 1 : &dummy;
179 T *rx_buf = (T*)msg->rx_buf;
180
181 /* note that we already have transmitted one SPI word above, hence the
182 * subtract one from the tx_len
183 */
184 uint32_t rx_len = msg->len / sizeof(T);
185 uint32_t tx_len = rx_len - 1;
186
187 uint16_t data;
188
189 do
190 {
191 /* fill TX FIFO but make sure we don't fill it to overflow */
192 if (tx_len && ((rx_len - tx_len) < 8))
193 {
194 if (data_put_non_blocking(*tx_buf) != 0)
195 {
196 if (msg->tx_buf)
197 {
198 ++tx_buf;
199 }
200 --tx_len;
201 }
202 }
203
204 /* empty RX FIFO */
205 if (rx_len)
206 {
207 if (data_get_non_blocking(&data) != 0)
208 {
209 if (msg->rx_buf)
210 {
211 *rx_buf++ = data;
212 }
213 --rx_len;
214 }
215 }
216 }
217 while (tx_len || rx_len);
218
219 return msg->len;
220 }
221
225 __attribute__((optimize("-O3")))
226 int transfer_polled(struct spi_ioc_transfer *msg) override
227 {
228 /* set instance specific configuration */
230
231 switch (bitsPerWord)
232 {
233 default:
234 case 8:
235 return transfer_polled<uint8_t>(msg);
236 case 16:
237 return transfer_polled<uint16_t>(msg);
238 case 32:
239 DIE("32-bit transers are not supported on this MCU.");
240 }
241 }
242
246 void config_dma(struct spi_ioc_transfer *msg);
247
253 __attribute__((optimize("-O3")))
254 long data_get_non_blocking(uint16_t *data)
255 {
256 if(HWREG(base_ + SSI_O_SR) & SSI_SR_RNE)
257 {
258 *data = HWREG(base_ + SSI_O_DR);
259 return 1;
260 }
261
262 return 0;
263 }
264
270 __attribute__((optimize("-O3")))
271 long data_put_non_blocking(uint16_t data)
272 {
273 if(HWREG(base_ + SSI_O_SR) & SSI_SR_TNF)
274 {
275 HWREG(base_ + SSI_O_DR) = data;
276 return 1;
277 }
278
279 return 0;
280 }
281
287 void data_put(uint16_t data)
288 {
289 while((HWREG(base_ + SSI_O_SR) & SSI_SR_TNF) == 0);
290 HWREG(base_ + SSI_O_DR) = data;
291 }
292
296 {
297 // Disable port first for reconfiguration.
298 HWREG(base_ + SSI_O_CR1) &= ~SSI_CR1_SSE;
299
300 HWREG(base_ + SSI_O_CR0) = spiCr0_;
301 HWREG(base_ + SSI_O_CPSR) = spiPrescaler_;
302 HWREG(base_ + SSI_O_CR1) = spiCr1_;
303 }
304
306 unsigned long base_;
307 unsigned long interrupt_;
312 uint16_t spiCr0_;
313 uint16_t spiCr1_;
314 uint16_t spiPrescaler_;
315
317};
318
319
320#endif // _FREERTOS_DRIVERS_TI_TIVASPI_HXX_
const char * name
device name
Definition Devtab.hxx:266
OSMutex lock_
protects internal structures.
Definition Devtab.hxx:588
This class provides a mutex API.
Definition OS.hxx:427
This class provides a counting semaphore API.
Definition OS.hxx:243
Private data for an SPI device.
Definition SPI.hxx:53
void bus_lock()
Lock the bus shared by many chip selects.
Definition SPI.hxx:141
uint8_t bitsPerWord
number of bits per word transaction
Definition SPI.hxx:193
void(* ChipSelectMethod)()
Function point for the chip select assert and deassert methods.
Definition SPI.hxx:56
OSSem * sem_
reference to the semaphore belonging to this bus
Definition TivaSPI.hxx:305
void disable() override
Function to disable device.
Definition TivaSPI.cxx:93
long data_put_non_blocking(uint16_t data)
Transmits a word on the specified port.
Definition TivaSPI.hxx:271
static constexpr uint32_t dmaTxConfig_[]
This lookup table is used to configure the DMA channels for the appropriate (8bit or 16bit) transfer ...
Definition TivaSPI.hxx:110
OSMutex * get_lock()
This method provides a reference to the Mutex used by this device driver.
Definition TivaSPI.hxx:81
static constexpr size_t DEFAULT_DMA_THRESHOLD_BYTES
Transfers longer than this will be with dma by default.
Definition TivaSPI.hxx:89
uint32_t dmaChannelIndexRx_
RX DMA channel index.
Definition TivaSPI.hxx:310
uint16_t spiCr1_
Configuration register 1 local copy.
Definition TivaSPI.hxx:313
uint32_t dmaChannelIndexTx_
TX DMA channel index.
Definition TivaSPI.hxx:309
unsigned long base_
base address of this device
Definition TivaSPI.hxx:306
uint16_t spiPrescaler_
Prescale register local copy.
Definition TivaSPI.hxx:314
int update_configuration() override
Update the configuration of the bus.
Definition TivaSPI.cxx:100
size_t dmaThreshold_
threshold in bytes to start using DMA
Definition TivaSPI.hxx:308
void interrupt_handler()
Call this from the SPI device's interrupt handler.
Definition TivaSPI.cxx:163
int transfer(struct spi_ioc_transfer *msg) override
Method to transmit/receive the data.
Definition TivaSPI.hxx:144
static constexpr uint32_t dmaNullConfig_[]
This lookup table is used to configure the DMA channels for the appropriate (8bit or 16bit) transfer ...
Definition TivaSPI.hxx:121
void data_put(uint16_t data)
Waits until the word is transmitted on the specified port.
Definition TivaSPI.hxx:287
void enable() override
Function to enable device.
Definition TivaSPI.cxx:89
long data_get_non_blocking(uint16_t *data)
Receives a word from the specified port.
Definition TivaSPI.hxx:254
void config_dma(struct spi_ioc_transfer *msg)
Configure a DMA transaction.
Definition TivaSPI.cxx:157
~TivaSPI()
Destructor.
Definition TivaSPI.cxx:85
static constexpr uint32_t dmaRxConfig_[]
This lookup table is used to configure the DMA channels for the appropriate (8bit or 16bit) transfer ...
Definition TivaSPI.hxx:99
static constexpr size_t MAX_DMA_TRANSFER_AMOUNT
Maximum number of bytes transferred in a single DMA transaction.
Definition TivaSPI.hxx:92
unsigned long interrupt_
interrupt of this device
Definition TivaSPI.hxx:307
uint16_t spiCr0_
Configuration register 0 local copy.
Definition TivaSPI.hxx:312
void set_configuration()
Set the instance local configuration.
Definition TivaSPI.hxx:295
int transfer_polled(struct spi_ioc_transfer *msg)
Method to transmit/receive the data.
Definition TivaSPI.hxx:169
#define DIE(MSG)
Unconditionally terminates the current process with a message.
Definition macros.h:143
#define DISALLOW_COPY_AND_ASSIGN(TypeName)
Removes default copy-constructor and assignment added by C++.
Definition macros.h:171