diff --git a/demo/stm32/usb_host/stm32h743xih6/Core/Src/main.c b/demo/stm32/usb_host/stm32h743xih6/Core/Src/main.c index 89736b13..1eaba9a6 100644 --- a/demo/stm32/usb_host/stm32h743xih6/Core/Src/main.c +++ b/demo/stm32/usb_host/stm32h743xih6/Core/Src/main.c @@ -118,6 +118,122 @@ void usb_hc_low_level_init(void) /* USER CODE END USB_OTG_HS_MspInit 1 */ } + +/*属性为Normal,cache的属性为 write-back,即仅更新cache, + *在合适的时候(由cache策略决定或者软件强制更新)将数据更新到相应的SRAM空间 + *特别注意:如果要数据立即更新,写之后要SCB_CleanDCache,读数据时要SCB_InvalidateDCache + */ +#define MPU_Normal_WB 0x00 + + +/*属性为Normal,cache的属性为 write-back,即仅更新cache, + *在合适的时候(由cache策略决定或者软件强制更新)将数据更新到相应的SRAM空间 + *特别注意:如果要数据立即更新,写之后要SCB_CleanDCache,读数据时要SCB_InvalidateDCache + */ +#define MPU_Normal_WBWARA 0x01 //外部和内部写入无写入分配 + + +/*属性为 normal,cache的属性为 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 策略,可以取值(0,1,2),一般只用0和1 + * + * @param Address MPU保护区域基地址,特别注意配置的Address需要被Size整除 + * @param Size MPU保护区域大小,可以取值(MPU_1KB,MPU_4KB ...MPU_512MB) + * @param IsShareable 保护的存储空间是否可以共享,1=允许共享,0=禁止共享。 + * @param IsCacheable 保护的存储空间是否可以缓存,1=允许缓存,0=禁止缓存。 + * @param IsBufferable 使能Cache之后,策略是write-through还是write-back(bufferable) + * 1=允许缓冲,即回写(write-back),0=禁止缓冲,即直写(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 内核只要开启了 Cache,read 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(); diff --git a/demo/stm32/usb_host/stm32h743xih6/MDK-ARM/stm32h743xih6.uvprojx b/demo/stm32/usb_host/stm32h743xih6/MDK-ARM/stm32h743xih6.uvprojx index da51abe3..4febb57b 100644 --- a/demo/stm32/usb_host/stm32h743xih6/MDK-ARM/stm32h743xih6.uvprojx +++ b/demo/stm32/usb_host/stm32h743xih6/MDK-ARM/stm32h743xih6.uvprojx @@ -338,7 +338,7 @@ 0 - USE_HAL_DRIVER,STM32H743xx,STM32H7,CONFIG_USBHOST_HIGH_WORKQ + USE_HAL_DRIVER,STM32H743xx,STM32H7,CONFIG_USBHOST_HIGH_WORKQ,CONFIG_USB_DCACHE_ENABLE ../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 diff --git a/port/dwc2/usb_hc_dwc2.c b/port/dwc2/usb_hc_dwc2.c index d25c01c8..5520b78a 100644 --- a/port/dwc2/usb_hc_dwc2.c +++ b/port/dwc2/usb_hc_dwc2.c @@ -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;