Skip to content

Commit 2ce8fa1

Browse files
psidhucarlescufi
authored andcommitted
spi: stm32: Enable sending 16bits at a time in 8bit mode if possible
If possible, allow sending 16bits at once instead of 8bits. I found large delays (up to 3us) between sending bytes due to Zephyr SPI overhead, so allowing 16bits at a time if possible helps save that time. Signed-off-by: Pushpal Sidhu <psidhu.devel@gmail.com>
1 parent 8f0788e commit 2ce8fa1

File tree

1 file changed

+88
-24
lines changed

1 file changed

+88
-24
lines changed

drivers/spi/spi_ll_stm32.c

Lines changed: 88 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -73,11 +73,40 @@ static int spi_stm32_get_err(SPI_TypeDef *spi)
7373
return 0;
7474
}
7575

76-
/* Shift a SPI frame as master. */
77-
static void spi_stm32_shift_m(SPI_TypeDef *spi, struct spi_stm32_data *data)
76+
static inline void spi_stm32_shift_m8(SPI_TypeDef *spi,
77+
struct spi_stm32_data *data)
7878
{
79+
struct spi_context *ctx = &(data->ctx);
7980
u16_t tx_frame = SPI_STM32_TX_NOP;
8081
u16_t rx_frame;
82+
bool xfer_16;
83+
84+
if (spi_context_tx_buf_on(ctx) && spi_context_rx_buf_on(ctx)) {
85+
xfer_16 = (MIN(ctx->tx_len, ctx->rx_len) > 1) ? true : false;
86+
} else if (spi_context_tx_buf_on(ctx)) {
87+
xfer_16 = (ctx->tx_len > 1) ? true : false;
88+
} else if (spi_context_rx_buf_on(ctx)) {
89+
xfer_16 = (ctx->rx_len > 1) ? true : false;
90+
} else {
91+
/* Should never get here, but place case for it anyways */
92+
return;
93+
}
94+
95+
#if defined(CONFIG_SPI_STM32_HAS_FIFO)
96+
if (xfer_16) {
97+
ll_func_set_fifo_threshold_16bit(spi);
98+
} else {
99+
ll_func_set_fifo_threshold_8bit(spi);
100+
}
101+
#endif
102+
103+
if (xfer_16 && spi_context_tx_buf_on(ctx)) {
104+
tx_frame = UNALIGNED_GET((u16_t *)(ctx->tx_buf));
105+
spi_context_update_tx(ctx, 1, 2);
106+
} else if (spi_context_tx_buf_on(ctx)) {
107+
tx_frame = UNALIGNED_GET((u8_t *)(ctx->tx_buf));
108+
spi_context_update_tx(ctx, 1, 1);
109+
}
81110

82111
while (!ll_func_tx_is_empty(spi)) {
83112
/* NOP */
@@ -95,37 +124,68 @@ static void spi_stm32_shift_m(SPI_TypeDef *spi, struct spi_stm32_data *data)
95124
}
96125
#endif
97126

98-
if (SPI_WORD_SIZE_GET(data->ctx.config->operation) == 8) {
99-
if (spi_context_tx_on(&data->ctx)) {
100-
tx_frame = UNALIGNED_GET((u8_t *)(data->ctx.tx_buf));
101-
}
102-
LL_SPI_TransmitData8(spi, tx_frame);
103-
/* The update is ignored if TX is off. */
104-
spi_context_update_tx(&data->ctx, 1, 1);
105-
} else {
106-
if (spi_context_tx_on(&data->ctx)) {
107-
tx_frame = UNALIGNED_GET((u16_t *)(data->ctx.tx_buf));
108-
}
127+
if (xfer_16) {
109128
LL_SPI_TransmitData16(spi, tx_frame);
110-
/* The update is ignored if TX is off. */
111-
spi_context_update_tx(&data->ctx, 2, 1);
129+
} else {
130+
LL_SPI_TransmitData8(spi, tx_frame);
112131
}
113132

114133
while (!ll_func_rx_is_not_empty(spi)) {
115134
/* NOP */
116135
}
117136

118-
if (SPI_WORD_SIZE_GET(data->ctx.config->operation) == 8) {
119-
rx_frame = LL_SPI_ReceiveData8(spi);
120-
if (spi_context_rx_buf_on(&data->ctx)) {
121-
UNALIGNED_PUT(rx_frame, (u8_t *)data->ctx.rx_buf);
137+
if (xfer_16) {
138+
rx_frame = LL_SPI_ReceiveData16(spi);
139+
if (spi_context_rx_buf_on(ctx)) {
140+
UNALIGNED_PUT(rx_frame, (u16_t *)ctx->rx_buf);
141+
spi_context_update_rx(ctx, 1, 2);
122142
}
123-
spi_context_update_rx(&data->ctx, 1, 1);
124143
} else {
125-
rx_frame = LL_SPI_ReceiveData16(spi);
126-
if (spi_context_rx_buf_on(&data->ctx)) {
127-
UNALIGNED_PUT(rx_frame, (u16_t *)data->ctx.rx_buf);
144+
rx_frame = LL_SPI_ReceiveData8(spi);
145+
if (spi_context_rx_buf_on(ctx)) {
146+
UNALIGNED_PUT(rx_frame, (u8_t *)ctx->rx_buf);
147+
spi_context_update_rx(ctx, 1, 1);
148+
}
149+
}
150+
}
151+
152+
static inline void spi_stm32_shift_m16(SPI_TypeDef *spi,
153+
struct spi_stm32_data *data)
154+
{
155+
u16_t tx_frame = SPI_STM32_TX_NOP;
156+
u16_t rx_frame;
157+
158+
if (spi_context_tx_buf_on(&data->ctx)) {
159+
tx_frame = UNALIGNED_GET((u16_t *)(data->ctx.tx_buf));
160+
spi_context_update_tx(&data->ctx, 2, 1);
161+
}
162+
163+
while (!ll_func_tx_is_empty(spi)) {
164+
/* NOP */
165+
}
166+
167+
#ifdef CONFIG_SOC_SERIES_STM32MP1X
168+
/* With the STM32MP1, if the device is the SPI master, we need to enable
169+
* the start of the transfer with LL_SPI_StartMasterTransfer(spi)
170+
*/
171+
if (LL_SPI_GetMode(spi) == LL_SPI_MODE_MASTER) {
172+
LL_SPI_StartMasterTransfer(spi);
173+
while (!LL_SPI_IsActiveMasterTransfer(spi)) {
174+
/* NOP */
128175
}
176+
}
177+
#endif
178+
179+
LL_SPI_TransmitData16(spi, tx_frame);
180+
181+
while (!ll_func_rx_is_not_empty(spi)) {
182+
/* NOP */
183+
}
184+
185+
rx_frame = LL_SPI_ReceiveData16(spi);
186+
187+
if (spi_context_rx_buf_on(&data->ctx)) {
188+
UNALIGNED_PUT(rx_frame, (u16_t *)data->ctx.rx_buf);
129189
spi_context_update_rx(&data->ctx, 2, 1);
130190
}
131191
}
@@ -176,7 +236,11 @@ static int spi_stm32_shift_frames(SPI_TypeDef *spi, struct spi_stm32_data *data)
176236
u16_t operation = data->ctx.config->operation;
177237

178238
if (SPI_OP_MODE_GET(operation) == SPI_OP_MODE_MASTER) {
179-
spi_stm32_shift_m(spi, data);
239+
if (SPI_WORD_SIZE_GET(data->ctx.config->operation) == 8) {
240+
spi_stm32_shift_m8(spi, data);
241+
} else {
242+
spi_stm32_shift_m16(spi, data);
243+
}
180244
} else {
181245
spi_stm32_shift_s(spi, data);
182246
}

0 commit comments

Comments
 (0)