File indexing completed on 2025-05-11 08:23:38
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036 #ifdef HAVE_CONFIG_H
0037 #include "config.h"
0038 #endif
0039
0040 #include <bsp.h>
0041 #include <bsp/fatal.h>
0042 #include <inttypes.h>
0043 #include <rtems/bspIo.h>
0044 #include <rtems/sysinit.h>
0045 #include <stdio.h>
0046 #include <stm32h7xx_hal_dma.h>
0047 #include <stm32h7xx_hal_spi.h>
0048
0049 #include <stm32h7/hal.h>
0050 #include <rtems/score/prioritybitmapimpl.h>
0051
0052 #define STM32H7_SPI_COMPLETE 0
0053 #define STM32H7_SPI_ERROR 1
0054 #define SPI_TIMEOUT_MS 100
0055
0056
0057 static stm32h7_spi_context * const stm32h7_spi_instances[] = {
0058 #ifdef STM32H7_SPI1_ENABLE
0059 #ifdef SPI1
0060 &stm32h7_spi1_instance,
0061 #else
0062 #error SPI1 configured, but not available
0063 #endif
0064 #else
0065 NULL,
0066 #endif
0067
0068 #ifdef STM32H7_SPI2_ENABLE
0069 #ifdef SPI2
0070 &stm32h7_spi2_instance,
0071 #else
0072 #error SPI2 configured, but not available
0073 #endif
0074 #else
0075 NULL,
0076 #endif
0077
0078 #ifdef STM32H7_SPI3_ENABLE
0079 #ifdef SPI3
0080 &stm32h7_spi3_instance,
0081 #else
0082 #error SPI3 configured, but not available
0083 #endif
0084 #else
0085 NULL,
0086 #endif
0087
0088 #ifdef STM32H7_SPI4_ENABLE
0089 #ifdef SPI4
0090 &stm32h7_spi4_instance,
0091 #else
0092 #error SPI4 configured, but not available
0093 #endif
0094 #else
0095 NULL,
0096 #endif
0097
0098 #ifdef STM32H7_SPI5_ENABLE
0099 #ifdef SPI5
0100 &stm32h7_spi5_instance,
0101 #else
0102 #error SPI5 configured, but not available
0103 #endif
0104 #else
0105 NULL,
0106 #endif
0107
0108 #ifdef STM32H7_SPI6_ENABLE
0109 #ifdef SPI6
0110 &stm32h7_spi6_instance,
0111 #else
0112 #error SPI6 configured, but not available
0113 #endif
0114 #else
0115 NULL,
0116 #endif
0117
0118
0119 NULL
0120 };
0121
0122 static int stm32h7_spi_set_prescaler(stm32h7_spi_context *ctx, uint32_t speed_hz)
0123 {
0124 uint32_t prescaler_mask = SPI_BAUDRATEPRESCALER_256;
0125
0126
0127 if (speed_hz < (ctx->bus.max_speed_hz / 128)) {
0128
0129 return 1;
0130 }
0131
0132 if (speed_hz > ctx->bus.max_speed_hz) {
0133 ctx->spi.Instance->CFG1 &= ~prescaler_mask;
0134 ctx->spi.Instance->CFG1 |= SPI_BAUDRATEPRESCALER_2;
0135 } else {
0136 uint32_t divider = 2 * ctx->bus.max_speed_hz / speed_hz;
0137 uint32_t remainder = (2 * ctx->bus.max_speed_hz) % speed_hz;
0138 uint32_t prescaler_value;
0139 if (divider > 256) {
0140
0141 return 1;
0142 }
0143
0144 prescaler_value = 7 - _Bitfield_Leading_zeros[divider & 0xff];
0145 if (remainder) {
0146 prescaler_value++;
0147 }
0148 if (prescaler_value > SPI_BAUDRATEPRESCALER_256 >> 24) {
0149
0150 return 1;
0151 }
0152 prescaler_value <<= 28;
0153 ctx->spi.Instance->CFG1 &= ~prescaler_mask;
0154 ctx->spi.Instance->CFG1 |= prescaler_value;
0155 }
0156
0157 return 0;
0158 }
0159
0160 static int stm32h7_spi_set_bpw(stm32h7_spi_context *ctx, uint32_t bits_per_word)
0161 {
0162 uint32_t bits_per_word_mask = SPI_DATASIZE_32BIT;
0163
0164 if (bits_per_word < 4 || bits_per_word > 32) {
0165 return 1;
0166 }
0167
0168
0169
0170
0171
0172 ctx->spi.Instance->CFG1 &= ~bits_per_word_mask;
0173 ctx->spi.Instance->CFG1 |= (bits_per_word - 1);
0174
0175 return 0;
0176 }
0177
0178 static void stm32h7_spi_set_mode(stm32h7_spi_context *ctx, uint32_t mode)
0179 {
0180 uint32_t mode_mask = SPI_POLARITY_HIGH | SPI_PHASE_2EDGE;
0181 ctx->spi.Instance->CFG2 &= ~mode_mask;
0182 if (mode & SPI_CPOL) {
0183 ctx->spi.Instance->CFG2 |= SPI_POLARITY_HIGH;
0184 }
0185 if (mode & SPI_CPHA) {
0186 ctx->spi.Instance->CFG2 |= SPI_PHASE_2EDGE;
0187 }
0188
0189 }
0190
0191 static int stm32h7_spi_setup(spi_bus *base)
0192 {
0193 stm32h7_spi_context *ctx = RTEMS_CONTAINER_OF(base, stm32h7_spi_context, bus);
0194
0195 if (stm32h7_spi_set_prescaler(ctx, ctx->bus.speed_hz)) {
0196 return -EINVAL;
0197 }
0198
0199 if (stm32h7_spi_set_bpw(ctx, ctx->bus.bits_per_word)) {
0200 return -EINVAL;
0201 }
0202
0203 stm32h7_spi_set_mode(ctx, ctx->bus.mode);
0204
0205 return 0;
0206 }
0207
0208 static void stm32h7_spi_destroy(spi_bus *base)
0209 {
0210 stm32h7_spi_context *ctx = RTEMS_CONTAINER_OF(base, stm32h7_spi_context, bus);
0211
0212 #ifdef STM32H7_SPI_USE_INTERRUPTS
0213 rtems_binary_semaphore_destroy(&ctx->sem);
0214 #endif
0215 HAL_SPI_DeInit(&ctx->spi);
0216
0217 spi_bus_destroy(base);
0218 }
0219
0220 static int stm32h7_spi_get_chip_select(
0221 stm32h7_spi_context *ctx,
0222 uint8_t cs,
0223 GPIO_TypeDef **gpio,
0224 uint16_t *pin)
0225 {
0226 const stm32h7_gpio_config *cs_gpio;
0227 if (cs >= STM32H7_NUM_SOFT_CS) {
0228 return 1;
0229 }
0230 cs_gpio = &ctx->config->cs_gpio[cs];
0231 if (cs_gpio->regs == NULL || cs_gpio->config.Pin == 0) {
0232
0233 return 1;
0234 }
0235 *gpio = cs_gpio->regs;
0236 *pin = cs_gpio->config.Pin;
0237 return 0;
0238 }
0239
0240 static int stm32h7_spi_apply_premessage_settings(
0241 stm32h7_spi_context *ctx,
0242 const spi_ioc_transfer *msg
0243 )
0244 {
0245 uint32_t mode_width = SPI_TX_DUAL | SPI_TX_QUAD | SPI_RX_DUAL | SPI_RX_QUAD;
0246
0247 if (msg->rx_nbits > 1 || msg->tx_nbits > 1 || (msg->mode & mode_width)) {
0248
0249 return 1;
0250 }
0251
0252 if (stm32h7_spi_set_prescaler(ctx, msg->speed_hz)) {
0253 return 1;
0254 }
0255
0256 if (stm32h7_spi_set_bpw(ctx, msg->bits_per_word)) {
0257 return 1;
0258 }
0259
0260 stm32h7_spi_set_mode(ctx, msg->mode);
0261
0262 GPIO_TypeDef *gpio_block = NULL;
0263 uint16_t gpio_pin = 0;
0264 if (stm32h7_spi_get_chip_select(ctx, msg->cs, &gpio_block, &gpio_pin)) {
0265
0266 return 1;
0267 }
0268
0269 HAL_GPIO_WritePin(gpio_block, gpio_pin, GPIO_PIN_RESET);
0270 return 0;
0271 }
0272
0273 static void stm32h7_spi_apply_postmessage_settings(
0274 stm32h7_spi_context *ctx,
0275 const spi_ioc_transfer *msg,
0276 bool final
0277 )
0278 {
0279 usleep(msg->delay_usecs);
0280 if (msg->cs_change || final) {
0281 GPIO_TypeDef *gpio_block = NULL;
0282 uint16_t gpio_pin = 0;
0283
0284
0285
0286
0287
0288 (void) stm32h7_spi_get_chip_select(ctx, msg->cs, &gpio_block, &gpio_pin);
0289
0290 HAL_GPIO_WritePin(gpio_block, gpio_pin, GPIO_PIN_SET);
0291 }
0292 }
0293
0294 static int stm32h7_spi_transfer_wait(stm32h7_spi_context *ctx, uint32_t timeout_ms)
0295 {
0296 #ifdef STM32H7_SPI_USE_INTERRUPTS
0297 int status;
0298 uint32_t timeout_ticks = timeout_ms;
0299
0300 timeout_ticks /= rtems_configuration_get_milliseconds_per_tick();
0301
0302 status = rtems_binary_semaphore_wait_timed_ticks(&ctx->sem, timeout_ticks);
0303 if (status != 0) {
0304 return -ETIME;
0305 }
0306 if (ctx->error == STM32H7_SPI_ERROR) {
0307 return -EIO;
0308 }
0309 #else
0310 (void) timeout_ms;
0311 #endif
0312 return 0;
0313 }
0314
0315 static int hal_status_to_errno(HAL_StatusTypeDef status)
0316 {
0317 _Assert(status != HAL_OK);
0318
0319 switch (status) {
0320 case HAL_BUSY:
0321 return -EBUSY;
0322 case HAL_ERROR:
0323 return -EINVAL;
0324 case HAL_TIMEOUT:
0325 return -ETIME;
0326 case HAL_OK:
0327 return -EIO;
0328 }
0329
0330 return -EIO;
0331 }
0332
0333 static int stm32h7_spi_txrx(
0334 stm32h7_spi_context *ctx,
0335 const uint8_t *pTxData,
0336 uint8_t *pRxData,
0337 uint16_t Size
0338 )
0339 {
0340 HAL_StatusTypeDef status;
0341
0342 #ifdef STM32H7_SPI_USE_INTERRUPTS
0343 status = HAL_SPI_TransmitReceive_IT(&ctx->spi, pTxData, pRxData, Size);
0344 #else
0345 status = HAL_SPI_TransmitReceive(
0346 &ctx->spi, pTxData, pRxData, Size, SPI_TIMEOUT_MS
0347 );
0348 #endif
0349 if (status != HAL_OK) {
0350 return hal_status_to_errno(status);
0351 }
0352
0353 return stm32h7_spi_transfer_wait(ctx, SPI_TIMEOUT_MS);
0354 }
0355
0356 static int stm32h7_spi_tx(
0357 stm32h7_spi_context *ctx,
0358 const uint8_t *pData,
0359 uint16_t Size
0360 )
0361 {
0362 HAL_StatusTypeDef status;
0363
0364 #ifdef STM32H7_SPI_USE_INTERRUPTS
0365 status = HAL_SPI_Transmit_IT(&ctx->spi, pData, Size);
0366 #else
0367 status = HAL_SPI_Transmit(&ctx->spi, pData, Size, SPI_TIMEOUT_MS);
0368 #endif
0369 if (status != HAL_OK) {
0370 return hal_status_to_errno(status);
0371 }
0372
0373 return stm32h7_spi_transfer_wait(ctx, SPI_TIMEOUT_MS);
0374 }
0375
0376 static int stm32h7_spi_rx(
0377 stm32h7_spi_context *ctx,
0378 uint8_t *pData,
0379 uint16_t Size
0380 )
0381 {
0382 HAL_StatusTypeDef status;
0383
0384 #ifdef STM32H7_SPI_USE_INTERRUPTS
0385 status = HAL_SPI_Receive_IT(&ctx->spi, pData, Size);
0386 #else
0387 status = HAL_SPI_Receive(&ctx->spi, pData, Size, SPI_TIMEOUT_MS);
0388 #endif
0389 if (status != HAL_OK) {
0390 return hal_status_to_errno(status);
0391 }
0392
0393 return stm32h7_spi_transfer_wait(ctx, SPI_TIMEOUT_MS);
0394 }
0395
0396 static int stm32h7_spi_transfer(
0397 spi_bus *base,
0398 const spi_ioc_transfer *msgs,
0399 uint32_t msg_count
0400 )
0401 {
0402 stm32h7_spi_context *ctx = RTEMS_CONTAINER_OF(base, stm32h7_spi_context, bus);
0403
0404 for (int i = 0; i < msg_count; i++) {
0405 const spi_ioc_transfer *msg = &msgs[i];
0406
0407 if (stm32h7_spi_apply_premessage_settings(ctx, msg)) {
0408 return -EINVAL;
0409 }
0410
0411 if (msg->tx_buf != NULL && msg->rx_buf != NULL) {
0412 int ret = stm32h7_spi_txrx(ctx, msg->tx_buf, msg->rx_buf, msg->len);
0413 if (ret != 0) {
0414 return ret;
0415 }
0416 } else if (msg->tx_buf != NULL) {
0417 int ret = stm32h7_spi_tx(ctx, msg->tx_buf, msg->len);
0418 if (ret != 0) {
0419 return ret;
0420 }
0421 } else if (msg->rx_buf != NULL) {
0422 int ret = stm32h7_spi_rx(ctx, msg->rx_buf, msg->len);
0423 if (ret != 0) {
0424 return ret;
0425 }
0426 }
0427
0428 stm32h7_spi_apply_postmessage_settings(ctx, msg, i == msg_count);
0429 }
0430
0431 return 0;
0432 }
0433
0434 void HAL_SPI_ErrorCallback(SPI_HandleTypeDef *spi)
0435 {
0436 #ifdef STM32H7_SPI_USE_INTERRUPTS
0437 stm32h7_spi_context *ctx = RTEMS_CONTAINER_OF(spi, stm32h7_spi_context, spi);
0438
0439 ctx->error = STM32H7_SPI_ERROR;
0440 rtems_binary_semaphore_post(&ctx->sem);
0441 #endif
0442 }
0443
0444 void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *spi)
0445 {
0446 #ifdef STM32H7_SPI_USE_INTERRUPTS
0447 stm32h7_spi_context *ctx = RTEMS_CONTAINER_OF(spi, stm32h7_spi_context, spi);
0448
0449 ctx->error = STM32H7_SPI_COMPLETE;
0450 rtems_binary_semaphore_post(&ctx->sem);
0451 #endif
0452 }
0453
0454 void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *spi)
0455 {
0456 #ifdef STM32H7_SPI_USE_INTERRUPTS
0457 stm32h7_spi_context *ctx = RTEMS_CONTAINER_OF(spi, stm32h7_spi_context, spi);
0458
0459 ctx->error = STM32H7_SPI_COMPLETE;
0460 rtems_binary_semaphore_post(&ctx->sem);
0461 #endif
0462 }
0463
0464 void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *spi)
0465 {
0466 #ifdef STM32H7_SPI_USE_INTERRUPTS
0467 stm32h7_spi_context *ctx = RTEMS_CONTAINER_OF(spi, stm32h7_spi_context, spi);
0468
0469 ctx->error = STM32H7_SPI_COMPLETE;
0470 rtems_binary_semaphore_post(&ctx->sem);
0471 #endif
0472 }
0473
0474 #ifdef STM32H7_SPI_USE_INTERRUPTS
0475 static void stm32h7_spi_irq_handler(void *arg)
0476 {
0477 stm32h7_spi_context *ctx = arg;
0478
0479 HAL_SPI_IRQHandler(&ctx->spi);
0480 }
0481 #endif
0482
0483 static int stm32h7_register_spi_device(
0484 stm32h7_spi_context *ctx,
0485 uint8_t device_index
0486 )
0487 {
0488 char path[sizeof("/dev/spiXXX")];
0489 int rv;
0490 #ifdef STM32H7_SPI_USE_INTERRUPTS
0491 rtems_status_code sc;
0492 #endif
0493 spi_bus *bus = &ctx->bus;
0494
0495 rv = spi_bus_init(bus);
0496 if (rv) {
0497 return rv;
0498 }
0499
0500 bus->transfer = stm32h7_spi_transfer;
0501 bus->destroy = stm32h7_spi_destroy;
0502 bus->setup = stm32h7_spi_setup;
0503
0504
0505
0506
0507
0508
0509 bus->max_speed_hz = ctx->config->max_speed_hz;
0510
0511
0512
0513
0514
0515
0516
0517 bus->speed_hz = bus->max_speed_hz;
0518 bus->cs_change = 0;
0519 bus->cs = 0;
0520 bus->bits_per_word = ctx->spi.Init.DataSize + 1;
0521 bus->lsb_first = false;
0522 if (ctx->spi.Init.FirstBit == SPI_FIRSTBIT_LSB) {
0523 bus->lsb_first = true;
0524 }
0525 bus->mode = 0;
0526 if (ctx->spi.Init.CLKPolarity == SPI_POLARITY_HIGH) {
0527 bus->mode |= SPI_CPOL;
0528 }
0529 if (ctx->spi.Init.CLKPhase == SPI_PHASE_2EDGE) {
0530 bus->mode |= SPI_CPHA;
0531 }
0532
0533 if (HAL_SPI_Init(&ctx->spi)) {
0534 return 1;
0535 }
0536
0537 #ifdef STM32H7_SPI_USE_INTERRUPTS
0538
0539 rtems_interrupt_entry_initialize(
0540 &ctx->spi_irq_entry,
0541 stm32h7_spi_irq_handler,
0542 ctx,
0543 "SPI"
0544 );
0545 sc = rtems_interrupt_entry_install(
0546 ctx->irq,
0547 RTEMS_INTERRUPT_SHARED,
0548 &ctx->spi_irq_entry
0549 );
0550 if (sc != RTEMS_SUCCESSFUL) {
0551 return false;
0552 }
0553 rtems_binary_semaphore_init(&ctx->sem, "STM32H7 SPI");
0554 #endif
0555
0556 snprintf(path, sizeof(path), "/dev/spi%" PRIu8, device_index);
0557 rv = spi_bus_register(bus, path);
0558 if (rv) {
0559 return rv;
0560 }
0561
0562 return 0;
0563 }
0564
0565 void stm32h7_register_spi_devices(void)
0566 {
0567 int i;
0568
0569 for (i = 0; i < (RTEMS_ARRAY_SIZE(stm32h7_spi_instances)); i++) {
0570 if (stm32h7_spi_instances[i] == NULL) {
0571 continue;
0572 }
0573 if (stm32h7_register_spi_device(stm32h7_spi_instances[i], i)) {
0574 bsp_fatal(STM32H7_FATAL_MMU_CANNOT_REGISTER_SPI);
0575 }
0576 }
0577 }