Ray Liu
/
NuMaker-mbed-Serial-to-Ethernet
Modify the file main.cpp for M487
Revision 0:c89ccc69a48b, committed 2017-09-29
- Comitter:
- shliu1
- Date:
- Fri Sep 29 05:45:43 2017 +0000
- Commit message:
- main.cpp adds the setting of TARGET_NUMAKER_PFM_M487 for M487
Changed in this revision
diff -r 000000000000 -r c89ccc69a48b BufferedSerial.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/BufferedSerial.lib Fri Sep 29 05:45:43 2017 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/sam_grove/code/BufferedSerial/#a0d37088b405
diff -r 000000000000 -r c89ccc69a48b NuMaker-mbed-SD-driver.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/NuMaker-mbed-SD-driver.lib Fri Sep 29 05:45:43 2017 +0000 @@ -0,0 +1,1 @@ +https://github.com/OpenNuvoton/NuMaker-mbed-SD-driver/#253f370c308331fc9a82b5387ed108750ac70ac8
diff -r 000000000000 -r c89ccc69a48b NuMaker-mbed-SD-driver/NuSDBlockDevice.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/NuMaker-mbed-SD-driver/NuSDBlockDevice.cpp Fri Sep 29 05:45:43 2017 +0000 @@ -0,0 +1,443 @@ +/* mbed Microcontroller Library + * Copyright (c) 2015-2016 Nuvoton + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* Nuvoton mbed enabled targets which support SD card of SD bus mode */ +#if defined(TARGET_NUMAKER_PFM_NUC472) || defined(TARGET_NUMAKER_PFM_M487) + +#include "NuSDBlockDevice.h" +#include "PeripheralPins.h" +#include "mbed_debug.h" +#include "nu_modutil.h" + +#if defined(TARGET_NUMAKER_PFM_NUC472) +#define NU_SDH_DAT0 PF_5 +#define NU_SDH_DAT1 PF_4 +#define NU_SDH_DAT2 PF_3 +#define NU_SDH_DAT3 PF_2 +#define NU_SDH_CMD PF_7 +#define NU_SDH_CLK PF_8 +#define NU_SDH_CDn PF_6 + +#elif defined(TARGET_NUMAKER_PFM_M487) +#define NU_SDH_DAT0 PE_2 +#define NU_SDH_DAT1 PE_3 +#define NU_SDH_DAT2 PE_4 +#define NU_SDH_DAT3 PE_5 +#define NU_SDH_CMD PE_7 +#define NU_SDH_CLK PE_6 +#define NU_SDH_CDn PD_13 + +#endif + +#if defined(TARGET_NUMAKER_PFM_NUC472) +extern DISK_DATA_T SD_DiskInfo0; +extern DISK_DATA_T SD_DiskInfo1; +extern SD_INFO_T SD0,SD1; +extern int sd0_ok,sd1_ok; + +#elif defined(TARGET_NUMAKER_PFM_M487) +extern int SDH_ok; +extern SDH_INFO_T SD0, SD1; + +#endif + + +static const struct nu_modinit_s sdh_modinit_tab[] = { +#if defined(TARGET_NUMAKER_PFM_NUC472) + {SD_0_0, SDH_MODULE, CLK_CLKSEL0_SDHSEL_PLL, CLK_CLKDIV0_SDH(2), SDH_RST, SD_IRQn, NULL}, + {SD_0_1, SDH_MODULE, CLK_CLKSEL0_SDHSEL_PLL, CLK_CLKDIV0_SDH(2), SDH_RST, SD_IRQn, NULL}, +#elif defined(TARGET_NUMAKER_PFM_M487) + {SD_0, SDH0_MODULE, CLK_CLKSEL0_SDH0SEL_HCLK, CLK_CLKDIV0_SDH0(2), SDH0_RST, SDH0_IRQn, NULL}, + {SD_1, SDH1_MODULE, CLK_CLKSEL0_SDH1SEL_HCLK, CLK_CLKDIV3_SDH1(2), SDH1_RST, SDH1_IRQn, NULL}, +#endif + + {NC, 0, 0, 0, 0, (IRQn_Type) 0, NULL} +}; + + + +#define SD_BLOCK_DEVICE_ERROR_WOULD_BLOCK -5001 /*!< operation would block */ +#define SD_BLOCK_DEVICE_ERROR_UNSUPPORTED -5002 /*!< unsupported operation */ +#define SD_BLOCK_DEVICE_ERROR_PARAMETER -5003 /*!< invalid parameter */ +#define SD_BLOCK_DEVICE_ERROR_NO_INIT -5004 /*!< uninitialized */ +#define SD_BLOCK_DEVICE_ERROR_NO_DEVICE -5005 /*!< device is missing or not connected */ +#define SD_BLOCK_DEVICE_ERROR_WRITE_PROTECTED -5006 /*!< write protected */ + + +NuSDBlockDevice::NuSDBlockDevice() : + _sectors(0), + _is_initialized(false), + _dbg(false), + _sdh_modinit(NULL), + _sdh((SDName) NC), + _sdh_base(NULL), +#if defined(TARGET_NUMAKER_PFM_NUC472) + _sdh_port((uint32_t) -1), +#endif + _sdh_irq_thunk(this, &NuSDBlockDevice::_sdh_irq), + _sd_dat0(NU_SDH_DAT0), + _sd_dat1(NU_SDH_DAT1), + _sd_dat2(NU_SDH_DAT2), + _sd_dat3(NU_SDH_DAT3), + _sd_cmd(NU_SDH_CMD), + _sd_clk(NU_SDH_CLK), + _sd_cdn(NU_SDH_CDn) +{ +} + +NuSDBlockDevice::NuSDBlockDevice(PinName sd_dat0, PinName sd_dat1, PinName sd_dat2, PinName sd_dat3, + PinName sd_cmd, PinName sd_clk, PinName sd_cdn) : + _sectors(0), + _is_initialized(false), + _dbg(false), + _sdh_modinit(NULL), + _sdh((SDName) NC), + _sdh_base(NULL), +#if defined(TARGET_NUMAKER_PFM_NUC472) + _sdh_port((uint32_t) -1), +#endif + _sdh_irq_thunk(this, &NuSDBlockDevice::_sdh_irq) +{ + _sd_dat0 = sd_dat0; + _sd_dat1 = sd_dat1; + _sd_dat2 = sd_dat2; + _sd_dat3 = sd_dat3; + _sd_cmd = sd_cmd; + _sd_clk = sd_clk; + _sd_cdn = sd_cdn; +} + +NuSDBlockDevice::~NuSDBlockDevice() +{ + if (_is_initialized) { + deinit(); + } +} + +int NuSDBlockDevice::init() +{ + _lock.lock(); + int err = BD_ERROR_OK; + + do { + err = _init_sdh(); + if (err != BD_ERROR_OK) { + break; + } + +#if defined(TARGET_NUMAKER_PFM_NUC472) + SD_Open(_sdh_port | CardDetect_From_GPIO); + SD_Probe(_sdh_port); + + switch (_sdh_port) { + case SD_PORT0: + _is_initialized = sd0_ok && (SD0.CardType != SD_TYPE_UNKNOWN); + break; + + case SD_PORT1: + _is_initialized = sd1_ok && (SD1.CardType != SD_TYPE_UNKNOWN); + break; + } + +#elif defined(TARGET_NUMAKER_PFM_M487) + MBED_ASSERT(_sdh_modinit != NULL); + + NVIC_SetVector(_sdh_modinit->irq_n, _sdh_irq_thunk.entry()); + NVIC_EnableIRQ(_sdh_modinit->irq_n); + + SDH_Open(_sdh_base, CardDetect_From_GPIO); + SDH_Probe(_sdh_base); + + switch (NU_MODINDEX(_sdh)) { + case 0: + _is_initialized = SDH_ok && (SD0.CardType != SDH_TYPE_UNKNOWN); + break; + + case 1: + _is_initialized = SDH_ok && (SD1.CardType != SDH_TYPE_UNKNOWN); + break; + } +#endif + + if (!_is_initialized) { + debug_if(_dbg, "Fail to initialize card\n"); + err = BD_ERROR_DEVICE_ERROR; + } + debug_if(_dbg, "init card = %d\n", _is_initialized); + _sectors = _sd_sectors(); + + } while (0); + + _lock.unlock(); + + return err; +} + +int NuSDBlockDevice::deinit() +{ + _lock.lock(); + + if (_sdh_modinit) { + CLK_DisableModuleClock(_sdh_modinit->clkidx); + } + +#if defined(TARGET_NUMAKER_PFM_NUC472) + // TODO +#elif defined(TARGET_NUMAKER_PFM_M487) + // TODO +#endif + + _is_initialized = false; + + _lock.unlock(); + + return BD_ERROR_OK; +} + +int NuSDBlockDevice::program(const void *b, bd_addr_t addr, bd_size_t size) +{ + if (! is_valid_program(addr, size)) { + return SD_BLOCK_DEVICE_ERROR_PARAMETER; + } + + _lock.lock(); + int err = BD_ERROR_OK; + + do { + if (! _is_initialized) { + err = SD_BLOCK_DEVICE_ERROR_NO_INIT; + } + +#if defined(TARGET_NUMAKER_PFM_NUC472) + if (SD_Write(_sdh_port, (uint8_t*)b, addr / 512, size / 512) != 0) { +#elif defined(TARGET_NUMAKER_PFM_M487) + if (SDH_Write(_sdh_base, (uint8_t*)b, addr / 512, size / 512) != 0) { +#endif + err = BD_ERROR_DEVICE_ERROR; + } + + } while (0); + + _lock.unlock(); + + return err; +} + +int NuSDBlockDevice::read(void *b, bd_addr_t addr, bd_size_t size) +{ + if (! is_valid_read(addr, size)) { + return SD_BLOCK_DEVICE_ERROR_PARAMETER; + } + + _lock.lock(); + int err = BD_ERROR_OK; + + do { + if (! _is_initialized) { + err = SD_BLOCK_DEVICE_ERROR_NO_INIT; + } + +#if defined(TARGET_NUMAKER_PFM_NUC472) + if (SD_Read(_sdh_port, (uint8_t*)b, addr / 512, size / 512) != 0) { +#elif defined(TARGET_NUMAKER_PFM_M487) + if (SDH_Read(_sdh_base, (uint8_t*)b, addr / 512, size / 512) != 0) { +#endif + err = BD_ERROR_DEVICE_ERROR; + } + + } while (0); + + _lock.unlock(); + + return err; +} + +int NuSDBlockDevice::erase(bd_addr_t addr, bd_size_t size) +{ + return BD_ERROR_OK; +} + +bd_size_t NuSDBlockDevice::get_read_size() const +{ + return 512; +} + +bd_size_t NuSDBlockDevice::get_program_size() const +{ + return 512; +} + +bd_size_t NuSDBlockDevice::get_erase_size() const +{ + return 512; +} + +bd_size_t NuSDBlockDevice::size() const +{ + return 512 * _sectors; +} + +void NuSDBlockDevice::debug(bool dbg) +{ + _dbg = dbg; +} + +int NuSDBlockDevice::_init_sdh() +{ + debug_if(_dbg, "SD MPF Setting & Enable SD IP Clock\n"); + + // Check if all pins belong to the same SD module + // Merge SD DAT0/1/2/3 + uint32_t sd_dat0_mod = pinmap_peripheral(_sd_dat0, PinMap_SD_DAT0); + uint32_t sd_dat1_mod = pinmap_peripheral(_sd_dat1, PinMap_SD_DAT1); + uint32_t sd_dat2_mod = pinmap_peripheral(_sd_dat2, PinMap_SD_DAT2); + uint32_t sd_dat3_mod = pinmap_peripheral(_sd_dat3, PinMap_SD_DAT3); + uint32_t sd_dat01_mod = (SDName) pinmap_merge(sd_dat0_mod, sd_dat1_mod); + uint32_t sd_dat23_mod = (SDName) pinmap_merge(sd_dat2_mod, sd_dat3_mod); + uint32_t sd_dat0123_mod = (SDName) pinmap_merge(sd_dat01_mod, sd_dat23_mod); + // Merge SD CMD/CLK/CDn + uint32_t sd_cmd_mod = pinmap_peripheral(_sd_cmd, PinMap_SD_CMD); + uint32_t sd_clk_mod = pinmap_peripheral(_sd_clk, PinMap_SD_CLK); + uint32_t sd_cdn_mod = pinmap_peripheral(_sd_cdn, PinMap_SD_CD); + uint32_t sd_cmdclk_mod = (SDName) pinmap_merge(sd_cmd_mod, sd_clk_mod); + uint32_t sd_cmdclkcdn_mod = (SDName) pinmap_merge(sd_cmdclk_mod, sd_cdn_mod); + // Merge SD DAT0/1/2/3 and SD CMD/CLK/CDn + uint32_t sd_mod = (SDName) pinmap_merge(sd_dat0123_mod, sd_cmdclkcdn_mod); + + if (sd_mod == (uint32_t) NC) { + debug("SD pinmap error\n"); + return BD_ERROR_DEVICE_ERROR; + } + + _sdh_modinit = get_modinit(sd_mod, sdh_modinit_tab); + MBED_ASSERT(_sdh_modinit != NULL); + MBED_ASSERT(_sdh_modinit->modname == sd_mod); + + + // Configure SD multi-function pins + pinmap_pinout(_sd_dat0, PinMap_SD_DAT0); + pinmap_pinout(_sd_dat1, PinMap_SD_DAT1); + pinmap_pinout(_sd_dat2, PinMap_SD_DAT2); + pinmap_pinout(_sd_dat3, PinMap_SD_DAT3); + pinmap_pinout(_sd_cmd, PinMap_SD_CMD); + pinmap_pinout(_sd_clk, PinMap_SD_CLK); + pinmap_pinout(_sd_cdn, PinMap_SD_CD); + + // Configure SD IP clock + SYS_UnlockReg(); + + // Determine SDH port dependent on passed-in pins + _sdh = (SDName) sd_mod; + _sdh_base = (SDH_T *) NU_MODBASE(_sdh); +#if defined(TARGET_NUMAKER_PFM_NUC472) + switch (NU_MODSUBINDEX(_sdh)) { + case 0: + _sdh_port = SD_PORT0; + break; + + case 1: + _sdh_port = SD_PORT1; + break; + } +#endif + + SYS_ResetModule(_sdh_modinit->rsetidx); + CLK_SetModuleClock(_sdh_modinit->clkidx, _sdh_modinit->clksrc, _sdh_modinit->clkdiv); + CLK_EnableModuleClock(_sdh_modinit->clkidx); + + SYS_LockReg(); + + return BD_ERROR_OK; +} + +uint32_t NuSDBlockDevice::_sd_sectors() +{ + _lock.lock(); + +#if defined(TARGET_NUMAKER_PFM_NUC472) + switch (_sdh_port) { + case SD_PORT0: + _sectors = SD_DiskInfo0.totalSectorN; + break; + case SD_PORT1: + _sectors = SD_DiskInfo1.totalSectorN; + break; + } + +#elif defined(TARGET_NUMAKER_PFM_M487) + switch (NU_MODINDEX(_sdh)) { + case 0: + _sectors = SD0.totalSectorN; + break; + case 1: + _sectors = SD1.totalSectorN; + break; + } + +#endif + + _lock.unlock(); + + return _sectors; +} + +void NuSDBlockDevice::_sdh_irq() +{ +#if defined(TARGET_NUMAKER_PFM_NUC472) + // TODO: Support IRQ + +#elif defined(TARGET_NUMAKER_PFM_M487) + // FMI data abort interrupt + if (_sdh_base->GINTSTS & SDH_GINTSTS_DTAIF_Msk) { + _sdh_base->GINTSTS = SDH_GINTSTS_DTAIF_Msk; + /* ResetAllEngine() */ + _sdh_base->GCTL |= SDH_GCTL_GCTLRST_Msk; + } + + //----- SD interrupt status + if (_sdh_base->INTSTS & SDH_INTSTS_BLKDIF_Msk) { + // block down + extern uint8_t volatile _SDH_SDDataReady; + _SDH_SDDataReady = TRUE; + _sdh_base->INTSTS = SDH_INTSTS_BLKDIF_Msk; + } + + // NOTE: On M487, there are two SDH instances which each support port 0 and don't support port 1. + // Port 0 (support): INTEN.CDIEN0, INTEN.CDSRC0, INTSTS.CDIF0, INTSTS.CDSTS0 + // Port 1 (no support): INTEN.CDIEN1, INTEN.CDSRC1, INTSTS.CDIF1, INTSTS.CDSTS1 + if (_sdh_base->INTSTS & SDH_INTSTS_CDIF_Msk) { // port 0 card detect + _sdh_base->INTSTS = SDH_INTSTS_CDIF_Msk; + // TBD: Support PnP + } + + // CRC error interrupt + if (_sdh_base->INTSTS & SDH_INTSTS_CRCIF_Msk) { + _sdh_base->INTSTS = SDH_INTSTS_CRCIF_Msk; // clear interrupt flag + } + + if (_sdh_base->INTSTS & SDH_INTSTS_DITOIF_Msk) { + _sdh_base->INTSTS = SDH_INTSTS_DITOIF_Msk; + } + + // Response in timeout interrupt + if (_sdh_base->INTSTS & SDH_INTSTS_RTOIF_Msk) { + _sdh_base->INTSTS |= SDH_INTSTS_RTOIF_Msk; + } +#endif +} + + +#endif //#if defined(TARGET_NUMAKER_PFM_NUC472) || defined(TARGET_NUMAKER_PFM_M487)
diff -r 000000000000 -r c89ccc69a48b NuMaker-mbed-SD-driver/NuSDBlockDevice.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/NuMaker-mbed-SD-driver/NuSDBlockDevice.h Fri Sep 29 05:45:43 2017 +0000 @@ -0,0 +1,135 @@ +/* mbed Microcontroller Library + * Copyright (c) 2015-2016 Nuvoton + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef __NU_SD_BLOCK_DEVICE_H__ +#define __NU_SD_BLOCK_DEVICE_H__ + +#include "BlockDevice.h" +#include "mbed.h" + +struct nu_modinit_s; + +class NuSDBlockDevice : public BlockDevice { +public: + /** Lifetime of an SD card + */ + NuSDBlockDevice(); + NuSDBlockDevice(PinName sd_dat0, PinName sd_dat1, PinName sd_dat2, PinName sd_dat3, + PinName sd_cmd, PinName sd_clk, PinName sd_cdn); + virtual ~NuSDBlockDevice(); + + /** Initialize a block device + * + * @return 0 on success or a negative error code on failure + */ + virtual int init(); + + /** Deinitialize a block device + * + * @return 0 on success or a negative error code on failure + */ + virtual int deinit(); + + /** Read blocks from a block device + * + * @param buffer Buffer to write blocks to + * @param addr Address of block to begin reading from + * @param size Size to read in bytes, must be a multiple of read block size + * @return 0 on success, negative error code on failure + */ + virtual int read(void *buffer, bd_addr_t addr, bd_size_t size); + + /** Program blocks to a block device + * + * The blocks must have been erased prior to being programmed + * + * @param buffer Buffer of data to write to blocks + * @param addr Address of block to begin writing to + * @param size Size to write in bytes, must be a multiple of program block size + * @return 0 on success, negative error code on failure + */ + virtual int program(const void *buffer, bd_addr_t addr, bd_size_t size); + + /** Erase blocks on a block device + * + * The state of an erased block is undefined until it has been programmed + * + * @param addr Address of block to begin erasing + * @param size Size to erase in bytes, must be a multiple of erase block size + * @return 0 on success, negative error code on failure + */ + virtual int erase(bd_addr_t addr, bd_size_t size); + + /** Get the size of a readable block + * + * @return Size of a readable block in bytes + */ + virtual bd_size_t get_read_size() const; + + /** Get the size of a programable block + * + * @return Size of a programable block in bytes + * @note Must be a multiple of the read size + */ + virtual bd_size_t get_program_size() const; + + /** Get the size of a eraseable block + * + * @return Size of a eraseable block in bytes + * @note Must be a multiple of the program size + */ + virtual bd_size_t get_erase_size() const; + + /** Get the total size of the underlying device + * + * @return Size of the underlying device in bytes + */ + virtual bd_size_t size() const; + + /** Enable or disable debugging + * + * @param State of debugging + */ + virtual void debug(bool dbg); + +private: + int _init_sdh(); + uint32_t _sd_sectors(); + void _sdh_irq(); + + uint32_t _sectors; + bool _is_initialized; + bool _dbg; + Mutex _lock; + + const struct nu_modinit_s * _sdh_modinit; + SDName _sdh; + SDH_T * _sdh_base; +#if defined(TARGET_NUMAKER_PFM_NUC472) + uint32_t _sdh_port; +#endif + + CThunk<NuSDBlockDevice> _sdh_irq_thunk; + + PinName _sd_dat0; + PinName _sd_dat1; + PinName _sd_dat2; + PinName _sd_dat3; + PinName _sd_cmd; + PinName _sd_clk; + PinName _sd_cdn; +}; + +#endif /* __NU_SD_BLOCK_DEVICE_H__ */
diff -r 000000000000 -r c89ccc69a48b NuMaker-mbed-SD-driver/README.md --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/NuMaker-mbed-SD-driver/README.md Fri Sep 29 05:45:43 2017 +0000 @@ -0,0 +1,17 @@ +# Block device driver for SD card supported by Nuvoton platforms + +This driver implements [BlockDevice class](https://github.com/ARMmbed/mbed-os/blob/master/features/filesystem/bd/BlockDevice.h) +introduced with mbed OS 5.4 for SD card running in SD bus mode on Nuvoton platforms which support it. + +ARM mbed team also releases an official [SD driver](https://github.com/armmbed/sd-driver), but it supports SPI bus mode +rather than SD bus mode. + +## Use with FAT file system +The [SD file system example](https://developer.mbed.org/teams/Nuvoton/code/NuMaker-mbed-SD-FileSystem-example/) is cloned from +the [FAT file system example](https://github.com/armmbed/mbed-os-example-fat-filesystem) released by ARM mbed team and +is modified to use this SD block device to back the FAT file system. + +## Support Nuvoton platforms +- [NuMaker-PFM-NUC472](https://developer.mbed.org/platforms/Nuvoton-NUC472/) +- NuMaker-PFM-M487 +
diff -r 000000000000 -r c89ccc69a48b main.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Fri Sep 29 05:45:43 2017 +0000 @@ -0,0 +1,324 @@ +/* + * Copyright (c) 2017 Nuvoton Tecnology Corp. All rights reserved. + * + * The code is forward data from UART port to Ethernet, and vice versa. + * + * + */ + +#include "ste_config.h" + +/* If define USE_STATIC_IP, specify the default IP address. */ +#if 0 + // private IP address for general purpose +#define IP_ADDRESS "192.168.1.2" +#define NETWORK_MASK "255.255.255.0" +#define GATEWAY_ADDRESS "192.168.1.1" +#else + // private IP address only for test with Windows when DHCP server doesn't exist. +#define IP_ADDRESS "169.254.108.2" +#define NETWORK_MASK "255.255.0.0" +#define GATEWAY_ADDRESS "169.254.108.1" +#endif + +/* Default configuration for network */ +S_NET_CONFIG net_config = {IP_STATIC_MODE, IP_ADDRESS, NETWORK_MASK, GATEWAY_ADDRESS}; + +#if defined (TARGET_NUMAKER_PFM_M487) +BufferedSerial serial_0(PH_8, PH_9, 256, 4); // UART1 +BufferedSerial serial_1(PC_12, PC_11, 256, 4); // UART0 +BufferedSerial serial_2(PA_3, PA_2, 256, 4); // UART4 + +#elif defined (TARGET_NUMAKER_PFM_NUC472) +BufferedSerial serial_0(PH_1, PH_0, 256, 4); // UART4 +BufferedSerial serial_1(PG_2, PG_1, 256, 4); // UART0 +BufferedSerial serial_2(PC_11, PC_10, 256, 4); // UART2 + +#elif defined (TARGET_NUMAKER_PFM_M453) +#error The board has no Ethernet. + +#else +#error define UART ports for your board. +#endif + +/* Default configuration for network ports and UART ports, etc. */ +S_PORT_CONFIG port_config[MAX_UART_PORTS] = { + +#if MAX_UART_PORTS == 1 + {NET_SERVER_MODE, NET_PORT_BASE, &serial_0, DEFAULT_UART_BAUD, 8, 1, SerialBase::None} + +#elif MAX_UART_PORTS == 2 + {NET_SERVER_MODE, NET_PORT_BASE + 0, &serial_0, DEFAULT_UART_BAUD, 8, 1, SerialBase::None}, + {NET_SERVER_MODE, NET_PORT_BASE + 1, &serial_1, DEFAULT_UART_BAUD, 8, 1, SerialBase::None} + +#elif MAX_UART_PORTS == 3 + {NET_SERVER_MODE, NET_PORT_BASE + 0, &serial_0, DEFAULT_UART_BAUD, 8, 1, SerialBase::None}, + {NET_SERVER_MODE, NET_PORT_BASE + 1, &serial_1, DEFAULT_UART_BAUD, 8, 1, SerialBase::None}, + {NET_SERVER_MODE, NET_PORT_BASE + 2, &serial_2, DEFAULT_UART_BAUD, 8, 1, SerialBase::None} + +#else +#error You have to define ports mapping table. +#endif +}; + +/* UART port to output debug message */ +RawSerial output(USBTX, USBRX); // UART3 on NuMaker-PFM-NUC472 +EthernetInterface eth; + +#ifdef ENABLE_WEB_CONFIG + +/* Declare the SD card as storage */ +NuSDBlockDevice bd; +FATFileSystem fs("fs"); +bool SD_Card_Mounted = FALSE; + +#endif + +/* --- --- */ + +/* + * Forward serial port data to ethernet, and vice versa. + * + */ +void exchange_data(S_PORT_CONFIG *pmap, TCPSocket *psocket) +{ + unsigned char n_buf[256]; + unsigned char s_buf[256]; + int n_len = 0, n_index = 0; + int s_len = 0, s_index = 0; + + while(1) + { + /*** Network to Serial ***/ + + if (n_len < 0 || n_len == n_index) + { + // net buffer is empty, try to get new data from network. + n_len = psocket->recv(n_buf, sizeof(n_buf)); + if (n_len == NSAPI_ERROR_WOULD_BLOCK) + { + } + else if (n_len < 0) + { + printf("Socket Recv Err (%d)\r\n", n_len); + psocket->close(); + break; + } + else + { + n_index = 0; + } + } + else + { + // send data to serial port. + for(;n_index < n_len && pmap->pserial->writeable(); n_index++) + { + pmap->pserial->putc(n_buf[n_index]); + } + } + + /*** Serial to Network ***/ + + if (pmap->pserial->readable()) + { + // try to get more data from serial port + for(s_index = 0; s_index < sizeof(s_buf) && pmap->pserial->readable(); s_index++) + s_buf[s_index] = pmap->pserial->getc(); + + // send all data to network. + if (s_index > 0) + { + s_len = psocket->send(s_buf, s_index); + if (s_len == NSAPI_ERROR_WOULD_BLOCK) + { + printf("Socket Send no block.\r\n"); + } + else if (s_len < 0) + { + printf("Socket Send Err (%d)\r\n", s_len); + psocket->close(); + break; + } + else if (s_len != s_index) + { + printf("Socket Send not complete.\r\n"); + psocket->close(); + break; + } + } + } + } +} + +void bridge_net_client(S_PORT_CONFIG *pmap) +{ + TCPSocket socket; + SocketAddress server_address; + nsapi_error_t err; + + printf("Thread %x in TCP client mode.\r\n", (unsigned int)pmap); + + if ((err=socket.open(ð)) < 0) + { + printf("TCP socket can't open (%d)(%x).\r\n", err, (unsigned int)pmap); + return; + } + + printf("Connecting server %s:%d ...\r\n", pmap->server_addr, pmap->server_port); + while(1) + { + if ((err=socket.connect(pmap->server_addr, pmap->server_port)) >= 0) + break; + } + + printf("\r\nConnected."); + + socket.set_timeout(1); + exchange_data(pmap, &socket); +} + +void bridge_net_server(S_PORT_CONFIG *pmap) +{ + TCPServer tcp_server; + TCPSocket client_socket; + SocketAddress client_address; + nsapi_error_t err; + + printf("Thread %x in TCP server mode.\r\n", (unsigned int)pmap); + + if ((err=tcp_server.open(ð)) < 0) + { + printf("TCP server can't open (%d)(%x).\r\n", err, (unsigned int)pmap); + return; + } + if ((err=tcp_server.bind(eth.get_ip_address(), pmap->port)) < 0) + { + printf("TCP server can't bind address and port (%d)(%x).\r\n", err, (unsigned int)pmap); + return; + } + if ((err=tcp_server.listen(1)) < 0) + { + printf("TCP server can't listen (%d)(%x).\r\n", err, (unsigned int)pmap); + return; + } + + client_socket.set_timeout(1); + + while(1) + { + if ((err=tcp_server.accept(&client_socket, &client_address)) < 0) + { + printf("TCP server fail to accept connection (%d)(%x).\r\n", err, (unsigned int)pmap); + return; + } + + printf("Connect (%d) from %s:%d ...\r\n", pmap->port, client_address.get_ip_address(), client_address.get_port()); + + exchange_data(pmap, &client_socket); + } +} + +int main() +{ + /* Set the console baud-rate */ + output.baud(115200); + printf("\r\nmbed OS version is %d.\r\n", MBED_VERSION); + printf("Start Serial-to-Ethernet...\r\n"); + +#ifdef ENABLE_WEB_CONFIG + + /* Restore configuration from SD card */ + + SD_Card_Mounted = (fs.mount(&bd) >= 0); + if (SD_Card_Mounted) + { + FILE *fd = fopen(SER_CONFIG_FILE, "r"); + if (fd != NULL) + { + char pBuf[sizeof(port_config)+2]; + int len = fread(pBuf, 1, sizeof(port_config)+2, fd); + if (len == (sizeof(port_config)+2) && pBuf[0] == 'N' && pBuf[1] == 'T') + { + printf("Set Serial ports from config file in SD card.\r\n"); + memcpy(port_config, pBuf+2, sizeof(port_config)); + } + else + printf("Incorrect serial config file.\r\n"); + + fclose(fd); + } + else + printf("Can't open serial config file.\r\n"); + + fd = fopen(NET_CONFIG_FILE, "r"); + if (fd != NULL) + { + char pBuf[sizeof(net_config)+2]; + int len = fread(pBuf, 1, sizeof(net_config)+2, fd); + if (len == (sizeof(net_config)+2) && pBuf[0] == 'N' && pBuf[1] == 'T') + { + printf("Set network from config file in SD card.\r\n"); + memcpy(&net_config, pBuf+2, sizeof(net_config)); + } + else + printf("Incorrect network config file.\r\n"); + + fclose(fd); + } + else + printf("Can't open network config file.\r\n"); + } + else + { + printf("Can't find SD card.\r\n"); + } + +#endif + + printf("Configure UART ports...\r\n"); + for(int i=0; i<MAX_UART_PORTS; i++) + { + port_config[i].pserial->baud(port_config[i].baud); + port_config[i].pserial->format(port_config[i].data, port_config[i].parity, port_config[i].stop); + } + + if (net_config.mode == IP_STATIC_MODE) + { + printf("Start Ethernet in Static mode.\r\n"); + eth.disconnect(); + ((NetworkInterface *)ð)->set_network(net_config.ip, net_config.mask, net_config.gateway); + } + else + printf("Start Ethernet in DHCP mode.\r\n"); + + eth.connect(); + printf("IP Address is %s\r\n", eth.get_ip_address()); + + Thread thread[MAX_UART_PORTS]; + + // Folk thread for each port + for(int i=0; i<MAX_UART_PORTS; i++) + { + if (port_config[i].mode == NET_SERVER_MODE) + { + thread[i].start(callback(bridge_net_server, &(port_config[i]))); + } + else // if (port_config[i].mode == TCP_CLIENT_MODE) + { + thread[i].start(callback(bridge_net_client, &(port_config[i]))); + } + } + +#ifdef ENABLE_WEB_CONFIG + + /*** main thread to be a web server for configuration ***/ + start_httpd(); + +#endif + + while(1); + + /* end of main task */ + //eth.disconnect(); +}
diff -r 000000000000 -r c89ccc69a48b mbed-os.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed-os.lib Fri Sep 29 05:45:43 2017 +0000 @@ -0,0 +1,1 @@ +https://github.com/ARMmbed/mbed-os/#ca661f9d28526ca8f874b05432493a489c9671ea
diff -r 000000000000 -r c89ccc69a48b mbed_app.json --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed_app.json Fri Sep 29 05:45:43 2017 +0000 @@ -0,0 +1,22 @@ +{ + "config": { + "SD_DAT0": "NC", + "SD_DAT1": "NC", + "SD_DAT2": "NC", + "SD_DAT3": "NC", + "SD_CMD": "NC", + "SD_CLK": "NC", + "SD_CD": "NC" + }, + "target_overrides": { + "NUMAKER_PFM_NUC472": { + "SD_DAT0": "PF_5", + "SD_DAT1": "PF_4", + "SD_DAT2": "PF_3", + "SD_DAT3": "PF_2", + "SD_CMD": "PF_7", + "SD_CLK": "PF_8", + "SD_CD": "PF_6" + } + } +}
diff -r 000000000000 -r c89ccc69a48b ste_config.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ste_config.h Fri Sep 29 05:45:43 2017 +0000 @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2017 Nuvoton Tecnology Corp. All rights reserved. + * + * Header for Serial-To-Ethernet configuration. + * + */ + +#ifndef _STE_CONFIG_H +#define _STE_CONFIG_H + +#include "mbed.h" +#include "EthernetInterface.h" +#include "TCPSocket.h" +#include "TCPServer.h" +#include "BufferedSerial.h" +#include "FATFileSystem.h" +#include "NuSDBlockDevice.h" + + +//#define ENABLE_WEB_CONFIG // Define this to active a simple web sever for + // UART ports and Ethernet port parameters configuration. + +/* Maximum UART ports supported */ +#define MAX_UART_PORTS 2 + +/* Default UART baud */ +#define DEFAULT_UART_BAUD 115200 + +/* Network base port number to listen. + So the base port maps to the 1st UART port, + the (base port + 1) maps to the 2nd UART port, etc. */ +#define NET_PORT_BASE 10001 + +/* Path and Filename of configuration files */ +#define SER_CONFIG_FILE "/fs/STE_SER.TXT" // for serial ports +#define NET_CONFIG_FILE "/fs/STE_NET.TXT" // for network + +/* Maximum size of server address */ +#define MAX_SERVER_ADDRESS_SIZE 63 + +/* Maximum size of IP address */ +#define MAX_IPV4_ADDRESS_SIZE 15 + +/* Functions and global variables declaration. */ + +typedef enum { + NET_SERVER_MODE = 0, + NET_CLIENT_MODE +} E_NetMode; + +typedef enum { + IP_STATIC_MODE = 0, + IP_DHCP_MODE +} E_IPMode; + +typedef struct { + E_IPMode mode; + char ip[MAX_IPV4_ADDRESS_SIZE+1]; + char mask[MAX_IPV4_ADDRESS_SIZE+1]; + char gateway[MAX_IPV4_ADDRESS_SIZE+1]; +} S_NET_CONFIG; + +typedef struct { + E_NetMode mode; // Network server or client mode + int port; // Network port number + BufferedSerial *pserial; // UART number + int baud; // UART baud + int data; // UART data bits + int stop; // UART stop bits + mbed::SerialBase::Parity parity; // UART parity bit + char server_addr[MAX_SERVER_ADDRESS_SIZE+1]; // Server address for TCP client mode + unsigned short server_port; // Server port for TCP client mode +} S_PORT_CONFIG; + +extern RawSerial output; // for debug output +extern EthernetInterface eth; +extern S_PORT_CONFIG port_config[MAX_UART_PORTS]; +extern S_NET_CONFIG net_config; + +extern bool SD_Card_Mounted; +void start_httpd(void); + +#endif
diff -r 000000000000 -r c89ccc69a48b uweb_server.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/uweb_server.cpp Fri Sep 29 05:45:43 2017 +0000 @@ -0,0 +1,536 @@ +/* + * Copyright (c) 2017 Nuvoton Tecnology Corp. All rights reserved. + * + * micro web server for serial to Ethernet configuration. + * + * + */ + +#include <string.h> +#include "ste_config.h" + +#ifdef ENABLE_WEB_CONFIG + +#define PAGE_HEADER \ +"<html><head>\r\n" \ +"<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\r\n" \ +"<title>Serial to Ethernet Configuration</title>\r\n" \ +"</head>\r\n" + +#define PAGE_HEADER_FOR_REFRESH \ +"<html><head>\r\n" \ +"<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\r\n" \ +"<meta http-equiv=\"refresh\" content=\"10; url=index.html\" />\r\n" \ +"<title>Serial to Ethernet Configuration</title>\r\n" \ +"</head>\r\n" + +#define PAGE_RESTART_FORM \ +"<form action=\"/config.html\" method=\"GET\">\r\n" \ +"<input type=\"hidden\" name=\"restart\" value=\"1\">\r\n" \ +"<input type=\"submit\" value=\"Restart\"> </form>\r\n" + +#define PAGE_RESETCONF_FORM \ +"<form action=\"/config.html\" method=\"GET\">\r\n" \ +"<input type=\"hidden\" name=\"resetconf\" value=\"1\">\r\n" \ +"<input type=\"submit\" value=\"Reset Config\"> </form>\r\n" + +#define PAGE_CONFIG_FORM_HEAD \ +"<form action=\"/config.html\" method=\"GET\">\r\n" + +#define PAGE_CONFIG_SERIAL_FORM \ +"<input type=\"hidden\" name=\"uart_port\" value=\"%d\">\r\n" \ +" Baud <select type=\"text\" name=\"baud\">\r\n \ + <option value=\"115200\"%s>115200</option>\r\n \ + <option value=\"9600\"%s>9600</option>\r\n \ + <option value=\"4800\"%s>4800</option>\r\n \ + <option value=\"2400\"%s>2400</option>\r\n \ + </select>   \r\n \ + Data bits <select type=\"text\" name=\"databits\">\r\n \ + <option value=\"8\"%s>8</option>\r\n \ + <option value=\"7\"%s>7</option>\r\n \ + <option value=\"6\"%s>6</option>\r\n \ + <option value=\"5\"%s>5</option>\r\n \ + </select> \r\n \ + Parity <select type=\"text\" name=\"parity\">\r\n \ + <option value=\"0\"%s>None</option>\r\n \ + <option value=\"1\"%s>Odd</option>\r\n \ + <option value=\"2\"%s>Even</option>\r\n \ + </select> \r\n \ + Stop bits <select type=\"text\" name=\"stopbits\">\r\n \ + <option value=\"1\"%s>1</option>\r\n \ + <option value=\"2\"%s>2</option>\r\n \ + </select> <br>\r\n \ +Network mode <select type=\"text\" name=\"netmode\">\r\n \ + <option value=\"0\"%s>Server</option>\r\n \ + <option value=\"1\"%s>Client</option>\r\n \ + </select> <br> Set following fields for Client only. <br>\r\n \ +Server address <input type=\"text\" name=\"sipaddr\" size=\"16\" value=\"%s\">   \r\n \ +Server port <input type=\"text\" name=\"sport\" size=\"5\" value=\"%d\">\r\n" + +#define PAGE_CONFIG_NET_FORM \ +"<input type=\"hidden\" name=\"net_config\" value=\"1\">\r\n \ +IP Address Mode <select type=\"text\" name=\"ipmode\">\r\n \ + <option value=\"0\"%s>Static</option>\r\n \ + <option value=\"1\"%s>DHCP</option>\r\n \ + </select> <br> Set following fields for Static IP only. <br>\r\n \ +IP Address <input type=\"text\" name=\"ipaddr\" size=\"16\" value=\"%s\">\r\n \ +Netmask <input type=\"text\" name=\"mask\" size=\"16\" value=\"%s\">\r\n \ +Gateway Address <input type=\"text\" name=\"gwaddr\" size=\"16\" value=\"%s\">\r\n" + +typedef void (*PROC_PAGE_PFN)(TCPSocket *, char *); + +typedef struct { + const char *vhtmlpage; // virtual page name, eg. index.html ... + PROC_PAGE_PFN pfn; +} S_WEB_PAGE_SETTING; + +extern void process_http_index_html(TCPSocket *, char *); +extern void process_http_restart_html(TCPSocket *, char *); +extern void process_http_resetconf_html(TCPSocket *, char *); +extern void process_http_config_html(TCPSocket *, char *); +extern void process_http_err_html(TCPSocket *, char *); + +#define MAX_WEB_GET_PAGE_SETTINGS 5 +S_WEB_PAGE_SETTING web_get_pages_setings[MAX_WEB_GET_PAGE_SETTINGS] = { + {"/ ", process_http_index_html}, + {"/index.html ", process_http_index_html}, + {"/config.html?restart=1 ", process_http_restart_html}, + {"/config.html?resetconf=1 ", process_http_resetconf_html}, + {"/config.html?", process_http_config_html} +}; + +#define MAX_WEB_POST_PAGE_SETTINGS 1 +S_WEB_PAGE_SETTING web_post_pages_setings[MAX_WEB_POST_PAGE_SETTINGS] = { + {"/config.html ", process_http_config_html}, +}; + +typedef struct { + int type; // 0: integer, 1:string + int value; // integer value for integer type + char *str; // point to string for string type + int min; + int max; // max value of integer or max length of string + const char *cmd; + int cmd_len; +} S_WEB_CMD_PARAMS; + +#define MAX_WEB_CMD_PARAMS 13 +S_WEB_CMD_PARAMS web_cmd_params[MAX_WEB_CMD_PARAMS] = { + {0, 0, NULL, 1, MAX_UART_PORTS, "uart_port=", 10}, + {0, 0, NULL, 2400, 115200, "baud=", 5}, + {0, 0, NULL, 5, 8, "databits=", 9}, + {0, 0, NULL, 0, 2, "parity=", 7}, + {0, 0, NULL, 1, 2, "stopbits=", 9}, + {0, 0, NULL, 0, 1, "netmode=", 8}, + {1, 0, NULL, 0, 16, "sipaddr=", 8}, + {0, 0, NULL, 0, 65535, "sport=", 6}, + {0, 0, NULL, 1, 1, "net_config=", 11}, + {0, 0, NULL, 0, 1, "ipmode=", 7}, + {1, 0, NULL, 0, 1, "ipaddr=", 7}, + {1, 0, NULL, 0, 1, "mask=", 5}, + {1, 0, NULL, 0, 1, "gwaddr=", 7} +}; + +const char *parity_string[] = {"None", "Odd", "Even"}; +const char *netmode_string[] = {"Server", "Client"}; +const char *ipmode_string[] = {"Static", "DHCP"}; + + +int inspect_each_setting(char *pbuf) +{ + int i; + int v; + + for(i=0; i<MAX_WEB_CMD_PARAMS; i++) + { + web_cmd_params[i].value = 0; + web_cmd_params[i].str = NULL; + } + + while(*pbuf != '\0') + { + for(i=0; i<MAX_WEB_CMD_PARAMS; i++) + { + if (strncmp(pbuf, web_cmd_params[i].cmd, web_cmd_params[i].cmd_len) == 0) + { + pbuf += web_cmd_params[i].cmd_len; + + if (web_cmd_params[i].type == 0) + { + v = atoi(pbuf); + if (v >= web_cmd_params[i].min && v <= web_cmd_params[i].max) + web_cmd_params[i].value = v; + } + else + { + web_cmd_params[i].str = pbuf; + } + + for(; *pbuf != '\0'; pbuf++) + { + if (*pbuf == '&') + { + *pbuf++ = '\0'; + break; + } + else if (*pbuf == ' ') + { + *pbuf = '\0'; + break; + } +// else if (*pbuf == '\r') +// { +// *pbuf++ = '\0'; +// if (*pbuf == '\n') +// *pbuf++ = '\0'; +// break; +// } +// else if (*pbuf == '\n' || *pbuf == ' ') +// { +// *pbuf++ = '\0'; +// break; +// } + } + + break; + } + } + + if (i >= MAX_WEB_CMD_PARAMS) + return -1; + } + + return 0; +} + +int process_settings(char *pbuf) +{ + FILE *fp; + + printf("Verify Configure setting...\r\n"); + printf("---Dump Settings---\r\n%s\r\n---End of dump---\r\n", pbuf); + + if (SD_Card_Mounted == FALSE) + { + printf("SD card doesn't exist. Ignore settings.\r\n"); + return -1; + } + + if (inspect_each_setting(pbuf) < 0) + { + printf("Unsupported parameters.\r\n"); + return -1; + } + + if (web_cmd_params[0].value > 0) + { + int port = web_cmd_params[0].value - 1; + port_config[port].baud = web_cmd_params[1].value; + port_config[port].data = web_cmd_params[2].value; + port_config[port].stop = web_cmd_params[4].value; + port_config[port].parity = (mbed::SerialBase::Parity) web_cmd_params[3].value; + port_config[port].mode = (E_NetMode) web_cmd_params[5].value; + + if (web_cmd_params[6].str != NULL) + { + strncpy(port_config[port].server_addr, web_cmd_params[6].str, MAX_SERVER_ADDRESS_SIZE); + port_config[port].server_addr[MAX_SERVER_ADDRESS_SIZE] = '\0'; + } + + port_config[port].server_port = web_cmd_params[7].value; + + printf("Save Serial Config setting...\r\n"); + fp = fopen(SER_CONFIG_FILE, "w"); + if (fp != NULL) + { + char pBuf[2] = {'N', 'T'}; + printf("Write config file to SD card.\r\n"); + fwrite(pBuf, 2, 1, fp); + fwrite(port_config, sizeof(port_config), 1, fp); + fclose(fp); + } + else + { + printf("Can't write to SD card.\r\n"); + } + } + else if (web_cmd_params[8].value > 0) + { + net_config.mode = (E_IPMode)web_cmd_params[9].value; + if (web_cmd_params[10].str != NULL) + { + strncpy(net_config.ip, web_cmd_params[10].str, MAX_IPV4_ADDRESS_SIZE); + net_config.ip[MAX_IPV4_ADDRESS_SIZE] = '\0'; + } + if (web_cmd_params[11].str != NULL) + { + strncpy(net_config.mask, web_cmd_params[11].str, MAX_IPV4_ADDRESS_SIZE); + net_config.mask[MAX_IPV4_ADDRESS_SIZE] = '\0'; + } + if (web_cmd_params[12].str != NULL) + { + strncpy(net_config.gateway, web_cmd_params[12].str, MAX_IPV4_ADDRESS_SIZE); + net_config.gateway[MAX_IPV4_ADDRESS_SIZE] = '\0'; + } + printf("Save Network Config setting...\r\n"); + fp = fopen(NET_CONFIG_FILE, "w"); + if (fp != NULL) + { + char pBuf[2] = {'N', 'T'}; + printf("Write config file to SD card.\r\n"); + fwrite(pBuf, 2, 1, fp); + fwrite(&net_config, sizeof(net_config), 1, fp); + fclose(fp); + } + else + { + printf("Can't write to SD card.\r\n"); + } + } + + return 0; +} + + +void send_web_data(TCPSocket *socket, char *pbuf) +{ + char *p = pbuf; + int size = strlen(pbuf); + + while(size > 0) + { + int ret = socket->send(p, size); + if (ret < 0) + break; + + p += ret; + size -= ret; + } +} + +void send_web_header(TCPSocket *socket, int num) +{ + static const char *webpage_header[] = { + PAGE_HEADER, + PAGE_HEADER_FOR_REFRESH + }; + + send_web_data(socket, (char *)webpage_header[num]); +} + +const char *status_messages[] = { + "\r\n", + "Configuration update successfully. </p>\r\n", + "Configuration setting error.</p>\r\n", + "Reset Configuration successfully. </p>\r\n", + "Web page will reload automatically after 10 seconds. </p>\r\n", + "Unknown settings. </p>\r\n" +}; + +void send_web_body(TCPSocket *socket, int num) +{ + int i; + static char pbuf[3072]; + + /* send page body */ + send_web_data(socket, (char *)"<body>Serial to Ethernet Configuration </p>\r\n"); + + /* send status message */ + send_web_data(socket, (char *)status_messages[num]); + + send_web_data(socket, (char *)PAGE_RESTART_FORM); + send_web_data(socket, (char *)PAGE_RESETCONF_FORM); + + /* send network configuration form */ + send_web_data(socket, (char *)PAGE_CONFIG_FORM_HEAD); + + sprintf(pbuf, PAGE_CONFIG_NET_FORM, + (net_config.mode == IP_STATIC_MODE)?" selected":"", + (net_config.mode == IP_DHCP_MODE)?" selected":"", + net_config.ip, + net_config.mask, + net_config.gateway); + + send_web_data(socket, pbuf); + send_web_data(socket, (char *)"<br><input type=\"submit\" value=\"Config Net\"> </form><br>\r\n"); + + /* send serial ports configuration form */ + send_web_data(socket, (char *)PAGE_CONFIG_FORM_HEAD); + for(i=0; i<MAX_UART_PORTS; i++) + { + S_PORT_CONFIG *s = &port_config[i]; + + sprintf(pbuf, "Serial port #%d<br>\r\n", i+1); + send_web_data(socket, pbuf); + sprintf(pbuf, PAGE_CONFIG_SERIAL_FORM, + i+1, + (s->baud == 115200)?" selected":"", + (s->baud == 9600)?" selected":"", + (s->baud == 4800)?" selected":"", + (s->baud == 2400)?" selected":"", + (s->data == 8)?" selected":"", + (s->data == 7)?" selected":"", + (s->data == 6)?" selected":"", + (s->data == 5)?" selected":"", + (s->parity == 0)?" selected":"", + (s->parity == 1)?" selected":"", + (s->parity == 2)?" selected":"", + (s->stop == 1)?" selected":"", + (s->stop == 2)?" selected":"", + (s->mode == 0)?" selected":"", + (s->mode == 1)?" selected":"", + s->server_addr, + s->server_port); + + send_web_data(socket, pbuf); + +#if MAX_UART_PORTS == 1 + sprintf(pbuf, "<br><input type=\"submit\" value=\"Config Port\"> </form><br>\r\n"); +#else + sprintf(pbuf, "<br><input type=\"submit\" value=\"Config Port #%d\"> </form><br>\r\n", i); +#endif + send_web_data(socket, pbuf); + } + + /* send end of page body */ + send_web_data(socket, (char *)"</body></html>\r\n"); +} + +void process_http_index_html(TCPSocket *socket, char *pbuf) +{ + send_web_header(socket, 0); + send_web_body(socket, 0); +} + +void process_http_restart_html(TCPSocket *socket, char *pbuf) +{ + send_web_header(socket, 1); + send_web_body(socket, 4); + + printf("Restart system...\r\n"); + wait(1); // wait 1 second +// SYS_ResetCPU(); + SYS_ResetChip(); + wait(100); +} + +void process_http_resetconf_html(TCPSocket *socket, char *pbuf) +{ + if (SD_Card_Mounted) + { + remove(SER_CONFIG_FILE); + remove(NET_CONFIG_FILE); + printf("Deleted config files.\r\n"); + } + else + { + printf("SD card doesn't exist.\r\n"); + } + + send_web_header(socket, 0); + send_web_body(socket, 3); +} + +void process_http_config_html(TCPSocket *socket, char *pbuf) +{ + send_web_header(socket, 0); + + if (process_settings(pbuf) >= 0) + send_web_body(socket, 1); + else + send_web_body(socket, 2); +} + +void process_http_err_html(TCPSocket *socket, char *pbuf) +{ + send_web_header(socket, 0); + send_web_body(socket, 5); +} + +void process_http_get_request(TCPSocket *socket, char *pbuf) +{ + int i; + + for(i=0; i<MAX_WEB_GET_PAGE_SETTINGS; i++) + { + int len = strlen(web_get_pages_setings[i].vhtmlpage); + if (strncmp(pbuf, web_get_pages_setings[i].vhtmlpage, len) == 0) + { + if (web_get_pages_setings[i].pfn != NULL) + { + web_get_pages_setings[i].pfn(socket, pbuf+len); + break; + } + } + } +} + +void process_http_post_request(TCPSocket *socket, char *pbuf) +{ +} + +void process_http_request(TCPSocket *socket) +{ + char w_buf[2048]; + int w_len; + + w_len = socket->recv(w_buf, 2047); + if (w_len <= 0) + return; + + w_buf[w_len] = '\0'; + printf("\n\r---DUMP HTTP DATA (%d)---\r\n%s\r\n---END OF DUMP---\r\n", w_len, w_buf); + + if (strncmp(w_buf, "GET ", 4) == 0) + { + process_http_get_request(socket, w_buf+4); + } + else if (strncmp(w_buf, "POST ", 5) == 0) + { + process_http_post_request(socket, w_buf+5); + } + else + { + process_http_get_request(socket, (char *)"/ "); + } +} + +void start_httpd(void) +{ + TCPServer http_server; + TCPSocket http_socket; + SocketAddress http_address; + + if (http_server.open(ð) < 0) + { + printf("http server can't open.\r\n"); + return; + } + if (http_server.bind(eth.get_ip_address(), 80) < 0) + { + printf("http server can't bind address and port.\r\n"); + return; + } + if (http_server.listen(1) < 0) + { + printf("http server can't listen.\r\n"); + return; + } + + printf("Start http server...\r\n"); + + while(1) + { + if (http_server.accept(&http_socket, &http_address) < 0) + { + printf("http server fail to accept connection.\r\n"); + return; + } + + printf("http from %s:%d ...\r\n", http_address.get_ip_address(), http_address.get_port()); + process_http_request(&http_socket); + http_socket.close(); + } +} + +#endif