|
最近在用STM32H7的SPI驱动W5500网络芯片,如果单独的使用阻塞等待的方式(如HAL_SPI_Transmit)就能够成功,但是使用DMA 的方式(如HAL_SPI_Transmit_DMA)就无法正常读写数据(但函数返回的状态是HAL_OK),我也做了数据一致性处理(SCB_CleanDCache_by_Addr和SCB_InvalidateDCache_by_Addr),研究了很久也没找到问题所在,请问这是什么原因导致的呀?
__attribute__((section (".RAM_D3"))) uint8_t SPI_DMATXBUF[DATA_BUF_SIZE];
void SPI_DMA_WRITE(uint8_t* Addref, uint8_t* pTxBuf, uint16_t tx_len)
{
uint16_t i;
osEvent event;
uint8_t res = HAL_ERROR;
uint32_t timer = 0;
while(HAL_SPI_GetState(&hspi2) != HAL_SPI_STATE_READY);
memset(SPI_DMATXBUF, 0, tx_len + 3);
SPI_DMATXBUF[0] = Addref[0];
SPI_DMATXBUF[1] = Addref[1];
SPI_DMATXBUF[2] = Addref[2];
for(i=0; i<tx_len; i++)
SPI_DMATXBUF[3 + i] = pTxBuf;
WIZCHIP.CS._select();
#if (ENABLE_SPI_DMA_CACHE_MAINTENANCE == 1)
uint32_t alignedAddr;
alignedAddr = (uint32_t)SPI_DMATXBUF & ~0x1F;
SCB_CleanDCache_by_Addr((uint32_t*)alignedAddr, tx_len + 3 + ((uint32_t)SPI_DMATXBUF - alignedAddr));
#endif
res = HAL_SPI_Transmit_DMA(&hspi2,(uint8_t*)SPI_DMATXBUF,tx_len + 3);
if(res == HAL_OK)
{
timer = osKernelSysTick() + SPI_DMA_TIMEOUT;
while(timer > osKernelSysTick())
{
if(HAL_SPI_GetState(&hspi2) == HAL_SPI_STATE_READY)
{
event = osMessageGet(SPIQueueID, SPI_DMA_TIMEOUT);
if(event.status == osEventMessage && event.value.v == WRITE_CPLT_MSG)
{
res = HAL_OK;
break;
}
}
}
}
WIZCHIP.CS._deselect();
}
void SPI_DMA_READ(uint8_t* Addref, uint8_t* pRxBuf, uint16_t rx_len)
{
osEvent event;
uint8_t res = HAL_ERROR;
uint32_t timer = 0;
while(HAL_SPI_GetState(&hspi2) != HAL_SPI_STATE_READY);
memset(SPI_DMATXBUF, 0, rx_len+3);
memset(SPI_DMARXBUF, 0, rx_len+3);
SPI_DMATXBUF[0] = Addref[0];
SPI_DMATXBUF[1] = Addref[1];
SPI_DMATXBUF[2] = Addref[2];
WIZCHIP.CS._select();
SPI_DMA_WRITE(Addref,NULL,0);
res = HAL_SPI_Receive_DMA(&hspi2,SPI_DMARXBUF,rx_len);
if(res == HAL_OK)
{
timer = osKernelSysTick() + SPI_DMA_TIMEOUT;
while(timer > osKernelSysTick())
{
if(HAL_SPI_GetState(&hspi2) == HAL_SPI_STATE_READY)
{
event = osMessageGet(SPIQueueID, SPI_DMA_TIMEOUT);
if(event.status == osEventMessage && event.value.v == READ_CPLT_MSG)
{
#if (ENABLE_SPI_DMA_CACHE_MAINTENANCE == 1)
uint32_t alignedAddr;
alignedAddr = (uint32_t)SPI_DMARXBUF & ~0x1F;
SCB_InvalidateDCache_by_Addr((uint32_t*)alignedAddr, rx_len + ((uint32_t)SPI_DMARXBUF - alignedAddr));
#endif
res = HAL_OK;
}
break;
}
}
}
WIZCHIP.CS._deselect();
memcpy(pRxBuf, SPI_DMARXBUF, rx_len);
}
|
|