Hello
I’ve developed an application using FREERTOS and FREERTOS plus TCP.
It’s designed to receive network information and send it to the DAC, and receive information from the ADC and send it to the network.
The application itself works perfectly, pings, performs all its functions, and has no issues.
However, while testing, I noticed that the xEthHandle, which is used to work with the network stack and has the ETH_HandleTypeDef type, contains errors in the fields.
The ErrorCode field is 0x40, which corresponds to DMA_Transfer_Error, and the DMA_ERROR_CODE field is 0x4080, but sometimes changes to 0x4480.
This corresponds to the error codes Abnormal Interrupt Summary - 0x00004000, Early Transmit Interrupt - 0x00000400, and Receive Buffer Unavailable - 0x00000080.
I’d like to understand why these errors appear, what they mean, and what the possible consequences might be. Considering there are no complaints about the application itself. I’ve run fairly long tests and haven’t detected any failures.
Additional information.
STM32h743 chip, Microchip 8742a phy, Keil development studio, FreeRTOS version 11.1.0 (from task.h), FreeRTOS Plus TCP version 4.3.3 (NetworkInterface\STM32\Drivers\H7).
The problem occurs on both the developed board and the Nucleo-h743zi2.
Memory allocation map
; 1. Flash (2 MB)
LR_IROM1 0x08000000 0x00200000 { ; load region size_region
ER_IROM1 0x08000000 0x00200000 { ; load address = execution address
\*.o (RESET, +First)
\*(InRoot$$Sections)
.ANY (+RO)
}
; 2. DTCM (128 KB - data + stack)
DTCM_RAM 0x20000000 0x00020000 {
.ANY (+RW +ZI)
}
; 3. AXI SRAM (512 KB - FreeRTOS heap and Ethernet DMA)
AXI_RAM 0x24000000 0x00080000 {
* (freertos_heap)
* (eth_dma)
}
;4. SRAM1 (128 KB - DAC/ADC DMA)
SRAM1 0x30000000 0x00020000 {
* (dac_adc_dma)
}
}
Setting up MPU
void MPU_Config(void)
{
MPU_Region_InitTypeDef MPU_InitStruct = {0};
/* Disables the MPU */
HAL_MPU_Disable();
/* Initializes and configures the Region and the memory to be protected*/
MPU_InitStruct.Enable = MPU_REGION_ENABLE;
MPU_InitStruct.Number = MPU_REGION_NUMBER0;
MPU_InitStruct.BaseAddress = 0x0;
MPU_InitStruct.Size = MPU_REGION_SIZE_4GB;
MPU_InitStruct.SubRegionDisable = 0x87;
MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
MPU_InitStruct.AccessPermission = MPU_REGION_NO_ACCESS;
MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE;
MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE;
MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;
MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;
HAL_MPU_ConfigRegion(&MPU_InitStruct);
// Region 0: AXI SRAM (Ethernet DMA + FreeRTOS heap)
MPU_InitStruct.Enable = MPU_REGION_ENABLE;
MPU_InitStruct.Number = MPU_REGION_NUMBER1;
MPU_InitStruct.BaseAddress = 0x24000000;
MPU_InitStruct.Size = MPU_REGION_SIZE_512KB;
MPU_InitStruct.SubRegionDisable = 0x00;
MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL1;
MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;
MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE; // Sharing
MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE; // Uncacheable
MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;
HAL_MPU_ConfigRegion(&MPU_InitStruct);
// Region 1: SRAM1 (DAC/ADC DMA)
MPU_InitStruct.Enable = MPU_REGION_ENABLE;
MPU_InitStruct.Number = MPU_REGION_NUMBER2;
MPU_InitStruct.BaseAddress = 0x30000000;
MPU_InitStruct.Size = MPU_REGION_SIZE_128KB;
MPU_InitStruct.SubRegionDisable = 0x00;
MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;
MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE; // Sharing
MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE; // Non-cached
MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;//MPU_ACCESS_BUFFERABLE;
HAL_MPU_ConfigRegion(&MPU_InitStruct);
HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);
}
Change in file heap_4.c
/* Allocate the memory for the heap. */
#if ( configAPPLICATION_ALLOCATED_HEAP == 1 )
/* The application writer has already defined the array used for the RTOS
* heap - probably so it can be placed in a special segment or address. */
extern uint8_t ucHeap[ configTOTAL_HEAP_SIZE ];
#else
__attribute__((section("freertos_heap"), aligned(32)))
static uint8_t ucHeap[ configTOTAL_HEAP_SIZE ];
#endif /* configAPPLICATION_ALLOCATED_HEAP */
I’ve compiled a version of the app with all the unnecessary stuff removed. I can attach it or the individual files if needed.
Thanks