Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

The DWC2 driver on the Cortex-M7 platform has unaligned access #2940

Closed
1 task done
tzy0002088 opened this issue Jan 11, 2025 · 15 comments
Closed
1 task done

The DWC2 driver on the Cortex-M7 platform has unaligned access #2940

tzy0002088 opened this issue Jan 11, 2025 · 15 comments
Labels

Comments

@tzy0002088
Copy link

Operating System

Linux

Board

stm32h750

Firmware

dcd_dwc2.c、hcd_dwc2.c

What happened ?

The DWC2 driver accesses registers with unaligned access, which leads to exceptions.

How to reproduce ?

It is reproducible on the STM32H750 board.

Debug Log as txt file (LOG/CFG_TUSB_DEBUG=2)

no

Screenshots

x

I have checked existing issues, dicussion and documentation

  • I confirm I have checked existing issues, dicussion and documentation.
@tzy0002088
Copy link
Author

Is there a way to allow unaligned access on Cortex-M7?

@HiFiPhile
Copy link
Collaborator

Is there a way to allow unaligned access on Cortex-M7?

Unaligned access is enabled by default on H7 and stock examples don't have this issue. I think you have misconfigured MPU and disabled unaligned access.

Please add details about your full code, where did exception occurred, compiler used.

@tzy0002088
Copy link
Author

Is there a way to allow unaligned access on Cortex-M7?

Unaligned access is enabled by default on H7 and stock examples don't have this issue. I think you have misconfigured MPU and disabled unaligned access.

Please add details about your full code, where did exception occurred, compiler used.

Yes, I tried disabling the Cortex-M7 unaligned access exception, but it didn't work. This is the MPU configuration code:

void MPU_Config(void)
{
    MPU_Region_InitTypeDef MPU_InitStruct;

    /* Disable the MPU */
    HAL_MPU_Disable();

    /* Configure the MPU attributes as WT for AXI SRAM */
    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_BUFFERABLE;
    MPU_InitStruct.IsCacheable       = MPU_ACCESS_CACHEABLE;
    MPU_InitStruct.IsShareable       = MPU_ACCESS_NOT_SHAREABLE;
    MPU_InitStruct.Number            = MPU_REGION_NUMBER0;
    MPU_InitStruct.TypeExtField      = MPU_TEX_LEVEL0;
    MPU_InitStruct.SubRegionDisable  = 0X00;
    MPU_InitStruct.DisableExec       = MPU_INSTRUCTION_ACCESS_ENABLE;

    HAL_MPU_ConfigRegion(&MPU_InitStruct);

    /* Enable the MPU */
    HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);

    /* Enable CACHE */
    SCB_EnableICache();
    SCB_EnableDCache();
}

@tzy0002088
Copy link
Author

Is there a way to allow unaligned access on Cortex-M7?

Unaligned access is enabled by default on H7 and stock examples don't have this issue. I think you have misconfigured MPU and disabled unaligned access.

Please add details about your full code, where did exception occurred, compiler used.

For example, the code dwc2->hprt_bm.speed will inevitably trigger an unaligned access exception on Cortex-M7. I don't know how to allow unaligned access. The compiler being used is armclang, and the compile parameters should not be the issue, right?

TU_ATTR_ALWAYS_INLINE static inline tusb_speed_t hprt_speed_get(dwc2_regs_t* dwc2) {
  tusb_speed_t speed;
  switch(dwc2->hprt_bm.speed) {
    case HPRT_SPEED_HIGH: speed = TUSB_SPEED_HIGH; break;
    case HPRT_SPEED_FULL: speed = TUSB_SPEED_FULL; break;
    case HPRT_SPEED_LOW : speed = TUSB_SPEED_LOW ; break;
    default:
      speed = TUSB_SPEED_INVALID;
      TU_BREAKPOINT();
    break;
  }
  return speed;
}

@tzy0002088
Copy link
Author

Is there a way to allow unaligned access on Cortex-M7?

Unaligned access is enabled by default on H7 and stock examples don't have this issue. I think you have misconfigured MPU and disabled unaligned access.
Please add details about your full code, where did exception occurred, compiler used.

For example, the code dwc2->hprt_bm.speed will inevitably trigger an unaligned access exception on Cortex-M7. I don't know how to allow unaligned access. The compiler being used is armclang, and the compile parameters should not be the issue, right?

TU_ATTR_ALWAYS_INLINE static inline tusb_speed_t hprt_speed_get(dwc2_regs_t* dwc2) {
  tusb_speed_t speed;
  switch(dwc2->hprt_bm.speed) {
    case HPRT_SPEED_HIGH: speed = TUSB_SPEED_HIGH; break;
    case HPRT_SPEED_FULL: speed = TUSB_SPEED_FULL; break;
    case HPRT_SPEED_LOW : speed = TUSB_SPEED_LOW ; break;
    default:
      speed = TUSB_SPEED_INVALID;
      TU_BREAKPOINT();
    break;
  }
  return speed;
}

image

@HiFiPhile
Copy link
Collaborator

HiFiPhile commented Jan 12, 2025

I've successfully reproduced the issue by manually adding asm("LDRH R0, [R0, #0x441]");, since I don't use Keil and both GCC and IAR are not affected.

I think it's a armclang bug: https://developer.arm.com/documentation/ka004594/latest/

Version prior to 6.16 doesn't access volatile bit-field using an access width appropriate to the type of its container.

I was wrong about the MPU, since peripheral address space (0x40000000-0x5FFFFFFF) is marked as Device memory to ensure correct access order and doesn't allow unaligned access.
Configure MPU won't resolve the issue since change the memory type to Normal will break more things.

@tzy0002088
Copy link
Author

I've successfully reproduced the issue by manually adding , since I don't use Keil and both GCC and IAR are not affected.asm("LDRH R0, [R0, #0x441]");

I think it's a armclang bug: https://developer.arm.com/documentation/ka004594/latest/

Version prior to 6.16 doesn't access volatile bit-field using an access width appropriate to the type of its container.

I was wrong about the MPU, since peripheral address space (0x40000000-0x5FFFFFFF) is marked as Device memory to ensure correct access order and doesn't allow unaligned access. Configure MPU won't resolve the issue since change the memory type to Normal will break more things.

In theory, this assembly instruction should trigger an unaligned access exception in both GCC and IAR compilers, unless GCC and IAR do not generate the LDRH instruction for bit-field accesses.

@tzy0002088
Copy link
Author

I've successfully reproduced the issue by manually adding , since I don't use Keil and both GCC and IAR are not affected.asm("LDRH R0, [R0, #0x441]");

I think it's a armclang bug: https://developer.arm.com/documentation/ka004594/latest/

Version prior to 6.16 doesn't access volatile bit-field using an access width appropriate to the type of its container.

I was wrong about the MPU, since peripheral address space (0x40000000-0x5FFFFFFF) is marked as Device memory to ensure correct access order and doesn't allow unaligned access. Configure MPU won't resolve the issue since change the memory type to Normal will break more things.

I can try to reproduce the issue using the GCC compiler later.

@HiFiPhile
Copy link
Collaborator

HiFiPhile commented Jan 12, 2025

In theory, this assembly instruction should trigger an unaligned access exception in both GCC and IAR compilers, unless GCC and IAR do not generate the LDRH instruction for bit-field accesses.

Yes, they don't generate LDRH for unaligned access as speed is uint32_t :

uint32_t speed : 2; // 17..18 Port speed

IAR:
image

GCC:
image

@tzy0002088
Copy link
Author

In theory, this assembly instruction should trigger an unaligned access exception in both GCC and IAR compilers, unless GCC and IAR do not generate the instruction for bit-field accesses.LDRH

Yes, they don't generate for unaligned access as speed is uint32_t :LDRH

uint32_t speed : 2; // 17..18 Port speed

IAR: image

GCC: image

After modifying the source code in this way, I was able to avoid the unaligned access exception, and it seems that the MPU configuration has taken effect (accessing an unaligned address within the 0x24000000 range).

1736686848977

@HiFiPhile
Copy link
Collaborator

@tzy0002088
Copy link
Author

Does -mno-unaligned-access fix the issue ? https://developer.arm.com/documentation/dui0774/l/Compiler-Command-line-Options/-munaligned-access---mno-unaligned-access

This can solve the problem of unaligned access, but the return value is incorrect, for example, dwc2->hprt_bm.speed returns a high-speed device, but it is actually a full-speed device

@HiFiPhile
Copy link
Collaborator

Does -mno-unaligned-access fix the issue ? https://developer.arm.com/documentation/dui0774/l/Compiler-Command-line-Options/-munaligned-access---mno-unaligned-access

This can solve the problem of unaligned access, but the return value is incorrect, for example, dwc2->hprt_bm.speed returns a high-speed device, but it is actually a full-speed device

Seems like armclang is really bugged. Also the fix you found may work currently but there is no guarantee that it won't break sometimes later.

Which version do you use, could you make an update?

@tzy0002088
Copy link
Author

Does -mno-unaligned-access fix the issue ? https://developer.arm.com/documentation/dui0774/l/Compiler-Command-line-Options/-munaligned-access---mno-unaligned-access

This can solve the problem of unaligned access, but the return value is incorrect, for example, dwc2->hprt_bm.speed returns a high-speed device, but it is actually a full-speed device

Seems like armclang is really bugged. Also the fix you found may work currently but there is no guarantee that it won't break sometimes later.

Which version do you use, could you make an update?

This problem occurs on both host and device. I just listed one point.

Use the master version

@tzy0002088
Copy link
Author

Does -mno-unaligned-access fix the issue ? https://developer.arm.com/documentation/dui0774/l/Compiler-Command-line-Options/-munaligned-access---mno-unaligned-access

This can solve the problem of unaligned access, but the return value is incorrect, for example, dwc2->hprt_bm.speed returns a high-speed device, but it is actually a full-speed device

Seems like armclang is really bugged. Also the fix you found may work currently but there is no guarantee that it won't break sometimes later.

Which version do you use, could you make an update?

We may consider supporting the dwc2 driver on the arm compiler later. I think this issue can be closed for now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants