bsps/stm32h7/spi: Add IRQ support

This commit is contained in:
Kinsey Moore
2024-09-13 10:40:06 -05:00
committed by Chris Johns
parent b1a350a18a
commit b3be636863
5 changed files with 222 additions and 15 deletions

View File

@@ -3138,6 +3138,7 @@ void HAL_SPI_IRQHandler(SPI_HandleTypeDef *hspi)
}
}
#ifndef __rtems__
/**
* @brief Tx Transfer completed callback.
* @param hspi: pointer to a SPI_HandleTypeDef structure that contains
@@ -3185,6 +3186,7 @@ __weak void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi) /* Derogation MISR
the HAL_SPI_TxRxCpltCallback should be implemented in the user file
*/
}
#endif
/**
* @brief Tx Half Transfer completed callback.
@@ -3234,6 +3236,7 @@ __weak void HAL_SPI_TxRxHalfCpltCallback(SPI_HandleTypeDef *hspi) /* Derogation
*/
}
#ifndef __rtems__
/**
* @brief SPI error callback.
* @param hspi: pointer to a SPI_HandleTypeDef structure that contains
@@ -3252,6 +3255,7 @@ __weak void HAL_SPI_ErrorCallback(SPI_HandleTypeDef *hspi) /* Derogation MISRAC2
and user can use HAL_SPI_GetError() API to check the latest error occurred
*/
}
#endif
/**
* @brief SPI Abort Complete callback.

View File

@@ -193,6 +193,11 @@ typedef struct {
bool transmitting;
const stm32h7_spi_config *config;
rtems_vector_number irq;
#ifdef STM32H7_SPI_USE_INTERRUPTS
rtems_interrupt_entry spi_irq_entry;
rtems_binary_semaphore sem;
int error;
#endif
} stm32h7_spi_context;
extern stm32h7_spi_context stm32h7_spi1_instance;

View File

@@ -43,10 +43,16 @@
#include <rtems/bspIo.h>
#include <rtems/sysinit.h>
#include <stdio.h>
#include <stm32h7xx_hal_dma.h>
#include <stm32h7xx_hal_spi.h>
#include <stm32h7/hal.h>
#include <rtems/score/prioritybitmapimpl.h>
#define STM32H7_SPI_COMPLETE 0
#define STM32H7_SPI_ERROR 1
#define SPI_TIMEOUT_MS 100
/* NULLs are included for disabled devices to preserve index */
static stm32h7_spi_context * const stm32h7_spi_instances[] = {
#ifdef STM32H7_SPI1_ENABLE
@@ -187,11 +193,11 @@ static int stm32h7_spi_setup(spi_bus *base)
stm32h7_spi_context *ctx = RTEMS_CONTAINER_OF(base, stm32h7_spi_context, bus);
if (stm32h7_spi_set_prescaler(ctx, ctx->bus.speed_hz)) {
return 1;
return -EINVAL;
}
if (stm32h7_spi_set_bpw(ctx, ctx->bus.bits_per_word)) {
return 1;
return -EINVAL;
}
stm32h7_spi_set_mode(ctx, ctx->bus.mode);
@@ -203,6 +209,9 @@ static void stm32h7_spi_destroy(spi_bus *base)
{
stm32h7_spi_context *ctx = RTEMS_CONTAINER_OF(base, stm32h7_spi_context, bus);
#ifdef STM32H7_SPI_USE_INTERRUPTS
rtems_binary_semaphore_destroy(&ctx->sem);
#endif
HAL_SPI_DeInit(&ctx->spi);
spi_bus_destroy(base);
@@ -282,6 +291,108 @@ static void stm32h7_spi_apply_postmessage_settings(
}
}
static int stm32h7_spi_transfer_wait(stm32h7_spi_context *ctx, uint32_t timeout_ms)
{
#ifdef STM32H7_SPI_USE_INTERRUPTS
int status;
uint32_t timeout_ticks = timeout_ms;
timeout_ticks /= rtems_configuration_get_milliseconds_per_tick();
status = rtems_binary_semaphore_wait_timed_ticks(&ctx->sem, timeout_ticks);
if (status != 0) {
return -ETIME;
}
if (ctx->error == STM32H7_SPI_ERROR) {
return -EIO;
}
#else
(void) timeout_ms;
#endif
return 0;
}
static int hal_status_to_errno(HAL_StatusTypeDef status)
{
_Assert(status != HAL_OK);
switch (status) {
case HAL_BUSY:
return -EBUSY;
case HAL_ERROR:
return -EINVAL;
case HAL_TIMEOUT:
return -ETIME;
case HAL_OK:
return -EIO;
}
return -EIO;
}
static int stm32h7_spi_txrx(
stm32h7_spi_context *ctx,
const uint8_t *pTxData,
uint8_t *pRxData,
uint16_t Size
)
{
HAL_StatusTypeDef status;
#ifdef STM32H7_SPI_USE_INTERRUPTS
status = HAL_SPI_TransmitReceive_IT(&ctx->spi, pTxData, pRxData, Size);
#else
status = HAL_SPI_TransmitReceive(
&ctx->spi, pTxData, pRxData, Size, SPI_TIMEOUT_MS
);
#endif
if (status != HAL_OK) {
return hal_status_to_errno(status);
}
return stm32h7_spi_transfer_wait(ctx, SPI_TIMEOUT_MS);
}
static int stm32h7_spi_tx(
stm32h7_spi_context *ctx,
const uint8_t *pData,
uint16_t Size
)
{
HAL_StatusTypeDef status;
#ifdef STM32H7_SPI_USE_INTERRUPTS
status = HAL_SPI_Transmit_IT(&ctx->spi, pData, Size);
#else
status = HAL_SPI_Transmit(&ctx->spi, pData, Size, SPI_TIMEOUT_MS);
#endif
if (status != HAL_OK) {
return hal_status_to_errno(status);
}
return stm32h7_spi_transfer_wait(ctx, SPI_TIMEOUT_MS);
}
static int stm32h7_spi_rx(
stm32h7_spi_context *ctx,
uint8_t *pData,
uint16_t Size
)
{
HAL_StatusTypeDef status;
#ifdef STM32H7_SPI_USE_INTERRUPTS
status = HAL_SPI_Receive_IT(&ctx->spi, pData, Size);
#else
status = HAL_SPI_Receive(&ctx->spi, pData, Size, SPI_TIMEOUT_MS);
#endif
if (status != HAL_OK) {
return hal_status_to_errno(status);
}
return stm32h7_spi_transfer_wait(ctx, SPI_TIMEOUT_MS);
}
static int stm32h7_spi_transfer(
spi_bus *base,
const spi_ioc_transfer *msgs,
@@ -292,28 +403,25 @@ static int stm32h7_spi_transfer(
for (int i = 0; i < msg_count; i++) {
const spi_ioc_transfer *msg = &msgs[i];
HAL_StatusTypeDef status;
if (stm32h7_spi_apply_premessage_settings(ctx, msg)) {
return 1;
return -EINVAL;
}
/* perform transfer */
if (msg->tx_buf != NULL && msg->rx_buf != NULL) {
status = HAL_SPI_TransmitReceive(
&ctx->spi, msg->tx_buf, msg->rx_buf, msg->len, 100
);
if (status != HAL_OK) {
return 1;
int ret = stm32h7_spi_txrx(ctx, msg->tx_buf, msg->rx_buf, msg->len);
if (ret != 0) {
return ret;
}
} else if (msg->tx_buf != NULL) {
status = HAL_SPI_Transmit(&ctx->spi, msg->tx_buf, msg->len, 100);
if (status != HAL_OK) {
return 1;
int ret = stm32h7_spi_tx(ctx, msg->tx_buf, msg->len);
if (ret != 0) {
return ret;
}
} else if (msg->rx_buf != NULL) {
status = HAL_SPI_Receive(&ctx->spi, msg->rx_buf, msg->len, 100);
if (status != HAL_OK) {
return 1;
int ret = stm32h7_spi_rx(ctx, msg->rx_buf, msg->len);
if (ret != 0) {
return ret;
}
}
/* set final to true on last iteration */
@@ -323,6 +431,55 @@ static int stm32h7_spi_transfer(
return 0;
}
void HAL_SPI_ErrorCallback(SPI_HandleTypeDef *spi)
{
#ifdef STM32H7_SPI_USE_INTERRUPTS
stm32h7_spi_context *ctx = RTEMS_CONTAINER_OF(spi, stm32h7_spi_context, spi);
ctx->error = STM32H7_SPI_ERROR;
rtems_binary_semaphore_post(&ctx->sem);
#endif
}
void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *spi)
{
#ifdef STM32H7_SPI_USE_INTERRUPTS
stm32h7_spi_context *ctx = RTEMS_CONTAINER_OF(spi, stm32h7_spi_context, spi);
ctx->error = STM32H7_SPI_COMPLETE;
rtems_binary_semaphore_post(&ctx->sem);
#endif
}
void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *spi)
{
#ifdef STM32H7_SPI_USE_INTERRUPTS
stm32h7_spi_context *ctx = RTEMS_CONTAINER_OF(spi, stm32h7_spi_context, spi);
ctx->error = STM32H7_SPI_COMPLETE;
rtems_binary_semaphore_post(&ctx->sem);
#endif
}
void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *spi)
{
#ifdef STM32H7_SPI_USE_INTERRUPTS
stm32h7_spi_context *ctx = RTEMS_CONTAINER_OF(spi, stm32h7_spi_context, spi);
ctx->error = STM32H7_SPI_COMPLETE;
rtems_binary_semaphore_post(&ctx->sem);
#endif
}
#ifdef STM32H7_SPI_USE_INTERRUPTS
static void stm32h7_spi_irq_handler(void *arg)
{
stm32h7_spi_context *ctx = arg;
HAL_SPI_IRQHandler(&ctx->spi);
}
#endif
static int stm32h7_register_spi_device(
stm32h7_spi_context *ctx,
uint8_t device_index
@@ -330,6 +487,9 @@ static int stm32h7_register_spi_device(
{
char path[sizeof("/dev/spiXXX")];
int rv;
#ifdef STM32H7_SPI_USE_INTERRUPTS
rtems_status_code sc;
#endif
spi_bus *bus = &ctx->bus;
rv = spi_bus_init(bus);
@@ -374,6 +534,25 @@ static int stm32h7_register_spi_device(
return 1;
}
#ifdef STM32H7_SPI_USE_INTERRUPTS
/* Configure interrupt */
rtems_interrupt_entry_initialize(
&ctx->spi_irq_entry,
stm32h7_spi_irq_handler,
ctx,
"SPI"
);
sc = rtems_interrupt_entry_install(
ctx->irq,
RTEMS_INTERRUPT_SHARED,
&ctx->spi_irq_entry
);
if (sc != RTEMS_SUCCESSFUL) {
return false;
}
rtems_binary_semaphore_init(&ctx->sem, "STM32H7 SPI");
#endif
snprintf(path, sizeof(path), "/dev/spi%" PRIu8, device_index);
rv = spi_bus_register(bus, path);
if (rv) {

View File

@@ -102,6 +102,8 @@ links:
uid: optprintkinstance
- role: build-dependency
uid: optpwrsupply
- role: build-dependency
uid: optspiirq
- role: build-dependency
uid: optbootcore
- role: build-dependency

View File

@@ -0,0 +1,17 @@
SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause
actions:
- get-boolean: null
- define-condition: null
build-type: option
copyrights:
- Copyright (C) 2024 On-Line Applications Research (OAR)
default:
- enabled-by: true
value: true
description: |
Use SPI devices in interrupt mode
enabled-by: true
format: '{}'
links: []
name: STM32H7_SPI_USE_INTERRUPTS
type: build