Alex
I understand you can have a hard fault in the following sequence:
1. (Called from USB OTG interrupt and interrupts globally disabled for fnUSB_handle_frame() handling)
uDisable_Interrupt(); // ensure interrupts remain blocked when handling the next possible transmission
fnUSB_handle_frame(USB_TX_ACKED, 0, iEndpoint_ref, &usb_hardware); // handle tx ack event
uEnable_Interrupt(); // allow higher priority interrupts again
2. (when extra data to send is in a linear block)
FNSEND_USB_DATA((tx_queue->ptrStart + tx_queue->usSent), usDataLength, iEndpoint, ptrUSB_HW); // transmit next buffer
fnPushLastLength(ptrUsbQueue, usDataLength); // save last length for use later
tx_queue->usSent += usDataLength; // total frame length in progress
3. Where
#define FNSEND_USB_DATA(pData, Len, iEndpoint, ptrUSB_HW) *ptrUSB_HW->ptrTxDatBuffer = (unsigned char *)pData; \
*ptrUSB_HW->ptr_ulUSB_BDControl = (unsigned long)(SET_FRAME_LENGTH(Len) | (OWN | ptrUSB_HW->ptrEndpoint->ulNextTxData0)); \
_SIM_USB(0, USB_SIM_TX, iEndpoint, ptrUSB_HW); \
ptrUSB_HW->ptrEndpoint->ulNextTxData0 ^= DATA_1; \
ptrUSB_HW->ptrEndpoint->ulEndpointSize ^= ALTERNATE_TX_BUFFER
and
the struct in question starts with
typedef struct stUSB_HW
{
unsigned long ulRxControl;
volatile unsigned long *ptr_ulUSB_BDControl; // pointer to the presently valid tx buffer descriptor control entry
USB_END_POINT *ptrEndpoint;
....
and
typedef struct stUSB_END_POINT
{
unsigned long ulNextRxData0;
unsigned long ulNextTxData0;
unsigned long ulEndpointSize; // contains size of endpoint plus some control flags
} USB_END_POINT;
4. From the screen shot it looks like this line can do it:
*ptrUSB_HW->ptr_ulUSB_BDControl = (unsigned long)(SET_FRAME_LENGTH(Len) | (OWN | ptrUSB_HW->ptrEndpoint->ulNextTxData0));
and specifically the
ptrUSB_HW->ptrEndpoint->ulNextTxData0
can fail.
5. The assembler to this is
ldr r2, [r7, #0]
ldr r2, [r2, #8]
ldr r2, [r2, #4]
ptrUSB_HW is in the register R7 (0x2002ff48), which points to a location at 0x2000ff48 according to the memory window.
r2 is however showing 0x400000, which is the previous content which is typically SET_FRAME_LENGTH(Len) [0x40 << 16], meaning that either this instruction has either not yet been executed or has been overwritten.
If the second assembly instruction is failing (with R2 at 0x400000) it would indeed be a read fr0m 0x400008, which is an invalid address, whereby the instruction's aim is to load the pointer ptrEndpoint so that the following instruction can load the value of ulNextTxData0.
The struct looks to be intact and the location of ptrEndpoint would be OK.
Can you check how uDisable_Interrupt() is set up in your system? I know that you are using FreeRTOs with the USB stack and USB driver and, since it doesn't look possible for r2 to not have the correct value after the first assembler instruction has been executed, I would carefully ensure that no task switching could be taking place (that is, that it is really correctly protected) and the register instance somehow being changed in the process.
Regards
Mark