Plus-TCP on SAMv71 hard fault debugging

Hello, I’m trying to get FreeRTOS-Plus-TCP working on an Atmel SAM V71 (which has a cortex M7 and a KSZ8061RNBVA ethernet PHY). I started with a working FreeRTOS 8.2.3 using heap4, added Plus-TCP (r160919) using BufferAllocation2, and based my NetworkInterface.c upon the included Cortex M3/M4 example, while using the latest Atmel ASF drivers for the GMAC and ethernet_phy for my device. This is producing a hard fault some time after the TCP tasks begin; it occurs whether or not there is a cable connected to the ethernet port. In either case, the vApplicationIPNetworkEventHook is correctly called with the eNetworkUp/Down event. And the GMAC_Handler interrupt handler is called at least once without apparent issues, when the cable is connected. For debugging purposes, I have disabled all other tasks, and disabled the -Plus-Trace library and printfs via the serial UART. configASSERT, configCHECKFORSTACKOVERFLOW (2), and configUSEMALLOCFAILEDHOOK are defined, but do not occur. configMACINTERRUPTPRIORITY is configLIBRARYMAXSYSCALLINTERRUPTPRIORITY, which is 4. configLIBRARYLOWESTINTERRUPTPRIORITY is 7 (configPRIOBITS is 3). configUSEPREEMPTION is 1, and configIDLESHOULDYIELD is currently 0, as is configUSETICKLESS_IDLE So far as I know, the only interrupt registered is for the network interface (interrupt number 39 as defined in the GMAC driver). I have seen the hard fault debugging advice here, but am having trouble making use of it. I have disabled ICache and DCache, TCM has never been enabled, and I set the DISDEFWBUF bit (SCnSCB->ACTLR |= 2;) to stop write buffering and prevent imprecise faults. I have confirmed that these are direct Hard faults, not MemManage, BusFault or UsageFaults, and are not imprecise (0xE000ED29 & 0x02 == 0). However when I use the code on the linked page, I don’t seem to be getting useful information and am at a bit of a loss for how to debug this. When I first arrive in the HardFault_Handler, (0xe000ed04) & 0xFF , which should contain the interrupt number, is 3 (like I mentioned I thought there was only one interrupt, number 39). When I use the provided code to restore the registers, I get: r0=0, r1=0x20404e1c, r2=0x10000000, r3=0xe000ed04, r12=0x20404de4, lr=0x0040a41d, pc=0x20400004, psr=0x00000200. pc points to the DTCM section of memory rather than flash (which starts at 0x00400000), and is apparently not executable code; certainly I’m not able to put a breakpoint there. So I can’t determine the source of the hard faults. I’m happy to share my current NetworkInterface.c code if it might help. Many thanks for any help!

Plus-TCP on SAMv71 hard fault debugging

Hi Justin, one of the most probably causes of a hard-fault in a +TCP driver is writing outside malloc’d area. Or writing to space that has been free’d already. Therefor it is very important to check who is the owner of all network buffers at any moment in time. configCHECK_FOR_STACK_OVERFLOW = 2 does give some protection, but while developing, just make sure that there is more than enough stack space. If you want attach your NetworkInterface.c along with your FreeRTOSIPConfig.h, and I’ll have a look at them

Plus-TCP on SAMv71 hard fault debugging

Hein, I’m attaching NetworkInterface.c and including FreeRTOSIPConfig.h below. I tried increasing the configMINIMALSTACKSIZE from 130 to 1300, but I still see the same hard fault. I’ll look through the code for reads and writes going wrong. Much appreciated. ~~~

ifndef FREERTOSIPCONFIG_H

define FREERTOSIPCONFIG_H

define ipconfigHASDEBUGPRINTF 0

if( ipconfigHASDEBUGPRINTF == 1 )

#define FreeRTOS_debug_printf(X)    printf X

endif

define ipconfigHAS_PRINTF 0

if( ipconfigHAS_PRINTF == 1 )

#define FreeRTOS_printf(X)  extern SemaphoreHandle_t printMutex; xSemaphoreTake(printMutex, 0); portDISABLE_INTERRUPTS();  printf X ;  portENABLE_INTERRUPTS(); xSemaphoreGive(printMutex);

endif

define ipconfigBYTEORDER pdFREERTOSLITTLE_ENDIAN

define ipconfigDRIVERINCLUDEDRXIPCHECKSUM 1

define ipconfigSOCKDEFAULTRECEIVEBLOCKTIME ( 5000 )

define ipconfigSOCKDEFAULTSENDBLOCKTIME ( 5000 )

define ipconfigIPTASKPRIORITY ( configMAX_PRIORITIES – 2 )

/* The size, in words (not bytes), of the stack allocated to the FreeRTOS+TCP task.*/

define ipconfigIPTASKSTACKSIZEWORDS ( configMINIMALSTACKSIZE * 5 )

/* ipconfigRAND32() is called by the IP stack to generate random numbers for things such as a DHCP transaction number or initial sequence number. / / JB: TODO – add true random number generator ASF module and implement this (if needed) / /extern UBaseType_t uxRand( void );

define ipconfigRAND32() uxRand()

*/

define ipconfigUSENETWORKEVENT_HOOK 1

define ipconfigUDPMAXSENDBLOCKTIMETICKS ( 5000 / portTICKPERIOD_MS )

define ipconfigARPCACHEENTRIES 6

define ipconfigMAXARPRETRANSMISSIONS ( 5 )

define ipconfigMAXARPAGE 150

define ipconfigINCLUDEFULLINET_ADDR 1

define ipconfigNUMNETWORKBUFFER_DESCRIPTORS 60

/* A FreeRTOS queue is used to send events from application tasks to the IP stack. ipconfigEVENTQUEUELENGTH sets the maximum number of events that can be queued for processing at any one time. The event queue must be a minimum of 5 greater than the total number of network buffers. */

define ipconfigEVENTQUEUELENGTH ( ipconfigNUMNETWORKBUFFER_DESCRIPTORS + 5 )

define ipconfigALLOWSOCKETSENDWITHOUTBIND 1

/* Defines the Time To Live (TTL) values used in outgoing UDP packets. */

define ipconfigUDPTIMETO_LIVE 128

define ipconfigTCPTIMETO_LIVE 128 /* also defined in FreeRTOSIPConfigDefaults.h */

/* USE_TCP: Use TCP and all its features */

define ipconfigUSE_TCP ( 1 )

/* USE_WIN: Let TCP use windowing mechanism. */

define ipconfigUSETCPWIN ( 1 )

/* The MTU is the maximum number of bytes the payload of a network frame can contain. For normal Ethernet V2 frames the maximum MTU is 1500. Setting a lower value can save RAM, depending on the buffer management scheme used. If ipconfigCANFRAGMENTOUTGOINGPACKETS is 1 then (ipconfigNETWORKMTU – 28) must be divisible by 8. */

define ipconfigNETWORK_MTU 1200

/** DNS **/ /* Set ipconfigUSE_DNS to 1 to include a basic DNS client/resolver. */

define ipconfigUSE_DNS 0

if ipconfigUSE_DNS

/*JB: if defined, apparently necessary to define xApplicationDNSQueryHook () */

/* Include support for LLMNR: Link-local Multicast Name Resolution
(non-Microsoft) */
#define ipconfigUSE_LLMNR                   ( 1 )

/* Include support for NBNS: NetBIOS Name Service (Microsoft) */
#define ipconfigUSE_NBNS                    ( 1 )

/* Include support for DNS caching. */
#define ipconfigUSE_DNS_CACHE               ( 1 )
#define ipconfigDNS_CACHE_NAME_LENGTH       ( 16 )
#define ipconfigDNS_CACHE_ENTRIES           ( 4 )
#define ipconfigDNS_REQUEST_ATTEMPTS        ( 2 )

endif /* ipconfigUSE_DNS */

/** End DNS **/ /** DHCP **/ /* If ipconfigUSEDHCP is 1 then FreeRTOS+TCP will attempt to retrieve an IP address, netmask, DNS server address and gateway address from a DHCP server. If ipconfigUSEDHCP is 0 then FreeRTOS+TCP will use a static IP address. */

define ipconfigUSE_DHCP 0

define ipconfigMAXIMUMDISCOVERTXPERIOD ( 120000 / portTICKPERIOD_MS )

/** End DHCP **/ /* If ipconfigREPLYTOINCOMING_PINGS is set to 1 then the IP stack will generate replies to incoming ICMP echo (ping) requests. */

define ipconfigREPLYTOINCOMING_PINGS 1

/* If ipconfigSUPPORTOUTGOINGPINGS is set to 1 then the FreeRTOS_SendPingRequest() API function is available. */

define ipconfigSUPPORTOUTGOINGPINGS 0

/* If ipconfigSUPPORTSELECTFUNCTION is set to 1 then the FreeRTOS_select() (and associated) API function is available. */

define ipconfigSUPPORTSELECTFUNCTION 1

/* If ipconfigFILTEROUTNONETHERNETII_FRAMES is set to 1 then Ethernet frames that are not in Ethernet II format will be dropped. This option is included for potential future IP stack developments. */

define ipconfigFILTEROUTNONETHERNETII_FRAMES 1

/* If ipconfigETHERNETDRIVERFILTERSFRAMETYPES is set to 1 then it is the responsibility of the Ethernet interface to filter out packets that are of no interest. If the Ethernet interface does not implement this functionality, then set ipconfigETHERNETDRIVERFILTERSFRAMETYPES to 0 to have the IP stack perform the filtering instead (it is much less efficient for the stack to do it because the packet will already have been passed into the stack). If the Ethernet driver does all the necessary filtering in hardware then software filtering can be removed by using a value other than 1 or 0. */

define ipconfigETHERNETDRIVERFILTERSFRAMETYPES 1

/* The windows simulator cannot really simulate MAC interrupts, and needs to block occasionally to allow other tasks to run. */

define configWINDOWSMACINTERRUPTSIMULATORDELAY ( 20 / portTICKPERIODMS )

/* Advanced only: in order to access 32-bit fields in the IP packets with 32-bit memory instructions, all packets will be stored 32-bit-aligned, plus 16-bits. This has to do with the contents of the IP-packets: all 32-bit fields are 32-bit-aligned, plus 16-bit(!) */

define ipconfigPACKETFILLERSIZE 2

/* Define the size of the pool of TCP window descriptors. On the average, each TCP socket will use up to 2 x 6 descriptors, meaning that it can have 2 x 6 outstanding packets (for Rx and Tx). When using up to 10 TP sockets simultaneously, one could define TCPWINSEG_COUNT as 120. */

define ipconfigTCPWINSEG_COUNT 240

/* Each TCP socket has a circular buffers for Rx and Tx, which have a fixed maximum size. Define the size of Rx buffer for TCP sockets. */

define ipconfigTCPRXBUFFER_LENGTH ( 1000 )

/* Define the size of Tx buffer for TCP sockets. */

define ipconfigTCPTXBUFFER_LENGTH ( 1000 )

/* When using call-back handlers, the driver may check if the handler points to real program memory (RAM or flash) or just has a random non-zero value. */

define ipconfigISVALIDPROG_ADDRESS(x) ( (x) != NULL )

/* Include support for TCP hang protection. All sockets in a connecting or disconnecting stage will timeout after a period of non-activity. */

define ipconfigTCPHANGPROTECTION ( 1 )

define ipconfigTCPHANGPROTECTION_TIME ( 30 )

/* Include support for TCP keep-alive messages. */

define ipconfigTCPKEEPALIVE ( 1 )

define ipconfigTCPKEEPALIVE_INTERVAL ( 20 ) /* in seconds */

/*JB: from website (undefined in defaults) When ipconfigUSE_LINKED_RX_MESSAGES is set to 1 it is possible to reduce CPU load during periods of heavy network traffic by linking multiple received packets together, then passing all the linked packets to the IP RTOS task in one go */

define ipconfigUSELINKEDRX_MESSAGES 0

/* JB: from website (undefined in defaults) TCP time stamp functionality is available, but its usage is quite limited. Time-stamps can only be used if the initial SYN packet contains the time-stamp option. In most cases, incoming connection won’t have the time-stamp option set. */

define ipconfigUSETCPTIMESTAMPS 0

/* JB: extra debugging A FreeRTOS queue is used to send events from application tasks to the IP stack. ipconfigEVENTQUEUELENGTH sets the maximum number of events that can be queued for processing at any one time. If ipconfigCHECKIPQUEUE_SPACE is set to 1 then the uxGetMinimumIPQueueSpace() function can be used to query the minimum amount of free space that has existed in the queue since the system booted. */

define ipconfigCHECKIPQUEUE_SPACE 1

define portINLINE __inline

endif /* FREERTOSIPCONFIG_H */

~~~

Plus-TCP on SAMv71 hard fault debugging

Before I look further in your networkInterface, can you check if the code gets into FreeRTOS_ARP.c. One user, Stefan Battmer, recently reported about an unaligned access in FreeRTOS_ARP.c. Maybe you can set a breakpoint both in ulSenderProtocolAddress() and in eARPProcessPacket(). it is the field ulSenderProtocolAddress that is 2-byte aligned and that might cause a crash / hardfault. If that is the cause, we’ll make an update available. Thanks, Hein

Plus-TCP on SAMv71 hard fault debugging

I put a breakpoint at the top of eARPProcessPacket() and vARPGenerateRequestPacket(), which appear to be the only functions to use ulSenderProtocolAddress (I couldn’t find a function with the same name). I can confirm that I got a hard fault without either of these triggering.

Plus-TCP on SAMv71 hard fault debugging

@Hein Just wondering if you’ve had a chance to look at the code. So far I’m still unsure what is causing the hard faults. Really appreciate it. -Justin

Plus-TCP on SAMv71 hard fault debugging

Hi Justin, I’m sorry, I had forgotten about your post. It is no problem to ring the bell earlier next time. The function gmac_dev_write() ends as follows: ~~~ uint32t gmacdevwrite(gmacdevicet* pgmacdev, void *pbuffer, uint32t ulsize, gmacdevtxcbt functxcb) { … /* Now start to transmit if it is still not done */ gmac_start_transmission(p_hw);
return GMAC_OK;
} ~~~ Your driver is sending out a packet, and immediately after that, it releases the network Buffer: ~~~ BaseTypet xNetworkInterfaceOutput( NetworkBufferDescriptort * const pxDescriptor, BaseTypet bReleaseAfterSend ) { if( ( ulPHYLinkStatus & BMSRLINKSTATUS ) != 0 ) { /* Not interested in a call-back after TX. */ gmacdevwrite( &gsgmacdev, QUEUEINDEX, (void *)pxDescriptor->pucEthernetBuffer, pxDescriptor->xDataLength, NULL ); iptraceNETWORK_INTERFACE_TRANSMIT(); }
if( bReleaseAfterSend != pdFALSE )
{
    vReleaseNetworkBufferAndDescriptor( pxDescriptor );
}
return pdTRUE;
} /———————————————————–/ ~~~ When vReleaseNetworkBufferAndDescriptor() is called, the pucEthernetBuffer might still be used in a DMA buffer. It is not correct but it won’t lead to hard fault. Your port has a function gmac_dev_read(). In case there are less than 2 Network buffers available, the function will be called with a NULL pointer. We want to flush the DMA buffer without using its contents. Did you adapt that function already to test for NULL? In the port for SAM4E, I made quite a few changes to gmac_dev_read() : ~~~ uint32t gmacdevread(gmacdevicet* pgmacdev, uint8t* pframe, uint32t ulframesize, uint32t* prcvsize) { int32t nextIdx; /* A copy of the Rx-index ‘ulrxidx’ */ int32_t bytesLeft = gmac_dev_poll (p_gmac_dev); gmac_rx_descriptor_t *pxHead;
if (bytesLeft == 0 )
{
    return GMAC_RX_NULL;
}

/* gmac_dev_poll has confirmed that there is a complete frame at
 * the current position 'ul_rx_idx'
 */
nextIdx = p_gmac_dev->ul_rx_idx;

/* Read +2 bytes because buffers are aligned at -2 bytes */
bytesLeft = min( bytesLeft + 2, ( int32_t )ul_frame_size );

/* The frame will be copied in 1 or 2 memcpy's */
if( ( p_frame != NULL ) && ( bytesLeft != 0 ) )
{
const uint8_t *source;
int32_t left;
int32_t toCopy;

    source = p_gmac_dev->p_rx_buffer + nextIdx * GMAC_RX_UNITSIZE;
    left = bytesLeft;
    toCopy = ( p_gmac_dev->ul_rx_list_size - nextIdx ) * GMAC_RX_UNITSIZE;
    if(toCopy > left )
    {
        toCopy = left;
    }
    memcpy (p_frame, source, toCopy);
    left -= toCopy;

    if( left != 0ul )
    {
        memcpy (p_frame + toCopy, (void*)p_gmac_dev->p_rx_buffer, left);
    }
}

do
{
    pxHead = &p_gmac_dev->p_rx_dscr[nextIdx];
    pxHead->addr.val &= ~(GMAC_RXD_OWNERSHIP);
    circ_inc32 (&nextIdx, p_gmac_dev->ul_rx_list_size);
} while ((pxHead->status.val & GMAC_RXD_EOF) == 0);

p_gmac_dev->ul_rx_idx = nextIdx;

*p_rcv_size = bytesLeft;

return GMAC_OK;
} ~~~ The code will test if p_frame equals NULL. I hope that it helps, please report back. Regards, Hein

Plus-TCP on SAMv71 hard fault debugging

Thanks for that. I hadn’t noticed the functional changes that were made to the GMAC driver in the example. I’ll work to integrate them and let you know how it goes.

Plus-TCP on SAMv71 hard fault debugging

I think I’ve addressed the issues you raised, but I’m still facing at least two types of Hard fault, both due to the program counter pointing to invalid instructions/non-code. I haven’t truly got to test these changes yet, though. I’ve been able to confirm the source of one of the hard faults, however, which remains despite the changes. The use case is simple. I don’t have a cable connected to the ethernet port. I attempt to auto-negotiate/initialize and fail. xNetworkInterfaceInitialise() returns pdFAIL. At FreeRTOS_IP.c: 1339, vTaskDelay() is called. (It would occur in another place if vTaskDelay were called prior to this point, as I tried to do while waiting for the PHY to be ready). By the time vTaskDelay arrives at the end of the function, the value it pops to the program counter is invalid (on the heap). After the pop, the program counter (always) it points to 0x20400044, which is in SRAM. Hence it always causes a hard fault after executing the last line below (the code shows disassembly of the end of vTaskDelay).
    if( xAlreadyYielded == pdFALSE )
0040C8A2 ldr r3, [r7, #20]
0040C8A4 cmp r3, #0
0040C8A6 bne #14
portYIELDWITHINAPI(); 0040C8A8 ldr r3, [pc, #52]
0040C8AA mov.w r2, #268435456
0040C8AE str r2, [r3]
0040C8B0 dsb sy
0040C8B4 isb sy
} 0040C8B8 nop
0040C8BA adds r7, #24
0040C8BC mov sp, r7
0040C8BE pop {r7, pc} During the course of vTaskDelay, I noticed that xPortPendSVHandler executes twice, and it’s just after finishing the second time that the end of vTaskDelay (above) executes, leading to the error. I guess this is the context switching that is occurring, but it seems something about the saving and restoring of the state is failing. Any idea what might be going wrong here? Note I am using FreeRTOS 8.2.3. I have also tried tripling my stack size to 0xF000 (60kb), which had no effect.

Plus-TCP on SAMv71 hard fault debugging

Justin, You’re getting closer …
By the time vTaskDelay arrives at the end of the function, the value it pops to the program counter is invalid (on the heap).
Not ‘heap’ but ‘stack’, I assume 🙂
After the pop, the program counter (always) it points to 0x20400044, which is in SRAM. Hence it always causes a hard fault after executing the last line below (the code shows disassembly of the end of vTaskDelay).
When vTaskDelay crashes at the end, it looks to me that the task’s stack has been corrupted / overwritten in a meanwhile.
Any idea what might be going wrong here? Note I am using FreeRTOS 8.2.3.
There are no known issues of this type with 8.2.3. Also +TCP was initially developed and tested with that kernel release.
I have also tried tripling my stack size to 0xF000 (60kb), which had no effect.
The size of what stack? There is a general program stack, that is used at boot time until the scheduler is started. But when the IP-task runs, it uses a stack that is determined as: ~~~ #define configMINIMALSTACKSIZE ( 130 ) #define ipconfigIPTASKSTACKSIZEWORDS ( configMINIMALSTACKSIZE * 5 ) ~~~ That makes 5 x 130 = 650 words ( 2600 bytes ). Should be more than enough. Unless you’re using stack-expensive routines for logging? Isn’t there some pointer that is not properly initialised and writing in the wrong space? What about the other tasks you are running? Do they have enough stack? Can you log or trace what happens during the call to vTaskDelay() ? That is maybe the first time that some other task becomes active?

Plus-TCP on SAMv71 hard fault debugging

Hein, Thanks again for your insight.
When vTaskDelay crashes at the end, it looks to me that the task’s stack has been corrupted / overwritten in a meanwhile.
I think that’s correct.
I have also tried tripling my stack size to 0xF000 (60kb), which had no effect.
The size of what stack? There is a general program stack, that is used at boot time until the scheduler is started.
I momentarily forgot about the task stacks and was talking about the program stack.
But when the IP-task runs, it uses a stack that is determined as: … That makes 5 x 130 = 650 words ( 2600 bytes ). Should be more than enough. Unless you’re using stack-expensive routines for logging?
I am using printf for logging. But I had set configMINIMALSTACKSIZE to 1300 for testing, which should be more than adequate so I doubt it’s that (I’ve now reset it to a more reasonable 450; no difference).
Isn’t there some pointer that is not properly initialised and writing in the wrong space?
This is possible. But so far I haven’t been able to find anything. And there’s not actually a lot of my code that’s running before this happens. I’ll keep digging into this though.
What about the other tasks you are running? Do they have enough stack? Can you log or trace what happens during the call to vTaskDelay() ? That is maybe the first time that some other task becomes active?
I have removed all user tasks from this test program so the only tasks running are those used by FreeRTOS and +TCP. I’ve tried debugging through vTaskDelay() but not found anything to really be happening. After vTaskDelay invokes PendSVHandler, it drops into the loop in portTASKFUNCTION(). It repeatedly tests if there are any tasks to delete (which there never are) and then since I have configUSEPREEMPTION == 1 and configIDLESHOULD_YIELD == 1, it checks to see if it needs to yield. I set a breakpoint on taskYIELD, but strangely this never gets hit, so I’m not sure how control leaves this function. I can only assume it itself is getting preempted somehow. This loop executes hundreds of times for even a 1ms delay (I know because I stepped through it hundreds of times) without anything else apparently happening. Eventually PendSVHandler is called again and at this point the program pointer popped from the stack is corrupted (always in the same way), causing the Usage Fault. Do you perhaps you have some ideas for other places I could put breakpoints to see if anything else is occurring during vTaskDelay without my knowledge?

Plus-TCP on SAMv71 hard fault debugging

I should note that I have the following in FreeRTOSConfig.h: ~~~ /* Definitions that map the FreeRTOS port interrupt handlers to their CMSIS standard names. */

define xPortPendSVHandler PendSV_Handler

define vPortSVCHandler SVC_Handler

define xPortSysTickHandler SysTick_Handler

~~~ The PendSVHandler that gets called is xPortPendSVHandler() in freertos-8.2.3/Source/portable/GCC/ARMCM7/r0p1/port.c

Plus-TCP on SAMv71 hard fault debugging

Indirect replies only – Make sure you have configCHECKFORSTACK_OVERFLOW set to 2, and the overflow hook function set to something that halts the program. That will take out a lot of guess work. configMINIMALSTACKSIZE only effects the size of the idle task stack, unless you are using it yourself to dimension the size of your application tasks. Have you tried taking out all the calls to printf()? Do you have compiler optimisation on? If so, that may explain why your break point is not being hit.

Plus-TCP on SAMv71 hard fault debugging

Thank you. I did indeed have a -Og snuck in there for the C++ compiler (optimization was disabled for the C compiler though, so it shouldn’t have affected this code). I still do not get the breakpoint on taskYIELD() to hit however. It appears that all tasks (again, the only tasks I have are created by FreeRTOS or +TCP) use stack size as a multiple of configMINIMALSTACKSIZE: ~~~

define configTIMERTASKSTACKDEPTH ( configMINIMALSTACK_SIZE * 2 )

define tskIDLESTACKSIZE configMINIMALSTACKSIZE

define ipconfigIPTASKSTACKSIZEWORDS ( configMINIMALSTACKSIZE * 5 )

// Used within the NetworkInterface:

define configEMACTASKSTACKSIZE ( 4 * configMINIMALSTACK_SIZE )

~~~ NOTE: the EMAC TASK is not yet launched when this Usage Fault occurs. configCHECKFORSTACK_OVERFLOW has been set to 2 but vApplicationStackOverflowHook is seemingly never called. Previously it didn’t disable interrupts from within that function though, so I just did that to be sure. Still never see it getting called.

Plus-TCP on SAMv71 hard fault debugging

Still stumped by this one. It’s difficult to debug because I don’t know when/what is causing the portTASKFUNCTION to return to the original vTaskDelayFunction(). I expect it’s just the timeout expiring and causing a context switch back. But then how/why would the stack be corrupted? This is just core RTOS code. I don’t know the mechanics of the delay expiring, and as I noted, taskYIELD() is seemingly never called from portTASKFUNCTION. I have now tried the example demo for the SAM4E on SAM4E hardware and and found that it does indeed work. In that demo, it uses heap5. Is there any reason that I should use that over heap4, which is what I’m currently using? But generally I’m not seeing any clear reason why it should work while the SAMV71 adaptation doesn’t. Could this potentially have to do with the lower number of available user interrupt priorities on the Cortex M7 vs M4E (7 vs 15)? Or perhaps the fact that there are floating point registers to save for the M7 that might not have been needed for the M4E? Many thanks.

Plus-TCP on SAMv71 hard fault debugging

I have now tried the example demo for the SAM4E on SAM4E hardware and and found that it does indeed work. In that demo, it uses heap5. Is there any reason that I should use that over heap4, which is what I’m currently using? But generally I’m not seeing any clear reason why it should work while the SAMV71 adaptation doesn’t.
Heap4 and heap5 use the same algorithm. Heap_5 just has the added ability to be split across multiple memory blocks.
Could this potentially have to do with the lower number of available user interrupt priorities on the Cortex M7 vs M4E (7 vs 15)?
Unlikely.
Or perhaps the fact that there are floating point registers to save for the M7 that might not have been needed for the M4E?
Unlikely. I’ve not read back through this thread, so maybe you have said already, but which version of FreeRTOS are you using? Unless you are using FreeRTOS V9 then the Cortex-M4F code is not completely compatible with the Cortex-M7. More importantly, what is the revision of the Cortex-M7 core you are using? If it is R0P1 then there are silicon errata that need to be worked around, and you will need to use the FreeRTOS port that is specific to that revision of the core (which is in the FreeRTOS/Source/Portable/GCC/ARM_CM7/r0p1 directory.

Plus-TCP on SAMv71 hard fault debugging

Thanks Richard, for those comments.
the fact that there are floating point registers to save for the M7
Richard, can there be a problem with memcpy() due to unsaved floating point registers like for the Cortex-A9? The SAM4E project is indeed using heap_5 because it has 3 different blocks of RAM memory. When there is a single heap block, heap_5 can still be usefull because it allows to use linker symbols that determine the location and size of the available RAM. When using heap_4, you need to set configTOTAL_HEAP_SIZE at compile time, which is often not known exactly before you have linked the project.

Plus-TCP on SAMv71 hard fault debugging

Richard, can there be a problem with |memcpy()| due to unsaved floating point registers like for the Cortex-A9 http://www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html#floating-point?
No, the way floating point works on the M class devices is different to the A class in-so-much-as the hardware detects if the FPU has been used, whereas on the A the user has to say. The context switch on the M devices looks for a bit being set in hardware, and if its set, handles the FPU context switch. In other words, if a library accessed an FPU register (as was happening on the A devices) the context switch code would notice, and the FPU registers would from then on form part of the task’s context automatically.

Plus-TCP on SAMv71 hard fault debugging

I am using FreeRTOS 8.2.3. It sounds like you would recommend upgrading to 9.0? (I only need to run on SAMV71Q21, not the SAM4E) I did not find any documentation of which cortex revision this board uses, but when I check the CPUID register, it indicates it is revision r0p1. I am already using the FreeRTOS port code for that revision. (Prior to integrating +TCP, my basic tests showed FreeRTOS to be working in the project).

Plus-TCP on SAMv71 hard fault debugging

I did not find any documentation of which cortex revision this board uses, but when I check the CPUID register, it indicates it is revision r0p1.
Ok – so the Cortex-M4F code is not going to work reliably on that part. It is only that core revision that has the problem, any other revision and using the Cortex-M4F code from FreeRTOS V9 onwards will be fine.
I am already using the FreeRTOS port code for that revision.
Do you mean you have switched to the port layer found in the V9 code? Previously you said you were using V8.x code, an the code with the silicon bug fix is only available in V9.

Plus-TCP on SAMv71 hard fault debugging

No, I only meant that I’m using the port code for 8.2.3 found under SourceportableGCCARM_CM7r0p1. So if the bug fix is not there then it sounds like it’s best that I switch to v9.

Plus-TCP on SAMv71 hard fault debugging

Oh – maybe I am mistaken then, if that directory is in V8.2.3 then it is also good to use. I thought it didn’t get added until V9.

Plus-TCP on SAMv71 hard fault debugging

Even more puzzling then. Because I’ve just updated to 9.0.0 and at first inspection, the problem appears to go away! I’ve only tested this simplest case that always caused a Hard Fault, but that’s already something!

Plus-TCP on SAMv71 hard fault debugging

Just wanted to confirm that using FreeRTOS 9.0.0 does indeed fix the faults. I’m now debugging functionality of the driver. Thanks for the help!