cancel
Showing results for 
Search instead for 
Did you mean: 

Hard Fault using STM32F0x2_USB-FS-Device_Lib V1.0.0 on STM32F072CB

p23
Associate II
Posted on June 15, 2015 at 13:27

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.c

Exactly 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-fault
7 REPLIES 7
Posted on June 15, 2015 at 14:00

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.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on June 15, 2015 at 14:06

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
}
}

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
p23
Associate II
Posted on June 15, 2015 at 14:39

I'm using:

IDE-Version:

µVision V5.11.1.0

Tool Version Numbers:

Toolchain:        MDK-ARM Standard Cortex-M only: 1 user  Version: 5.11.0.0

Toolchain Path:    C:\Keil\ARM\ARMCC\bin\

C Compiler:         Armcc.Exe       V5.04.0.49

Assembler:          Armasm.Exe       V5.04.0.49

Linker/Locator:     ArmLink.Exe       V5.04.0.49

Librarian:             ArmAr.Exe       V5.04.0.49

Hex Converter:      FromElf.Exe       V5.04.0.49

CPU DLL:               SARMCM3.DLL       V5.11.0.0

Dialog DLL:         DARMCM1.DLL       V1.11.00.0

Target DLL:             ULP2CM3.DLL       V2.197.23.0

Dialog DLL:         TARMCM1.DLL       V1.08.00.0

The assembler code doesn't look bad to me:

   705:   for (i = n; i != 0; i--) 

   706:   { 

0x08000E4E 462B      MOV      r3,r5

0x08000E50 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,#2

0x08000E58 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,#1

0x08000E5E 2B00      CMP      r3,#0x00

0x08000E60 D1F7      BNE      0x08000E52

   710: } 

0x08000E62 BD70      POP      {r4-r6,pc}

0x08000E64 6000      DCW      0x6000

0x08000E66 4000      DCW      0x4000

I'll try your suggestion. If this doesn't work I'll update µVision, the latest Version is 5.15

p23
Associate II
Posted on June 15, 2015 at 14:46

It's solved, your suggestion works fine!

Thanks a lot!

Posted on June 15, 2015 at 16:50

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?

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
drojfjord
Associate II
Posted on November 04, 2015 at 04:50

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++;
}
}

Nesrine M_O
Lead II
Posted on November 22, 2016 at 16:15

Hi wong.daniel,

Thank you for your feedback. The issue has been reported internally.

-Syrine-