1.新增STM32-SPI驱动。
This commit is contained in:
388
bsp/st/driver/drv_spi.c
Normal file
388
bsp/st/driver/drv_spi.c
Normal file
@@ -0,0 +1,388 @@
|
||||
/*
|
||||
* Copyright (c) 2023, mr-library Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2023-10-8 MacRsh first version
|
||||
*/
|
||||
|
||||
#include "drv_spi.h"
|
||||
|
||||
#if (MR_CFG_SPI == MR_CFG_ENABLE)
|
||||
|
||||
#define PIN_PORT(pin) ((uint8_t)(((pin) >> 4) & 0x0Fu))
|
||||
#define PIN_STPORT(pin) ((GPIO_TypeDef *)(GPIOA_BASE + (0x400u * PIN_PORT(pin))))
|
||||
#define PIN_STPIN(pin) ((uint16_t)(1u << (mr_uint8_t)(pin & 0x0Fu)))
|
||||
|
||||
enum drv_spi_index
|
||||
{
|
||||
#ifdef MR_BSP_SPI_1
|
||||
DRV_SPI_1_INDEX,
|
||||
#endif
|
||||
#ifdef MR_BSP_SPI_2
|
||||
DRV_SPI_2_INDEX,
|
||||
#endif
|
||||
#ifdef MR_BSP_SPI_3
|
||||
DRV_SPI_3_INDEX,
|
||||
#endif
|
||||
#ifdef MR_BSP_SPI_4
|
||||
DRV_SPI_4_INDEX,
|
||||
#endif
|
||||
#ifdef MR_BSP_SPI_5
|
||||
DRV_SPI_5_INDEX,
|
||||
#endif
|
||||
#ifdef MR_BSP_SPI_6
|
||||
DRV_SPI_6_INDEX,
|
||||
#endif
|
||||
};
|
||||
|
||||
static struct drv_spi_bus_data drv_spi_bus_data[] =
|
||||
{
|
||||
#ifdef MR_BSP_SPI_1
|
||||
{"spi1", {0}, SPI1, SPI1_IRQn},
|
||||
#endif
|
||||
#ifdef MR_BSP_SPI_2
|
||||
{"spi2", {0}, SPI2, SPI2_IRQn},
|
||||
#endif
|
||||
#ifdef MR_BSP_SPI_3
|
||||
{"spi3", {0}, SPI3, SPI3_IRQn},
|
||||
#endif
|
||||
#ifdef MR_BSP_SPI_4
|
||||
{"spi4", {0}, SPI4, SPI4_IRQn},
|
||||
#endif
|
||||
#ifdef MR_BSP_SPI_5
|
||||
{"spi5", {0}, SPI5, SPI5_IRQn},
|
||||
#endif
|
||||
#ifdef MR_BSP_SPI_6
|
||||
{"spi6", {0}, SPI6, SPI6_IRQn},
|
||||
#endif
|
||||
};
|
||||
|
||||
static struct mr_spi_bus spi_bus_device[mr_array_num(drv_spi_bus_data)];
|
||||
|
||||
static mr_uint16_t stm32_spi_baud_rate_prescaler(mr_uint32_t pclk_freq, mr_uint32_t baud_rate)
|
||||
{
|
||||
mr_uint32_t psc = pclk_freq / baud_rate;
|
||||
|
||||
if (psc >= 256)
|
||||
{
|
||||
return SPI_BAUDRATEPRESCALER_256;
|
||||
} else if (psc >= 128)
|
||||
{
|
||||
return SPI_BAUDRATEPRESCALER_128;
|
||||
} else if (psc >= 64)
|
||||
{
|
||||
return SPI_BAUDRATEPRESCALER_64;
|
||||
} else if (psc >= 32)
|
||||
{
|
||||
return SPI_BAUDRATEPRESCALER_32;
|
||||
} else if (psc >= 16)
|
||||
{
|
||||
return SPI_BAUDRATEPRESCALER_16;
|
||||
} else if (psc >= 8)
|
||||
{
|
||||
return SPI_BAUDRATEPRESCALER_8;
|
||||
} else if (psc >= 4)
|
||||
{
|
||||
return SPI_BAUDRATEPRESCALER_4;
|
||||
} else if (psc >= 2)
|
||||
{
|
||||
return SPI_BAUDRATEPRESCALER_2;
|
||||
}
|
||||
return SPI_BAUDRATEPRESCALER_2;
|
||||
}
|
||||
|
||||
static mr_err_t drv_spi_configure(mr_spi_bus_t spi_bus, mr_spi_config_t config)
|
||||
{
|
||||
struct drv_spi_bus_data *spi_bus_data = (struct drv_spi_bus_data *)spi_bus->device.data;
|
||||
mr_uint32_t pclk_freq = 0;
|
||||
|
||||
if ((uint32_t)spi_bus_data->instance > APB2PERIPH_BASE)
|
||||
{
|
||||
pclk_freq = HAL_RCC_GetPCLK2Freq();
|
||||
} else
|
||||
{
|
||||
pclk_freq = HAL_RCC_GetPCLK1Freq();
|
||||
}
|
||||
|
||||
spi_bus_data->handle.Instance = spi_bus_data->instance;
|
||||
|
||||
switch (config->host_slave)
|
||||
{
|
||||
case MR_SPI_HOST:
|
||||
{
|
||||
spi_bus_data->handle.Init.Mode = SPI_MODE_MASTER;
|
||||
break;
|
||||
}
|
||||
|
||||
case MR_SPI_SLAVE:
|
||||
{
|
||||
spi_bus_data->handle.Init.Mode = SPI_MODE_SLAVE;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
return MR_ERR_INVALID;
|
||||
}
|
||||
|
||||
switch (config->mode)
|
||||
{
|
||||
case MR_SPI_MODE_0:
|
||||
{
|
||||
spi_bus_data->handle.Init.CLKPolarity = SPI_POLARITY_LOW;
|
||||
spi_bus_data->handle.Init.CLKPhase = SPI_PHASE_1EDGE;
|
||||
break;
|
||||
}
|
||||
|
||||
case MR_SPI_MODE_1:
|
||||
{
|
||||
spi_bus_data->handle.Init.CLKPolarity = SPI_POLARITY_LOW;
|
||||
spi_bus_data->handle.Init.CLKPhase = SPI_PHASE_2EDGE;
|
||||
break;
|
||||
}
|
||||
|
||||
case MR_SPI_MODE_2:
|
||||
{
|
||||
spi_bus_data->handle.Init.CLKPolarity = SPI_POLARITY_HIGH;
|
||||
spi_bus_data->handle.Init.CLKPhase = SPI_PHASE_1EDGE;
|
||||
break;
|
||||
}
|
||||
|
||||
case MR_SPI_MODE_3:
|
||||
{
|
||||
spi_bus_data->handle.Init.CLKPolarity = SPI_POLARITY_HIGH;
|
||||
spi_bus_data->handle.Init.CLKPhase = SPI_PHASE_2EDGE;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
return MR_ERR_INVALID;
|
||||
}
|
||||
|
||||
switch (config->data_bits)
|
||||
{
|
||||
case MR_SPI_DATA_BITS_8:
|
||||
{
|
||||
spi_bus_data->handle.Init.DataSize = SPI_DATASIZE_8BIT;
|
||||
break;
|
||||
}
|
||||
|
||||
case MR_SPI_DATA_BITS_16:
|
||||
{
|
||||
spi_bus_data->handle.Init.DataSize = SPI_DATASIZE_16BIT;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
return MR_ERR_INVALID;
|
||||
}
|
||||
|
||||
switch (config->bit_order)
|
||||
{
|
||||
case MR_SPI_BIT_ORDER_LSB:
|
||||
{
|
||||
spi_bus_data->handle.Init.FirstBit = SPI_FIRSTBIT_LSB;
|
||||
break;
|
||||
}
|
||||
|
||||
case MR_SPI_BIT_ORDER_MSB:
|
||||
{
|
||||
spi_bus_data->handle.Init.FirstBit = SPI_FIRSTBIT_MSB;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
return MR_ERR_INVALID;
|
||||
}
|
||||
|
||||
switch (config->cs_active)
|
||||
{
|
||||
case MR_SPI_CS_ACTIVE_LOW:
|
||||
case MR_SPI_CS_ACTIVE_HIGH:
|
||||
{
|
||||
spi_bus_data->handle.Init.NSS = SPI_NSS_SOFT;
|
||||
break;
|
||||
}
|
||||
|
||||
case MR_SPI_CS_ACTIVE_HARDWARE:
|
||||
{
|
||||
if (config->host_slave == MR_SPI_HOST)
|
||||
{
|
||||
spi_bus_data->handle.Init.NSS = SPI_NSS_HARD_OUTPUT;
|
||||
} else
|
||||
{
|
||||
spi_bus_data->handle.Init.NSS = SPI_NSS_HARD_INPUT;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
return MR_ERR_INVALID;
|
||||
}
|
||||
|
||||
spi_bus_data->handle.Init.BaudRatePrescaler = stm32_spi_baud_rate_prescaler(pclk_freq, config->baud_rate);
|
||||
spi_bus_data->handle.Init.Direction = SPI_DIRECTION_2LINES;
|
||||
spi_bus_data->handle.Init.TIMode = SPI_TIMODE_DISABLE;
|
||||
spi_bus_data->handle.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
|
||||
spi_bus_data->handle.Init.CRCPolynomial = 7;
|
||||
if (HAL_SPI_Init(&spi_bus_data->handle) != HAL_OK)
|
||||
{
|
||||
return MR_ERR_GENERIC;
|
||||
}
|
||||
|
||||
if (config->baud_rate != 0)
|
||||
{
|
||||
__HAL_SPI_ENABLE(&spi_bus_data->handle);
|
||||
} else
|
||||
{
|
||||
__HAL_SPI_DISABLE(&spi_bus_data->handle);
|
||||
}
|
||||
|
||||
if (config->host_slave == MR_SPI_HOST)
|
||||
{
|
||||
HAL_NVIC_SetPriority(spi_bus_data->irq_type, 1, 0);
|
||||
HAL_NVIC_DisableIRQ(spi_bus_data->irq_type);
|
||||
__HAL_UART_DISABLE_IT(&spi_bus_data->handle, SPI_IT_RXNE);
|
||||
} else
|
||||
{
|
||||
HAL_NVIC_SetPriority(spi_bus_data->irq_type, 1, 0);
|
||||
HAL_NVIC_EnableIRQ(spi_bus_data->irq_type);
|
||||
__HAL_UART_ENABLE_IT(&spi_bus_data->handle, SPI_IT_RXNE);
|
||||
}
|
||||
|
||||
return MR_ERR_OK;
|
||||
}
|
||||
|
||||
static void drv_spi_write(mr_spi_bus_t spi_bus, mr_uint32_t data)
|
||||
{
|
||||
struct drv_spi_bus_data *spi_bus_data = (struct drv_spi_bus_data *)spi_bus->device.data;
|
||||
mr_size_t i = 0;
|
||||
|
||||
while (__HAL_SPI_GET_FLAG(&spi_bus_data->handle, SPI_FLAG_TXE) == RESET)
|
||||
{
|
||||
i++;
|
||||
if (i > MR_UINT16_MAX)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
spi_bus_data->instance->DR = data;
|
||||
}
|
||||
|
||||
static mr_uint32_t drv_spi_read(mr_spi_bus_t spi_bus)
|
||||
{
|
||||
struct drv_spi_bus_data *spi_bus_data = (struct drv_spi_bus_data *)spi_bus->device.data;
|
||||
mr_size_t i = 0;
|
||||
|
||||
while (__HAL_SPI_GET_FLAG(&spi_bus_data->handle, SPI_FLAG_RXNE) == RESET)
|
||||
{
|
||||
i++;
|
||||
if (i > MR_UINT16_MAX)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return (mr_uint32_t)spi_bus_data->instance->DR;
|
||||
}
|
||||
|
||||
static void drv_spi_cs_write(mr_spi_bus_t spi_bus, mr_off_t cs_number, mr_level_t level)
|
||||
{
|
||||
if (cs_number > MR_BSP_PIN_NUMBER)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
HAL_GPIO_WritePin(PIN_STPORT(cs_number), PIN_STPIN(cs_number), (GPIO_PinState)level);
|
||||
}
|
||||
|
||||
static mr_level_t drv_spi_cs_read(mr_spi_bus_t spi_bus, mr_off_t cs_number)
|
||||
{
|
||||
if (cs_number > MR_BSP_PIN_NUMBER)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (mr_level_t)HAL_GPIO_ReadPin(PIN_STPORT(cs_number), PIN_STPIN(cs_number));
|
||||
}
|
||||
|
||||
static void drv_spi_isr(mr_spi_bus_t spi_bus)
|
||||
{
|
||||
struct drv_spi_bus_data *spi_bus_data = (struct drv_spi_bus_data *)spi_bus->device.data;
|
||||
|
||||
if (__HAL_UART_GET_FLAG(&spi_bus_data->handle, SPI_FLAG_RXNE) != RESET &&
|
||||
__HAL_UART_GET_IT_SOURCE(&spi_bus_data->handle, SPI_IT_RXNE) != RESET)
|
||||
{
|
||||
mr_spi_bus_isr(spi_bus, MR_SPI_BUS_EVENT_RX_INT);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef MR_BSP_SPI_1
|
||||
void SPI1_IRQHandler(void)
|
||||
{
|
||||
drv_spi_isr(&spi_bus_device[DRV_SPI_1_INDEX]);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef MR_BSP_SPI_2
|
||||
void SPI2_IRQHandler(void)
|
||||
{
|
||||
drv_spi_isr(&spi_bus_device[DRV_SPI_2_INDEX]);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef MR_BSP_SPI_3
|
||||
void SPI3_IRQHandler(void)
|
||||
{
|
||||
drv_spi_isr(&spi_bus_device[DRV_SPI_3_INDEX]);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef MR_BSP_SPI_4
|
||||
void SPI4_IRQHandler(void)
|
||||
{
|
||||
drv_spi_isr(&spi_bus_device[DRV_SPI_4_INDEX]);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef MR_BSP_SPI_5
|
||||
void SPI5_IRQHandler(void)
|
||||
{
|
||||
drv_spi_isr(&spi_bus_device[DRV_SPI_5_INDEX]);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef MR_BSP_SPI_6
|
||||
void SPI6_IRQHandler(void)
|
||||
{
|
||||
drv_spi_isr(&spi_bus_device[DRV_SPI_6_INDEX]);
|
||||
}
|
||||
#endif
|
||||
|
||||
mr_err_t drv_spi_bus_init(void)
|
||||
{
|
||||
static struct mr_spi_bus_ops drv_ops =
|
||||
{
|
||||
drv_spi_configure,
|
||||
drv_spi_write,
|
||||
drv_spi_read,
|
||||
drv_spi_cs_write,
|
||||
drv_spi_cs_read,
|
||||
};
|
||||
mr_size_t count = mr_array_num(spi_bus_device);
|
||||
mr_err_t ret = MR_ERR_OK;
|
||||
|
||||
while (count--)
|
||||
{
|
||||
ret =
|
||||
mr_spi_bus_add(&spi_bus_device[count], drv_spi_bus_data[count].name, &drv_ops, &drv_spi_bus_data[count]);
|
||||
MR_ASSERT(ret == MR_ERR_OK);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
MR_INIT_DRIVER_EXPORT(drv_spi_bus_init);
|
||||
|
||||
#endif
|
||||
33
bsp/st/driver/drv_spi.h
Normal file
33
bsp/st/driver/drv_spi.h
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (c) 2023, mr-library Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2023-10-8 MacRsh first version
|
||||
*/
|
||||
|
||||
#ifndef _DRV_SPI_H_
|
||||
#define _DRV_SPI_H_
|
||||
|
||||
#include "device/spi.h"
|
||||
#include "mrboard.h"
|
||||
|
||||
#if (MR_CFG_SPI == MR_CFG_ENABLE)
|
||||
|
||||
/**
|
||||
* @struct Driver spi bus data
|
||||
*/
|
||||
struct drv_spi_bus_data
|
||||
{
|
||||
const char *name;
|
||||
|
||||
SPI_HandleTypeDef handle;
|
||||
SPI_TypeDef *instance;
|
||||
IRQn_Type irq_type;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* _DRV_SPI_H_ */
|
||||
Reference in New Issue
Block a user