bs_bcu_app/drv/drv_stm32f4xx/drv_dma.c

313 lines
8.5 KiB
C
Raw Normal View History

2024-11-07 17:24:19 +08:00
#include "drv_dma.h"
#include "drv_clk.h"
#include "drv_misc.h"
#include "kit_time.h"
#include "kit_debug.h"
#define DMA_IT_TC ((uint32_t)0x00000002)
#define DMA_IT_HT ((uint32_t)0x00000004)
#define DMA_IT_TE ((uint32_t)0x00000008)
#define DMA_CCR_EN ((uint32_t)0x00000001)
#define DMA1_IT_TE2 ((uint32_t)0x00000080)
#define DMA1_IT_TC2 ((uint32_t)0x00000020)
#define DMA_Mode_Normal ((uint32_t)0x00000000)
#define DMA_Mode_Circular ((uint32_t)0x00000020)
#define DMA_DIR_PeripheralDST ((uint32_t)0x00000010)
#define DMA_DIR_PeripheralSRC ((uint32_t)0x00000000)
#define DMA_MemoryDataSize_Byte ((uint32_t)0x00000000)
#define DMA_MemoryDataSize_HalfWord ((uint32_t)0x00000400)
#define DMA_MemoryDataSize_Word ((uint32_t)0x00000800)
#define DMA_PeripheralDataSize_Byte ((uint32_t)0x00000000)
#define DMA_PeripheralDataSize_HalfWord ((uint32_t)0x00000100)
#define DMA_PeripheralDataSize_Word ((uint32_t)0x00000200)
#define DMA_STREAM3_IT_ERR ((uint32_t)0x03400000)
#define DMA_STREAM3_IT_FLAG ((uint32_t)0x0F400000)
typedef enum
{
kDmaIdx_0,
kDmaIdx_1,
kDmaIdx_End,
}DmaIdx;
typedef struct
{
uint8_t irq;
uint8_t ch_id; //通道实际编号,如通道5编号为4
DmaIdx dma_idx;
DMA_Stream_TypeDef *channel_reg;
}Stm32DmaProp;
static KitIrqCall dma_irq_call[kDmaStream_End];
const DMA_TypeDef * dma_array[kDmaIdx_End] = {DMA1, DMA2};
static const Stm32DmaProp stm32_dma[kDmaStream_End] =
{
{DMA1_Stream0_IRQn, 0, kDmaIdx_0, DMA1_Stream0},
{DMA1_Stream1_IRQn, 1, kDmaIdx_0, DMA1_Stream1},
{DMA1_Stream2_IRQn, 2, kDmaIdx_0, DMA1_Stream2},
{DMA1_Stream3_IRQn, 3, kDmaIdx_0, DMA1_Stream3},
{DMA1_Stream4_IRQn, 4, kDmaIdx_0, DMA1_Stream4},
{DMA1_Stream5_IRQn, 5, kDmaIdx_0, DMA1_Stream5},
{DMA1_Stream6_IRQn, 6, kDmaIdx_0, DMA1_Stream6},
{DMA1_Stream7_IRQn, 7, kDmaIdx_0, DMA1_Stream7},
{DMA2_Stream0_IRQn, 0, kDmaIdx_1, DMA2_Stream0},
{DMA2_Stream1_IRQn, 1, kDmaIdx_1, DMA2_Stream1},
{DMA2_Stream2_IRQn, 2, kDmaIdx_1, DMA2_Stream2},
{DMA2_Stream3_IRQn, 3, kDmaIdx_1, DMA2_Stream3},
{DMA2_Stream4_IRQn, 4, kDmaIdx_1, DMA2_Stream4},
{DMA2_Stream5_IRQn, 5, kDmaIdx_1, DMA2_Stream5},
{DMA2_Stream6_IRQn, 6, kDmaIdx_1, DMA2_Stream6},
{DMA2_Stream7_IRQn, 6, kDmaIdx_1, DMA2_Stream7},
};
#define DMA1_Channel1_IT_Mask ((uint32_t)(DMA_ISR_GIF1 | DMA_ISR_TCIF1 | DMA_ISR_HTIF1 | DMA_ISR_TEIF1))
void dma_reset(DmaStream stream_idx)
{
DMA_Stream_TypeDef* DMAy_Streamx = stm32_dma[stream_idx].channel_reg;
DMAy_Streamx->CR &= (uint16_t)(~DMA_SxCR_EN);
/* Reset DMAy Channelx control register */
DMAy_Streamx->CR = 0;
/* Reset DMAy Channelx remaining bytes register */
DMAy_Streamx->NDTR = 0;
/* Reset DMAy Channelx peripheral address register */
DMAy_Streamx->PAR = 0;
/* Reset DMAy Channelx memory address register */
DMAy_Streamx->M0AR = 0;
DMAy_Streamx->M1AR = 0;
DMAy_Streamx->FCR = (uint32_t)0x00000021;
}
const uint32_t dma_clk_en[kDmaIdx_End] = {RCC_AHB1ENR_DMA1EN, RCC_AHB1ENR_DMA2EN};
KitResult drv_dma_init(DmaStream stream_idx, DmaChannel channel, uint32_t dma_config, uint32_t addr)
{
uint32_t reg = 0;
KitResult res = kKitResult_Ok;
KIT_ASSERT_PARAM((stream_idx < kDmaStream_End) && (addr != NULL));
if((stream_idx < kDmaStream_End) && (addr != NULL))
{
RCC->AHB1ENR |= dma_clk_en[stm32_dma[stream_idx].dma_idx]; //开启时钟
//dma初始化
dma_reset(stream_idx);
if((dma_config & DMA_CFG_DATA_DIR_M2P) == DMA_CFG_DATA_DIR_M2P)
{
reg |= KIT_CREAT_BIT(6);
}
else if((dma_config & DMA_CFG_DATA_DIR_M2M) == DMA_CFG_DATA_DIR_M2P)
{
reg |= KIT_CREAT_BIT(7);
}
if((dma_config & DMA_CFG_CYCLE_EXE) == DMA_CFG_CYCLE_EXE)
{
reg |= KIT_CREAT_BIT(8);
}
if((dma_config & DMA_CFG_DATA_P_I) == DMA_CFG_DATA_P_I)
{
reg |= KIT_CREAT_BIT(9);
}
if((dma_config & DMA_CFG_DATA_M_I) == DMA_CFG_DATA_M_I)
{
reg |= KIT_CREAT_BIT(10);
}
if((dma_config & DMA_CFG_DATA_LEN_2B) == DMA_CFG_DATA_LEN_2B)
{
reg |= (KIT_CREAT_BIT(11) | KIT_CREAT_BIT(13));
}
else if((dma_config & DMA_CFG_DATA_LEN_4B) == DMA_CFG_DATA_LEN_4B)
{
reg |= (KIT_CREAT_BIT(12) | KIT_CREAT_BIT(14));
}
reg |= ((uint32_t)channel) << 25;
stm32_dma[stream_idx].channel_reg->CR |= reg;
stm32_dma[stream_idx].channel_reg->PAR = addr;
}
else
{
res = kKitResult_ParamErr;
}
return res;
}
void drv_dma_set_interrupt(DmaStream stream_idx, uint8_t priority, KitIrqCall call)
{
KIT_ASSERT_PARAM(stream_idx < kDmaStream_End);
stm32_dma[stream_idx].channel_reg->CR |= (DMA_SxCR_TCIE | DMA_SxCR_TEIE);
drv_misc_set_nvic(stm32_dma[stream_idx].irq, priority);
dma_irq_call[stream_idx] = call;
}
__IO uint32_t * dma_ifcr[4] = {&DMA1->LIFCR, &DMA1->HIFCR, &DMA2->LIFCR, &DMA2->HIFCR};
const uint32_t dma_ifcr_clr_bit[4] = {0x0000003D, 0x00000F40, 0x003D0000, 0x0F400000};
//传输错误或者结束标志位
__IO uint32_t * dma_isr[4] = {&DMA1->LISR, &DMA1->HISR, &DMA2->LISR, &DMA2->HISR};
const uint32_t dma_isr_transfer_end_bit[4] = {0x0000002C, 0x00000B00, 0x002C0000, 0x0B000000};
void drv_dma_set_buf(DmaStream stream_idx,uint8_t* buf, uint16_t len)
{
DMA_Stream_TypeDef * stream_reg;
KIT_ASSERT_PARAM((buf != NULL) && (len > 0));
KIT_ASSERT_PARAM(stream_idx < kDmaStream_End);
if((stream_idx < kDmaStream_End) && (buf != NULL))
{
stream_reg = stm32_dma[stream_idx].channel_reg;
//清除标志位
*dma_ifcr[stream_idx / 4] |= dma_ifcr_clr_bit[stream_idx % 4];
stream_reg->NDTR = len;
stream_reg->M0AR = (uint32_t)buf;
stream_reg->CR |= DMA_CCR_EN;
}
}
KitResult drv_dma_send(DmaStream dma_tx_ch, uint8_t *tx_buf, uint16_t tx_len)
{
uint32_t dly = 0;
KitResult res = kKitResult_Ok;
KIT_ASSERT_PARAM((tx_buf != NULL) && (tx_len > 0));
drv_dma_set_buf(dma_tx_ch, tx_buf, tx_len);
//等待接收完成
while((*dma_isr[dma_tx_ch >> 2] & dma_isr_transfer_end_bit[dma_tx_ch % 4]) == 0)
{
kit_time_dly_ms(1);
if(++dly > 500)
{
res = kKitResult_TimeOut;
break;
}
}
stm32_dma[dma_tx_ch].channel_reg->CR &= ~DMA_CCR_EN ; //关闭DMA通道2
return res;
}
KitResult drv_dma_receive(DmaStream dma_rx_ch, DmaStream dma_tx_ch, uint8_t *rx_buf, uint16_t rx_len)
{
uint32_t dly = 0;
KitResult res = kKitResult_Ok;
KIT_ASSERT_PARAM(timeout > 0);
KIT_ASSERT_PARAM(((tx_buf != NULL) && (tx_len > 0)) || ((tx_buf == NULL) && (tx_len == 0)));
KIT_ASSERT_PARAM(((rx_buf != NULL) && (rx_len > 0)) || ((rx_buf == NULL) && (rx_len == 0)));
drv_dma_set_buf(dma_rx_ch, rx_buf, rx_len);
drv_dma_set_buf(dma_tx_ch, rx_buf, rx_len);
//等待接收完成
while((*dma_isr[dma_rx_ch >> 2] & dma_isr_transfer_end_bit[dma_rx_ch % 4]) == 0)
{
kit_time_dly_ms(1);
if(++dly > 200)
{
res = kKitResult_TimeOut;
break;
}
}
stm32_dma[dma_tx_ch].channel_reg->CR &= ~DMA_CCR_EN ; //关闭DMA通道3
stm32_dma[dma_tx_ch].channel_reg->CR &= ~DMA_CCR_EN ; //关闭DMA通道2
return res;
}
void DMA1_Stream0_IRQHandler(void)
{
}
void DMA1_Stream1_IRQHandler(void)
{
}
void DMA1_Stream2_IRQHandler(void)
{
}
void DMA1_Stream3_IRQHandler(void)
{
KitResult res = kKitResult_Ok;
DMA1_Stream3->CR &= ~DMA_CCR_EN ; //关闭DMA通道2
DMA1_Stream4->CR &= ~DMA_CCR_EN ; //关闭DMA通道3
if((DMA1->LISR & DMA_STREAM3_IT_ERR) != 0)
{
KIT_ASSERT_RES(0, kKitResult_Error);
res = kKitResult_Error;
}
DMA1->LIFCR = DMA_STREAM3_IT_FLAG; //清楚标志位
if(dma_irq_call[kDma1Stream_3] != NULL)
dma_irq_call[kDma1Stream_3](res, NULL);
}
void DMA1_Stream4_IRQHandler(void)
{
}
void DMA1_Stream5_IRQHandler(void)
{
}
void DMA1_Channel6_IRQHandler(void)
{
}
void DMA2_Stream0_IRQHandler(void)
{
}
void DMA2_Stream1_IRQHandler(void)
{
}
void DMA2_Stream2_IRQHandler(void)
{
}
void DMA2_Stream3_IRQHandler(void)
{
}
void DMA2_Stream4_IRQHandler(void)
{
}
void DMA2_Stream5_IRQHandler(void)
{
}
void DMA2_Stream6_IRQHandler(void)
{
}
void DMA2_Stream7_IRQHandler(void)
{
}