Webserver+3d print
Diff: web_server_demo/src/main.c
- Revision:
- 0:8918a71cdbe9
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web_server_demo/src/main.c Sat Feb 04 18:15:49 2017 +0000 @@ -0,0 +1,549 @@ +/** + * @file main.c + * @brief Main routine + * + * @section License + * + * Copyright (C) 2010-2017 Oryx Embedded SARL. All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * @author Oryx Embedded SARL (www.oryx-embedded.com) + * @version 1.7.6 + **/ + +//Dependencies +#include <stdlib.h> +#include "stm32f7xx.h" +#include "stm32f7xx_hal.h" +#include "stm32f7xx_nucleo_144.h" +#include "os_port.h" +#include "core/net.h" +#include "drivers/stm32f7xx_eth.h" +#include "drivers/lan8742.h" +#include "dhcp/dhcp_client.h" +#include "ipv6/slaac.h" +#include "http/http_server.h" +#include "http/mime.h" +#include "path.h" +#include "date_time.h" +#include "resource_manager.h" +#include "debug.h" + +//Application configuration +#define APP_MAC_ADDR "00-AB-CD-EF-07-46" + +#define APP_USE_DHCP ENABLED +#define APP_IPV4_HOST_ADDR "192.168.0.20" +#define APP_IPV4_SUBNET_MASK "255.255.255.0" +#define APP_IPV4_DEFAULT_GATEWAY "192.168.0.254" +#define APP_IPV4_PRIMARY_DNS "8.8.8.8" +#define APP_IPV4_SECONDARY_DNS "8.8.4.4" + +#define APP_USE_SLAAC ENABLED +#define APP_IPV6_LINK_LOCAL_ADDR "fe80::746" +#define APP_IPV6_PREFIX "2001:db8::" +#define APP_IPV6_PREFIX_LENGTH 64 +#define APP_IPV6_GLOBAL_ADDR "2001:db8::746" +#define APP_IPV6_ROUTER "fe80::1" +#define APP_IPV6_PRIMARY_DNS "2001:4860:4860::8888" +#define APP_IPV6_SECONDARY_DNS "2001:4860:4860::8844" + +#define APP_HTTP_MAX_CONNECTIONS 8 + +//Global variables +DhcpClientSettings dhcpClientSettings; +DhcpClientContext dhcpClientContext; +SlaacSettings slaacSettings; +SlaacContext slaacContext; +HttpServerSettings httpServerSettings; +HttpServerContext httpServerContext; +HttpConnection httpConnections[APP_HTTP_MAX_CONNECTIONS]; + +//Forward declaration of functions +error_t httpServerCgiCallback(HttpConnection *connection, + const char_t *param); + +error_t httpServerUriNotFoundCallback(HttpConnection *connection, + const char_t *uri); + + +/** + * @brief System clock configuration + **/ + +void SystemClock_Config(void) +{ + RCC_OscInitTypeDef RCC_OscInitStruct; + RCC_ClkInitTypeDef RCC_ClkInitStruct; + + //Enable Power Control clock + __HAL_RCC_PWR_CLK_ENABLE(); + + //Enable HSE Oscillator and activate PLL with HSE as source + RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; + RCC_OscInitStruct.HSEState = RCC_HSE_BYPASS; + RCC_OscInitStruct.HSIState = RCC_HSI_OFF; + RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; + RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; + RCC_OscInitStruct.PLL.PLLM = 8; + RCC_OscInitStruct.PLL.PLLN = 432; + RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; + RCC_OscInitStruct.PLL.PLLQ = 9; + HAL_RCC_OscConfig(&RCC_OscInitStruct); + + //Enable overdrive mode + HAL_PWREx_EnableOverDrive(); + + //Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2 + //clocks dividers + RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2; + RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; + RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; + RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4; + RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2; + HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_7); +} + + +/** + * @brief MPU configuration + **/ + +void MPU_Config(void) +{ + MPU_Region_InitTypeDef MPU_InitStruct; + + //Disable MPU + HAL_MPU_Disable(); + + //SRAM + MPU_InitStruct.Enable = MPU_REGION_ENABLE; + MPU_InitStruct.Number = MPU_REGION_NUMBER0; + MPU_InitStruct.BaseAddress = 0x20000000; + MPU_InitStruct.Size = MPU_REGION_SIZE_512KB; + MPU_InitStruct.SubRegionDisable = 0; + 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_CACHEABLE; + MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE; + HAL_MPU_ConfigRegion(&MPU_InitStruct); + + //SRAM2 + MPU_InitStruct.Enable = MPU_REGION_ENABLE; + MPU_InitStruct.Number = MPU_REGION_NUMBER1; + MPU_InitStruct.BaseAddress = 0x2004C000; + MPU_InitStruct.Size = MPU_REGION_SIZE_16KB; + MPU_InitStruct.SubRegionDisable = 0; + 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_NOT_BUFFERABLE; + HAL_MPU_ConfigRegion(&MPU_InitStruct); + + //Enable MPU + HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT); +} + + +/** + * @brief LED blinking task + **/ + +void blinkTask(void *param) +{ + //Endless loop + while(1) + { + BSP_LED_On(LED1); + osDelayTask(100); + BSP_LED_Off(LED1); + osDelayTask(900); + } +} + + +/** + * @brief Main entry point + * @return Unused value + **/ + +int_t main(void) +{ + error_t error; + NetInterface *interface; + OsTask *task; + MacAddr macAddr; +#if (APP_USE_DHCP == DISABLED) + Ipv4Addr ipv4Addr; +#endif +#if (APP_USE_SLAAC == DISABLED) + Ipv6Addr ipv6Addr; +#endif + + //MPU configuration + MPU_Config(); + //HAL library initialization + HAL_Init(); + //Configure the system clock + SystemClock_Config(); + + //Enable I-cache and D-cache + SCB_EnableICache(); + SCB_EnableDCache(); + + //Initialize kernel + osInitKernel(); + //Configure debug UART + debugInit(115200); + + //Start-up message + TRACE_INFO("\r\n"); + TRACE_INFO("**********************************\r\n"); + TRACE_INFO("*** CycloneTCP Web Server Demo ***\r\n"); + TRACE_INFO("**********************************\r\n"); + TRACE_INFO("Copyright: 2010-2017 Oryx Embedded SARL\r\n"); + TRACE_INFO("Compiled: %s %s\r\n", __DATE__, __TIME__); + TRACE_INFO("Target: STM32F746\r\n"); + TRACE_INFO("\r\n"); + + //LED configuration + BSP_LED_Init(LED1); + BSP_LED_Init(LED2); + BSP_LED_Init(LED3); + + //Clear LEDs + BSP_LED_Off(LED1); + BSP_LED_Off(LED2); + BSP_LED_Off(LED3); + + //Initialize user button + BSP_PB_Init(BUTTON_KEY, BUTTON_MODE_GPIO); + + //TCP/IP stack initialization + error = netInit(); + //Any error to report? + if(error) + { + //Debug message + TRACE_ERROR("Failed to initialize TCP/IP stack!\r\n"); + } + + //Configure the first Ethernet interface + interface = &netInterface[0]; + + //Set interface name + netSetInterfaceName(interface, "eth0"); + //Set host name + netSetHostname(interface, "WebServerDemo"); + //Select the relevant network adapter + netSetDriver(interface, &stm32f7xxEthDriver); + netSetPhyDriver(interface, &lan8742PhyDriver); + //Set host MAC address + macStringToAddr(APP_MAC_ADDR, &macAddr); + netSetMacAddr(interface, &macAddr); + + //Initialize network interface + error = netConfigInterface(interface); + //Any error to report? + if(error) + { + //Debug message + TRACE_ERROR("Failed to configure interface %s!\r\n", interface->name); + } + +#if (IPV4_SUPPORT == ENABLED) +#if (APP_USE_DHCP == ENABLED) + //Get default settings + dhcpClientGetDefaultSettings(&dhcpClientSettings); + //Set the network interface to be configured by DHCP + dhcpClientSettings.interface = interface; + //Disable rapid commit option + dhcpClientSettings.rapidCommit = FALSE; + + //DHCP client initialization + error = dhcpClientInit(&dhcpClientContext, &dhcpClientSettings); + //Failed to initialize DHCP client? + if(error) + { + //Debug message + TRACE_ERROR("Failed to initialize DHCP client!\r\n"); + } + + //Start DHCP client + error = dhcpClientStart(&dhcpClientContext); + //Failed to start DHCP client? + if(error) + { + //Debug message + TRACE_ERROR("Failed to start DHCP client!\r\n"); + } +#else + //Set IPv4 host address + ipv4StringToAddr(APP_IPV4_HOST_ADDR, &ipv4Addr); + ipv4SetHostAddr(interface, ipv4Addr); + + //Set subnet mask + ipv4StringToAddr(APP_IPV4_SUBNET_MASK, &ipv4Addr); + ipv4SetSubnetMask(interface, ipv4Addr); + + //Set default gateway + ipv4StringToAddr(APP_IPV4_DEFAULT_GATEWAY, &ipv4Addr); + ipv4SetDefaultGateway(interface, ipv4Addr); + + //Set primary and secondary DNS servers + ipv4StringToAddr(APP_IPV4_PRIMARY_DNS, &ipv4Addr); + ipv4SetDnsServer(interface, 0, ipv4Addr); + ipv4StringToAddr(APP_IPV4_SECONDARY_DNS, &ipv4Addr); + ipv4SetDnsServer(interface, 1, ipv4Addr); +#endif +#endif + +#if (IPV6_SUPPORT == ENABLED) +#if (APP_USE_SLAAC == ENABLED) + //Get default settings + slaacGetDefaultSettings(&slaacSettings); + //Set the network interface to be configured + slaacSettings.interface = interface; + + //SLAAC initialization + error = slaacInit(&slaacContext, &slaacSettings); + //Failed to initialize SLAAC? + if(error) + { + //Debug message + TRACE_ERROR("Failed to initialize SLAAC!\r\n"); + } + + //Start IPv6 address autoconfiguration process + error = slaacStart(&slaacContext); + //Failed to start SLAAC process? + if(error) + { + //Debug message + TRACE_ERROR("Failed to start SLAAC!\r\n"); + } +#else + //Set link-local address + ipv6StringToAddr(APP_IPV6_LINK_LOCAL_ADDR, &ipv6Addr); + ipv6SetLinkLocalAddr(interface, &ipv6Addr); + + //Set IPv6 prefix + ipv6StringToAddr(APP_IPV6_PREFIX, &ipv6Addr); + ipv6SetPrefix(interface, 0, &ipv6Addr, APP_IPV6_PREFIX_LENGTH); + + //Set global address + ipv6StringToAddr(APP_IPV6_GLOBAL_ADDR, &ipv6Addr); + ipv6SetGlobalAddr(interface, 0, &ipv6Addr); + + //Set default router + ipv6StringToAddr(APP_IPV6_ROUTER, &ipv6Addr); + ipv6SetDefaultRouter(interface, 0, &ipv6Addr); + + //Set primary and secondary DNS servers + ipv6StringToAddr(APP_IPV6_PRIMARY_DNS, &ipv6Addr); + ipv6SetDnsServer(interface, 0, &ipv6Addr); + ipv6StringToAddr(APP_IPV6_SECONDARY_DNS, &ipv6Addr); + ipv6SetDnsServer(interface, 1, &ipv6Addr); +#endif +#endif + + //Get default settings + httpServerGetDefaultSettings(&httpServerSettings); + //Bind HTTP server to the desired interface + httpServerSettings.interface = &netInterface[0]; + //Listen to port 80 + httpServerSettings.port = HTTP_PORT; + //Client connections + httpServerSettings.maxConnections = APP_HTTP_MAX_CONNECTIONS; + httpServerSettings.connections = httpConnections; + //Specify the server's root directory + strcpy(httpServerSettings.rootDirectory, "/www/"); + //Set default home page + strcpy(httpServerSettings.defaultDocument, "index.shtm"); + //Callback functions + httpServerSettings.cgiCallback = httpServerCgiCallback; + httpServerSettings.uriNotFoundCallback = httpServerUriNotFoundCallback; + + //HTTP server initialization + error = httpServerInit(&httpServerContext, &httpServerSettings); + //Failed to initialize HTTP server? + if(error) + { + //Debug message + TRACE_ERROR("Failed to initialize HTTP server!\r\n"); + } + + //Start HTTP server + error = httpServerStart(&httpServerContext); + //Failed to start HTTP server? + if(error) + { + //Debug message + TRACE_ERROR("Failed to start HTTP server!\r\n"); + } + + //Create a task to blink the LED + task = osCreateTask("Blink", blinkTask, NULL, 500, OS_TASK_PRIORITY_NORMAL); + //Failed to create the task? + if(task == OS_INVALID_HANDLE) + { + //Debug message + TRACE_ERROR("Failed to create task!\r\n"); + } + + //Start the execution of tasks + osStartKernel(); + + //This function should never return + return 0; +} + + +/** + * @brief CGI callback function + * @param[in] connection Handle referencing a client connection + * @param[in] param NULL-terminated string that contains the CGI parameter + * @return Error code + **/ + +error_t httpServerCgiCallback(HttpConnection *connection, + const char_t *param) +{ + static uint_t pageCounter = 0; + uint_t length; + MacAddr macAddr; +#if (IPV4_SUPPORT == ENABLED) + Ipv4Addr ipv4Addr; +#endif +#if (IPV6_SUPPORT == ENABLED) + uint_t n; + Ipv6Addr ipv6Addr; +#endif + + //Underlying network interface + NetInterface *interface = connection->socket->interface; + + //Check parameter name + if(!strcasecmp(param, "PAGE_COUNTER")) + { + pageCounter++; + sprintf(connection->buffer, "%u time%s", pageCounter, (pageCounter >= 2) ? "s" : ""); + } + else if(!strcasecmp(param, "BOARD_NAME")) + { + strcpy(connection->buffer, "Nucleo-F746ZG"); + } + else if(!strcasecmp(param, "SYSTEM_TIME")) + { + systime_t time = osGetSystemTime(); + formatSystemTime(time, connection->buffer); + } + else if(!strcasecmp(param, "MAC_ADDR")) + { + netGetMacAddr(interface, &macAddr); + macAddrToString(&macAddr, connection->buffer); + } + else if(!strcasecmp(param, "IPV4_ADDR")) + { + ipv4GetHostAddr(interface, &ipv4Addr); + ipv4AddrToString(ipv4Addr, connection->buffer); + } + else if(!strcasecmp(param, "SUBNET_MASK")) + { + ipv4GetSubnetMask(interface, &ipv4Addr); + ipv4AddrToString(ipv4Addr, connection->buffer); + } + else if(!strcasecmp(param, "DEFAULT_GATEWAY")) + { + ipv4GetDefaultGateway(interface, &ipv4Addr); + ipv4AddrToString(ipv4Addr, connection->buffer); + } + else if(!strcasecmp(param, "IPV4_PRIMARY_DNS")) + { + ipv4GetDnsServer(interface, 0, &ipv4Addr); + ipv4AddrToString(ipv4Addr, connection->buffer); + } + else if(!strcasecmp(param, "IPV4_SECONDARY_DNS")) + { + ipv4GetDnsServer(interface, 1, &ipv4Addr); + ipv4AddrToString(ipv4Addr, connection->buffer); + } +#if (IPV6_SUPPORT == ENABLED) + else if(!strcasecmp(param, "LINK_LOCAL_ADDR")) + { + ipv6GetLinkLocalAddr(interface, &ipv6Addr); + ipv6AddrToString(&ipv6Addr, connection->buffer); + } + else if(!strcasecmp(param, "GLOBAL_ADDR")) + { + ipv6GetGlobalAddr(interface, 0, &ipv6Addr); + ipv6AddrToString(&ipv6Addr, connection->buffer); + } + else if(!strcasecmp(param, "IPV6_PREFIX")) + { + ipv6GetPrefix(interface, 0, &ipv6Addr, &n); + ipv6AddrToString(&ipv6Addr, connection->buffer); + length = strlen(connection->buffer); + sprintf(connection->buffer + length, "/%u", n); + } + else if(!strcasecmp(param, "ROUTER")) + { + ipv6GetDefaultRouter(interface, 0, &ipv6Addr); + ipv6AddrToString(&ipv6Addr, connection->buffer); + } + else if(!strcasecmp(param, "IPV6_PRIMARY_DNS")) + { + ipv6GetDnsServer(interface, 0, &ipv6Addr); + ipv6AddrToString(&ipv6Addr, connection->buffer); + } + else if(!strcasecmp(param, "IPV6_SECONDARY_DNS")) + { + ipv6GetDnsServer(interface, 1, &ipv6Addr); + ipv6AddrToString(&ipv6Addr, connection->buffer); + } +#endif + else + { + return ERROR_INVALID_TAG; + } + + //Get the length of the resulting string + length = strlen(connection->buffer); + + //Send the contents of the specified environment variable + return httpWriteStream(connection, connection->buffer, length); +} + + +/** + * @brief URI not found callback + * @param[in] connection Handle referencing a client connection + * @param[in] uri NULL-terminated string containing the path to the requested resource + * @return Error code + **/ + +error_t httpServerUriNotFoundCallback(HttpConnection *connection, + const char_t *uri) +{ + //Not implemented + return ERROR_NOT_FOUND; +} + +