stmhal/spi: Factor out SPI transfer code to a single function.
This commit is contained in:
parent
3be8b688c0
commit
9b64d1966b
147
stmhal/spi.c
147
stmhal/spi.c
@ -327,6 +327,79 @@ STATIC HAL_StatusTypeDef spi_wait_dma_finished(SPI_HandleTypeDef *spi, uint32_t
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
STATIC void spi_transfer(mp_obj_base_t *self_in, size_t src_len, const uint8_t *src_buf, size_t dest_len, uint8_t *dest_buf, uint32_t timeout) {
|
||||
// Note: there seems to be a problem sending 1 byte using DMA the first
|
||||
// time directly after the SPI/DMA is initialised. The cause of this is
|
||||
// unknown but we sidestep the issue by using polling for 1 byte transfer.
|
||||
|
||||
pyb_spi_obj_t *self = (pyb_spi_obj_t*)self_in;
|
||||
HAL_StatusTypeDef status;
|
||||
|
||||
if (dest_len == 0) {
|
||||
// send only
|
||||
if (src_len == 1 || query_irq() == IRQ_STATE_DISABLED) {
|
||||
status = HAL_SPI_Transmit(self->spi, (uint8_t*)src_buf, src_len, timeout);
|
||||
} else {
|
||||
DMA_HandleTypeDef tx_dma;
|
||||
dma_init(&tx_dma, self->tx_dma_descr, self->spi);
|
||||
self->spi->hdmatx = &tx_dma;
|
||||
self->spi->hdmarx = NULL;
|
||||
status = HAL_SPI_Transmit_DMA(self->spi, (uint8_t*)src_buf, src_len);
|
||||
if (status == HAL_OK) {
|
||||
status = spi_wait_dma_finished(self->spi, timeout);
|
||||
}
|
||||
dma_deinit(self->tx_dma_descr);
|
||||
}
|
||||
} else if (src_len == 0) {
|
||||
// receive only
|
||||
if (dest_len == 1 || query_irq() == IRQ_STATE_DISABLED) {
|
||||
status = HAL_SPI_Receive(self->spi, dest_buf, dest_len, timeout);
|
||||
} else {
|
||||
DMA_HandleTypeDef tx_dma, rx_dma;
|
||||
if (self->spi->Init.Mode == SPI_MODE_MASTER) {
|
||||
// in master mode the HAL actually does a TransmitReceive call
|
||||
dma_init(&tx_dma, self->tx_dma_descr, self->spi);
|
||||
self->spi->hdmatx = &tx_dma;
|
||||
} else {
|
||||
self->spi->hdmatx = NULL;
|
||||
}
|
||||
dma_init(&rx_dma, self->rx_dma_descr, self->spi);
|
||||
self->spi->hdmarx = &rx_dma;
|
||||
|
||||
status = HAL_SPI_Receive_DMA(self->spi, dest_buf, dest_len);
|
||||
if (status == HAL_OK) {
|
||||
status = spi_wait_dma_finished(self->spi, timeout);
|
||||
}
|
||||
if (self->spi->hdmatx != NULL) {
|
||||
dma_deinit(self->tx_dma_descr);
|
||||
}
|
||||
dma_deinit(self->rx_dma_descr);
|
||||
}
|
||||
} else {
|
||||
// send and receive
|
||||
// requires src_len==dest_len
|
||||
if (src_len == 1 || query_irq() == IRQ_STATE_DISABLED) {
|
||||
status = HAL_SPI_TransmitReceive(self->spi, (uint8_t*)src_buf, dest_buf, src_len, timeout);
|
||||
} else {
|
||||
DMA_HandleTypeDef tx_dma, rx_dma;
|
||||
dma_init(&tx_dma, self->tx_dma_descr, self->spi);
|
||||
self->spi->hdmatx = &tx_dma;
|
||||
dma_init(&rx_dma, self->rx_dma_descr, self->spi);
|
||||
self->spi->hdmarx = &rx_dma;
|
||||
status = HAL_SPI_TransmitReceive_DMA(self->spi, (uint8_t*)src_buf, dest_buf, src_len);
|
||||
if (status == HAL_OK) {
|
||||
status = spi_wait_dma_finished(self->spi, timeout);
|
||||
}
|
||||
dma_deinit(self->tx_dma_descr);
|
||||
dma_deinit(self->rx_dma_descr);
|
||||
}
|
||||
}
|
||||
|
||||
if (status != HAL_OK) {
|
||||
mp_hal_raise(status);
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/* Micro Python bindings */
|
||||
|
||||
@ -556,27 +629,7 @@ STATIC mp_obj_t pyb_spi_send(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_
|
||||
pyb_buf_get_for_send(args[0].u_obj, &bufinfo, data);
|
||||
|
||||
// send the data
|
||||
// Note: there seems to be a problem sending 1 byte using DMA the first
|
||||
// time directly after the SPI/DMA is initialised. The cause of this is
|
||||
// unknown but we sidestep the issue by using polling for 1 byte transfer.
|
||||
HAL_StatusTypeDef status;
|
||||
if (bufinfo.len == 1 || query_irq() == IRQ_STATE_DISABLED) {
|
||||
status = HAL_SPI_Transmit(self->spi, bufinfo.buf, bufinfo.len, args[1].u_int);
|
||||
} else {
|
||||
DMA_HandleTypeDef tx_dma;
|
||||
dma_init(&tx_dma, self->tx_dma_descr, self->spi);
|
||||
self->spi->hdmatx = &tx_dma;
|
||||
self->spi->hdmarx = NULL;
|
||||
status = HAL_SPI_Transmit_DMA(self->spi, bufinfo.buf, bufinfo.len);
|
||||
if (status == HAL_OK) {
|
||||
status = spi_wait_dma_finished(self->spi, args[1].u_int);
|
||||
}
|
||||
dma_deinit(self->tx_dma_descr);
|
||||
}
|
||||
|
||||
if (status != HAL_OK) {
|
||||
mp_hal_raise(status);
|
||||
}
|
||||
spi_transfer((mp_obj_base_t*)self, bufinfo.len, bufinfo.buf, 0, NULL, args[1].u_int);
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
@ -610,34 +663,7 @@ STATIC mp_obj_t pyb_spi_recv(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_
|
||||
mp_obj_t o_ret = pyb_buf_get_for_recv(args[0].u_obj, &vstr);
|
||||
|
||||
// receive the data
|
||||
HAL_StatusTypeDef status;
|
||||
if (vstr.len == 1 || query_irq() == IRQ_STATE_DISABLED) {
|
||||
status = HAL_SPI_Receive(self->spi, (uint8_t*)vstr.buf, vstr.len, args[1].u_int);
|
||||
} else {
|
||||
DMA_HandleTypeDef tx_dma, rx_dma;
|
||||
if (self->spi->Init.Mode == SPI_MODE_MASTER) {
|
||||
// in master mode the HAL actually does a TransmitReceive call
|
||||
dma_init(&tx_dma, self->tx_dma_descr, self->spi);
|
||||
self->spi->hdmatx = &tx_dma;
|
||||
} else {
|
||||
self->spi->hdmatx = NULL;
|
||||
}
|
||||
dma_init(&rx_dma, self->rx_dma_descr, self->spi);
|
||||
self->spi->hdmarx = &rx_dma;
|
||||
|
||||
status = HAL_SPI_Receive_DMA(self->spi, (uint8_t*)vstr.buf, vstr.len);
|
||||
if (status == HAL_OK) {
|
||||
status = spi_wait_dma_finished(self->spi, args[1].u_int);
|
||||
}
|
||||
if (self->spi->hdmatx != NULL) {
|
||||
dma_deinit(self->tx_dma_descr);
|
||||
}
|
||||
dma_deinit(self->rx_dma_descr);
|
||||
}
|
||||
|
||||
if (status != HAL_OK) {
|
||||
mp_hal_raise(status);
|
||||
}
|
||||
spi_transfer((mp_obj_base_t*)self, 0, NULL, vstr.len, (uint8_t*)vstr.buf, args[1].u_int);
|
||||
|
||||
// return the received data
|
||||
if (o_ret != MP_OBJ_NULL) {
|
||||
@ -706,27 +732,8 @@ STATIC mp_obj_t pyb_spi_send_recv(mp_uint_t n_args, const mp_obj_t *pos_args, mp
|
||||
}
|
||||
}
|
||||
|
||||
// send and receive the data
|
||||
HAL_StatusTypeDef status;
|
||||
if (bufinfo_send.len == 1 || query_irq() == IRQ_STATE_DISABLED) {
|
||||
status = HAL_SPI_TransmitReceive(self->spi, bufinfo_send.buf, bufinfo_recv.buf, bufinfo_send.len, args[2].u_int);
|
||||
} else {
|
||||
DMA_HandleTypeDef tx_dma, rx_dma;
|
||||
dma_init(&tx_dma, self->tx_dma_descr, self->spi);
|
||||
self->spi->hdmatx = &tx_dma;
|
||||
dma_init(&rx_dma, self->rx_dma_descr, self->spi);
|
||||
self->spi->hdmarx = &rx_dma;
|
||||
status = HAL_SPI_TransmitReceive_DMA(self->spi, bufinfo_send.buf, bufinfo_recv.buf, bufinfo_send.len);
|
||||
if (status == HAL_OK) {
|
||||
status = spi_wait_dma_finished(self->spi, args[2].u_int);
|
||||
}
|
||||
dma_deinit(self->tx_dma_descr);
|
||||
dma_deinit(self->rx_dma_descr);
|
||||
}
|
||||
|
||||
if (status != HAL_OK) {
|
||||
mp_hal_raise(status);
|
||||
}
|
||||
// do the transfer
|
||||
spi_transfer((mp_obj_base_t*)self, bufinfo_send.len, bufinfo_send.buf, bufinfo_recv.len, bufinfo_recv.buf, args[2].u_int);
|
||||
|
||||
// return the received data
|
||||
if (o_ret != MP_OBJ_NULL) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user