2023-06-18 05:21 AM - edited 2023-06-18 05:57 AM
I have a project with STM32H743ZI, lwIP, noOS. I've read the document with the suggested settings for MPU, linker file, lwIP head placement and applied the changes to CubeMX generated code.
Additionally, I have set the MEM_ALIGNMENT to 32 bytes and added a cache cleaning in the low_level_output function:
static err_t custom_low_level_output(struct netif *netif, struct pbuf *p)
{
uint32_t i = 0U;
struct pbuf *q = NULL;
err_t errval = ERR_OK;
ETH_BufferTypeDef Txbuffer[ETH_TX_DESC_CNT] = {0};
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;
const size_t cacheLineSize = 32;
uintptr_t beginAddrRounded = ((uintptr_t) q->payload) & ~((uintptr_t) (cacheLineSize - 1));
uintptr_t endAddr = ((uintptr_t) q->payload) + q->len;
uintptr_t endAddrRounded = ((endAddr % cacheLineSize) == 0) ? endAddr : endAddr + (cacheLineSize - (endAddr % cacheLineSize ));
size_t range = endAddrRounded - beginAddrRounded;
SCB_CleanDCache_by_Addr((void*) beginAddrRounded, range);
if(i>0)
{
Txbuffer[i-1].next = &Txbuffer[i];
}
if(q->next == NULL)
{
Txbuffer[i].next = NULL;
}
i++;
}
TxConfig.Length = p->tot_len;
TxConfig.TxBuffer = Txbuffer;
TxConfig.pData = p;
HAL_ETH_Transmit(&heth, &TxConfig, ETH_DMA_TRANSMIT_TIMEOUT);
return errval;
}
This works fine. But now I have two of the same hardware boxes and the start at the same time. Then it happens in about 1 of 20 times that one or both controllers do not send the dhcp discover message.
I was able to catch this state by attaching the debugger and followed the execution. There is a loop (custom code) that restarts the netif and runs dhcp_start() again when there is no IP address received within about 60 s.
The sequence is ok, it runs up to sending the ethernet frame with HAL_ETH_Transmit(), but Wireshark does not show a packet on the wire. I have checked the DMACSR, its content is 0x404. This means the Bit TBU is set and indicating
Bit 2 TBU: Transmit Buffer Unavailable
This bit indicates that the application owns the next descriptor in the Transmit list, and the
DMA cannot acquire it. Transmission is suspended. The TPS0 field of the
DMA_Debug_Status0 register explains the Transmit Process state transitions.
To resume processing the Transmit descriptors, the application should do the following:
1. Change the ownership of the descriptor by setting Bit 31 of TDES3.
2. Issue a Transmit Poll Demand command.
For ring mode, the application should advance the Transmit Descriptor Tail Pointer register of
a channel.
I don't quite understand this and also why this could happen. What can I do?
this is the TxDescriptor list:
2023-06-23 07:00 AM - edited 2023-06-26 06:11 AM
I think my problem is related to this link status detection problem:
https://community.st.com/t5/embedded-software-mcus/stm32h7-phy-driver-for-lan8742-2s-delay/td-p/112767
In the error case, the link is wrongly reported as 10M half duplex and so the ETH is initialized bad.
It seems that autonegotiation takes more time when several controllers are started at the same time. The same problem appeared with two different switches.
update:
arghhh, the return code from LAN8742_Init(&LAN8742); in low_level_init() is not checked. In case of a cold start, I get sometimes an error code LAN8742_STATUS_RESET_TIMEOUT and this case is not handled. No wait time for the link check and wrong link speed is used.
I have created an issue, at least the rc of LAN8742_init should be printed in a debug build.
https://github.com/STMicroelectronics/STM32CubeH7/issues/261
2023-06-26 08:37 AM
because it is not a lwIP dhcp problem, I have started a new topic for this problem:
https://community.st.com/t5/stm32cubemx-mcu/h743-and-lan8742-init/td-p/570179