![](/media/cache/img/default_profile.jpg.50x50_q85.jpg)
Webserver only w/o any other functions, single thread. Running on STM32F013+W5500
Dependencies: NTPClient W5500Interface Watchdog device_configuration eeprom_flash mbed-rpc-nucleo mbed-rtos mbed
Fork of F103-Serial-to-Ethernet by
main.cpp
- Committer:
- olympux
- Date:
- 2014-09-27
- Revision:
- 11:709f90a3b599
- Parent:
- 10:4cd965d79de0
- Child:
- 12:7c152c0ca4d8
File content as of revision 11:709f90a3b599:
/* * * Alarm and Monitoring application */ #include "mbed.h" //#include "eeprom.h" #include "EthernetInterface.h" #include "NTPClient.h" #include "rtos.h" /* * Hardware defines */ #define ST_NUCLEO // hardware pin mapping #ifdef ST_NUCLEO // Ethernet SPI spi(PA_7, PA_6, PA_5); // mosi, miso, sclk EthernetInterface eth(&spi, PA_4, PC_9); // spi, cs, reset #endif // Serial Serial uart(USBTX,USBRX); // Digital inputs DigitalIn din0(PB_14); DigitalIn din1(PB_12); DigitalIn din2(PB_10); DigitalIn din3(PB_1); DigitalIn din4(PB_15); DigitalIn din5(PB_13); DigitalIn din6(PB_11); DigitalIn din7(PB_2); // Digital outputs DigitalOut dout0(PB_3); DigitalOut dout1(PB_5); DigitalOut dout2(PB_7); DigitalOut dout3(PB_9); DigitalOut dout4(PD_2); DigitalOut dout5(PB_4); DigitalOut dout6(PB_6); DigitalOut dout7(PB_8); // Analog inputs AnalogIn ain0(PC_0); AnalogIn ain1(PC_1); // Analog outputs //AnalogOut ano0(PA_8); //AnalogOut ano1(PA_15); void update_digital_outputs(void); // eeprom #define NumbOfVar ((uint8_t)0x80) // REMEMBER: update this variable in eeprom.h too #define IP_ADDRESS_POS 0 #define IP_SUBNET_POS 4 #define IP_GATEWAY_POS 8 #define TCP_SERVER_PORT_POS 12 #define UDP_SERVER_PORT_POS 13 #define FIRST_RUN_FLAG_POS 14 #define MAC_ADDRESS_POS 15 // Virtual address defined by the user: 0xFFFF value is prohibited uint16_t VirtAddVarTab[NumbOfVar] = {0x1212, 0x1313, 0x1414, 0x1515, // IP_Addr 0x2212, 0x2313, 0x2414, 0x2515, // IP_Subnet 0x3212, 0x3313, 0x3414, 0x3515, // IP_Gateway 0x4212, // TCP server port, not used 0x5212, // UDP server port, not used 0x8888, // 1st run? 0x6212, 0x6313, 0x6414 // MAC }; extern "C" uint16_t EE_Init(void); extern "C" uint16_t EE_ReadVariable(uint16_t VirtAddress, uint16_t* Data); extern "C" uint16_t EE_WriteVariable(uint16_t VirtAddress, uint16_t Data); /* * Network configuration */ #define TCP_SERVER //#define TCP_CLIENT #define UDP_SERVER //#define UDP_CLIENT #define NTP #define DEFAULT_IP_ADDRESS "192.168.0.249" #define DEFAULT_IP_SUBNET "255.255.255.0" #define DEFAULT_IP_GATEWAY "192.168.0.1" #define DEFAULT_MAC0 0x00 #define DEFAULT_MAC1 0x08 #define DEFAULT_MAC2 0xDC #define DEFAULT_MAC3 0x00 #define DEFAULT_MAC4 0x00 #define DEFAULT_MAC5 0x01 #define TCP_SERVER_WAIT_CLIENT_TIMEOUT 200 #define TCP_SERVER_RECEIVE_TIMEOUT 3000 #define UDP_SERVER_RECEIVE_TIMEOUT 200 // for static IP setting uint8_t u8mac[6], u8ip_addr[4];// keep mac and ip address in 8-bits char * IP_Addr; // pointers to ip_xxx[16] char * IP_Subnet; char * IP_Gateway; uint16_t u16mac_addr[3], u16ip_addr[4], u16ip_subnet[4], u16ip_gateway[4]; // 16-bits, directly loaded from eeprom char str_ip_addr[16], str_ip_subnet[16], str_ip_gateway[16]; // for printf, converted from 16-bits u16ip_xxx uint16_t first_run = 0; // first run flag const uint16_t tcp_server_port = 10000; // fixed const uint16_t udp_server_port = 11000; // fixed char buffer[256]; // socket buffer NTPClient ntp; // Commands #define DEVICE_ID "NNIO" #define DISCOVERY_COMMAND "NNIODS" #define TCP_SERVER_PORT_COMAMND "NNIOTP" #define UDP_SERVER_PORT_COMAMND "NNIOUP" #define RECEIVING_PROTOCOL_ENABLE_OUTPUT 'O' #define QUERY_STATUS_COMMAND 'Q' #define DIGITAL_HIGH 'H' #define DIGITAL_LOW 'L' // Positions #define RECEIVING_PROTOCOL_LENGTH 58 #define RECEIVING_PROTOCOL_ID_POS 0 #define RECEIVING_PROTOCOL_OP_POS 4 #define RECEIVING_PROTOCOL_EN_DO_POS RECEIVING_PROTOCOL_OP_POS + 0 #define RECEIVING_PROTOCOL_EN_A0O_POS RECEIVING_PROTOCOL_OP_POS + 1 #define RECEIVING_PROTOCOL_EN_A1O_POS RECEIVING_PROTOCOL_OP_POS + 2 #define RECEIVING_PROTOCOL_EN_UART_POS RECEIVING_PROTOCOL_OP_POS + 3 #define RECEIVING_PROTOCOL_COMMAND_POS RECEIVING_PROTOCOL_OP_POS + 4 #define RECEIVING_PROTOCOL_IP_POS 9 #define RECEIVING_PROTOCOL_DO_POS 13 #define RECEIVING_PROTOCOL_A0O_POS 21 #define RECEIVING_PROTOCOL_A01_POS 23 #define RECEIVING_PROTOCOL_UART_POS 25 #define SENDING_PROTOCOL_LENGTH 39 #define SENDING_PROTOCOL_ID_POS 0 #define SENDING_PROTOCOL_MAC_POS 4 #define SENDING_PROTOCOL_IP_POS 10 #define SENDING_PROTOCOL_DI_POS 14 #define SENDING_PROTOCOL_DO_POS 22 #define SENDING_PROTOCOL_AI0_POS 30 #define SENDING_PROTOCOL_AI1_POS 32 #define SENDING_PROTOCOL_AO0_POS 34 #define SENDING_PROTOCOL_AO1_POS 36 #define SENDING_PROTOCOL_CR_POS 38 /* * RTOS */ struct message_t { int len; char *msg; }; Queue<message_t, 16> uart_queue; Mutex uart_mutex; /* * Threads */ void uart_thread(void const *args) { message_t *p_message; while (true) { osEvent evt = uart_queue.get(); if (evt.status == osEventMessage) { p_message = (message_t*)evt.value.p; uart_mutex.lock(); // mutex for stdio is not neccessary //uart.printf("len=%d\n", p_message->len); uart.printf("%s\n", p_message->msg); uart_mutex.unlock(); } } } /* * Ethernet init */ int ethernet_init(void) { printf("Start initialising ethernet\n"); int ret = eth.init(u8mac, IP_Addr, IP_Subnet, IP_Gateway); // static if (!ret) { printf("Initialized, MAC: %s\n", eth.getMACAddress()); } else { printf("Error eth.init() - ret = %d\n", ret); return -1; } ret = eth.connect(); if (!ret) { printf("IP: %s, MASK: %s, GW: %s\n", eth.getIPAddress(), eth.getNetworkMask(), eth.getGateway()); } else { printf("Error eth.connect() - ret = %d\n", ret); return -1; } return 0; } /* * EEPROM functions */ void write_eeprom(char *buffer) { // Write network configuration // 4-byte IP address + 4-byte subnet + 4-byte gateway + 3-byte MAC printf("Saving configuration\r\n"); // Unlock the Flash Program Erase controller */ FLASH_Unlock(); // EEPROM Init EE_Init(); // IP address EE_WriteVariable(VirtAddVarTab[IP_ADDRESS_POS+0], *buffer++); EE_WriteVariable(VirtAddVarTab[IP_ADDRESS_POS+1], *buffer++); EE_WriteVariable(VirtAddVarTab[IP_ADDRESS_POS+2], *buffer++); EE_WriteVariable(VirtAddVarTab[IP_ADDRESS_POS+3], *buffer++); // IP subnet EE_WriteVariable(VirtAddVarTab[IP_SUBNET_POS+0], *buffer++); EE_WriteVariable(VirtAddVarTab[IP_SUBNET_POS+1], *buffer++); EE_WriteVariable(VirtAddVarTab[IP_SUBNET_POS+2], *buffer++); EE_WriteVariable(VirtAddVarTab[IP_SUBNET_POS+3], *buffer++); // IP gateway EE_WriteVariable(VirtAddVarTab[IP_GATEWAY_POS+0], *buffer++); EE_WriteVariable(VirtAddVarTab[IP_GATEWAY_POS+1], *buffer++); EE_WriteVariable(VirtAddVarTab[IP_GATEWAY_POS+2], *buffer++); EE_WriteVariable(VirtAddVarTab[IP_GATEWAY_POS+3], *buffer++); //// TCP server port, not used //EE_WriteVariable(VirtAddVarTab[TCP_SERVER_PORT_POS], *buffer++); //// UDP server port, not used //EE_WriteVariable(VirtAddVarTab[UDP_SERVER_PORT_POS], *buffer++); // erase first_run flag EE_WriteVariable(VirtAddVarTab[FIRST_RUN_FLAG_POS], 0xA5A5); // MAC address EE_WriteVariable(VirtAddVarTab[MAC_ADDRESS_POS+0], *buffer++); EE_WriteVariable(VirtAddVarTab[MAC_ADDRESS_POS+1], *buffer++); EE_WriteVariable(VirtAddVarTab[MAC_ADDRESS_POS+2], *buffer++); FLASH_Lock(); printf("Success\r\n"); } void load_eeprom(void) { mbed_mac_address((char *)u8mac); printf("Loading network configuration...\r\n"); EE_Init(); // check if 1st run EE_ReadVariable(VirtAddVarTab[FIRST_RUN_FLAG_POS], &first_run); // if not first run, load network config if (first_run == 0xA5A5) { printf("User settings\r\n"); // IP address EE_ReadVariable(VirtAddVarTab[IP_ADDRESS_POS+0], &u16ip_addr[0]); EE_ReadVariable(VirtAddVarTab[IP_ADDRESS_POS+1], &u16ip_addr[1]); EE_ReadVariable(VirtAddVarTab[IP_ADDRESS_POS+2], &u16ip_addr[2]); EE_ReadVariable(VirtAddVarTab[IP_ADDRESS_POS+3], &u16ip_addr[3]); u8ip_addr[0] = (uint8_t)(u16ip_addr[0] & 0x00FF); u8ip_addr[1] = (uint8_t)(u16ip_addr[1] & 0x00FF); u8ip_addr[2] = (uint8_t)(u16ip_addr[2] & 0x00FF); u8ip_addr[3] = (uint8_t)(u16ip_addr[3] & 0x00FF); // IP subnet EE_ReadVariable(VirtAddVarTab[IP_SUBNET_POS+0], &u16ip_subnet[0]); EE_ReadVariable(VirtAddVarTab[IP_SUBNET_POS+1], &u16ip_subnet[1]); EE_ReadVariable(VirtAddVarTab[IP_SUBNET_POS+2], &u16ip_subnet[2]); EE_ReadVariable(VirtAddVarTab[IP_SUBNET_POS+3], &u16ip_subnet[3]); // IP gateway EE_ReadVariable(VirtAddVarTab[IP_GATEWAY_POS+0], &u16ip_gateway[0]); EE_ReadVariable(VirtAddVarTab[IP_GATEWAY_POS+1], &u16ip_gateway[1]); EE_ReadVariable(VirtAddVarTab[IP_GATEWAY_POS+2], &u16ip_gateway[2]); EE_ReadVariable(VirtAddVarTab[IP_GATEWAY_POS+3], &u16ip_gateway[3]); //// TCP server port //EE_ReadVariable(VirtAddVarTab[TCP_SERVER_PORT_POS], &tcp_server_port); //// UDP server port //EE_ReadVariable(VirtAddVarTab[UDP_SERVER_PORT_POS], &udp_server_port); // First run flag, already read above // MAC address EE_ReadVariable(VirtAddVarTab[MAC_ADDRESS_POS+0], &u16mac_addr[0]); EE_ReadVariable(VirtAddVarTab[MAC_ADDRESS_POS+1], &u16mac_addr[1]); EE_ReadVariable(VirtAddVarTab[MAC_ADDRESS_POS+2], &u16mac_addr[2]); u8mac[0] = DEFAULT_MAC0; u8mac[1] = DEFAULT_MAC1; u8mac[2] = DEFAULT_MAC2; u8mac[3] = (uint8_t)(u16mac_addr[0] & 0x00FF); u8mac[4] = (uint8_t)(u16mac_addr[1] & 0x00FF); u8mac[5] = (uint8_t)(u16mac_addr[2] & 0x00FF); //FLASH_Lock(); sprintf(str_ip_addr, "%d.%d.%d.%d", (uint8_t)u16ip_addr[0], (uint8_t)u16ip_addr[1], (uint8_t)u16ip_addr[2], (uint8_t)u16ip_addr[3]); sprintf(str_ip_subnet, "%d.%d.%d.%d", (uint8_t)u16ip_subnet[0], (uint8_t)u16ip_subnet[1], (uint8_t)u16ip_subnet[2], (uint8_t)u16ip_subnet[3]); sprintf(str_ip_gateway, "%d.%d.%d.%d", (uint8_t)u16ip_gateway[0], (uint8_t)u16ip_gateway[1], (uint8_t)u16ip_gateway[2], (uint8_t)u16ip_gateway[3]); } // if 1st run, use default addresses else { printf("No user settings, load defaults\r\n"); u8mac[0] = DEFAULT_MAC0; u8mac[1] = DEFAULT_MAC1; u8mac[2] = DEFAULT_MAC2; u8mac[3] = DEFAULT_MAC3; u8mac[4] = DEFAULT_MAC4; u8mac[5] = DEFAULT_MAC5; sprintf(str_ip_addr, DEFAULT_IP_ADDRESS); sprintf(str_ip_subnet, DEFAULT_IP_SUBNET); sprintf(str_ip_gateway, DEFAULT_IP_GATEWAY); } printf("Success\r\n"); printf("IP: %s\r\n", str_ip_addr); printf("MASK: %s\r\n", str_ip_subnet); printf("GW: %s\r\n", str_ip_gateway); printf("TCP server: %d\r\n", tcp_server_port); printf("UDP server: %d\r\n", udp_server_port); } int main() { message_t message; int n, ret; /* * Configure */ uart.baud(115200); /* * UI threads */ Thread t1(uart_thread); /* * FLASH */ load_eeprom(); IP_Addr = str_ip_addr; IP_Subnet = str_ip_subnet; IP_Gateway = str_ip_gateway; /* * Ethernet */ ret = ethernet_init(); if (ret) { printf("Ethernet initialisation failed. App halted\r\n"); while (true) {}; } #ifdef TCP_SERVER TCPSocketServer tcp_server; TCPSocketConnection tcp_client; tcp_server.bind(tcp_server_port); tcp_server.listen(); printf("TCP server started...\r\n"); tcp_server.set_blocking(false, TCP_SERVER_WAIT_CLIENT_TIMEOUT); #endif #ifdef UDP_SERVER UDPSocket udp_server; Endpoint ep_udp_client; ret = udp_server.bind(udp_server_port); printf("UDP started (sock.bind = %d)\r\n", ret); udp_server.set_blocking(false, UDP_SERVER_RECEIVE_TIMEOUT); #endif // Network processor while (true) { // FOR INTERFACING #ifdef TCP_SERVER // no tcp client connected if (!tcp_client.is_connected()) { // wait for client within timeout ret = tcp_server.accept(tcp_client); // tcp client connected if (ret > -1) { printf("Connection from: %s\r\n", tcp_client.get_address()); // loop waiting and receiving data within timeout tcp_client.set_blocking(false, TCP_SERVER_RECEIVE_TIMEOUT); // Timeout after x seconds while (true) { n = tcp_client.receive(buffer, sizeof(buffer)); if (n <= 0) break; // got some data, test it printf("TCP server received: %s\r\n", buffer); //// send to uart //buffer[n] = '\0'; //message.len = n; //message.msg = buffer; //uart_queue.put(&message); //// echo to tcp client //tcp_client.send_all(buffer, n); //if (n <= 0) break; // process received data switch (n) { // length 58-bytes, Receiving protocol case RECEIVING_PROTOCOL_LENGTH: { printf("Checking device ID..."); // check device id char* id = strstr(buffer, DEVICE_ID); if (id == NULL) break; else if ((id - buffer) > 0) break; printf("Correct.\r\n"); // firstly, update outputs if required // digital outputs if (buffer[RECEIVING_PROTOCOL_EN_DO_POS] == RECEIVING_PROTOCOL_ENABLE_OUTPUT) { printf("Update digital outputs\r\n"); update_digital_outputs(); } // analog output 0 if (buffer[RECEIVING_PROTOCOL_EN_A0O_POS] == RECEIVING_PROTOCOL_ENABLE_OUTPUT) { printf("Update analog output 0\r\n"); } // analog output 1 if (buffer[RECEIVING_PROTOCOL_EN_A1O_POS] == RECEIVING_PROTOCOL_ENABLE_OUTPUT) { printf("Update analog output 1\r\n"); } // UART if (buffer[RECEIVING_PROTOCOL_EN_UART_POS] == RECEIVING_PROTOCOL_ENABLE_OUTPUT) { printf("UART data: "); char str_uart[33]; memcpy(str_uart, &buffer[RECEIVING_PROTOCOL_UART_POS], 32); str_uart[32] = '\0'; printf("%s\r\n", str_uart); } // then, check query status command and sending protocol if required if (buffer[RECEIVING_PROTOCOL_COMMAND_POS] == QUERY_STATUS_COMMAND) { printf("Sent device status through TCP\r\n"); // sending protocol memcpy(&buffer[SENDING_PROTOCOL_ID_POS], DEVICE_ID, 4); // device id memcpy(&buffer[SENDING_PROTOCOL_MAC_POS], &u8mac, 6); memcpy(&buffer[SENDING_PROTOCOL_IP_POS], &u8ip_addr, 4); //memcpy(&buffer[SENDING_PROTOCOL_DI_POS], //memcpy(&buffer[SENDING_PROTOCOL_D0_POS], //memcpy(&buffer[SENDING_PROTOCOL_AI0_POS], //memcpy(&buffer[SENDING_PROTOCOL_AI1_POS], //memcpy(&buffer[SENDING_PROTOCOL_AO0_POS], //memcpy(&buffer[SENDING_PROTOCOL_AO1_POS], buffer[SENDING_PROTOCOL_CR_POS] = 0x0D; buffer[SENDING_PROTOCOL_CR_POS+1] = '\0'; tcp_client.send_all(buffer, SENDING_PROTOCOL_LENGTH); } break; } default: break; } } // end loop if no data received within timeout tcp_client.close(); } // if client connected } // if no client connected #endif // ONLY FOR CONFIGRATION #ifdef UDP_SERVER // wait for udp packet within timeout n = udp_server.receiveFrom(ep_udp_client, buffer, sizeof(buffer)); if (n <= 0) continue; // got some data, test it printf("UDP received: %s\r\n", buffer); //// send to uart //buffer[n] = '\0'; //message.len = n; //message.msg = buffer; //uart_queue.put(&message); //// echo //printf("Received packet from: %s\r\n", client.get_address()); //udp_server.sendTo(ep_udp_client, buffer, n); // process received data switch (n) { // length = 6, a CONFIGURATION command (discovery command, TCP port, or UDP port) // Format: NNIODS, NNIOTP or NNIOUP case 6: // discovery command if (strstr(buffer, "NNIODS") != NULL) { udp_server.sendTo(ep_udp_client, str_ip_addr, strlen(str_ip_addr)); } // NNIODS // ask for TCP server port else if (strstr(buffer, "NNIOTP") != NULL) { char port[5]; sprintf(port, "%5d", tcp_server_port); udp_server.sendTo(ep_udp_client, port, strlen(port)); } // NNIOTP // ask for UDP server port else if (strstr(buffer, "NNIOUP") != NULL) { char port[5]; sprintf(port, "%5d", udp_server_port); udp_server.sendTo(ep_udp_client, port, strlen(port)); } // NNIOUP else if (strstr(buffer, "NNIOTM") != NULL) { #ifdef NTP char str_time[50]; printf("Trying to update time...\r\n"); if (ntp.setTime("0.pool.ntp.org") == 0) { printf("Set time successfully\r\n"); time_t ctTime; ctTime = time(NULL); printf("Time is set to (UTC): %s\r\n", ctime(&ctTime)); sprintf(str_time, "%s", ctime(&ctTime)); udp_server.sendTo(ep_udp_client, str_time, strlen(str_time)); } else { printf("Error\r\n"); sprintf(str_time, "ERR"); udp_server.sendTo(ep_udp_client, str_time, strlen(str_time)); } #elif printf("NTP disabled\r\n"); sprintf(str_time, "DIS"); udp_server.sendTo(ep_udp_client, str_time, strlen(str_time)); #endif } // NNIOTM break; // length = 19, SET NETWORK CONFIGURATION // Format: 4E 4E 49 4F C0 A8 00 78 FF FF FF 00 C0 A8 00 01 00 00 01 // (NNIO; IP: 192.168.0.120; Subnet: 255.255.255.0; GW: 192.168.0.1; MAC: 0 0 1) case 19:{ // check device id char* id = strstr(buffer, DEVICE_ID); if (id == NULL) break; else if ((id - buffer) > 0) break; printf("Received user configuration\r\n"); write_eeprom(&buffer[4]); // parameters from 3rd char, 15-bytes break; } default: break; } #endif } // network processor } void update_digital_outputs(void) { char dat = buffer[RECEIVING_PROTOCOL_DO_POS+0]; switch (dat) { case DIGITAL_HIGH: dout0 = 1; break; case DIGITAL_LOW: dout0 = 0; break; default: break; } dat = buffer[RECEIVING_PROTOCOL_DO_POS+1]; switch (dat) { case DIGITAL_HIGH: dout1 = 1; break; case DIGITAL_LOW: dout1 = 0; break; default: break; } dat = buffer[RECEIVING_PROTOCOL_DO_POS+2]; switch (dat) { case DIGITAL_HIGH: dout2 = 1; break; case DIGITAL_LOW: dout2 = 0; break; default: break; } dat = buffer[RECEIVING_PROTOCOL_DO_POS+3]; switch (dat) { case DIGITAL_HIGH: dout3 = 1; break; case DIGITAL_LOW: dout3 = 0; break; default: break; } dat = buffer[RECEIVING_PROTOCOL_DO_POS+4]; switch (dat) { case DIGITAL_HIGH: dout1 = 4; break; case DIGITAL_LOW: dout1 = 4; break; default: break; } dat = buffer[RECEIVING_PROTOCOL_DO_POS+5]; switch (dat) { case DIGITAL_HIGH: dout5 = 1; break; case DIGITAL_LOW: dout5 = 0; break; default: break; } dat = buffer[RECEIVING_PROTOCOL_DO_POS+6]; switch (dat) { case DIGITAL_HIGH: dout6 = 1; break; case DIGITAL_LOW: dout6 = 0; break; default: break; } dat = buffer[RECEIVING_PROTOCOL_DO_POS+7]; switch (dat) { case DIGITAL_HIGH: dout7 = 1; break; case DIGITAL_LOW: dout7 = 0; break; default: break; } }