Why TxTimestampStatus is alway 0, for esp32's IEEE 1588
Posted: Fri Dec 02, 2022 5:18 am
Dear everyone, I would like to develop the PTP IEEE 1588.
But found some problems:
1) At first, I use netif and got the IP (just as \examples\ethernet\basic ), then broadcast a buffer just using eth (I refer to \components\esp_eth\test_apps\main\esp_eth_test.c), the program works, and I have gotten the packet from esp32 in wireshark.
2) then, I modify the "esp_eth_mac_new_esp32()".
I just let "emac_esp32_t *emac = NULL" defined outside the function, let it be a gloable var and I could access "hal.tx_desc->TimeStampLow" and "hal.tx_desc->TimeStampHigh"
I make a loop waiting for "emac->hal.tx_desc->TDES0.FirstSegment" and "TDES0.LastSegment" becomes 1, and this is also realized .
3) I found "emac->hal.tx_desc->TDES0.TxTimestampStatus" will never become 1. and the value of timestamp is always 0. And I have check that "TDES0.TransmitTimestampEnable" is 1.
so, what should I do. below is the main program.
void app_main(void)
{
// Initialize TCP/IP network interface (should be called only once in application)
ESP_ERROR_CHECK(esp_netif_init());
// Create default event loop that running in background
ESP_ERROR_CHECK(esp_event_loop_create_default());
// Create new default instance of esp-netif for Ethernet
esp_netif_config_t cfg = ESP_NETIF_DEFAULT_ETH();
esp_netif_t *eth_netif = esp_netif_new(&cfg);
// Init MAC and PHY configs to default
eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG();
eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG();
phy_config.phy_addr = CONFIG_EXAMPLE_ETH_PHY_ADDR;
phy_config.reset_gpio_num = CONFIG_EXAMPLE_ETH_PHY_RST_GPIO;
mac_config.smi_mdc_gpio_num = CONFIG_EXAMPLE_ETH_MDC_GPIO;
mac_config.smi_mdio_gpio_num = CONFIG_EXAMPLE_ETH_MDIO_GPIO;
esp_eth_mac_t *mac = esp_eth_mac_new_esp32_2(&mac_config); // using modified function
esp_eth_phy_t *phy = esp_eth_phy_new_lan87xx(&phy_config);
esp_eth_config_t config = ETH_DEFAULT_CONFIG(mac, phy);
esp_eth_handle_t eth_handle = NULL;
ESP_ERROR_CHECK(esp_eth_driver_install(&config, ð_handle));
//--------------Initialize netif---------------------------------
// attach Ethernet driver to TCP/IP stack
ESP_ERROR_CHECK(esp_netif_attach(eth_netif, esp_eth_new_netif_glue(eth_handle)));
//TDES0.TransmitTimestampEnable
ESP_LOGI(TAG, "\n\n TransmitTimestampEnable:%d",emac->hal.tx_desc->TDES0.TransmitTimestampEnable);
//------------broadcast-------------------
SemaphoreHandle_t mutex = xSemaphoreCreateBinary();
esp_event_loop_create_default();
esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, ð_event_handler, mutex);
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &got_ip_event_handler, NULL));
emac->hal.tx_desc->TDES0.TxTimestampStatus = 1;
ESP_LOGI(TAG, "\n\n TxTimestampStatus:%d",emac->hal.tx_desc->TDES0.TxTimestampStatus);
ESP_ERROR_CHECK(esp_eth_start(eth_handle));
ESP_LOGI(TAG, "\n\n TxTimestampStatus:%d",emac->hal.tx_desc->TDES0.TxTimestampStatus);
xSemaphoreTake(mutex, pdMS_TO_TICKS(3000));
// even if PHY (IP101) indicates autonegotiation done and link up, it sometimes may miss few packets after atonego reset, hence wait a bit
vTaskDelay(pdMS_TO_TICKS(100));
ESP_LOGI(TAG, "\n\n TxTimestampStatus:%d",emac->hal.tx_desc->TDES0.TxTimestampStatus);
emac_frame_t *pkt = malloc(1024);
pkt->proto = 0x2222;
memset(pkt->dest, 0xff, 6); // broadcast addr
printf("packet len:%d\n", 40 - ETH_HEADER_LEN);
for (int i = 0; i < (40 - ETH_HEADER_LEN); ++i){
pkt->data = i & 0xff;
}
esp_eth_transmit(eth_handle, pkt, 40);
vTaskDelay(pdMS_TO_TICKS(100));
free(pkt);
/*
ESP_ERROR_CHECK(esp_eth_stop(eth_handle));
ESP_ERROR_CHECK(esp_event_loop_delete_default());
ESP_ERROR_CHECK(esp_eth_driver_uninstall(eth_handle));
phy->del(phy);
mac->del(mac);
vSemaphoreDelete(mutex);
*/
printf("waiting for timestamp\n");
while(emac->hal.tx_desc->TDES0.FirstSegment == 0) {
printf("still waiting for timestamp\n");
vTaskDelay(pdMS_TO_TICKS(10));
}
//--------------try capture Timestamps-------------------
ESP_LOGI(TAG, "\n\n TxTimestampStatus:%d",emac->hal.tx_desc->TDES0.TxTimestampStatus);
//TDES0.TransmitTimestampEnable
ESP_LOGI(TAG, "\n\n TransmitTimestampEnable:%d",emac->hal.tx_desc->TDES0.TransmitTimestampEnable);
ESP_LOGI(TAG, "if tx timestamp is available TDES0.FirstSegment %d TDES0.LastSegment %d",emac->hal.tx_desc->TDES0.FirstSegment,
emac->hal.tx_desc->TDES0.LastSegment );
ESP_LOGI(TAG, "tx timestmap: TimeStampLow:%d, TimeStampHigh:%d\n",emac->hal.tx_desc->TimeStampLow,
emac->hal.tx_desc->TimeStampHigh );
/*
ESP_LOGI(TAG, "if rx timestamp is available, RDES0.LastDescriptor: %d ",emac->hal.rx_desc->RDES0.LastDescriptor );
ESP_LOGI(TAG, "rx timestmap: TimeStampLow %d TimeStampHigh %d\n",emac->hal.rx_desc->TimeStampLow,
emac->hal.rx_desc->TimeStampHigh );
*/
ESP_LOGI(TAG, "Buffer1Addr:%d, Buffer2NextDescAddr %d\n",emac->hal.tx_desc->Buffer1Addr,
emac->hal.tx_desc->Buffer2NextDescAddr);
ESP_LOGI(TAG,"capture system time %lld", esp_timer_get_time() );
//---------------
ESP_LOGI(TAG, "\n\n TxTimestampStatus:%d",emac->hal.tx_desc->TDES0.TxTimestampStatus);
while(emac->hal.tx_desc->TDES0.TxTimestampStatus == 0) {
//printf("still waiting TTTS becaome 1\n");
emac->hal.tx_desc->TDES0.TxTimestampStatus = 1;
ESP_LOGI(TAG, "1 TxTimestampStatus:%d",emac->hal.tx_desc->TDES0.TxTimestampStatus);
esp_eth_transmit(eth_handle, pkt, 40);
ESP_LOGI(TAG, "2 TxTimestampStatus:%d",emac->hal.tx_desc->TDES0.TxTimestampStatus);
//vTaskDelay(pdMS_TO_TICKS(10));
ESP_LOGI(TAG, "if tx timestamp is available TDES0.FirstSegment %d TDES0.LastSegment %d",emac->hal.tx_desc->TDES0.FirstSegment,
emac->hal.tx_desc->TDES0.LastSegment );
ESP_LOGI(TAG, "tx timestmap: TimeStampLow:%d, TimeStampHigh:%d\n",emac->hal.tx_desc->TimeStampLow,
emac->hal.tx_desc->TimeStampHigh );
}
printf("Finished!\n");
//------------broadcast end-------------------
}
But found some problems:
1) At first, I use netif and got the IP (just as \examples\ethernet\basic ), then broadcast a buffer just using eth (I refer to \components\esp_eth\test_apps\main\esp_eth_test.c), the program works, and I have gotten the packet from esp32 in wireshark.
2) then, I modify the "esp_eth_mac_new_esp32()".
I just let "emac_esp32_t *emac = NULL" defined outside the function, let it be a gloable var and I could access "hal.tx_desc->TimeStampLow" and "hal.tx_desc->TimeStampHigh"
I make a loop waiting for "emac->hal.tx_desc->TDES0.FirstSegment" and "TDES0.LastSegment" becomes 1, and this is also realized .
3) I found "emac->hal.tx_desc->TDES0.TxTimestampStatus" will never become 1. and the value of timestamp is always 0. And I have check that "TDES0.TransmitTimestampEnable" is 1.
so, what should I do. below is the main program.
void app_main(void)
{
// Initialize TCP/IP network interface (should be called only once in application)
ESP_ERROR_CHECK(esp_netif_init());
// Create default event loop that running in background
ESP_ERROR_CHECK(esp_event_loop_create_default());
// Create new default instance of esp-netif for Ethernet
esp_netif_config_t cfg = ESP_NETIF_DEFAULT_ETH();
esp_netif_t *eth_netif = esp_netif_new(&cfg);
// Init MAC and PHY configs to default
eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG();
eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG();
phy_config.phy_addr = CONFIG_EXAMPLE_ETH_PHY_ADDR;
phy_config.reset_gpio_num = CONFIG_EXAMPLE_ETH_PHY_RST_GPIO;
mac_config.smi_mdc_gpio_num = CONFIG_EXAMPLE_ETH_MDC_GPIO;
mac_config.smi_mdio_gpio_num = CONFIG_EXAMPLE_ETH_MDIO_GPIO;
esp_eth_mac_t *mac = esp_eth_mac_new_esp32_2(&mac_config); // using modified function
esp_eth_phy_t *phy = esp_eth_phy_new_lan87xx(&phy_config);
esp_eth_config_t config = ETH_DEFAULT_CONFIG(mac, phy);
esp_eth_handle_t eth_handle = NULL;
ESP_ERROR_CHECK(esp_eth_driver_install(&config, ð_handle));
//--------------Initialize netif---------------------------------
// attach Ethernet driver to TCP/IP stack
ESP_ERROR_CHECK(esp_netif_attach(eth_netif, esp_eth_new_netif_glue(eth_handle)));
//TDES0.TransmitTimestampEnable
ESP_LOGI(TAG, "\n\n TransmitTimestampEnable:%d",emac->hal.tx_desc->TDES0.TransmitTimestampEnable);
//------------broadcast-------------------
SemaphoreHandle_t mutex = xSemaphoreCreateBinary();
esp_event_loop_create_default();
esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, ð_event_handler, mutex);
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &got_ip_event_handler, NULL));
emac->hal.tx_desc->TDES0.TxTimestampStatus = 1;
ESP_LOGI(TAG, "\n\n TxTimestampStatus:%d",emac->hal.tx_desc->TDES0.TxTimestampStatus);
ESP_ERROR_CHECK(esp_eth_start(eth_handle));
ESP_LOGI(TAG, "\n\n TxTimestampStatus:%d",emac->hal.tx_desc->TDES0.TxTimestampStatus);
xSemaphoreTake(mutex, pdMS_TO_TICKS(3000));
// even if PHY (IP101) indicates autonegotiation done and link up, it sometimes may miss few packets after atonego reset, hence wait a bit
vTaskDelay(pdMS_TO_TICKS(100));
ESP_LOGI(TAG, "\n\n TxTimestampStatus:%d",emac->hal.tx_desc->TDES0.TxTimestampStatus);
emac_frame_t *pkt = malloc(1024);
pkt->proto = 0x2222;
memset(pkt->dest, 0xff, 6); // broadcast addr
printf("packet len:%d\n", 40 - ETH_HEADER_LEN);
for (int i = 0; i < (40 - ETH_HEADER_LEN); ++i){
pkt->data = i & 0xff;
}
esp_eth_transmit(eth_handle, pkt, 40);
vTaskDelay(pdMS_TO_TICKS(100));
free(pkt);
/*
ESP_ERROR_CHECK(esp_eth_stop(eth_handle));
ESP_ERROR_CHECK(esp_event_loop_delete_default());
ESP_ERROR_CHECK(esp_eth_driver_uninstall(eth_handle));
phy->del(phy);
mac->del(mac);
vSemaphoreDelete(mutex);
*/
printf("waiting for timestamp\n");
while(emac->hal.tx_desc->TDES0.FirstSegment == 0) {
printf("still waiting for timestamp\n");
vTaskDelay(pdMS_TO_TICKS(10));
}
//--------------try capture Timestamps-------------------
ESP_LOGI(TAG, "\n\n TxTimestampStatus:%d",emac->hal.tx_desc->TDES0.TxTimestampStatus);
//TDES0.TransmitTimestampEnable
ESP_LOGI(TAG, "\n\n TransmitTimestampEnable:%d",emac->hal.tx_desc->TDES0.TransmitTimestampEnable);
ESP_LOGI(TAG, "if tx timestamp is available TDES0.FirstSegment %d TDES0.LastSegment %d",emac->hal.tx_desc->TDES0.FirstSegment,
emac->hal.tx_desc->TDES0.LastSegment );
ESP_LOGI(TAG, "tx timestmap: TimeStampLow:%d, TimeStampHigh:%d\n",emac->hal.tx_desc->TimeStampLow,
emac->hal.tx_desc->TimeStampHigh );
/*
ESP_LOGI(TAG, "if rx timestamp is available, RDES0.LastDescriptor: %d ",emac->hal.rx_desc->RDES0.LastDescriptor );
ESP_LOGI(TAG, "rx timestmap: TimeStampLow %d TimeStampHigh %d\n",emac->hal.rx_desc->TimeStampLow,
emac->hal.rx_desc->TimeStampHigh );
*/
ESP_LOGI(TAG, "Buffer1Addr:%d, Buffer2NextDescAddr %d\n",emac->hal.tx_desc->Buffer1Addr,
emac->hal.tx_desc->Buffer2NextDescAddr);
ESP_LOGI(TAG,"capture system time %lld", esp_timer_get_time() );
//---------------
ESP_LOGI(TAG, "\n\n TxTimestampStatus:%d",emac->hal.tx_desc->TDES0.TxTimestampStatus);
while(emac->hal.tx_desc->TDES0.TxTimestampStatus == 0) {
//printf("still waiting TTTS becaome 1\n");
emac->hal.tx_desc->TDES0.TxTimestampStatus = 1;
ESP_LOGI(TAG, "1 TxTimestampStatus:%d",emac->hal.tx_desc->TDES0.TxTimestampStatus);
esp_eth_transmit(eth_handle, pkt, 40);
ESP_LOGI(TAG, "2 TxTimestampStatus:%d",emac->hal.tx_desc->TDES0.TxTimestampStatus);
//vTaskDelay(pdMS_TO_TICKS(10));
ESP_LOGI(TAG, "if tx timestamp is available TDES0.FirstSegment %d TDES0.LastSegment %d",emac->hal.tx_desc->TDES0.FirstSegment,
emac->hal.tx_desc->TDES0.LastSegment );
ESP_LOGI(TAG, "tx timestmap: TimeStampLow:%d, TimeStampHigh:%d\n",emac->hal.tx_desc->TimeStampLow,
emac->hal.tx_desc->TimeStampHigh );
}
printf("Finished!\n");
//------------broadcast end-------------------
}