2017-10-08 06:11 AM
Hi all.
Does anyone have a working example for Ethernet?
I tried to build one wih CubeMX (HAL 1.1.0) with and without FreeRTOS.
I did it many times for F746, F767 (A and Z) and F769 (A) but Ethernet with STM32H743ZI (Ver. Y) will not work.
- IDE is OpenSTM32 (GNU C)
- RAM is AXI SRAM in Domain D1 or AHB SRAM1 in Domain D2
- no DTCM RAM is used (in linker script: i.e. RAM_D1 >AT FLASH, _estack is adapted)
- Instruction Cache enabled and Data Cache is disabled
- no MPU
- ethernetif.c line 421 is commented out: // SCB_CleanInvalidateDCache();
- ethernetif.c line 443 is commented out: // SCB_CleanInvalidateDCache();
Another options:
- using 0x30040000 and MPU for DMARxDscrTab[ETH_RX_DESC_CNT] and DMATxDscrTab[ETH_TX_DESC_CNT]
- DHCP or static IP
- Data cache enabled and using original SCB_CleanIvalidDCache();
The result:
stm32h7xx_hal_eth.c : HAL_ETH_Transmit(...) throws a timeout in line 708 and returns HAL_ERROR
which is not recognized by low_level_output() in ethernetif.c
Using a different timeout value (>0) in the HAL_ETH_Transmit( &heth, &TxConfig, myTimeOutVal) throws a timeout as well.
When I enable MPUETHADDR16_COPY(ðhdr->src, src); in ethernet.c it will end in Infinite_Loop. (Edited: wrong MPU settings)
Using AHB SRAM2 in Domain D2, the software cannot be debugged. I hope not to forget something: payload is in domain D2, LAN8742 is activated in CubeMX (Platform settings), ...
In conclusion: The DMA transfer does not work.
I spent so many hours to find a solution and I'm thankful for any advice.
Note: this post was migrated and contained many threaded conversations, some content may be missing.Solved! Go to Solution.
2017-10-23 06:13 AM
Using HAL only works.
The next CubeMX release should fix this. There are many differences in the produced code.
A good starting point to use HAL only and to get mature.
- Joerg -
2017-10-09 06:30 AM
Hello Joerg,
When the HAL_ETH_Transmit(...) throws a timeout, it doesn't mean that the DMA transfer failed, it means that the Transmit function returned without waiting for the Tx status (Transmission is ongoing)
Please ensure that your DMA descriptors are configured by MPU as Device (not cacheable).
For more information, please refer to the HTTP server application in the STM32Cube H7 FW package:
..\Projects\STM32H743ZI-Nucleo\Applications\LwIP\LwIP_HTTP_Server_Netconn_RTOS\
Best regards,
Oussema
2017-10-09 11:39 AM
Hello Oussema.
I connected a scope to the signals RMII_TXD0 and RM_TXD1. There is no traffic anytime!
This is a note in the original hal driver:
@Note: This interface is implemented to operate in zero-copy mode only:
- Rx buffers are allocated statically and passed directly to the LwIP stack they will return back to DMA after been processed by the stack. - Tx Buffers will be allocated from LwIP stack memory heap, then passed to ETH HAL driver.Why are Tx Buffers allocated from heap? If your data is in DTCMRAM there is no interconnect to the DMA. Anyway, but I tried it also to put TxBuffer in 0x3400XXXX and somewhere else except DTCM, not cacheable.
Using SW4STM32, I prepared the linker script to have the ETH descriptors like in LwIP (0x34000000, 0x34000060) with this in MPU_Config():
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_SHAREABLE; MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE; MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE;HAL_MPU_ConfigRegion(&MPU_InitStruct);
HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);I visited a friend with the board to use KEIL and we adopted a sample MDK project from H743-EVAL to NUCLEO-H743, because the __attribute__ sections are already prepared. Same result: no traffic.
In the reference manual RM0433 on page 2679 cont'd is an explanation of the DMA flow. This means in my case the Own bit is set but not resetted by the controller.
Thank you, Joerg
2017-10-09 12:28 PM
Hello Joerg,
To ensure zero-copy, the ETH driver needs to send buffers allocated by the LwIP stack and not copy them in any other shadow buffers.
If you are using
DTCMRAM, it is obvious that Tx buffers will be allocated in this memory, so you have to relocate the LWIP heap to D1 or D2 SRAM by defining LWIP_RAM_HEAP_POINTER in the lwipopts.h file.
Could you please check the Fatal Bus Error bit of the DMACSR register, after trying to send data, if it's SET, so it's clear that the Tx buffers are in DTCMRAM.
also please try to run the application with RAM starting from 0x24000000 (don't use theDTCMRAM)
Hope this will help you,
Best regards,
Oussema.
2017-10-09 12:59 PM
Hello Oussema.
ETH_DMACSR_FBE is not set anytime. It means I do not have DMA memory trouble.
I tried your advice to reallocate the LwIP with LWIP_RAM_HEAP_Pointer, no success.
The descriptor tables and buffers are located here:
.RxDecripSection
0x0000000030040000 0x60 load address 0x000000000800da08 *(.RxDecripSection) .RxDecripSection 0x0000000030040000 0x60 Src/ethernetif.o 0x0000000030040000 DMARxDscrTab *(.RxDecripSection*).TxDecripSection
0x0000000030040060 0x60 load address 0x000000000800da68 *(.TxDecripSection) .TxDecripSection 0x0000000030040060 0x60 Src/ethernetif.o 0x0000000030040060 DMATxDscrTab *(.TxDecripSection*).ETH_Fill 0x00000000300400c0 0x140 load address 0x000000000800dac8
0x0000000000000140 . = 0x140 *fill* 0x00000000300400c0 0x140.RxArraySection
0x0000000030040200 0x17e0 load address 0x000000000800dac8 0x0000000030040200 . = ALIGN (0x20) *(.RxArraySection) .RxArraySection 0x0000000030040200 0x17e0 Src/ethernetif.o 0x0000000030040200 Rx_Buff *(.RxArraySection*).TxArraySection
0x00000000300419e0 0x0 load address 0x000000000800f2a8 0x00000000300419e0 . = ALIGN (0x20) *(.TxArraySection) *(.TxArraySection*)I do not use SCB_EnableDCache() to avoid trouble.
If you have a little working example that would be awesome.
Thank you, Joerg
2017-10-10 04:53 AM
Hello Oussema.
Today I built with CubeMX two tiny projects (SW4STM32) for you to analyze.
I attached the files to my original question.
App &sharp1 is developed for NUCLEO-F767ZI and App &sharp2 is created for NUCLEO-H743ZI.
Both have just ETH Init only, no RTOS, no LwIP. The purpose is to transfer data (dummy values) via Ethernet_DMA
to the LAN8742 PHY. I connected an oscilloscope to PG13 and PB13 (RMII_TXD0 and RMII_TXD1)
to visualize the traffic to the PHY.
There is traffic on the F767 board but there is no data sent on the H743 board.
Thank you, Joerg
2017-10-10 08:19 AM
Hello Joerg,
I will test your project and I'll return to as soon as possible.
BR,
Oussema
2017-10-11 12:07 PM
Hello Joerg,
I reviewed your code, and I found that you are not enabling the ETH MAC and DMA transmission and reception.
So could you please add the call to HAL_ETH_Start(&heth); after the ETH initialization.
Also I see that the ETH GPIO speed configuration is set GPIO_SPEED_FREQ_LOW so could you please replace it by GPIO_SPEED_FREQ_HIGH, because in RMII mode the IO communication frequency is 50 MHz
When I did the test I can see that the OWN bit is set to 0 after frame each frame transmission
BR,
Oussema.
2017-10-11 02:45 PM
Hello Oussema,
First, thank you for your time. You are right, I forgot to call HAL_ETH_Start(&heth);
The setting
GPIO_SPEED_FREQ_LOW
comes from CubeMX generation and I corrected this by hand.If found 2 other mistakes:
CubeMX connects RMII_TXD0 to PB12 and this is totally wrong. It must be PG13 like with the NUCLEO-F767 board.
Close to the PG13 pin at the Morpho connector is the resistor SB182 and he is physically connected to the PG13 at the die, like in the current schematics V1.1.
CubeMX initializes PB12 and PG13 is forgotten. Same with RMII_TXEN, must be PG
I must be like this:
/**ETH GPIO Configuration
PC1 ------> ETH_MDC PA1 ------> ETH_REF_CLK PA2 ------> ETH_MDIO PA7 ------> ETH_CRS_DV PC4 ------> ETH_RXD0 PC5 ------> ETH_RXD1 PB11 ------> ETH_TX_EN : wrong, must be PG11 PB12 ------> ETH_TXD0 : wrong, must be PG13 PB13 ------> ETH_TXD1 */ GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_4|GPIO_PIN_5; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF11_ETH; HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF11_ETH; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);GPIO_InitStruct.Pin = GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF11_ETH; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);// --- NEW! --- TXEN and TXD0
GPIO_InitStruct.Pin = GPIO_PIN_11|GPIO_PIN_13; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF11_ETH; HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);With this modification there is traffic on TXD0 to the LAN8742A PHY and the Own bit will be resetted after a time.
But there is still the timeout error everytime in the HAL driver. The The timeout check should be implemented in a different way.
My test application 'check the DMA transfer' works, but a real application not!
I have two apps prepared, with RTOS and without. It was a step forward but not the final solution.
:(
Joerg2017-10-14 12:22 PM
I prepared an application (simple) with RTOS and static IP: 192.168.99.85/24, destination 192.168.99.99/24
ARP request is sent:
'Who has 192.168.99.99? Tell 192.168.99.85'
The oscilloscope shows the answer on PC4/PC5 (RMII_RXD0 / RMII_RXD1):
'192.168.99.99 is at ...'
But then another broadcast ARP packet is sent:
'Who has 192.168.42.0? Tell 192.168.99.85' [ETHERNET FRAME CHECK SEQUENCE INCORRECT]
This confuses me, the netmask is set to 255.255.255.0.
The request will loop forever, because ARP cannot be resolved, UDP and TCP are not useable.
LWIP_DEBUG shows:
etharp_request: sending ARP request.
etharp_raw: sending raw ARP packet.ethernet_output: sending packet 0x30000008etharp_timer...
Joerg