2019-07-04 03:44 AM
I reading all topics about ethernet problems in Cube H7 1.1-1.3.
And run example LwIP_HTTP_Server_Netconn_RTOS - it working good.
But - I can't to repeat this example.
I using NUCLEO-H743ZI board.
Creating project from STMCUbe, enabling LWIP with static IP, modifing STM32H743ZITX_FLASH.ld script from example by adding this :
.lwip_sec (NOLOAD) : {
. = ABSOLUTE(0x30040000);
*(.RxDecripSection)
. = ABSOLUTE(0x30040060);
*(.TxDecripSection)
. = ABSOLUTE(0x30040200);
*(.RxArraySection)
} >RAM_D2 AT> FLASH
Modify MPU Settings as in example:
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 = 0x30040000;
MPU_InitStruct.Size = MPU_REGION_SIZE_256B;
MPU_InitStruct.SubRegionDisable = 0x0;
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_NOT_SHAREABLE;
MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;
MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE;
HAL_MPU_ConfigRegion(&MPU_InitStruct);
/** Initializes and configures the Region and the memory to be protected
*/
MPU_InitStruct.Enable = MPU_REGION_ENABLE;
MPU_InitStruct.Number = MPU_REGION_NUMBER1;
MPU_InitStruct.BaseAddress = 0x30044000;
MPU_InitStruct.Size = MPU_REGION_SIZE_16KB;
MPU_InitStruct.SubRegionDisable = 0x0;
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_NOT_SHAREABLE;
MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE;
MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;
HAL_MPU_ConfigRegion(&MPU_InitStruct);
/* Enables the MPU */
HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);
}
Modify main:
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
ethernetif_input(&gnetif);
sys_check_timeouts();
}
/* USER CODE END 3 */
Building and RUN - and it doesn't work..
I try using MPU init code from this topic
https://community.st.com/s/article/FAQ-Ethernet-not-working-on-STM32H7x3?t=1562229776524
void MPU_Config(void)
{
MPU_Region_InitTypeDef MPU_InitStruct;
/* 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_NUMBER2;
MPU_InitStruct.BaseAddress = 0x30040000;
MPU_InitStruct.Size = MPU_REGION_SIZE_256B;
MPU_InitStruct.SubRegionDisable = 0x0;
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_NOT_SHAREABLE;
MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;
MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE;
HAL_MPU_ConfigRegion(&MPU_InitStruct);
/**Initializes and configures the Region and the memory to be protected
*/
MPU_InitStruct.Enable = MPU_REGION_ENABLE;
MPU_InitStruct.Number = MPU_REGION_NUMBER1;
MPU_InitStruct.BaseAddress = 0x30044000;
MPU_InitStruct.Size = MPU_REGION_SIZE_16KB;
MPU_InitStruct.SubRegionDisable = 0x0;
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_NOT_SHAREABLE;
MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE;
MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;
HAL_MPU_ConfigRegion(&MPU_InitStruct);
MPU_InitStruct.Enable = MPU_REGION_ENABLE;
MPU_InitStruct.Number = MPU_REGION_NUMBER0;
MPU_InitStruct.BaseAddress = 0x30040000;
MPU_InitStruct.Size = MPU_REGION_SIZE_16KB;
MPU_InitStruct.SubRegionDisable = 0x0;
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_NOT_SHAREABLE;
MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;
MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;
HAL_MPU_ConfigRegion(&MPU_InitStruct);
/* Enables the MPU */
HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);
It doesn't work too.
So, I try to create the working example with FreeRTOS.
Creating project from Cube, modify STM32H743ZITX_FLASH.ld, modify MPU settings, build project - and it doesn't work :(
I using DHCP and static IP, and can't to ping this board in all variant, working only LwIP_HTTP_Server_Netconn_RTOS sample poject.
But this sample project without ioc file, I can't create my own project based on this sample code.
May be exists working ioc file with LWIP ethernet without FreeRTOS? And ld script for it?
2019-07-05 06:40 AM
I found good working example on HAL H7 V1.3.0:
https://github.com/MX-Master/STM32H7_Nucleo-H743ZI_Ethernet_LwIP
But can't to move it to new version of stm cube.
After ioc file updating and project regeneration this project can't to work properly.
Checking all critical places of code by readme file get full coincidence.
And can't to open this ioc file without updating - because STM Cube hangs and does not respond.
STM Cube work properly only with updating this ioc file to new version.
2019-07-05 03:20 PM
Working!
For the first - needed all necessary settings from this project - readme file:
https://github.com/MX-Master/STM32H7_Nucleo-H743ZI_Ethernet_LwIP
For the second HAL H7 v1.4.0 file ethernetif.c needing this simple modification:
static err_t low_level_output(struct netif *netif, struct pbuf *p)
{
uint32_t i=0, framelen = 0;
struct pbuf *q;
err_t errval = ERR_OK;
ETH_BufferTypeDef Txbuffer[ETH_TX_DESC_CNT];
memset(Txbuffer, 0 , ETH_TX_DESC_CNT*sizeof(ETH_BufferTypeDef));
for(q = p; q != NULL; q = q->next)
{
if(i >= ETH_TX_DESC_CNT)
return ERR_IF;
Txbuffer[i].buffer = q->payload;
Txbuffer[i].len = q->len;
framelen += q->len;
if(i>0)
{
Txbuffer[i-1].next = &Txbuffer[i];
}
if(q->next == NULL)
{
Txbuffer[i].next = NULL;
}
i++;
}
TxConfig.Length = framelen;
TxConfig.TxBuffer = Txbuffer;
SCB_CleanInvalidateDCache();
HAL_ETH_Transmit(&heth, &TxConfig, ETH_DMA_TRANSMIT_TIMEOUT);
return errval;
}
static struct pbuf * low_level_input(struct netif *netif)
{
struct pbuf *p = NULL;
ETH_BufferTypeDef RxBuff;
uint32_t framelength = 0;
struct pbuf_custom* custom_pbuf;
if (HAL_ETH_IsRxDataAvailable(&heth))
{
SCB_CleanInvalidateDCache();
HAL_ETH_GetRxDataBuffer(&heth, &RxBuff);
HAL_ETH_GetRxDataLength(&heth, &framelength);
/* Build Rx descriptor to be ready for next data reception */
HAL_ETH_BuildRxDescriptors(&heth);
#if defined(DUAL_CORE) && defined(CORE_CM7)
/* Invalidate data cache for ETH Rx Buffers */
SCB_InvalidateDCache_by_Addr((uint32_t *)RxBuff.buffer, framelength);
#endif
custom_pbuf = (struct pbuf_custom*)LWIP_MEMPOOL_ALLOC(RX_POOL);
custom_pbuf->custom_free_function = pbuf_free_custom;
p = pbuf_alloced_custom(PBUF_RAW, framelength, PBUF_REF, custom_pbuf, RxBuff.buffer, ETH_RX_BUFFER_SIZE);
return p;
}
else
{
return NULL;
}
}
Only inserting this code row:
HAL_ETH_Transmit(&heth, &TxConfig, ETH_DMA_TRANSMIT_TIMEOUT);
in two places.
This is all.
All will be good working with Nucleo-H743ZI.
And I tested this code with Apollo H743 development board, with LAN8720A PHY, good working too, start code for this board:
/* USER CODE BEGIN 2 */
SetLED0(1);
PCF8574_Init(pPCF8574, &hi2c2, false, 0, 0, 0);
PCF8574_SetDir(pPCF8574, 0b11000101);
SetETHReset(0);
HAL_Delay(100);
SetETHReset(1);
HAL_Delay(100);
MX_LWIP_Init();
SetLED1(1);
HAL_Delay(1000);
/* USER CODE END 2 */
This board using PCF8574 for resetting PHY. That's why MX_LWIP_Init() must be selected in project manager - advanced settings - not generate function call.
And call manually after PHY reset finished by PCF8574.
2019-07-05 03:24 PM
One moment - in project https://github.com/MX-Master/STM32H7_Nucleo-H743ZI_Ethernet_LwIP in MPU Settings Region 1 was set as
MPU_InitStruct.AccessPermission = MPU_REGION_NO_ACCESS;
This is not right for normal working (but with simple ICMP query all OK).
Normal setting - FULL_ACCESS.
MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
2019-07-05 03:28 PM
And PHY Pin Speed can be set as Very HIGH (not only High):
.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
2019-07-06 08:29 AM
SCB_CleanInvalidateDCache();
Cleaning all D-cache, damages data that's changed by DMA - descriptors and Rx buffers.
Invalidating all D-cache damages data that's changed by CPU - any cached (but not written to RAM) data.
This is a very popular flaw in general and ST's code is also full of it...
2019-07-07 03:37 PM
HAL 1.4.0 removed "SCB_CleanInvalidateDCache()" from "low_level_output" and "low_level_input" but for my board, lwip became slow and instable. Adding the function again, worked fine...
2020-03-16 07:01 PM
Actually, the code snippets described "good working" above would not work reliably, and would increasingly fail with increasing packet rate and possibly size.
These are problems with low_level_input alone just by inspection:
Applies FW_H7 v1.4.0, v1.5.0 and v1.6.0.
My documented inspection of ST's H7 ETH code plus coded bug-fixes and efficiency improvements are at https://community.st.com/s/question/0D50X0000C6eNNSSQ2/bug-fixes-stm32h7-ethernet. My code is for a custom board and you'd need some expertise to port it. If you use my code please post your success or problems there to assist other developers.
2020-09-05 04:31 AM
Hi alexey_public.
I can't read "For the first - needed all necessary settings from this project - readme file:"
Can you re-upload?
I create ETH Project with STM32CubeMxIde follow steps above, but it doesn't work.