2015-06-15 04:27 AM
Hello,
I'm working with the USB Library on a STM32F072CB.The project I use is the virtual com port example inclueded in the library.If I run the example without changing anything it works fine. Because the project isn't exactly what I need I have to change it a little bit. Therefor I changed the optimization level from 3 to 0, so I'm able to see all local variables in watch windows and so on.Apperently this results in getting an hard fault over and over again.All happens in the ''PMAToUserBufferCopy'' function in usb_core.cExactly the instruction: *(uint16_t*)pbUsrBuf++ = *pdwVal++; in the for loop of this function. /** * @brief Copy a buffer from user memory area to packet memory area (PMA) * @param pbUsrBuf = pointer to user memory area. * @param wPMABufAddr: address into PMA. * @param wNBytes: no. of bytes to be copied. * @retval None */void PMAToUserBufferCopy(uint8_t *pbUsrBuf, uint16_t wPMABufAddr, uint16_t wNBytes){ uint32_t n = (wNBytes + 1) >> 1; uint32_t i; uint16_t *pdwVal; pdwVal = (uint16_t *)(wPMABufAddr + PMAAddr); for (i = n; i != 0; i--) { *(uint16_t*)pbUsrBuf++ = *pdwVal++; pbUsrBuf++; }}I have no idea why this happens with optimization level 0 but not with level 3.Does anyone has/had this issue?It would be great if someone could help me out.Blubimo #stm32f0-usb-hard-fault2015-06-15 05:00 AM
Using what compiler/tool-chain?
Is the produced assembler code enlightening?I really don't like the casting of the 8-bit pointer to 16-bit one, and the incrementing. That would seem ripe for incrementing a byte at a time, creating an unaligned write, pretty sure the Cortex-M0 isn't keen on those.2015-06-15 05:06 AM
void PMAToUserBufferCopy(uint8_t *pbUsrBuf, uint16_t wPMABufAddr, uint16_t wNBytes)
{
uint32_t n = (wNBytes + 1) >> 1; // word count
uint32_t i;
uint16_t *pdwVal;
pdwVal = (uint16_t *)(wPMABufAddr + PMAAddr); // Watch if PMAAddr is odd
for (i = n; i != 0; i--)
{
uint16_t tmp = *pdwVal++; // pbUsrBuf might not be aligned
*pbUsrBuf++ = (uint8_t)((tmp >> 0) & 0xFF); // Low byte
*pbUsrBuf++ = (uint8_t)((tmp >> 8) & 0xFF); // High byte
}
}
2015-06-15 05:39 AM
I'm using:
IDE-Version:µVision V5.11.1.0Tool Version Numbers:Toolchain: MDK-ARM Standard Cortex-M only: 1 user Version: 5.11.0.0Toolchain Path: C:\Keil\ARM\ARMCC\bin\C Compiler: Armcc.Exe V5.04.0.49Assembler: Armasm.Exe V5.04.0.49Linker/Locator: ArmLink.Exe V5.04.0.49Librarian: ArmAr.Exe V5.04.0.49Hex Converter: FromElf.Exe V5.04.0.49CPU DLL: SARMCM3.DLL V5.11.0.0Dialog DLL: DARMCM1.DLL V1.11.00.0Target DLL: ULP2CM3.DLL V2.197.23.0Dialog DLL: TARMCM1.DLL V1.08.00.0The assembler code doesn't look bad to me: 705: for (i = n; i != 0; i--) 706: { 0x08000E4E 462B MOV r3,r50x08000E50 E005 B 0x08000E5E 707: *(uint16_t*)pbUsrBuf++ = *pdwVal++; 0x08000E52 8826 LDRH r6,[r4,#0x00]0x08000E54 8006 STRH r6,[r0,#0x00]0x08000E56 1CA4 ADDS r4,r4,#20x08000E58 1C40 ADDS r0,r0,#1 708: pbUsrBuf++; 709: } 0x08000E5A 1C40 ADDS r0,r0,#1 705: for (i = n; i != 0; i--) 706: { 707: *(uint16_t*)pbUsrBuf++ = *pdwVal++; 708: pbUsrBuf++; 709: } 0x08000E5C 1E5B SUBS r3,r3,#10x08000E5E 2B00 CMP r3,#0x000x08000E60 D1F7 BNE 0x08000E52 710: } 0x08000E62 BD70 POP {r4-r6,pc}0x08000E64 6000 DCW 0x60000x08000E66 4000 DCW 0x4000I'll try your suggestion. If this doesn't work I'll update µVision, the latest Version is 5.152015-06-15 05:46 AM
It's solved, your suggestion works fine!
Thanks a lot!2015-06-15 07:50 AM
Something old time ARM and MIPS coders have had to deal with before.
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0497a/BABFAIGG.html
If the input byte pointer is poorly aligned then a 16-bit read/write against it will fault.This was in some ST release library code for the Cortex-M0? or something adapted?2015-11-03 07:50 PM
Hi clive1,
As of 11/4/15, the offending code is still directly generated from CubeMX, using package ''STM32Cube FW_F0 V1.3.0''. I'm not sure who to bring this up with to get it 'fixed', so I'll reply here. I'm using Atollic Truestudio as my IDE if that makes any difference. The offending file is ''stm32f0xx_hal_pcd.c'', the function PCD_ReadPMA(...), on line 1 The function name appears to be different, but the problem triggers the same way for me./**
* @brief Copy a buffer from user memory area to packet memory area (PMA)
* @param USBx: USB peripheral instance register address.
* @param pbUsrBuf = pointer to user memory area.
* @param wPMABufAddr: address into PMA.
* @param wNBytes: no. of bytes to be copied.
* @retval None
*/
void PCD_ReadPMA(USB_TypeDef *USBx, uint8_t *pbUsrBuf, uint16_t wPMABufAddr, uint16_t wNBytes)
{
uint32_t n = (wNBytes + 1) >> 1;
uint32_t i;
uint16_t *pdwVal;
pdwVal = (uint16_t *)(wPMABufAddr + (uint32_t)USBx + 0x400);
for (i = n; i != 0; i--)
{
*(uint16_t*)pbUsrBuf++ = *pdwVal++;
pbUsrBuf++;
}
}
2016-11-22 07:15 AM
Hi wong.daniel,
Thank you for your feedback. The issue has been reported internally.-Syrine-