Skip to content

Commit 756f6f5

Browse files
committed
Fix STM32 SPI 16-bit logic
Update SPI logic to process 16 bit words in the same way by sync/async, 3/4 wires modes: - fix 3-wire synchronous transmission to move 2 or more bytes between buffer and SPI register per word tarnsmission - fix 4-wire synchronous transmission to move 2 or more bytes between buffer and SPI register per word tarnsmission
1 parent c02e10b commit 756f6f5

File tree

1 file changed

+52
-12
lines changed

1 file changed

+52
-12
lines changed

targets/TARGET_STM/stm_spi_api.c

Lines changed: 52 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -939,6 +939,33 @@ static inline int datasize_to_transfer_bitshift(uint32_t DataSize)
939939
}
940940
}
941941

942+
static inline int spi_get_word_from_buffer(const void *buffer, int bitshift)
943+
{
944+
if (bitshift == 1) {
945+
return *((uint16_t *)buffer);
946+
#ifdef HAS_32BIT_SPI_TRANSFERS
947+
} else if (bitshift == 2) {
948+
return *((uint32_t *)buffer);
949+
#endif /* HAS_32BIT_SPI_TRANSFERS */
950+
} else {
951+
return *((uint8_t *)buffer);
952+
}
953+
}
954+
955+
static inline void spi_put_word_to_buffer(void *buffer, int bitshift, int data)
956+
{
957+
if (bitshift == 1) {
958+
*((uint16_t *)buffer) = data;
959+
#ifdef HAS_32BIT_SPI_TRANSFERS
960+
} else if (bitshift == 2) {
961+
*((uint32_t *)buffer) = data;
962+
#endif /* HAS_32BIT_SPI_TRANSFERS */
963+
} else {
964+
*((uint8_t *)buffer) = data;
965+
}
966+
}
967+
968+
942969
/**
943970
* Check if SPI master interface is writable.
944971
*
@@ -1057,6 +1084,7 @@ static int spi_master_one_wire_transfer(spi_t *obj, const char *tx_buffer, int t
10571084
SPI_HandleTypeDef *handle = &(spiobj->handle);
10581085
const int bitshift = datasize_to_transfer_bitshift(handle->Init.DataSize);
10591086
MBED_ASSERT(bitshift >= 0);
1087+
const int word_size = 0x01 << bitshift;
10601088

10611089
/* Ensure that spi is disabled */
10621090
LL_SPI_Disable(SPI_INST(obj));
@@ -1066,17 +1094,17 @@ static int spi_master_one_wire_transfer(spi_t *obj, const char *tx_buffer, int t
10661094
LL_SPI_SetTransferDirection(SPI_INST(obj), LL_SPI_HALF_DUPLEX_TX);
10671095
#if defined(SPI_IP_VERSION_V2)
10681096
/* Set transaction size */
1069-
LL_SPI_SetTransferSize(SPI_INST(obj), tx_length);
1097+
LL_SPI_SetTransferSize(SPI_INST(obj), tx_length >> bitshift);
10701098
#endif /* SPI_IP_VERSION_V2 */
10711099
LL_SPI_Enable(SPI_INST(obj));
10721100
#if defined(SPI_IP_VERSION_V2)
10731101
/* Master transfer start */
10741102
LL_SPI_StartMasterTransfer(SPI_INST(obj));
10751103
#endif /* SPI_IP_VERSION_V2 */
10761104

1077-
for (int i = 0; i < tx_length; i++) {
1105+
for (int i = 0; i < tx_length; i += word_size) {
10781106
msp_wait_writable(obj);
1079-
msp_write_data(obj, tx_buffer[i], bitshift);
1107+
msp_write_data(obj, spi_get_word_from_buffer(tx_buffer + i, bitshift), bitshift);
10801108
}
10811109

10821110
/* Wait end of transaction */
@@ -1098,14 +1126,14 @@ static int spi_master_one_wire_transfer(spi_t *obj, const char *tx_buffer, int t
10981126
LL_SPI_SetTransferDirection(SPI_INST(obj), LL_SPI_HALF_DUPLEX_RX);
10991127
#if defined(SPI_IP_VERSION_V2)
11001128
/* Set transaction size and run SPI */
1101-
LL_SPI_SetTransferSize(SPI_INST(obj), rx_length);
1129+
LL_SPI_SetTransferSize(SPI_INST(obj), rx_length >> bitshift);
11021130
LL_SPI_Enable(SPI_INST(obj));
11031131
LL_SPI_StartMasterTransfer(SPI_INST(obj));
11041132

11051133
/* Receive data */
1106-
for (int i = 0; i < rx_length; i++) {
1134+
for (int i = 0; i < rx_length; i += word_size) {
11071135
msp_wait_readable(obj);
1108-
rx_buffer[i] = msp_read_data(obj, bitshift);
1136+
spi_put_word_to_buffer(rx_buffer + i, bitshift, msp_read_data(obj, bitshift));
11091137
}
11101138

11111139
/* Stop SPI */
@@ -1134,7 +1162,7 @@ static int spi_master_one_wire_transfer(spi_t *obj, const char *tx_buffer, int t
11341162
/* get estimation about one SPI clock cycle */
11351163
uint32_t baudrate_period_ns = 1000000000 / spi_get_baudrate(obj);
11361164

1137-
for (int i = 0; i < rx_length; i++) {
1165+
for (int i = 0; i < rx_length; i += word_size) {
11381166
core_util_critical_section_enter();
11391167
LL_SPI_Enable(SPI_INST(obj));
11401168
/* Wait single SPI clock cycle. */
@@ -1143,7 +1171,7 @@ static int spi_master_one_wire_transfer(spi_t *obj, const char *tx_buffer, int t
11431171
core_util_critical_section_exit();
11441172

11451173
msp_wait_readable(obj);
1146-
rx_buffer[i] = msp_read_data(obj, bitshift);
1174+
spi_put_word_to_buffer(rx_buffer + i, bitshift, msp_read_data(obj, bitshift));
11471175
}
11481176

11491177
#endif /* SPI_IP_VERSION_V2 */
@@ -1198,13 +1226,25 @@ int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length,
11981226
{
11991227
struct spi_s *spiobj = SPI_S(obj);
12001228
SPI_HandleTypeDef *handle = &(spiobj->handle);
1229+
const int bitshift = datasize_to_transfer_bitshift(handle->Init.DataSize);
1230+
/* check buffer sizes are multiple of spi word size */
1231+
MBED_ASSERT(tx_length >> bitshift << bitshift == tx_length);
1232+
MBED_ASSERT(rx_length >> bitshift << bitshift == rx_length);
12011233
int total = (tx_length > rx_length) ? tx_length : rx_length;
1234+
12021235
if (handle->Init.Direction == SPI_DIRECTION_2LINES) {
1203-
for (int i = 0; i < total; i++) {
1204-
char out = (i < tx_length) ? tx_buffer[i] : write_fill;
1205-
char in = spi_master_write(obj, out);
1236+
int write_fill_frame = write_fill;
1237+
/* extend fill symbols for 16/32 bit modes */
1238+
for (int i = 0; i < bitshift; i++) {
1239+
write_fill_frame = (write_fill_frame << 8) | write_fill;
1240+
}
1241+
1242+
const int word_size = 0x01 << bitshift;
1243+
for (int i = 0; i < total; i += word_size) {
1244+
int out = (i < tx_length) ? spi_get_word_from_buffer(tx_buffer + i, bitshift) : write_fill_frame;
1245+
int in = spi_master_write(obj, out);
12061246
if (i < rx_length) {
1207-
rx_buffer[i] = in;
1247+
spi_put_word_to_buffer(rx_buffer + i, bitshift, in);
12081248
}
12091249
}
12101250
} else {

0 commit comments

Comments
 (0)