- 本文以串口dma为例,发送和接收都设计到一致性问题
- mpu配置,只有mpu配置好后,才能使用缓存策略提升性能,特别是对外部sdram速度提升很高
int mpu_init(void)
{
MPU_Region_InitTypeDef MPU_InitStruct;
HAL_MPU_Disable();
MPU_InitStruct.Enable = MPU_REGION_ENABLE;
MPU_InitStruct.BaseAddress = 0x24000000;
MPU_InitStruct.Size = MPU_REGION_SIZE_512KB;
MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;
MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE;
MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
MPU_InitStruct.Number = MPU_REGION_NUMBER6;
MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
MPU_InitStruct.SubRegionDisable = 0X00;
MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;
HAL_MPU_ConfigRegion(&MPU_InitStruct);
#ifdef BSP_USING_SDRAM
MPU_InitStruct.Enable = MPU_REGION_ENABLE;
MPU_InitStruct.BaseAddress = 0xD0000000;
MPU_InitStruct.Size = MPU_REGION_SIZE_64MB;
MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE;
MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE;
MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
MPU_InitStruct.Number = MPU_REGION_NUMBER1;
MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL1;
MPU_InitStruct.SubRegionDisable = 0x00;
MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;
HAL_MPU_ConfigRegion(&MPU_InitStruct);
#endif
#define BSP_USING_ETH
#ifdef BSP_USING_ETH
MPU_InitStruct.Enable = MPU_REGION_ENABLE;
MPU_InitStruct.BaseAddress = 0x30040000;
MPU_InitStruct.Size = MPU_REGION_SIZE_256B;
MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE;
MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;
MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
MPU_InitStruct.Number = MPU_REGION_NUMBER2;
MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
MPU_InitStruct.SubRegionDisable = 0x00;
MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;
HAL_MPU_ConfigRegion(&MPU_InitStruct);
MPU_InitStruct.Enable = MPU_REGION_ENABLE;
MPU_InitStruct.BaseAddress = 0x30044000;
MPU_InitStruct.Size = MPU_REGION_SIZE_16KB;
MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;
MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE;
MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
MPU_InitStruct.Number = MPU_REGION_NUMBER3;
MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
MPU_InitStruct.SubRegionDisable = 0x00;
MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;
HAL_MPU_ConfigRegion(&MPU_InitStruct);
#endif
HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);
SCB_EnableICache();
SCB_EnableDCache();
return RT_EOK;
}
- 串口接收,dma将数据更新到主存中,缓存中的数据不是最新的数据,读之前需要把数据从主存中读出来
rt_inline int _serial_dma_rx(struct rt_serial_device *serial, rt_uint8_t *data, int length){
...
SCB_InvalidateDCache_by_Addr(rx_fifo, serial->config.rx_bufsz);
if (rx_fifo->get_index + recv_len < serial->config.bufsz)
rt_memcpy(data, rx_fifo->buffer + rx_fifo->get_index, recv_len);
else
{
rt_memcpy(data, rx_fifo->buffer + rx_fifo->get_index,
serial->config.bufsz - rx_fifo->get_index);
rt_memcpy(data + serial->config.bufsz - rx_fifo->get_index, rx_fifo->buffer,
recv_len + rx_fifo->get_index - serial->config.bufsz);
}
...
}
static rt_size_t _serial_fifo_rx(struct rt_device *dev,
rt_off_t pos,
void *buffer,
rt_size_t size)
{
level = rt_hw_interrupt_disable();
SCB_InvalidateDCache_by_Addr(rx_fifo->buffer, serial->config.rx_bufsz);
recv_len = rt_ringbuffer_get(&(rx_fifo->rb), buffer, size);
}
- dma发送,无特殊要求,因为mpu中配置为透写了,个人理解,使用dma时,只能使用透写模式,否则缓存中有新数据,主存中也有新的数据,舍弃那组数据都不行