2017-05-01 11:20 AM
I'm running into a Hard Fault when sending 9 bytes from a PC to a STM32F103C8T6 using USB CDC code generated by Cube 4.20.1, FW F1 V1.4.0. I can send 8 bytes to the microcontroller without issue, but once I try 9 bytes, the micro runs into a Hard Fault.
The project is generated in CubeMX, using System Workbench IDE, and running on a custom board. The only changes to the generated code is a section that pulls down D+ and waits 500 ms before calling MX_USB_DEVICE_Init(). This allows the PC to de-numerate and renumerate the device.
I'm running RealTerm on my Windows 10 PC, under the 'Send' tab, using the data '123456789', and then 'Send ASCII'. At this point, the microcontrolller goes to a Hard Fault. (See attached image for stack trace) If I send '12345678' instead, everything runs fine.
I'm not sure how to debug this, so any advice is appreciated.
Thank you!
#cdc #usb-cdc #usb #hard-faultSolved! Go to Solution.
2017-05-02 09:00 PM
I found the issue. There is a define in usbd_cdc_if.c that defines the size of the Rx buffer.
#define APP_RX_DATA_SIZE 4
Since the Rx Buffer was undersized, the USB_ReadPMA function was going out of bounds, overwriting values in PCD_HandleTypeDef. USBx is the same pointer as
PCD_HandleTypeDef->Instance which was overwritten in the USB_ReadPMA function. Since USBx became an invalid pointer, evaluating USBx->BTABLE caused the hard fault.
Changing APP_RX_DATA_SIZE to a larger value seems to have fixed the hard fault.
2017-05-01 12:50 PM
Not sure the stack trace is immensely helpful. Suggest you look at the faulting instruction, the registers and what it was doing.
2017-05-01 03:18 PM
,
,
The line of code where the fault happens is :
/*Set RX buffer count*/
,
PCD_SET_EP_RX_CNT(USBx, ep->,num, len),Unfortunately, the rest of the code from there are a series of ♯ defines, so I can't get the exact line past this. ,As a note, len is set to 64 at this point.
♯ define PCD_SET_EP_RX_CNT(USBx, bEpNum,wCount) {\
,
uint32_t *pdwReg = PCD_EP_RX_CNT((USBx), (bEpNum)), \,
PCD_SET_EP_CNT_RX_REG(pdwReg, (wCount)),\,
}♯ define PCD_EP_RX_CNT(USBx, bEpNum) ((uint32_t *)(((USBx)->,BTABLE+(bEpNum)*8+6)*2+ ((uint32_t)(USBx) + 0x400)))
♯ define PCD_SET_EP_CNT_RX_REG(dwReg,wCount) {\
,
uint16_t wNBlocks,\,
if((wCount) >, 62) \,
{ \,
PCD_CALC_BLK32((dwReg),(wCount),wNBlocks), \,
} \,
else \,
{ \,
PCD_CALC_BLK2((dwReg),(wCount),wNBlocks), \,
} \,
}/* PCD_SET_EP_CNT_RX_REG */,
♯ define PCD_CALC_BLK32(dwReg,wCount,wNBlocks) {\,
(wNBlocks) = (wCount) >,>, 5,\,
if(((wCount) &, 0x1f) == 0)\,
{ \,
(wNBlocks)--,\,
} \,
*pdwReg = (uint16_t)((uint16_t)((wNBlocks) <,<, 10) | 0x8000), \,
}/* PCD_CALC_BLK32 */♯ define PCD_CALC_BLK2(dwReg,wCount,wNBlocks) {\
,
(wNBlocks) = (wCount) >,>, 1,\,
if(((wCount) &, 0x1) != 0)\,
{ \,
(wNBlocks)++,\,
} \,
*pdwReg = (uint16_t)((wNBlocks) <,<, 10),\,
}/* PCD_CALC_BLK2 */2017-05-01 03:31 PM
You'd want to be looking at a disassembly, from either a listing or code file (ie source/assembler intermixed), you're interested in the instruction the processor is trying to execute and the register content for those used by the instruction.
ep->num is likely some out-of-range value, resulting in pdwReg touching memory it shouldn't
2017-05-02 09:00 PM
I found the issue. There is a define in usbd_cdc_if.c that defines the size of the Rx buffer.
#define APP_RX_DATA_SIZE 4
Since the Rx Buffer was undersized, the USB_ReadPMA function was going out of bounds, overwriting values in PCD_HandleTypeDef. USBx is the same pointer as
PCD_HandleTypeDef->Instance which was overwritten in the USB_ReadPMA function. Since USBx became an invalid pointer, evaluating USBx->BTABLE caused the hard fault.
Changing APP_RX_DATA_SIZE to a larger value seems to have fixed the hard fault.