update dwc2 dcache process

This commit is contained in:
sakumisu
2022-06-23 21:22:00 +08:00
parent 2bd38a0e1c
commit edee76c3e5
3 changed files with 200 additions and 9 deletions

View File

@@ -118,6 +118,122 @@ void usb_hc_low_level_init(void)
/* USER CODE END USB_OTG_HS_MspInit 1 */
}
/*属性为Normalcache的属性为 write-back即仅更新cache
*在合适的时候(由cache策略决定或者软件强制更新)将数据更新到相应的SRAM空间
*特别注意如果要数据立即更新写之后要SCB_CleanDCache读数据时要SCB_InvalidateDCache
*/
#define MPU_Normal_WB 0x00
/*属性为Normalcache的属性为 write-back即仅更新cache
*在合适的时候(由cache策略决定或者软件强制更新)将数据更新到相应的SRAM空间
*特别注意如果要数据立即更新写之后要SCB_CleanDCache读数据时要SCB_InvalidateDCache
*/
#define MPU_Normal_WBWARA 0x01 //外部和内部写入无写入分配
/*属性为 normalcache的属性为 Write-through即更新cache的同时
*将数据同时写入相应的物理地址空间
*特别注意如果要数据立即更新可以直接往内存写数据但读数据时要SCB_InvalidateDCache
*/
#define MPU_Normal_WT 0x02
/*属性为 normal禁用共享,禁用缓存
*/
#define MPU_Normal_NonCache 0x03
/*属性为 Device共享设置无效禁用共享,禁用缓存
*/
#define MPU_Device_NonCache 0x04
/**
* @brief 配置MPU区域属性和大小寄存器值
* @param Region MPU保护区域取值范围0—7
* @param AccessPermission 数据访问权限取值范围MPU_NO_ACCESS—MPU_PRIV_RO_URO
* @param TypeExtField 用于配置 Cache 策略可以取值012一般只用0和1
*
* @param Address MPU保护区域基地址特别注意配置的Address需要被Size整除
* @param Size MPU保护区域大小,可以取值MPU_1KBMPU_4KB ...MPU_512MB
* @param IsShareable 保护的存储空间是否可以共享1=允许共享0=禁止共享。
* @param IsCacheable 保护的存储空间是否可以缓存1=允许缓存0=禁止缓存。
* @param IsBufferable 使能Cache之后策略是write-through还是write-back(bufferable)
* 1=允许缓冲即回写write-back0=禁止缓冲即直写write-through
* @retval None
*/
static void BSP_MPU_ConfigRegion(uint8_t Number,
uint8_t TypeExtField,
uint32_t Address,
uint32_t Size,
uint8_t IsBufferable,
uint8_t IsCacheable)
{
MPU_Region_InitTypeDef MPU_InitStruct;
/* 禁用MPU */
HAL_MPU_Disable();
/* 配置MPU属性*/
MPU_InitStruct.Enable = MPU_REGION_ENABLE;
MPU_InitStruct.BaseAddress = Address; //区域基地址。
MPU_InitStruct.Size = Size; //要配置的区域的区域大小。
MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS; //数据访问权限允许您配置用户和特权模式的读/写访问权限。
MPU_InitStruct.IsBufferable = IsBufferable; //区域是可缓冲的,即使用回写缓存。 可缓存但不可缓冲的区域使用直写策略。WB
MPU_InitStruct.IsCacheable = IsCacheable; //区域是否可缓存的,即其值是否可以保存在缓存中。//M7 内核只要开启了 Cacheread allocate 就是开启的
MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE; //区域是否可以在多个总线主控器之间共享。H7 的应用笔记对齐的描述是开启共享基本等同于关闭 Cache
MPU_InitStruct.Number = Number; //区域号。
MPU_InitStruct.TypeExtField = TypeExtField; //键入扩展字段,允许您配置内存访问类型。
MPU_InitStruct.SubRegionDisable = 0x00; //子区域禁用字段。
MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;//指令访问禁用位0=允许指令访问1=禁止指令访问
HAL_MPU_ConfigRegion(&MPU_InitStruct);
/* 启用MPU */
HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT); //表示禁止了背景区,访问任何未使能 MPU 的区域均会造成内存异常 MemFault
}
void cpu_mpu_config(uint8_t Region, uint8_t Mode, uint32_t Address, uint32_t Size)
{
switch (Mode)
{
case MPU_Normal_WB:
/*write back,no write allocate */
/* 设置内存为Normal类型,禁用共享, 回写模式不带写入读取分配*/
BSP_MPU_ConfigRegion(Region, MPU_TEX_LEVEL0, Address, Size, MPU_ACCESS_BUFFERABLE, MPU_ACCESS_CACHEABLE);
break;
case MPU_Normal_WBWARA:
/*write back,write and read allocate */
/* 设置内存为Normal类型,禁用共享, 回写模式带写入读取分配*/
BSP_MPU_ConfigRegion(Region, MPU_TEX_LEVEL1, Address, Size, MPU_ACCESS_BUFFERABLE, MPU_ACCESS_CACHEABLE);
break;
case MPU_Normal_WT:
/*write through,no write allocate */
/* 设置内存为Normal类型,禁用共享, 直写模式*/
BSP_MPU_ConfigRegion(Region, MPU_TEX_LEVEL0, Address, Size, MPU_ACCESS_NOT_BUFFERABLE, MPU_ACCESS_CACHEABLE);
break;
case MPU_Normal_NonCache:
/* 设置内存为Normal类型,禁用共享,禁用缓存模式*/
BSP_MPU_ConfigRegion(Region, MPU_TEX_LEVEL1, Address, Size, MPU_ACCESS_NOT_BUFFERABLE, MPU_ACCESS_NOT_CACHEABLE);
break;
}
}
void usb_dwc2_dcache_clean(uintptr_t addr, uint32_t len)
{
SCB_CleanDCache_by_Addr((uint32_t*)addr,len);
}
void usb_dwc2_dcache_invalidate(uintptr_t addr, uint32_t len)
{
SCB_InvalidateDCache_by_Addr((uint32_t*)addr,len);
}
/* USER CODE END 0 */
/**
@@ -132,10 +248,10 @@ int main(void)
/* Enable I-Cache---------------------------------------------------------*/
SCB_EnableICache();
#ifdef CONFIG_USB_DCACHE_ENABLE
/* Enable D-Cache---------------------------------------------------------*/
// SCB_EnableDCache();
SCB_EnableDCache();
#endif
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
@@ -157,6 +273,9 @@ int main(void)
MX_USART1_UART_Init();
//MX_USB_OTG_HS_HCD_Init();
/* USER CODE BEGIN 2 */
#ifdef CONFIG_USB_DCACHE_ENABLE
cpu_mpu_config(0, MPU_Normal_WB, 0x24000000, MPU_REGION_SIZE_512KB);
#endif
usbh_initialize();
printf("Start usb host task...\r\n");
vTaskStartScheduler();

View File

@@ -338,7 +338,7 @@
<v6Rtti>0</v6Rtti>
<VariousControls>
<MiscControls></MiscControls>
<Define>USE_HAL_DRIVER,STM32H743xx,STM32H7,CONFIG_USBHOST_HIGH_WORKQ</Define>
<Define>USE_HAL_DRIVER,STM32H743xx,STM32H7,CONFIG_USBHOST_HIGH_WORKQ,CONFIG_USB_DCACHE_ENABLE</Define>
<Undefine></Undefine>
<IncludePath>../Core/Inc;../Drivers/STM32H7xx_HAL_Driver/Inc;../Drivers/STM32H7xx_HAL_Driver/Inc/Legacy;../Drivers/CMSIS/Device/ST/STM32H7xx/Include;../Drivers/CMSIS/Include;..\..\..\..\..\core;..\..\..\..\..\common;..\..\..\..\..\osal;..\..\..\..\..\class\cdc;..\..\..\..\..\class\hid;..\..\..\..\..\class\msc;..\..\..\..\..\class\hub;..\..\..\..\..\third_party\FreeRTOS-10.4\include;..\..\..\..\..\third_party\FreeRTOS-10.4\portable\GCC\ARM_CM7\r0p1</IncludePath>
</VariousControls>

View File

@@ -59,6 +59,14 @@ struct dwc2_hcd {
struct dwc2_pipe chan[CONFIG_USB_DWC2_PIPE_NUM];
} g_dwc2_hcd;
#ifdef CONFIG_USB_DCACHE_ENABLE
void usb_dwc2_dcache_clean(uintptr_t addr, uint32_t len);
void usb_dwc2_dcache_invalidate(uintptr_t addr, uint32_t len);
#else
#define usb_dwc2_dcache_clean(addr, len)
#define usb_dwc2_dcache_invalidate(addr, len)
#endif
static inline int dwc2_reset(void)
{
uint32_t count = 0U;
@@ -787,6 +795,17 @@ int usbh_control_transfer(usbh_epinfo_t ep, struct usb_setup_packet *setup, uint
chan = (struct dwc2_pipe *)ep;
#ifdef CONFIG_USB_DCACHE_ENABLE
if ((((uint32_t)setup) & 0x1f) || (buffer && (((uint32_t)buffer) & 0x1f))) {
return -EINVAL;
}
#endif
#if defined(STM32F7) || defined(STM32H7)
if (((((uint32_t)setup) & 0x24000000) != 0x24000000) ||
((buffer && (((uint32_t)buffer) & 0x24000000) != 0x24000000))) {
return -EINVAL;
}
#endif
ret = usb_osal_mutex_take(chan->exclsem);
if (ret < 0) {
return ret;
@@ -802,6 +821,7 @@ int usbh_control_transfer(usbh_epinfo_t ep, struct usb_setup_packet *setup, uint
chan->waiter = true;
chan->result = -EBUSY;
chan->num_packets = dwc2_calculate_packet_num(8, chan->ep_addr, chan->ep_mps, &chan->xferlen);
usb_dwc2_dcache_clean((uintptr_t)setup, 8);
dwc2_pipe_init(chidx, chan->dev_addr, 0x00, 0x00, chan->ep_mps, chan->speed);
dwc2_pipe_transfer(chidx, 0x00, (uint32_t *)setup, chan->xferlen, chan->num_packets, HC_PID_SETUP);
ret = dwc2_pipe_wait(chan, CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT);
@@ -820,6 +840,7 @@ int usbh_control_transfer(usbh_epinfo_t ep, struct usb_setup_packet *setup, uint
if (ret < 0) {
goto error_out;
}
usb_dwc2_dcache_invalidate((uintptr_t)buffer, setup->wLength);
chan->waiter = true;
chan->result = -EBUSY;
chan->num_packets = dwc2_calculate_packet_num(0, 0x00, chan->ep_mps, &chan->xferlen);
@@ -833,6 +854,7 @@ int usbh_control_transfer(usbh_epinfo_t ep, struct usb_setup_packet *setup, uint
chan->waiter = true;
chan->result = -EBUSY;
chan->num_packets = dwc2_calculate_packet_num(setup->wLength, 0x00, chan->ep_mps, &chan->xferlen);
usb_dwc2_dcache_clean((uintptr_t)buffer, setup->wLength);
dwc2_pipe_init(chidx, chan->dev_addr, 0x00, 0x00, chan->ep_mps, chan->speed);
dwc2_pipe_transfer(chidx, 0x00, (uint32_t *)buffer, chan->xferlen, chan->num_packets, HC_PID_DATA1);
ret = dwc2_pipe_wait(chan, CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT);
@@ -875,7 +897,16 @@ int usbh_ep_bulk_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t buflen, ui
int ret;
chan = (struct dwc2_pipe *)ep;
#ifdef CONFIG_USB_DCACHE_ENABLE
if (buffer && (((uint32_t)buffer) & 0x1f)) {
return -EINVAL;
}
#endif
#if defined(STM32F7) || defined(STM32H7)
if ((buffer && (((uint32_t)buffer) & 0x24000000) != 0x24000000)) {
return -EINVAL;
}
#endif
ret = usb_osal_mutex_take(chan->exclsem);
if (ret < 0) {
return ret;
@@ -888,12 +919,21 @@ int usbh_ep_bulk_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t buflen, ui
chidx = chan->chidx;
chan->num_packets = dwc2_calculate_packet_num(buflen, chan->ep_addr, chan->ep_mps, &chan->xferlen);
#ifdef CONFIG_USB_DCACHE_ENABLE
if ((chan->ep_addr & 0x80) == 0x00) {
usb_dwc2_dcache_clean((uintptr_t)buffer, buflen);
}
#endif
dwc2_pipe_transfer(chidx, chan->ep_addr, (uint32_t *)buffer, chan->xferlen, chan->num_packets, chan->data_pid);
ret = dwc2_pipe_wait(chan, timeout);
if (ret < 0) {
goto error_out;
}
#ifdef CONFIG_USB_DCACHE_ENABLE
if ((chan->ep_addr & 0x80) == 0x80) {
usb_dwc2_dcache_invalidate((uintptr_t)buffer, buflen);
}
#endif
usb_osal_mutex_give(chan->exclsem);
return ret;
error_out:
@@ -910,7 +950,16 @@ int usbh_ep_intr_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t buflen, ui
uint32_t wait_ms_count = 0;
chan = (struct dwc2_pipe *)ep;
#ifdef CONFIG_USB_DCACHE_ENABLE
if (buffer && (((uint32_t)buffer) & 0x1f)) {
return -EINVAL;
}
#endif
#if defined(STM32F7) || defined(STM32H7)
if ((buffer && (((uint32_t)buffer) & 0x24000000) != 0x24000000)) {
return -EINVAL;
}
#endif
ret = usb_osal_mutex_take(chan->exclsem);
if (ret < 0) {
return ret;
@@ -923,7 +972,11 @@ int usbh_ep_intr_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t buflen, ui
chidx = chan->chidx;
chan->num_packets = dwc2_calculate_packet_num(buflen, chan->ep_addr, chan->ep_mps, &chan->xferlen);
#ifdef CONFIG_USB_DCACHE_ENABLE
if ((chan->ep_addr & 0x80) == 0x00) {
usb_dwc2_dcache_clean((uintptr_t)buffer, buflen);
}
#endif
while (1) {
wait_ms_count++;
dwc2_pipe_transfer(chidx, chan->ep_addr, (uint32_t *)buffer, chan->xferlen, chan->num_packets, chan->data_pid);
@@ -941,6 +994,11 @@ int usbh_ep_intr_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t buflen, ui
if (ret < 0) {
goto error_out;
}
#ifdef CONFIG_USB_DCACHE_ENABLE
if ((chan->ep_addr & 0x80) == 0x80) {
usb_dwc2_dcache_invalidate((uintptr_t)buffer, buflen);
}
#endif
usb_osal_mutex_give(chan->exclsem);
return ret;
error_out:
@@ -956,7 +1014,16 @@ int usbh_ep_bulk_async_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t bufl
int ret;
chan = (struct dwc2_pipe *)ep;
#ifdef CONFIG_USB_DCACHE_ENABLE
if (buffer && (((uint32_t)buffer) & 0x1f)) {
return -EINVAL;
}
#endif
#if defined(STM32F7) || defined(STM32H7)
if ((buffer && (((uint32_t)buffer) & 0x24000000) != 0x24000000)) {
return -EINVAL;
}
#endif
ret = usb_osal_mutex_take(chan->exclsem);
if (ret < 0) {
return ret;
@@ -969,6 +1036,11 @@ int usbh_ep_bulk_async_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t bufl
chidx = chan->chidx;
chan->num_packets = dwc2_calculate_packet_num(buflen, chan->ep_addr, chan->ep_mps, &chan->xferlen);
#ifdef CONFIG_USB_DCACHE_ENABLE
if ((chan->ep_addr & 0x80) == 0x00) {
usb_dwc2_dcache_clean((uintptr_t)buffer, buflen);
}
#endif
dwc2_pipe_transfer(chidx, chan->ep_addr, (uint32_t *)buffer, chan->xferlen, chan->num_packets, chan->data_pid);
return 0;