drivers: spi: Fix the Ambiq apollo4p SPI transmission failure.
The instruction length can only be 0~5. Use am_hal_iom_blocking_transfer and specify clearly the TX/RX direction. Hold CS to continue to RX expected response after instruction transmission. Signed-off-by: Aaron Ye <aye@ambiq.com>
This commit is contained in:
parent
7cf21d1080
commit
a94422f686
|
@ -130,33 +130,51 @@ static int spi_ambiq_xfer(const struct device *dev, const struct spi_config *con
|
|||
int ret = 0;
|
||||
|
||||
am_hal_iom_transfer_t trans = {0};
|
||||
uint8_t *buf3;
|
||||
|
||||
trans.eDirection = AM_HAL_IOM_FULLDUPLEX;
|
||||
|
||||
uint16_t cmd = *ctx->tx_buf;
|
||||
|
||||
trans.ui32InstrLen = ctx->tx_len;
|
||||
spi_context_update_tx(ctx, 1, 1);
|
||||
cmd = __bswap_16(cmd | *ctx->tx_buf << 8);
|
||||
trans.ui64Instr = cmd;
|
||||
|
||||
if (ctx->rx_buf != NULL) {
|
||||
trans.pui32TxBuffer = (uint32_t *)ctx->tx_buf;
|
||||
spi_context_update_rx(ctx, 1, ctx->rx_len);
|
||||
buf3 = (uint8_t *)malloc(sizeof(uint8_t) * ctx->rx_len);
|
||||
trans.ui32NumBytes = ctx->rx_len;
|
||||
trans.pui32RxBuffer = (uint32_t *)&buf3;
|
||||
ret = am_hal_iom_spi_blocking_fullduplex(data->IOMHandle, &trans);
|
||||
|
||||
memcpy(ctx->rx_buf, &buf3, (ctx->rx_len * sizeof(uint8_t)));
|
||||
|
||||
} else if (ctx->tx_buf != NULL) {
|
||||
if (ctx->tx_len) {
|
||||
trans.ui64Instr = *ctx->tx_buf;
|
||||
trans.ui32InstrLen = 1;
|
||||
spi_context_update_tx(ctx, 1, 1);
|
||||
trans.ui32NumBytes = ctx->tx_len;
|
||||
trans.pui32TxBuffer = (uint32_t *)ctx->tx_buf;
|
||||
trans.pui32RxBuffer = (uint32_t *)ctx->tx_buf;
|
||||
ret = am_hal_iom_spi_blocking_fullduplex(data->IOMHandle, &trans);
|
||||
|
||||
if (ctx->rx_buf != NULL) {
|
||||
if (ctx->tx_len > 0) {
|
||||
/* The instruction length can only be 0~5. */
|
||||
if (ctx->tx_len > 4) {
|
||||
spi_context_complete(ctx, dev, 0);
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
/* Put the remaining TX data in instruction. */
|
||||
trans.ui32InstrLen += ctx->tx_len;
|
||||
for (int i = 0; i < trans.ui32InstrLen - 1; i++) {
|
||||
trans.ui64Instr = (trans.ui64Instr << 8) | (*ctx->tx_buf);
|
||||
spi_context_update_tx(ctx, 1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Set RX direction and hold CS to continue to receive data. */
|
||||
trans.eDirection = AM_HAL_IOM_RX;
|
||||
trans.bContinue = true;
|
||||
trans.pui32RxBuffer = (uint32_t *)ctx->rx_buf;
|
||||
trans.ui32NumBytes = ctx->rx_len;
|
||||
ret = am_hal_iom_blocking_transfer(data->IOMHandle, &trans);
|
||||
} else if (ctx->tx_buf != NULL) {
|
||||
/* Set TX direction to send data and release CS after transmission. */
|
||||
trans.eDirection = AM_HAL_IOM_TX;
|
||||
trans.bContinue = false;
|
||||
trans.ui32NumBytes = ctx->tx_len;
|
||||
trans.pui32TxBuffer = (uint32_t *)ctx->tx_buf;
|
||||
ret = am_hal_iom_blocking_transfer(data->IOMHandle, &trans);
|
||||
}
|
||||
} else {
|
||||
/* Set RX direction to receive data and release CS after transmission. */
|
||||
trans.ui64Instr = 0;
|
||||
trans.ui32InstrLen = 0;
|
||||
trans.eDirection = AM_HAL_IOM_RX;
|
||||
trans.bContinue = false;
|
||||
trans.pui32RxBuffer = (uint32_t *)ctx->rx_buf;
|
||||
trans.ui32NumBytes = ctx->rx_len;
|
||||
ret = am_hal_iom_blocking_transfer(data->IOMHandle, &trans);
|
||||
}
|
||||
|
||||
spi_context_complete(ctx, dev, 0);
|
||||
|
|
Loading…
Reference in a new issue