Tool/software: Code Composer Studio
Hello All,
I am using Code Composer Studio (CCS) version 9.2 for development with TM4C1294NCPDT Launch XL with TivaWare_C_Series-2.1.4.178.
In my application, I have implemented MQTT client using LWIP stack where i used enet_weather and enet_lwip example as a reference, which is working fine.
This current Code flow for MQTT client
1. Initialize Ethernet, GPIO, Timer, Systick Timer and UART, DHCP.
2. Get MAC Address and IP.
3. Resolve DNS
4. Initialize TCP and Establish MQTT connection over TCP,
5. Setup MQTT Subscription and then periodically using timer keep publishing Data.
Now I also have RTC attached to my board for that i need to get Time stamp from the NTP server and update the RTC when device is powered up.
For getting time from NTP server i am using UPD protocol with LWIP stack, however this has to be done in MQTT client code itself which is TCP protocol based in LWIP stack.
For implementing this i made few changes in the code flow where now after step 2 i Resolve DNS for NTP Server address and,
Then i send UPD packets and register its reception callback to receive response after this again i resolve DNS for MQTT client and continue wiith further step as explained above.
After that as UDP is connection less protocol i start sending the UDP packet in order get time stamp, However i am not able to receive any response,
I have attached the code snippet which i have added for UDP to get Time Stamp, I request to please check with it and help me if i am going wrong any where,
Also please help me with if any other suggestion for getting Timestamp from NTP server.
//NTP server Details
#define NTP_SERVER_ADDRESS "66.228.59.187"
#define NTP_PORT_NUMBER 123
struct
{
volatile uint32_t ui32Flags;
............
// Global define of the TCP structure used.
struct tcp_pcb *psTCP;
struct udp_pcb *psUDP;
...........
// Global IP structure to hold a copy of the DNS resolved address.
struct ip_addr sServerIP;
struct ip_addr sNTPServerIP;
}
g_sEnet;
main()
{
.....
ROM_IntMasterEnable();
//Display the DHCP assigned IP
WaitforIP();
//Resolve the String Formated server URL/IP
ResolveDNSForNTPserver();
udp_Send_function();
.....
while(1)
{
......
}
}
void udp_Send_function(void)
{
struct pbuf udppacket;
a = sizeof(udppacket);
b = sizeof(udppacket.payload);
c = sizeof(packetBuffer);
d = sizeof(packet);
e = sizeof(struct pbuf);
f = sizeof(ntp_packet);
/* get new pcb */
g_sEnet.psUDP = udp_new();
if (g_sEnet.psUDP == NULL) {
return;
}
SysCtlDelay(2000000);
/* bind to any IP address on port 23 */
// if (udp_bind(g_sEnet.psUDP, &g_sEnet.sServerIP2, 123) != ERR_OK) {
//// LWIP_DEBUGF(UDP_DEBUG, ("udp_bind failed!\n"));
//// UARTSend(0, "udp_bind failed!\n\r", strlen("udp_bind failed!\n\r"));
// return;
// }
if (udp_connect(g_sEnet.psUDP, &g_sEnet.sServerIP2, 123) != ERR_OK) {
return;
}
// set all bytes in the buffer to 0
memset(packetBuffer, 0, NTP_PACKET_SIZE);
// Initialize values needed to form NTP request
// (see URL above for details on the packets)
packetBuffer[0] = 0b11100011; // LI, Version, Mode
packetBuffer[1] = 0; // Stratum, or type of clock
packetBuffer[2] = 6; // Polling Interval
packetBuffer[3] = 0xEC; // Peer Clock Precision
// 8 bytes of zero for Root Delay & Root Dispersion
packetBuffer[12] = 49;
packetBuffer[13] = 0x4E;
packetBuffer[14] = 49;
packetBuffer[15] = 52;
udppacket.payload = &packetBuffer;
udppacket.len = NTP_PACKET_SIZE;
if(udp_send(g_sEnet.psUDP, &udppacket) == ERR_OK)
{
/* set udp_echo_recv() as callback function
for received packets */
udp_recv(g_sEnet.psUDP, udp_echo_recv, NULL);
}
}
void udp_echo_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *addr, u16_t port)
{
UARTprintf("UDP Reception\n");
if (p != NULL) {
/* send received packet back to sender */
// udp_sendto(pcb, p, addr, port);
// memcpy(&packet, p->payload, sizeof( ntp_packet ));
/* free the pbuf */
pbuf_free(p);
}
}
void ResolveDNSForNTPserver()
{
int iCnt;
if(HWREGBITW(&g_sEnet.ui32Flags, FLAG_TIMER_DNS_EN))
{
dns_tmr();
}
// Update the DHCP IP address.
g_sEnet.sLocalIP.addr = ui32NewIPAddress;
// Stop DHCP timer since an address has been provided.
HWREGBITW(&g_sEnet.ui32Flags, FLAG_DHCP_STARTED) = 0;
//initialize server ip variable
g_sEnet.sNTPServerIP.addr = NULL;
// Resolve the host by name.
EthClientDNSResolveForNTP(NTP_SERVER_ADDRESS);
UARTprintf("\n Resolving DNS for NTP server \n");
for(iCnt=0; iCnt<60; iCnt++)
{
MAP_GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_1, GPIO_PIN_1);
SysCtlDelay(2000000);
MAP_GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_1, 0);
SysCtlDelay(2000000);
UARTprintf(".");
if(g_sEnet.sNTPServerIP.addr != NULL)
break;
}
if((iCnt >= 60) && (g_sEnet.sNTPServerIP.addr == NULL))
{
UARTprintf("Error while Resolving DNS for NTP\n\r");
}
else
{
UARTprintf("DNS Resolved for NTP server\n\r");
}
}
int32_t EthClientDNSResolve2(const char *pcName)
{
err_t iRet;
if(HWREGBITW(&g_sEnet.ui32Flags, FLAG_TIMER_DNS_EN))
{
return(ERR_INPROGRESS);
}
// Set DNS config timer to true.
HWREGBITW(&g_sEnet.ui32Flags, FLAG_TIMER_DNS_EN) = 1;
// Initialize the host name IP address found flag to false.
HWREGBITW(&g_sEnet.ui32Flags, FLAG_DNS_ADDRFOUND) = 0;
// Resolve host name.
iRet = dns_gethostbyname(pcName, &g_sEnet.sNTPServerIP, DNSServerFoundforNTP, 0);
// If ERR_OK is returned, the local DNS table resolved the host name. If
// ERR_INPROGRESS is returned, the DNS request has been queued and will be
// sent to the DNS server.
if(iRet == ERR_OK)
{
// Stop calling the DNS timer function.
HWREGBITW(&g_sEnet.ui32Flags, FLAG_TIMER_DNS_EN) = 0;
}
// Return host name not found.
return(iRet);
}
static void DNSServerFoundforNTP(const char *pcName, struct ip_addr *psIPAddr, void *vpArg)
{
// Check if a valid DNS server address was found.
if(psIPAddr != NULL)
{
// Copy the returned IP address into a global IP address.
g_sEnet.sNTPServerIP= *psIPAddr;
// Tell the main program that a DNS address was found.
HWREGBITW(&g_sEnet.ui32Flags, FLAG_DNS_ADDRFOUND) = 1;
UARTprintf("DNS Resolved for NTP\n");
}
else
{
// Disable the DNS timer.
HWREGBITW(&g_sEnet.ui32Flags, FLAG_TIMER_DNS_EN) = 0;
}
}
Thanks and regards
Utkarsh
