前言
配置功能参考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_AREATX_DISABLEHAL_DMA_IRQHandler ( & spi1_dma_rx) ; TX_RESTORE
} void DMA2_Stream3_IRQHandler ( void ) { TX_INTERRUPT_SAVE_AREATX_DISABLEHAL_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_AREATX_DISABLEHAL_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逻辑框架无需修改