前言
配置功能参考rt-thread驱动代码 将中断配置和dma配置单独分开管理
代码
中断管理
头文件
# ifndef TX_STM32_F4_DRV_NVIC_OS_H
# define TX_STM32_F4_DRV_NVIC_OS_H
# include "drv_common.h"
void stm32_nvic_common_enable ( uint32_t instance, uint32_t preempt, uint32_t sub) ;
void stm32_nvic_common_disable ( uint32_t instance) ;
uint8_t stm32_nvic_common_enabled_check ( uint32_t instance) ;
# endif
源文件
# include "drv_nvic_os.h"
enum stm32_irq_op_enum {
OPEN_IRQn,
CLOSE_IRQn,
READ_IRQn
} ;
static uint32_t stm32_nvic_common ( uint32_t instance, uint32_t preempt, uint32_t sub, enum stm32_irq_op_enum mode) {
uint32_t irq;
switch ( instance) {
# define irq_set ( IRQn) { irq= IRQn; } break
case ( uint32_t ) SPI1: irq_set ( SPI1_IRQn) ;
case ( uint32_t ) SPI2: irq_set ( SPI2_IRQn) ;
case ( uint32_t ) SPI3: irq_set ( SPI3_IRQn) ;
case ( uint32_t ) USART1: irq_set ( USART1_IRQn) ;
case ( uint32_t ) USART2: irq_set ( USART2_IRQn) ;
case ( uint32_t ) USART3: irq_set ( USART3_IRQn) ;
case ( uint32_t ) UART4: irq_set ( UART4_IRQn) ;
case ( uint32_t ) UART5: irq_set ( UART5_IRQn) ;
case ( uint32_t ) DMA2_Stream0: irq_set ( DMA2_Stream0_IRQn) ;
case ( uint32_t ) DMA2_Stream1: irq_set ( DMA2_Stream1_IRQn) ;
case ( uint32_t ) DMA2_Stream2: irq_set ( DMA2_Stream2_IRQn) ;
case ( uint32_t ) DMA2_Stream3: irq_set ( DMA2_Stream3_IRQn) ;
case ( uint32_t ) DMA2_Stream4: irq_set ( DMA2_Stream4_IRQn) ;
case ( uint32_t ) DMA2_Stream5: irq_set ( DMA2_Stream5_IRQn) ;
case ( uint32_t ) DMA2_Stream6: irq_set ( DMA2_Stream6_IRQn) ;
case ( uint32_t ) DMA2_Stream7: irq_set ( DMA2_Stream7_IRQn) ;
case ( uint32_t ) DMA1_Stream0: irq_set ( DMA1_Stream0_IRQn) ;
case ( uint32_t ) DMA1_Stream1: irq_set ( DMA1_Stream1_IRQn) ;
case ( uint32_t ) DMA1_Stream2: irq_set ( DMA1_Stream2_IRQn) ;
case ( uint32_t ) DMA1_Stream3: irq_set ( DMA1_Stream3_IRQn) ;
case ( uint32_t ) DMA1_Stream4: irq_set ( DMA1_Stream4_IRQn) ;
case ( uint32_t ) DMA1_Stream5: irq_set ( DMA1_Stream5_IRQn) ;
case ( uint32_t ) DMA1_Stream6: irq_set ( DMA1_Stream6_IRQn) ;
case ( uint32_t ) DMA1_Stream7: irq_set ( DMA1_Stream7_IRQn) ;
default : {
return UINT32_MAX;
}
}
# undef irq_set
switch ( mode) {
case OPEN_IRQn: {
HAL_NVIC_SetPriority ( irq, preempt, sub) ;
HAL_NVIC_EnableIRQ ( irq) ;
}
break ;
case CLOSE_IRQn: {
HAL_NVIC_DisableIRQ ( irq) ;
}
break ;
default : {
break ;
}
}
return irq;
}
void stm32_nvic_common_enable ( uint32_t instance, uint32_t preempt, uint32_t sub) {
stm32_nvic_common ( instance, preempt, sub, OPEN_IRQn) ;
}
void stm32_nvic_common_disable ( uint32_t instance) {
stm32_nvic_common ( instance, 0 , 0 , CLOSE_IRQn) ;
}
uint8_t stm32_nvic_common_enabled_check ( uint32_t instance) {
uint32_t irq = stm32_nvic_common ( instance, 0 , 0 , READ_IRQn) ;
return NVIC_GetEnableIRQ ( irq) ;
}
DMA管理
头文件
# ifndef TX_STM32_F4_DRV_DMA_OS_H
# define TX_STM32_F4_DRV_DMA_OS_H
# include "drv_common.h"
struct stm32_dma_info {
uint32_t instance;
DMA_HandleTypeDef * dma_tx;
DMA_HandleTypeDef * dma_rx;
} ;
struct stm32_dma_info * dma_info_get ( uint32_t instance) ;
void dma_clk_enable ( DMA_HandleTypeDef * handle) ;
# endif
源文件
# include "drv_dma_os.h"
static DMA_HandleTypeDef spi1_dma_tx = { . Instance= DMA2_Stream3, . Init. Channel= DMA_CHANNEL_3} ;
static DMA_HandleTypeDef spi1_dma_rx = { . Instance= DMA2_Stream0, . Init. Channel= DMA_CHANNEL_3} ;
static struct stm32_dma_info dma_info_map[ ] = {
{ ( uint32_t ) SPI1, & spi1_dma_tx, & spi1_dma_rx}
} ;
# define DMA_MAP_CNT ( sizeof ( dma_info_map) / sizeof ( dma_info_map[ 0 ] ) )
struct stm32_dma_info * dma_info_get ( uint32_t instance) {
for ( int i = 0 ; i < DMA_MAP_CNT; ++ i) {
if ( dma_info_map[ i] . instance == instance) {
return dma_info_map + i;
}
}
return NULL ;
}
void dma_clk_enable ( DMA_HandleTypeDef * handle) {
switch ( ( uint32_t ) handle-> Instance) {
case ( uint32_t ) DMA2_Stream0:
case ( uint32_t ) DMA2_Stream1:
case ( uint32_t ) DMA2_Stream2:
case ( uint32_t ) DMA2_Stream3:
case ( uint32_t ) DMA2_Stream4:
case ( uint32_t ) DMA2_Stream5:
case ( uint32_t ) DMA2_Stream6:
case ( uint32_t ) DMA2_Stream7:
__HAL_RCC_DMA2_CLK_ENABLE ( ) ;
break ;
case ( uint32_t ) DMA1_Stream0:
case ( uint32_t ) DMA1_Stream1:
case ( uint32_t ) DMA1_Stream2:
case ( uint32_t ) DMA1_Stream3:
case ( uint32_t ) DMA1_Stream4:
case ( uint32_t ) DMA1_Stream5:
case ( uint32_t ) DMA1_Stream6:
case ( uint32_t ) DMA1_Stream7:
__HAL_RCC_DMA1_CLK_ENABLE ( ) ;
break ;
default :
return ;
}
}
void DMA2_Stream0_IRQHandler ( void ) {
TX_INTERRUPT_SAVE_AREA
TX_DISABLE
HAL_DMA_IRQHandler ( & spi1_dma_rx) ;
TX_RESTORE
}
void DMA2_Stream3_IRQHandler ( void ) {
TX_INTERRUPT_SAVE_AREA
TX_DISABLE
HAL_DMA_IRQHandler ( & spi1_dma_tx) ;
TX_RESTORE
}
SPI驱动
头文件
# ifndef TX_STM32_F4_DRV_SPI_OS_H
# define TX_STM32_F4_DRV_SPI_OS_H
# include "drv_common.h"
# define SPI_CONTROLLER_NUM 1
# define SPI_CPHA ( 1 << 0 )
# define SPI_CPOL ( 1 << 1 )
# define SPI_LSB ( 0 << 2 )
# define SPI_MSB ( 1 << 2 )
# define SPI_MASTER ( 0 << 3 )
# define SPI_SLAVE ( 1 << 3 )
# define SPI_CS_HIGH ( 1 << 4 )
# define SPI_NO_CS ( 1 << 5 )
# define SPI_3WIRE ( 1 << 6 )
# define SPI_READY ( 1 << 7 )
# define SPI_MODE_MASK ( SPI_CPHA | SPI_CPOL | SPI_MSB | SPI_SLAVE | SPI_CS_HIGH | SPI_NO_CS | SPI_3WIRE | SPI_READY)
# define SPI_MODE_0 ( 0 | 0 )
# define SPI_MODE_1 ( 0 | SPI_CPHA)
# define SPI_MODE_2 ( SPI_CPOL | 0 )
# define SPI_MODE_3 ( SPI_CPOL | SPI_CPHA)
# define spi_lock_init ( controller) ( ( controller) -> lock_obj)
# define spi_lock ( controller)
# define spi_unlock ( controller)
struct stm32_spi_configuration {
uint8_t mode;
uint8_t data_width;
uint16_t reserved;
uint32_t max_hz;
} ;
struct stm32_spi_controller {
SPI_HandleTypeDef handle;
uint8_t mode;
volatile uint32_t cpt_flag;
struct {
GPIO_TypeDef * port;
uint32_t pin;
} cs;
void * lock_obj;
} ;
struct spi_message {
const void * send_buf;
void * recv_buf;
size_t length;
struct spi_message * next;
unsigned cs_take: 1 ;
unsigned cs_release: 1 ;
} ;
void bsp_SpiConfig ( SPI_TypeDef * spi, struct stm32_spi_configuration * cfg) ;
void bsp_SpiDmaEnable ( SPI_TypeDef * spi, uint8_t tx_dma_flag, uint8_t rx_dma_flag) ;
void bsp_SpiDmaParSet ( SPI_TypeDef * spi, DMA_InitTypeDef * tx_cfg, DMA_InitTypeDef * rx_cfg) ;
void bsp_SpiCsParSet ( SPI_TypeDef * spi, GPIO_TypeDef * port, uint32_t pin) ;
void bsp_InitSpi ( SPI_TypeDef * spi, uint8_t it_flag) ;
HAL_StatusTypeDef stm32_spi_data_trans ( SPI_TypeDef * spi, uint8_t * write_buf, uint8_t * read_buf, uint16_t len) ;
uint32_t stm32_spi_trans ( SPI_TypeDef * spi, struct spi_message * msg) ;
struct spi_message * spi_transfer_message ( SPI_TypeDef * spi, struct spi_message * message) ;
uint8_t spi_send_then_recv ( SPI_TypeDef * spi,
const void * send_buf, size_t send_length,
void * recv_buf, size_t recv_length) ;
uint8_t spi_send_then_send ( SPI_TypeDef * spi,
const void * send_buf1, size_t send_length1,
const void * send_buf2, size_t send_length2) ;
uint32_t spi_transfer ( SPI_TypeDef * spi, const void * send_buf, void * recv_buf, size_t length) ;
uint8_t spi_sendrecv8 ( SPI_TypeDef * spi, uint8_t senddata, uint8_t * recvdata) ;
inline rt_size_t spi_recv ( SPI_TypeDef * spi, void * recv_buf, size_t length) {
return spi_transfer ( spi, RT_NULL, recv_buf, length) ;
}
inline rt_size_t spi_send ( SPI_TypeDef * spi, const void * send_buf, size_t length) {
return spi_transfer ( spi, send_buf, RT_NULL, length) ;
}
# endif
源文件
# include "drv_spi_os.h"
# include "drv_dma_os.h"
# include "drv_gpio.h"
# include "drv_nvic_os.h"
enum {
TRANSFER_WAIT,
TRANSFER_COMPLETE,
TRANSFER_ERROR
} ;
enum {
SPI1_IDX = 0 ,
SPI2_IDX = 1 ,
SPI3_IDX = 2 ,
} ;
static struct stm32_spi_controller controller[ SPI_CONTROLLER_NUM] = { 0 } ;
static inline int spi_idx_get ( SPI_TypeDef * spi) {
# define spi_ret_idx ( v) { return v; } break
switch ( ( uint32_t ) spi) {
case ( uint32_t ) SPI1: spi_ret_idx ( SPI1_IDX) ;
case ( uint32_t ) SPI2: spi_ret_idx ( SPI2_IDX) ;
case ( uint32_t ) SPI3: spi_ret_idx ( SPI3_IDX) ;
}
# undef spi_ret_idx
return - 1 ;
}
static void spi_cs_pin_init ( SPI_TypeDef * spi) {
int idx;
idx = spi_idx_get ( spi) ;
if ( idx < 0 || idx >= SPI_CONTROLLER_NUM) return ;
if ( controller[ idx] . cs. port) {
GPIO_InitTypeDef gpio_init;
bsp_GpioClkEnable ( controller[ idx] . cs. port) ;
gpio_init. Mode = GPIO_MODE_OUTPUT_PP;
gpio_init. Pull = GPIO_NOPULL;
gpio_init. Speed = GPIO_SPEED_HIGH;
gpio_init. Pin = controller[ idx] . cs. pin;
HAL_GPIO_Init ( controller[ idx] . cs. port, & gpio_init) ;
if ( controller[ idx] . mode & SPI_CS_HIGH) {
HAL_GPIO_WritePin ( controller[ idx] . cs. port, controller[ idx] . cs. pin, GPIO_PIN_RESET) ;
} else {
HAL_GPIO_WritePin ( controller[ idx] . cs. port, controller[ idx] . cs. pin, GPIO_PIN_SET) ;
}
}
}
static inline void * stm32_spi_lock_init ( struct stm32_spi_controller * control) {
return spi_lock_init ( control) ;
}
static inline void stm32_spi_lock ( struct stm32_spi_controller * control) {
spi_lock ( control) ;
}
static inline void stm32_spi_unlock ( struct stm32_spi_controller * control) {
spi_unlock ( control) ;
}
static inline void spi_dma_tx_default_set ( DMA_HandleTypeDef * dma_tx) {
dma_tx-> Init. FIFOMode = DMA_FIFOMODE_DISABLE;
dma_tx-> Init. FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
dma_tx-> Init. MemBurst = DMA_MBURST_SINGLE;
dma_tx-> Init. PeriphBurst = DMA_PBURST_SINGLE;
dma_tx-> Init. Direction = DMA_MEMORY_TO_PERIPH;
dma_tx-> Init. PeriphInc = DMA_PINC_DISABLE;
dma_tx-> Init. MemInc = DMA_MINC_ENABLE;
dma_tx-> Init. PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
dma_tx-> Init. MemDataAlignment = DMA_MDATAALIGN_BYTE;
dma_tx-> Init. Mode = DMA_NORMAL;
dma_tx-> Init. Priority = DMA_PRIORITY_MEDIUM;
}
static inline void spi_dma_rx_default_set ( DMA_HandleTypeDef * dma_rx) {
dma_rx-> Init. FIFOMode = DMA_FIFOMODE_DISABLE;
dma_rx-> Init. FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
dma_rx-> Init. MemBurst = DMA_MBURST_SINGLE;
dma_rx-> Init. PeriphBurst = DMA_PBURST_SINGLE;
dma_rx-> Init. Direction = DMA_PERIPH_TO_MEMORY;
dma_rx-> Init. PeriphInc = DMA_PINC_DISABLE;
dma_rx-> Init. MemInc = DMA_MINC_ENABLE;
dma_rx-> Init. PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
dma_rx-> Init. MemDataAlignment = DMA_MDATAALIGN_BYTE;
dma_rx-> Init. Mode = DMA_NORMAL;
dma_rx-> Init. Priority = DMA_PRIORITY_MEDIUM;
}
void bsp_SpiConfig ( SPI_TypeDef * spi, struct stm32_spi_configuration * cfg) {
int idx;
idx = spi_idx_get ( spi) ;
if ( idx < 0 || idx >= SPI_CONTROLLER_NUM) return ;
SPI_HandleTypeDef * spi_handle = & ( controller[ idx] . handle) ;
if ( cfg == NULL ) {
struct stm32_spi_configuration spi_conf;
{
spi_conf. mode = SPI_MASTER | SPI_MSB | SPI_MODE_0;
spi_conf. data_width = 8 ;
spi_conf. max_hz = 20 * 1000 * 1000 ;
}
cfg = & spi_conf;
}
controller[ idx] . mode = cfg-> mode;
spi_handle-> Instance = spi;
spi_handle-> Init. Mode = cfg-> mode & SPI_SLAVE ? SPI_MODE_SLAVE : SPI_MODE_MASTER;
spi_handle-> Init. Direction = cfg-> mode & SPI_3WIRE ? SPI_DIRECTION_1LINE : SPI_DIRECTION_2LINES;
spi_handle-> Init. DataSize = cfg-> data_width == 8 ? SPI_DATASIZE_8BIT : SPI_DATASIZE_16BIT;
spi_handle-> Init. CLKPhase = cfg-> mode & SPI_CPHA ? SPI_PHASE_2EDGE : SPI_PHASE_1EDGE;
spi_handle-> Init. CLKPolarity = cfg-> mode & SPI_CPOL ? SPI_POLARITY_HIGH : SPI_POLARITY_LOW;
spi_handle-> Init. FirstBit = cfg-> mode & SPI_MSB ? SPI_FIRSTBIT_MSB : SPI_FIRSTBIT_LSB;
spi_handle-> Init. NSS = cfg-> mode & SPI_NO_CS ? SPI_NSS_HARD_OUTPUT : SPI_NSS_SOFT;
uint32_t SPI_APB_CLOCK = HAL_RCC_GetPCLK2Freq ( ) ;
if ( cfg-> max_hz >= SPI_APB_CLOCK / 2 ) {
spi_handle-> Init. BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;
} else if ( cfg-> max_hz >= SPI_APB_CLOCK / 4 ) {
spi_handle-> Init. BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4;
} else if ( cfg-> max_hz >= SPI_APB_CLOCK / 8 ) {
spi_handle-> Init. BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8;
} else if ( cfg-> max_hz >= SPI_APB_CLOCK / 16 ) {
spi_handle-> Init. BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16;
} else if ( cfg-> max_hz >= SPI_APB_CLOCK / 32 ) {
spi_handle-> Init. BaudRatePrescaler = SPI_BAUDRATEPRESCALER_32;
} else if ( cfg-> max_hz >= SPI_APB_CLOCK / 64 ) {
spi_handle-> Init. BaudRatePrescaler = SPI_BAUDRATEPRESCALER_64;
} else if ( cfg-> max_hz >= SPI_APB_CLOCK / 128 ) {
spi_handle-> Init. BaudRatePrescaler = SPI_BAUDRATEPRESCALER_128;
} else {
spi_handle-> Init. BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256;
}
spi_handle-> Init. TIMode = SPI_TIMODE_DISABLE;
spi_handle-> Init. CRCCalculation = SPI_CRCCALCULATION_DISABLE;
spi_handle-> State = HAL_SPI_STATE_RESET;
}
void bsp_SpiDmaEnable ( SPI_TypeDef * spi, uint8_t tx_dma_flag, uint8_t rx_dma_flag) {
int idx;
idx = spi_idx_get ( spi) ;
if ( idx < 0 || idx >= SPI_CONTROLLER_NUM) return ;
struct stm32_dma_info * info = dma_info_get ( ( uint32_t ) spi) ;
if ( info == NULL ) {
Error_Handler ( ) ;
return ;
}
if ( tx_dma_flag) {
controller[ idx] . handle. hdmatx = info-> dma_tx;
info-> dma_tx-> Parent = & ( controller[ idx] . handle) ;
}
if ( rx_dma_flag) {
controller[ idx] . handle. hdmarx = info-> dma_rx;
info-> dma_rx-> Parent = & ( controller[ idx] . handle) ;
}
}
void bsp_SpiDmaParSet ( SPI_TypeDef * spi, DMA_InitTypeDef * tx_cfg, DMA_InitTypeDef * rx_cfg) {
int idx;
idx = spi_idx_get ( spi) ;
if ( idx < 0 || idx >= SPI_CONTROLLER_NUM) return ;
SPI_HandleTypeDef * spi_handle = & ( controller[ idx] . handle) ;
if ( spi_handle-> hdmatx) {
if ( tx_cfg == NULL ) {
spi_dma_tx_default_set ( spi_handle-> hdmatx) ;
} else {
spi_handle-> hdmatx-> Init. FIFOMode = tx_cfg-> FIFOMode;
spi_handle-> hdmatx-> Init. FIFOThreshold = tx_cfg-> FIFOThreshold;
spi_handle-> hdmatx-> Init. MemBurst = tx_cfg-> MemBurst;
spi_handle-> hdmatx-> Init. PeriphBurst = tx_cfg-> PeriphBurst;
spi_handle-> hdmatx-> Init. Direction = tx_cfg-> Direction;
spi_handle-> hdmatx-> Init. PeriphInc = tx_cfg-> PeriphInc;
spi_handle-> hdmatx-> Init. MemInc = tx_cfg-> MemInc;
spi_handle-> hdmatx-> Init. PeriphDataAlignment = tx_cfg-> PeriphDataAlignment;
spi_handle-> hdmatx-> Init. MemDataAlignment = tx_cfg-> MemDataAlignment;
spi_handle-> hdmatx-> Init. Mode = tx_cfg-> Mode;
spi_handle-> hdmatx-> Init. Priority = tx_cfg-> Priority;
}
}
if ( spi_handle-> hdmarx) {
if ( rx_cfg == NULL ) {
spi_dma_rx_default_set ( spi_handle-> hdmarx) ;
} else {
spi_handle-> hdmarx-> Init. FIFOMode = rx_cfg-> FIFOMode;
spi_handle-> hdmarx-> Init. FIFOThreshold = rx_cfg-> FIFOThreshold;
spi_handle-> hdmarx-> Init. MemBurst = rx_cfg-> MemBurst;
spi_handle-> hdmarx-> Init. PeriphBurst = rx_cfg-> PeriphBurst;
spi_handle-> hdmarx-> Init. Direction = rx_cfg-> Direction;
spi_handle-> hdmarx-> Init. PeriphInc = rx_cfg-> PeriphInc;
spi_handle-> hdmarx-> Init. MemInc = rx_cfg-> MemInc;
spi_handle-> hdmarx-> Init. PeriphDataAlignment = rx_cfg-> PeriphDataAlignment;
spi_handle-> hdmarx-> Init. MemDataAlignment = rx_cfg-> MemDataAlignment;
spi_handle-> hdmarx-> Init. Mode = rx_cfg-> Mode;
spi_handle-> hdmarx-> Init. Priority = rx_cfg-> Priority;
}
}
}
void bsp_SpiCsParSet ( SPI_TypeDef * spi, GPIO_TypeDef * port, uint32_t pin) {
int idx;
idx = spi_idx_get ( spi) ;
if ( idx < 0 || idx >= SPI_CONTROLLER_NUM) return ;
controller[ idx] . cs. port = port;
controller[ idx] . cs. pin = pin;
}
void bsp_InitSpi ( SPI_TypeDef * spi, uint8_t it_flag) {
int idx;
idx = spi_idx_get ( spi) ;
if ( idx < 0 || idx >= SPI_CONTROLLER_NUM) return ;
controller[ idx] . lock_obj = stm32_spi_lock_init ( & ( controller[ idx] ) ) ;
spi_cs_pin_init ( spi) ;
HAL_SPI_Init ( & ( controller[ idx] . handle) ) ;
if ( controller[ idx] . handle. hdmatx) {
stm32_nvic_common_enable ( ( uint32_t ) ( controller[ idx] . handle. hdmatx-> Instance) , 1 , 0 ) ;
}
if ( controller[ idx] . handle. hdmarx) {
stm32_nvic_common_enable ( ( uint32_t ) ( controller[ idx] . handle. hdmarx-> Instance) , 1 , 0 ) ;
}
if ( it_flag) {
stm32_nvic_common_enable ( ( uint32_t ) spi, 2 , 0 ) ;
}
}
HAL_StatusTypeDef stm32_spi_data_trans ( SPI_TypeDef * spi, uint8_t * write_buf, uint8_t * read_buf, uint16_t len) {
HAL_StatusTypeDef state = HAL_ERROR;
int idx;
idx = spi_idx_get ( spi) ;
if ( idx < 0 || idx >= SPI_CONTROLLER_NUM) return HAL_ERROR;
SPI_HandleTypeDef * handle_ptr = & ( controller[ idx] . handle) ;
ATOMIC_SET_BIT ( controller[ idx] . cpt_flag, TRANSFER_WAIT) ;
if ( write_buf && read_buf) {
if ( handle_ptr-> hdmatx && handle_ptr-> hdmarx) {
state = HAL_SPI_TransmitReceive_DMA ( handle_ptr, write_buf, read_buf, len) ;
} else if ( stm32_nvic_common_enabled_check ( ( uint32_t ) spi) ) {
state = HAL_SPI_TransmitReceive_IT ( handle_ptr, write_buf, read_buf, len) ;
} else {
state = HAL_SPI_TransmitReceive ( handle_ptr, write_buf, read_buf, len, 1000 ) ;
controller[ idx] . cpt_flag = state == HAL_OK ? TRANSFER_COMPLETE : TRANSFER_ERROR;
}
} else if ( write_buf) {
if ( handle_ptr-> hdmatx) {
state = HAL_SPI_Transmit_DMA ( handle_ptr, write_buf, len) ;
} else if ( stm32_nvic_common_enabled_check ( ( uint32_t ) spi) ) {
state = HAL_SPI_Transmit_IT ( handle_ptr, write_buf, len) ;
} else {
state = HAL_SPI_Transmit ( handle_ptr, write_buf, len, 1000 ) ;
controller[ idx] . cpt_flag = state == HAL_OK ? TRANSFER_COMPLETE : TRANSFER_ERROR;
}
} else if ( read_buf) {
if ( handle_ptr-> hdmarx) {
state = HAL_SPI_Receive_DMA ( handle_ptr, read_buf, len) ;
} else if ( stm32_nvic_common_enabled_check ( ( uint32_t ) spi) ) {
state = HAL_SPI_Receive_IT ( handle_ptr, read_buf, len) ;
} else {
state = HAL_SPI_Receive ( handle_ptr, read_buf, len, 1000 ) ;
controller[ idx] . cpt_flag = state == HAL_OK ? TRANSFER_COMPLETE : TRANSFER_ERROR;
}
}
return state;
}
uint32_t stm32_spi_trans ( SPI_TypeDef * spi, struct spi_message * msg) {
int idx;
idx = spi_idx_get ( spi) ;
if ( idx < 0 || idx >= SPI_CONTROLLER_NUM) return 0 ;
rt_size_t message_length, already_send_length;
rt_uint16_t send_length;
rt_uint8_t * recv_buf;
const uint8_t * send_buf;
struct stm32_spi_controller * control = & controller[ idx] ;
if ( msg-> cs_take && ! ( control-> mode & SPI_NO_CS) ) {
{
if ( control-> mode & SPI_CS_HIGH)
HAL_GPIO_WritePin ( control-> cs. port, control-> cs. pin, GPIO_PIN_SET) ;
else
HAL_GPIO_WritePin ( control-> cs. port, control-> cs. pin, GPIO_PIN_RESET) ;
}
}
message_length = msg-> length;
while ( message_length) {
if ( message_length > 65535 ) {
send_length = 65535 ;
message_length = message_length - 65535 ;
} else {
send_length = message_length;
message_length = 0 ;
}
already_send_length = msg-> length - send_length - message_length;
send_buf = ( uint8_t * ) msg-> send_buf + already_send_length;
recv_buf = ( uint8_t * ) msg-> recv_buf + already_send_length;
stm32_spi_data_trans ( spi, ( uint8_t * ) send_buf, recv_buf, send_length) ;
while ( control-> cpt_flag == TRANSFER_WAIT) ;
if ( control-> cpt_flag == TRANSFER_ERROR) {
msg-> length = 0 ;
}
}
if ( msg-> cs_release && ! ( control-> mode & SPI_NO_CS) ) {
{
if ( control-> mode & SPI_CS_HIGH)
HAL_GPIO_WritePin ( control-> cs. port, control-> cs. pin, GPIO_PIN_RESET) ;
else
HAL_GPIO_WritePin ( control-> cs. port, control-> cs. pin, GPIO_PIN_SET) ;
}
}
return msg-> length;
}
__attribute__ ( ( used) ) void SPI1_IRQHandler ( void ) {
TX_INTERRUPT_SAVE_AREA
TX_DISABLE
HAL_SPI_IRQHandler ( & controller[ SPI1_IDX] . handle) ;
TX_RESTORE
}
void HAL_SPI_TxCpltCallback ( SPI_HandleTypeDef * hspi) {
struct stm32_spi_controller * control = rt_container_of ( hspi, struct stm32_spi_controller , handle) ;
control-> cpt_flag = TRANSFER_COMPLETE;
}
void HAL_SPI_RxCpltCallback ( SPI_HandleTypeDef * hspi) {
struct stm32_spi_controller * control = rt_container_of ( hspi, struct stm32_spi_controller , handle) ;
control-> cpt_flag = TRANSFER_COMPLETE;
}
void HAL_SPI_TxRxCpltCallback ( SPI_HandleTypeDef * hspi) {
struct stm32_spi_controller * control = rt_container_of ( hspi, struct stm32_spi_controller , handle) ;
control-> cpt_flag = TRANSFER_COMPLETE;
}
void HAL_SPI_ErrorCallback ( SPI_HandleTypeDef * hspi) {
struct stm32_spi_controller * control = rt_container_of ( hspi, struct stm32_spi_controller , handle) ;
control-> cpt_flag = TRANSFER_ERROR;
}
static void spi_lock_get ( SPI_TypeDef * spi) {
int idx;
idx = spi_idx_get ( spi) ;
if ( idx < 0 || idx >= SPI_CONTROLLER_NUM) return ;
stm32_spi_lock ( & controller[ idx] ) ;
}
static void spi_lock_put ( SPI_TypeDef * spi) {
int idx;
idx = spi_idx_get ( spi) ;
if ( idx < 0 || idx >= SPI_CONTROLLER_NUM) return ;
stm32_spi_unlock ( & controller[ idx] ) ;
}
struct spi_message * spi_transfer_message ( SPI_TypeDef * spi, struct spi_message * message) {
uint32_t result;
struct spi_message * index;
index = message;
spi_lock_get ( spi) ;
while ( index != RT_NULL) {
result = stm32_spi_trans ( spi, index) ;
if ( result != index-> length) {
LOG_E ( "transfer error" ) ;
break ;
}
index = index-> next;
}
spi_lock_put ( spi) ;
return index;
}
uint8_t spi_send_then_recv ( SPI_TypeDef * spi,
const void * send_buf, size_t send_length,
void * recv_buf, size_t recv_length) {
uint8_t result = 0 ;
struct spi_message message;
spi_lock_get ( spi) ;
{
message. send_buf = send_buf;
message. recv_buf = RT_NULL;
message. length = send_length;
message. cs_take = 1 ;
message. cs_release = 0 ;
message. next = RT_NULL;
if ( stm32_spi_trans ( spi, & message) != message. length) {
LOG_E ( "SPI device transfer failed" ) ;
result = 1 ;
goto __exit;
}
message. send_buf = RT_NULL;
message. recv_buf = recv_buf;
message. length = recv_length;
message. cs_take = 0 ;
message. cs_release = 1 ;
message. next = RT_NULL;
if ( stm32_spi_trans ( spi, & message) != message. length) {
LOG_E ( "SPI device transfer failed" ) ;
goto __exit;
}
result = RT_EOK;
}
__exit:
spi_lock_put ( spi) ;
return result;
}
uint8_t spi_send_then_send ( SPI_TypeDef * spi, const void * send_buf1, size_t send_length1, const void * send_buf2,
size_t send_length2) {
uint8_t result = 0 ;
struct spi_message message;
spi_lock_get ( spi) ;
{
message. send_buf = send_buf1;
message. recv_buf = RT_NULL;
message. length = send_length1;
message. cs_take = 1 ;
message. cs_release = 0 ;
message. next = RT_NULL;
if ( stm32_spi_trans ( spi, & message) != message. length) {
LOG_E ( "SPI device transfer failed" ) ;
result = 1 ;
goto __exit;
}
message. send_buf = send_buf2;
message. recv_buf = RT_NULL;
message. length = send_length2;
message. cs_take = 0 ;
message. cs_release = 1 ;
message. next = RT_NULL;
if ( stm32_spi_trans ( spi, & message) != message. length) {
LOG_E ( "SPI device transfer failed" ) ;
result = 1 ;
goto __exit;
}
result = 0 ;
}
__exit:
spi_lock_put ( spi) ;
return result;
}
uint32_t spi_transfer ( SPI_TypeDef * spi, const void * send_buf, void * recv_buf, size_t length) {
uint32_t result;
struct spi_message message;
spi_lock_get ( spi) ;
{
message. send_buf = send_buf;
message. recv_buf = recv_buf;
message. length = length;
message. cs_take = 1 ;
message. cs_release = 1 ;
message. next = RT_NULL;
if ( stm32_spi_trans ( spi, & message) != message. length) {
LOG_E ( "SPI device transfer failed" ) ;
result = 0 ;
goto __exit;
}
result = message. length;
}
__exit:
spi_lock_put ( spi) ;
return result;
}
uint8_t spi_sendrecv8 ( SPI_TypeDef * spi, uint8_t senddata, uint8_t * recvdata) {
return spi_transfer ( spi, & senddata, recvdata, 1 ) ;
}
SPI的IO驱动
# include "board.h"
# include "drv_nvic_os.h"
# include "drv_dma_os.h"
void HAL_SPI_MspInit ( SPI_HandleTypeDef* hspi)
{
GPIO_InitTypeDef GPIO_InitStruct = { 0 } ;
if ( hspi-> Instance== SPI1)
{
__HAL_RCC_SPI1_CLK_ENABLE ( ) ;
__HAL_RCC_GPIOB_CLK_ENABLE ( ) ;
GPIO_InitStruct. Pin = GPIO_PIN_3| GPIO_PIN_4| GPIO_PIN_5;
GPIO_InitStruct. Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct. Pull = GPIO_NOPULL;
GPIO_InitStruct. Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct. Alternate = GPIO_AF5_SPI1;
HAL_GPIO_Init ( GPIOB, & GPIO_InitStruct) ;
if ( hspi-> hdmatx) {
dma_clk_enable ( hspi-> hdmatx) ;
HAL_DMA_Init ( hspi-> hdmatx) ;
}
if ( hspi-> hdmarx) {
dma_clk_enable ( hspi-> hdmarx) ;
HAL_DMA_Init ( hspi-> hdmarx) ;
}
}
}
void HAL_SPI_MspDeInit ( SPI_HandleTypeDef * hspi) {
if ( hspi-> Instance== SPI1)
{
__HAL_RCC_SPI1_CLK_DISABLE ( ) ;
HAL_GPIO_DeInit ( GPIOB, GPIO_PIN_3| GPIO_PIN_4| GPIO_PIN_5) ;
if ( hspi-> hdmatx) {
HAL_DMA_DeInit ( hspi-> hdmatx) ;
}
if ( hspi-> hdmarx) {
HAL_DMA_DeInit ( hspi-> hdmarx) ;
}
}
}
测试
说明,如果dma和中断同时打开,底层逻辑优先采用dma的方式
使用DMA的方式,中断关闭(推荐,如果使用dma的话,中断就没有必要打开)
bsp_SpiConfig ( SPI1, NULL ) ;
bsp_SpiDmaEnable ( SPI1, 1 , 1 ) ;
bsp_SpiDmaParSet ( SPI1, NULL , NULL ) ;
bsp_SpiCsParSet ( SPI1, GPIOB, GPIO_PIN_14) ;
bsp_InitSpi ( SPI1, 0 ) ;
使用DMA的方式。中断打开
bsp_SpiConfig ( SPI1, NULL ) ;
bsp_SpiDmaEnable ( SPI1, 1 , 1 ) ;
bsp_SpiDmaParSet ( SPI1, NULL , NULL ) ;
bsp_SpiCsParSet ( SPI1, GPIOB, GPIO_PIN_14) ;
bsp_InitSpi ( SPI1, 1 ) ;
使用中断的方式.DMA关闭
bsp_SpiConfig ( SPI1, NULL ) ;
bsp_SpiDmaEnable ( SPI1, 0 , 0 ) ;
bsp_SpiDmaParSet ( SPI1, NULL , NULL ) ;
bsp_SpiCsParSet ( SPI1, GPIOB, GPIO_PIN_14) ;
bsp_InitSpi ( SPI1, 1 ) ;
使用阻塞的方式
bsp_SpiConfig ( SPI1, NULL ) ;
bsp_SpiDmaEnable ( SPI1, 0 , 0 ) ;
bsp_SpiDmaParSet ( SPI1, NULL , NULL ) ;
bsp_SpiCsParSet ( SPI1, GPIOB, GPIO_PIN_14) ;
bsp_InitSpi ( SPI1, 0 ) ;
测试例程
# include "test_inc.h"
struct rt_spi_device * spi_device = RT_NULL;
static rt_err_t w25q128_tx_rx ( uint8_t * send, uint16_t send_len, uint8_t * rec, uint16_t rec_len) {
if ( send && rec) {
return spi_send_then_recv ( SPI1, send, send_len, rec, rec_len) ;
} else if ( send) {
return spi_send ( SPI1, ( const void * ) send, send_len) == send_len ? RT_EOK : RT_EIO;
}
return spi_recv ( SPI1, rec, rec_len) == rec_len ? RT_EOK : RT_EIO;
}
uint16_t w25q128_read_deviceID ( ) {
uint8_t cmd[ 4 ] = { 0x90 , 00 , 00 , 00 } ;
uint8_t rec[ 2 ] ;
if ( w25q128_tx_rx ( cmd, 4 , rec, 2 ) != RT_EOK) return 0 ;
return ( uint16_t ) ( rec[ 0 ] << 8 | rec[ 1 ] ) ;
}
int spi_dev_tst ( ) {
LOG_D ( "issd12:%#x\r\n" , w25q128_read_deviceID ( ) ) ;
LOG_D ( "..............." ) ;
return 0 ;
}
TX_TST_EXPORT ( spi_dev_tst) ;
结果
总结
此版本的驱动,并没有做相关宏定义的显示,所以可以直接通过参数配置来进行切换,如果需要限定的话,可以根据以上代码进行调整。这里只添加了spi1,如果需要其他的spi,需要添加spi硬件部分io,dma配置部分,spi中断部分即可,整体的spi逻辑框架无需修改