mirror of https://github.com/ARMmbed/mbed-os.git
SiLabs Pearl: More SPI fixes for 9-16 bit frames
spi_buffer_tx_write fixed to work correctly with 9-16 bit frames, if transfer length > 1. If frame is 9-16 bit client can use uint16_t or uint32_t buffer for data storage, spi_api's default is to use uint16_t. Added precompiler condition USE_UINT16_BUFFER to change assumption for DMA and IRQ -transfers.pull/1501/head
parent
6bb98769b0
commit
0dfca1ad86
|
|
@ -51,6 +51,8 @@
|
||||||
static uint16_t fill_word = SPI_FILL_WORD;
|
static uint16_t fill_word = SPI_FILL_WORD;
|
||||||
|
|
||||||
#define SPI_LEAST_ACTIVE_SLEEPMODE EM0
|
#define SPI_LEAST_ACTIVE_SLEEPMODE EM0
|
||||||
|
#define USE_UINT16_BUFFER
|
||||||
|
|
||||||
static inline CMU_Clock_TypeDef spi_get_clock_tree(spi_t *obj)
|
static inline CMU_Clock_TypeDef spi_get_clock_tree(spi_t *obj)
|
||||||
{
|
{
|
||||||
switch ((int)obj->spi.spi) {
|
switch ((int)obj->spi.spi) {
|
||||||
|
|
@ -488,53 +490,36 @@ void spi_buffer_set(spi_t *obj, const void *tx, uint32_t tx_length, void *rx, ui
|
||||||
static void spi_buffer_tx_write(spi_t *obj)
|
static void spi_buffer_tx_write(spi_t *obj)
|
||||||
{
|
{
|
||||||
uint32_t data;
|
uint32_t data;
|
||||||
// This routine gets triggered on TXBL (= buffer empty), so check to see if we can write a double value
|
if(obj->spi.bits >= 9) {
|
||||||
if (obj->spi.bits % 9 != 0) {
|
// write double frame
|
||||||
// No special 9-bit scenario
|
if (obj->tx_buff.buffer == (void *)0) {
|
||||||
if((obj->tx_buff.pos < obj->tx_buff.length - 1) && ((obj->tx_buff.pos & 0x1) == 0)) {
|
data = SPI_FILL_WORD;
|
||||||
// write double frame
|
} else {
|
||||||
if (obj->tx_buff.buffer == (void *)0) {
|
#ifdef USE_UINT16_BUFFER
|
||||||
data = SPI_FILL_WORD;
|
uint16_t *tx = (uint16_t *)(obj->tx_buff.buffer);
|
||||||
} else {
|
#else
|
||||||
uint16_t *tx = (uint16_t *)(obj->tx_buff.buffer);
|
uint32_t *tx = (uint16_t *)(obj->tx_buff.buffer);
|
||||||
data = tx[obj->tx_buff.pos / 2] & 0xFFFF;
|
#endif
|
||||||
}
|
data = tx[obj->tx_buff.pos] & 0xFFFF;
|
||||||
obj->tx_buff.pos += 2;
|
|
||||||
obj->spi.spi->TXDOUBLE = data;
|
|
||||||
} else if (obj->tx_buff.pos < obj->tx_buff.length) {
|
|
||||||
// write single frame
|
|
||||||
if (obj->tx_buff.buffer == (void *)0) {
|
|
||||||
data = SPI_FILL_WORD & 0xFF;
|
|
||||||
} else {
|
|
||||||
uint8_t *tx = (uint8_t *)(obj->tx_buff.buffer);
|
|
||||||
data = tx[obj->tx_buff.pos] & 0xFF;
|
|
||||||
}
|
|
||||||
obj->tx_buff.pos++;
|
|
||||||
obj->spi.spi->TXDATA = data;
|
|
||||||
}
|
}
|
||||||
} else {
|
obj->tx_buff.pos += 1;
|
||||||
// 9-bit frame
|
if(obj->spi.bits == 9){
|
||||||
if(obj->tx_buff.pos < obj->tx_buff.length - 3) {
|
|
||||||
// write double frame
|
|
||||||
if (obj->tx_buff.buffer == (void *)0) {
|
|
||||||
data = ((SPI_FILL_WORD & 0x01FF) << 16) | (SPI_FILL_WORD & 0x1FF);
|
|
||||||
} else {
|
|
||||||
uint32_t *tx = (uint32_t *)(obj->tx_buff.buffer);
|
|
||||||
data = tx[obj->tx_buff.pos / 4] & 0x01FF01FF;
|
|
||||||
}
|
|
||||||
obj->tx_buff.pos += 4;
|
|
||||||
obj->spi.spi->TXDOUBLEX = data;
|
|
||||||
} else if (obj->tx_buff.pos < obj->tx_buff.length - 1) {
|
|
||||||
// write single frame
|
|
||||||
if (obj->tx_buff.buffer == (void *)0) {
|
|
||||||
data = SPI_FILL_WORD & 0x01FF;
|
|
||||||
} else {
|
|
||||||
uint16_t *tx = (uint16_t *)(obj->tx_buff.buffer);
|
|
||||||
data = tx[obj->tx_buff.pos / 2] & 0x01FF;
|
|
||||||
}
|
|
||||||
obj->tx_buff.pos += 2;
|
|
||||||
obj->spi.spi->TXDATAX = data;
|
obj->spi.spi->TXDATAX = data;
|
||||||
|
}else {
|
||||||
|
obj->spi.spi->TXDOUBLE = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} else if (obj->tx_buff.pos < obj->tx_buff.length) {
|
||||||
|
// write single frame
|
||||||
|
if (obj->tx_buff.buffer == (void *)0) {
|
||||||
|
data = SPI_FILL_WORD & 0xFF;
|
||||||
|
} else {
|
||||||
|
uint8_t *tx = (uint8_t *)(obj->tx_buff.buffer);
|
||||||
|
data = tx[obj->tx_buff.pos] & 0xFF;
|
||||||
|
}
|
||||||
|
obj->tx_buff.pos++;
|
||||||
|
|
||||||
|
obj->spi.spi->TXDATA = data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -897,8 +882,12 @@ static void spi_activate_dma(spi_t *obj, void* rxdata, const void* txdata, int t
|
||||||
LDMA_TransferCfg_t xferConf = LDMA_TRANSFER_CFG_PERIPHERAL(dma_periph);
|
LDMA_TransferCfg_t xferConf = LDMA_TRANSFER_CFG_PERIPHERAL(dma_periph);
|
||||||
LDMA_Descriptor_t desc = LDMA_DESCRIPTOR_SINGLE_M2P_BYTE(txdata, target_addr, tx_length);
|
LDMA_Descriptor_t desc = LDMA_DESCRIPTOR_SINGLE_M2P_BYTE(txdata, target_addr, tx_length);
|
||||||
if(obj->spi.bits >= 9){
|
if(obj->spi.bits >= 9){
|
||||||
|
#ifdef USE_UINT16_BUFFER
|
||||||
|
desc.xfer.size = ldmaCtrlSizeHalf;
|
||||||
|
#else
|
||||||
desc.xfer.size = ldmaCtrlSizeHalf;
|
desc.xfer.size = ldmaCtrlSizeHalf;
|
||||||
desc.xfer.srcInc = ldmaCtrlSrcIncTwo;
|
desc.xfer.srcInc = ldmaCtrlSrcIncTwo;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
LDMA_StartTransfer(obj->spi.dmaOptionsTX.dmaChannel, &xferConf, &desc, serial_dmaTransferComplete,obj->spi.dmaOptionsRX.dmaCallback.userPtr);
|
LDMA_StartTransfer(obj->spi.dmaOptionsTX.dmaChannel, &xferConf, &desc, serial_dmaTransferComplete,obj->spi.dmaOptionsRX.dmaCallback.userPtr);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue