NuMaker Transfer data UART to Ethernet
Fork of Serial-to-Ethernet by
Revision 6:014b1a469aed, committed 2021-03-02
- Comitter:
- SHLIU1@OANBE02333.nuvoton.com
- Date:
- Tue Mar 02 10:09:10 2021 +0800
- Parent:
- 5:b079098a3f0b
- Child:
- 7:c03b2ed97d94
- Commit message:
- Support the both V5.X and V6.X for mbed-os
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/BufferSerial/BufferSerial.cpp Tue Mar 02 10:09:10 2021 +0800 @@ -0,0 +1,183 @@ +/** + * @file BufferSerial.cpp + * @brief Software Buffer - Extends mbed Serial functionallity adding irq driven TX and RX + * @author sam grove + * @version 1.0 + * @see + * + * Copyright (c) 2013 + * + * 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. + */ + +#include "BufferSerial.h" +#include <stdarg.h> + +#if MBED_MAJOR_VERSION >= 6 + +BufferSerial::BufferSerial(PinName tx, PinName rx, uint32_t buf_size, uint32_t tx_multiple, const char* name) + : MyUnbufferedSerial(tx, rx) , _rxbuf(buf_size), _txbuf((uint32_t)(tx_multiple*buf_size)) +#else +BufferSerial::BufferSerial(PinName tx, PinName rx, uint32_t buf_size, uint32_t tx_multiple, const char* name) + : RawSerial(tx, rx) , _rxbuf(buf_size), _txbuf((uint32_t)(tx_multiple*buf_size)) +#endif +{ +#if MBED_MAJOR_VERSION >= 6 + MyUnbufferedSerial::attach(callback(this, &BufferSerial::rxIrq), SerialBase::RxIrq); +#else + RawSerial::attach(this, &BufferSerial::rxIrq, Serial::RxIrq); +#endif + this->_buf_size = buf_size; + this->_tx_multiple = tx_multiple; + return; +} + +BufferSerial::~BufferSerial(void) +{ +#if MBED_MAJOR_VERSION >= 6 + MyUnbufferedSerial::attach(NULL, MyUnbufferedSerial::RxIrq); + MyUnbufferedSerial::attach(NULL, MyUnbufferedSerial::TxIrq); +#else + RawSerial::attach(NULL, RawSerial::RxIrq); + RawSerial::attach(NULL, RawSerial::TxIrq); +#endif + + return; +} + +int BufferSerial::readable(void) +{ + return _rxbuf.available(); // note: look if things are in the buffer +} + +int BufferSerial::writeable(void) +{ + return 1; // buffer allows overwriting by design, always true +} + +int BufferSerial::getc(void) +{ + return _rxbuf; +} + +int BufferSerial::putc(int c) +{ + _txbuf = (char)c; + BufferSerial::prime(); + + return c; +} + +int BufferSerial::puts(const char *s) +{ + if (s != NULL) { + const char* ptr = s; + + while(*(ptr) != 0) { + _txbuf = *(ptr++); + } + _txbuf = '\n'; // done per puts definition + BufferSerial::prime(); + + return (ptr - s) + 1; + } + return 0; +} + +int BufferSerial::printf(const char* format, ...) +{ + char buffer[this->_buf_size]; + memset(buffer,0,this->_buf_size); + int r = 0; + + va_list arg; + va_start(arg, format); + r = vsprintf(buffer, format, arg); + // this may not hit the heap but should alert the user anyways + if(r > this->_buf_size) { + error("%s %d buffer overwrite (max_buf_size: %d exceeded: %d)!\r\n", __FILE__, __LINE__,this->_buf_size,r); + va_end(arg); + return 0; + } + va_end(arg); + r = BufferSerial::write(buffer, r); + + return r; +} + +ssize_t BufferSerial::write(const void *s, size_t length) +{ + if (s != NULL && length > 0) { + const char* ptr = (const char*)s; + const char* end = ptr + length; + + while (ptr != end) { + _txbuf = *(ptr++); + } + BufferSerial::prime(); + + return ptr - (const char*)s; + } + return 0; +} + + +void BufferSerial::rxIrq(void) +{ + // read from the peripheral and make sure something is available + if(serial_readable(&_serial)) { + _rxbuf = serial_getc(&_serial); // if so load them into a buffer + } + + return; +} + +void BufferSerial::txIrq(void) +{ + // see if there is room in the hardware fifo and if something is in the software fifo + while(serial_writable(&_serial)) { + if(_txbuf.available()) { + serial_putc(&_serial, (int)_txbuf.get()); + } else { + // disable the TX interrupt when there is nothing left to send +#if MBED_MAJOR_VERSION >= 6 + MyUnbufferedSerial::attach(NULL, MyUnbufferedSerial::TxIrq); +#else + RawSerial::attach(NULL, RawSerial::TxIrq); +#endif + break; + } + } + + return; +} + +void BufferSerial::prime(void) +{ + // if already busy then the irq will pick this up + if(serial_writable(&_serial)) { +#if MBED_MAJOR_VERSION >= 6 + MyUnbufferedSerial::attach(NULL, MyUnbufferedSerial::TxIrq); // make sure not to cause contention in the irq + BufferSerial::txIrq(); // only write to hardware in one place + MyUnbufferedSerial::attach(callback(this, &BufferSerial::txIrq), MyUnbufferedSerial::TxIrq); +#else + RawSerial::attach(NULL, RawSerial::TxIrq); // make sure not to cause contention in the irq + BufferSerial::txIrq(); // only write to hardware in one place + RawSerial::attach(this, &BufferSerial::txIrq, RawSerial::TxIrq); +#endif + } + + return; +} + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/BufferSerial/BufferSerial.h Tue Mar 02 10:09:10 2021 +0800 @@ -0,0 +1,154 @@ + +/** + * @file BufferSerial.h + * @brief Software Buffer - Extends mbed Serial functionallity adding irq driven TX and RX + * @author sam grove + * @version 1.0 + * @see + * + * Copyright (c) 2013 + * + * 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 BUFFEREDSERIAL_H +#define BUFFEREDSERIAL_H + +#include "mbed.h" +#include "MyBuffer.h" + +#if (MBED_MAJOR_VERSION == 5) && (MBED_MINOR_VERSION >= 2) +#elif (MBED_MAJOR_VERSION == 2) && (MBED_PATCH_VERSION > 130) +#else +//#error "BufferSerial version 13 and newer requires use of Mbed OS 5.2.0 and newer or Mbed 2 version 130 and newer. Use BufferSerial version 12 and older or upgrade the Mbed version. +#endif + +/** A serial port (UART) for communication with other serial devices + * + * Can be used for Full Duplex communication, or Simplex by specifying + * one pin as NC (Not Connected) + * + * Example: + * @code + * #include "mbed.h" + * #include "BufferSerial.h" + * + * BufferSerial pc(USBTX, USBRX); + * + * int main() + * { + * while(1) + * { + * Timer s; + * + * s.start(); + * pc.printf("Hello World - buffer\n"); + * int buffer_time = s.read_us(); + * wait(0.1f); // give time for the buffer to empty + * + * s.reset(); + * printf("Hello World - blocking\n"); + * int polled_time = s.read_us(); + * s.stop(); + * wait(0.1f); // give time for the buffer to empty + * + * pc.printf("printf buffer took %d us\n", buffer_time); + * pc.printf("printf blocking took %d us\n", polled_time); + * wait(0.5f); + * } + * } + * @endcode + */ + +/** + * @class BufferSerial + * @brief Software buffers and interrupt driven tx and rx for Serial + */ + +#if MBED_MAJOR_VERSION >= 6 +#include "MyUnbufferedSerial.h" +class BufferSerial : public MyUnbufferedSerial +{ +#else +class BufferSerial : public RawSerial +{ +#endif + +private: + MyBuffer <char> _rxbuf; + MyBuffer <char> _txbuf; + uint32_t _buf_size; + uint32_t _tx_multiple; + + void rxIrq(void); + void txIrq(void); + void prime(void); + +public: + /** Create a BufferSerial port, connected to the specified transmit and receive pins + * @param tx Transmit pin + * @param rx Receive pin + * @param buf_size printf() buffer size + * @param tx_multiple amount of max printf() present in the internal ring buffer at one time + * @param name optional name + * @note Either tx or rx may be specified as NC if unused + */ + BufferSerial(PinName tx, PinName rx, uint32_t buf_size = 256, uint32_t tx_multiple = 4,const char* name=NULL); + + /** Destroy a BufferSerial port + */ + virtual ~BufferSerial(void); + + /** Check on how many bytes are in the rx buffer + * @return 1 if something exists, 0 otherwise + */ + virtual int readable(void); + + /** Check to see if the tx buffer has room + * @return 1 always has room and can overwrite previous content if too small / slow + */ + virtual int writeable(void); + + /** Get a single byte from the BufferSerial Port. + * Should check readable() before calling this. + * @return A byte that came in on the Serial Port + */ + virtual int getc(void); + + /** Write a single byte to the BufferSerial Port. + * @param c The byte to write to the Serial Port + * @return The byte that was written to the Serial Port Buffer + */ + virtual int putc(int c); + + /** Write a string to the BufferSerial Port. Must be NULL terminated + * @param s The string to write to the Serial Port + * @return The number of bytes written to the Serial Port Buffer + */ + virtual int puts(const char *s); + + /** Write a formatted string to the BufferSerial Port. + * @param format The string + format specifiers to write to the Serial Port + * @return The number of bytes written to the Serial Port Buffer + */ + virtual int printf(const char* format, ...); + + /** Write data to the Buffer Serial Port + * @param s A pointer to data to send + * @param length The amount of data being pointed to + * @return The number of bytes written to the Serial Port Buffer + */ + virtual ssize_t write(const void *s, std::size_t length); +}; + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/BufferSerial/MyBuffer.cpp Tue Mar 02 10:09:10 2021 +0800 @@ -0,0 +1,76 @@ + +/** + * @file Buffer.cpp + * @brief Software Buffer - Templated Ring Buffer for most data types + * @author sam grove + * @version 1.0 + * @see + * + * Copyright (c) 2013 + * + * 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. + */ + +#include "MyBuffer.h" + +template <class T> +MyBuffer<T>::MyBuffer(uint32_t size) +{ + _buf = new T [size]; + _size = size; + clear(); + + return; +} + +template <class T> +MyBuffer<T>::~MyBuffer() +{ + delete [] _buf; + + return; +} + +template <class T> +uint32_t MyBuffer<T>::getSize() +{ + return this->_size; +} + +template <class T> +void MyBuffer<T>::clear(void) +{ + _wloc = 0; + _rloc = 0; + memset(_buf, 0, _size); + + return; +} + +template <class T> +uint32_t MyBuffer<T>::peek(char c) +{ + return 1; +} + +// make the linker aware of some possible types +template class MyBuffer<uint8_t>; +template class MyBuffer<int8_t>; +template class MyBuffer<uint16_t>; +template class MyBuffer<int16_t>; +template class MyBuffer<uint32_t>; +template class MyBuffer<int32_t>; +template class MyBuffer<uint64_t>; +template class MyBuffer<int64_t>; +template class MyBuffer<char>; +template class MyBuffer<wchar_t>;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/BufferSerial/MyBuffer.h Tue Mar 02 10:09:10 2021 +0800 @@ -0,0 +1,163 @@ + +/** + * @file Buffer.h + * @brief Software Buffer - Templated Ring Buffer for most data types + * @author sam grove + * @version 1.0 + * @see + * + * Copyright (c) 2013 + * + * 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 MYBUFFER_H +#define MYBUFFER_H + +#include <stdint.h> +#include <string.h> + +/** A templated software ring buffer + * + * Example: + * @code + * #include "mbed.h" + * #include "MyBuffer.h" + * + * MyBuffer <char> buf; + * + * int main() + * { + * buf = 'a'; + * buf.put('b'); + * char *head = buf.head(); + * puts(head); + * + * char whats_in_there[2] = {0}; + * int pos = 0; + * + * while(buf.available()) + * { + * whats_in_there[pos++] = buf; + * } + * printf("%c %c\n", whats_in_there[0], whats_in_there[1]); + * buf.clear(); + * error("done\n\n\n"); + * } + * @endcode + */ + +template <typename T> +class MyBuffer +{ +private: + T *_buf; + volatile uint32_t _wloc; + volatile uint32_t _rloc; + uint32_t _size; + +public: + /** Create a Buffer and allocate memory for it + * @param size The size of the buffer + */ + MyBuffer(uint32_t size = 0x100); + + /** Get the size of the ring buffer + * @return the size of the ring buffer + */ + uint32_t getSize(); + + /** Destry a Buffer and release it's allocated memory + */ + ~MyBuffer(); + + /** Add a data element into the buffer + * @param data Something to add to the buffer + */ + void put(T data); + + /** Remove a data element from the buffer + * @return Pull the oldest element from the buffer + */ + T get(void); + + /** Get the address to the head of the buffer + * @return The address of element 0 in the buffer + */ + T *head(void); + + /** Reset the buffer to 0. Useful if using head() to parse packeted data + */ + void clear(void); + + /** Determine if anything is readable in the buffer + * @return 1 if something can be read, 0 otherwise + */ + uint32_t available(void); + + /** Overloaded operator for writing to the buffer + * @param data Something to put in the buffer + * @return + */ + MyBuffer &operator= (T data) + { + put(data); + return *this; + } + + /** Overloaded operator for reading from the buffer + * @return Pull the oldest element from the buffer + */ + operator int(void) + { + return get(); + } + + uint32_t peek(char c); + +}; + +template <class T> +inline void MyBuffer<T>::put(T data) +{ + _buf[_wloc++] = data; + _wloc %= (_size-1); + + return; +} + +template <class T> +inline T MyBuffer<T>::get(void) +{ + T data_pos = _buf[_rloc++]; + _rloc %= (_size-1); + + return data_pos; +} + +template <class T> +inline T *MyBuffer<T>::head(void) +{ + T *data_pos = &_buf[0]; + + return data_pos; +} + +template <class T> +inline uint32_t MyBuffer<T>::available(void) +{ + return (_wloc == _rloc) ? 0 : 1; +} + +#endif +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/BufferSerial/MyUnbufferedSerial.cpp Tue Mar 02 10:09:10 2021 +0800 @@ -0,0 +1,128 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2019 ARM Limited + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + */ + +#include "MyUnbufferedSerial.h" +#if (MBED_MAJOR_VERSION >= 6) +#if DEVICE_SERIAL + +#include "platform/mbed_critical.h" + +namespace mbed { + +MyUnbufferedSerial::MyUnbufferedSerial( + PinName tx, + PinName rx, + int baud +) : SerialBase(tx, rx, baud) +{ + // No lock needed in the constructor +} + +MyUnbufferedSerial::MyUnbufferedSerial( + const serial_pinmap_t &static_pinmap, int baud +) : SerialBase(static_pinmap, baud) +{ + // No lock needed in the constructor +} + +ssize_t MyUnbufferedSerial::write(const void *buffer, size_t size) +{ + const unsigned char *buf = static_cast<const unsigned char *>(buffer); + + if (size == 0) { + return 0; + } + + bool lock_api = !core_util_in_critical_section(); + + if (lock_api) { + lock(); + } + + for (size_t i = 0; i < size; i++) { + _base_putc(buf[i]); + } + + if (lock_api) { + unlock(); + } + + return size; +} + +ssize_t MyUnbufferedSerial::read(void *buffer, size_t size) +{ + unsigned char *buf = static_cast<unsigned char *>(buffer); + + if (size == 0) { + return 0; + } + + lock(); + + buf[0] = _base_getc(); + + unlock(); + + return 1; +} + +short MyUnbufferedSerial::poll(short events) const +{ + short revents = 0; + if ( + (events & POLLIN) + && (const_cast <MyUnbufferedSerial *>(this))->SerialBase::readable() + ) { + revents |= POLLIN; + } + if ( + (events & POLLOUT) + && (const_cast <MyUnbufferedSerial *>(this))->SerialBase::writeable() + ) { + revents |= POLLOUT; + } + return revents; +} + +int MyUnbufferedSerial::enable_input(bool enabled) +{ + SerialBase::enable_input(enabled); + + return 0; +} + +int MyUnbufferedSerial::enable_output(bool enabled) +{ + SerialBase::enable_output(enabled); + + return 0; +} + +#if DEVICE_SERIAL_FC +void MyUnbufferedSerial::set_flow_control(Flow type, PinName flow1, PinName flow2) +{ + lock(); + SerialBase::set_flow_control(type, flow1, flow2); + unlock(); +} +#endif // DEVICE_SERIAL_FC + +} // namespace mbed + +#endif // #if DEVICE_SERIAL +#endif // (MBED_MAJOR_VERSION >= 6 ) \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/BufferSerial/MyUnbufferedSerial.h Tue Mar 02 10:09:10 2021 +0800 @@ -0,0 +1,223 @@ +/* mbed Microcontroller Library + * Copyright (c) 2019 ARM Limited + * SPDX-License-Identifier: Apache-2.0 + * + * 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 MBED_MYUNBUFFERED_SERIAL_H +#define MBED_MYUNBUFFERED_SERIAL_H +#include "mbed.h" +#if (MBED_MAJOR_VERSION >= 6) + +#include "platform/platform.h" + +#if DEVICE_SERIAL || defined(DOXYGEN_ONLY) + +#include <cstdarg> + +#include "drivers/SerialBase.h" +#include "platform/FileHandle.h" +#include "platform/mbed_toolchain.h" +#include "platform/NonCopyable.h" + + +namespace mbed { +/** \defgroup drivers-public-api-uart UART + * \ingroup drivers-public-api + */ + +/** + * \defgroup drivers_MyUnbufferedSerial MyUnbufferedSerial class + * \ingroup drivers-public-api-uart + * @{ + */ + +/** + * Class implementation for unbuffered I/O for an interrupt driven application + * or one that needs to have more control. + */ +class MyUnbufferedSerial: + public SerialBase, + public FileHandle, + private NonCopyable<MyUnbufferedSerial> { +public: + /** + * Create a serial port instance connected to the specified transmit and + * receive pins, with the specified baud rate. + * + * @param tx Transmit pin + * @param rx Receive pin + * @param baud The baud rate of the serial port (optional, defaults to MBED_CONF_PLATFORM_DEFAULT_SERIAL_BAUD_RATE) + * + * @note + * Either tx or rx may be specified as NC if unused + */ + MyUnbufferedSerial( + PinName tx, + PinName rx, + int baud = MBED_CONF_PLATFORM_DEFAULT_SERIAL_BAUD_RATE + ); + + /** Create a MyUnbufferedSerial port, connected to the specified transmit and + * receive pins, with a particular baud rate. + * @param static_pinmap reference to structure which holds static pinmap + * @param baud The baud rate of the serial port (optional, defaults to + * MBED_CONF_PLATFORM_DEFAULT_SERIAL_BAUD_RATE) + */ + MyUnbufferedSerial( + const serial_pinmap_t &static_pinmap, + int baud = MBED_CONF_PLATFORM_DEFAULT_SERIAL_BAUD_RATE + ); + + /** Write the contents of a buffer to a file + * + * Blocks until all data is written + * + * @param buffer The buffer to write from + * @param size The number of bytes to write + * @return The number of bytes written + */ + ssize_t write(const void *buffer, size_t size) override; + + /** Read the contents of a file into a buffer + * + * Blocks and reads exactly one character + * + * @param buffer The buffer to read in to + * @param size The number of bytes to read + * @return The number of bytes read + */ + ssize_t read(void *buffer, size_t size) override; + + /** Move the file position to a given offset from from a given location + * + * Not valid for a device type FileHandle like MyUnbufferedSerial. + * In case of MyUnbufferedSerial, returns ESPIPE + * + * @param offset The offset from whence to move to + * @param whence The start of where to seek + * SEEK_SET to start from beginning of file, + * SEEK_CUR to start from current position in file, + * SEEK_END to start from end of file + * @return The new offset of the file, negative error code on failure + */ + off_t seek(off_t offset, int whence = SEEK_SET) override + { + return -ESPIPE; + } + + /** Get the size of the file + * + * @return Size of the file in bytes + */ + off_t size() override + { + return -EINVAL; + } + + /** Check if the file in an interactive terminal device + * + * @return True if the file is a terminal + * @return False if the file is not a terminal + * @return Negative error code on failure + */ + int isatty() override + { + return true; + } + + /** Close a file + * + * @return 0 on success, negative error code on failure + */ + int close() override + { + return 0; + } + + /** Enable or disable input + * + * Control enabling of device for input. This is primarily intended + * for temporary power-saving; the overall ability of the device to operate + * for input and/or output may be fixed at creation time, but this call can + * allow input to be temporarily disabled to permit power saving without + * losing device state. + * + * @param enabled true to enable input, false to disable. + * + * @return 0 on success + * @return Negative error code on failure + */ + int enable_input(bool enabled) override; + + /** Enable or disable output + * + * Control enabling of device for output. This is primarily intended + * for temporary power-saving; the overall ability of the device to operate + * for input and/or output may be fixed at creation time, but this call can + * allow output to be temporarily disabled to permit power saving without + * losing device state. + * + * @param enabled true to enable output, false to disable. + * + * @return 0 on success + * @return Negative error code on failure + */ + int enable_output(bool enabled) override; + + /** Check for poll event flags + * Check the events listed in events to see if data can be read or written + * without blocking. + * Call is nonblocking - returns state of events. + * + * @param events bitmask of poll events we're interested in - POLLIN/POLLOUT etc. + * + * @returns bitmask of poll events that have occurred. + */ + short poll(short events) const override; + + using SerialBase::attach; + using SerialBase::baud; + using SerialBase::format; + using SerialBase::readable; + using SerialBase::writeable; + using SerialBase::IrqCnt; + using SerialBase::RxIrq; + using SerialBase::TxIrq; + +#if DEVICE_SERIAL_FC + // For now use the base enum - but in future we may have extra options + // such as XON/XOFF or manual GPIO RTSCTS. + using SerialBase::Flow; + // In C++11, we wouldn't need to also have using directives for each value + using SerialBase::Disabled; + using SerialBase::RTS; + using SerialBase::CTS; + using SerialBase::RTSCTS; + + /** Set the flow control type on the serial port + * + * @param type the flow control type (Disabled, RTS, CTS, RTSCTS) + * @param flow1 the first flow control pin (RTS for RTS or RTSCTS, CTS for CTS) + * @param flow2 the second flow control pin (CTS for RTSCTS) + */ + void set_flow_control(Flow type, PinName flow1 = NC, PinName flow2 = NC); +#endif // DEVICE_SERIAL_FC +}; + +} // namespace mbed + +#endif // DEVICE_SERIAL || defined(DOXYGEN_ONLY) + +#endif // (MBED_MAJOR_VERSION >= 6 ) +#endif // MBED_MYUNBUFFERED_SERIAL_H
--- a/BufferedSerial.lib Thu Apr 19 14:03:33 2018 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -https://mbed.org/users/sam_grove/code/BufferedSerial/#a0d37088b405
--- a/NuMaker-mbed-SD-driver.lib Thu Apr 19 14:03:33 2018 +0800 +++ b/NuMaker-mbed-SD-driver.lib Tue Mar 02 10:09:10 2021 +0800 @@ -1,1 +1,1 @@ -https://github.com/OpenNuvoton/NuMaker-mbed-SD-driver/#7b763a96fa361da47a294efbe4bc201f7fb9c818 +https://github.com/OpenNuvoton/NuMaker-mbed-SD-driver/#8027c2c886a6bb2d850d3121ec3e2e179450e41c
--- a/main.cpp Thu Apr 19 14:03:33 2018 +0800 +++ b/main.cpp Tue Mar 02 10:09:10 2021 +0800 @@ -5,10 +5,9 @@ * * */ - #include "ste_config.h" -/* If define USE_STATIC_IP, specify the default IP address. */ +/* If choose static IP, specify the default IP address here. */ #if 0 // private IP address for general purpose #define IP_ADDRESS "192.168.1.2" @@ -16,25 +15,38 @@ #define GATEWAY_ADDRESS "192.168.1.1" #else // private IP address only for test with Windows when DHCP server doesn't exist. + // Windows set its LAN IP address to 169.254.xxx.xxx / 255.255.0.0 #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 */ +/* Default IP configuration for Ethernet 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 +#if defined (TARGET_NUMAKER_PFM_M487) || defined(TARGET_NUMAKER_IOT_M487) +#if MBED_MAJOR_VERSION <= 5 +BufferSerial serial_0(PB_3, PB_2, 256, 4); // UART1 +BufferSerial serial_1(PA_5, PA_4, 256, 4); // UART5 +//BufferSerial serial_2(PB_13, PB_12, 256, 4); // UART0, Debug +#else +BufferSerial serial_0(PB_3, PB_2); // UART1 +BufferSerial serial_1(PA_5, PA_4); // UART5 +//BufferSerial serial_2(PB_13, PB_12); // UART0, Debug +#endif #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 +#if MBED_MAJOR_VERSION <= 5 +BufferSerial serial_0(PH_1, PH_0, 256, 4); // UART4 +BufferSerial serial_1(PG_2, PG_1, 256, 4); // UART0 +BufferSerial serial_2(PC_11, PC_10, 256, 4); // UART2 +#else +BufferSerial serial_0(PH_1, PH_0); // UART4 +BufferSerial serial_1(PG_2, PG_1); // UART0 +BufferSerial serial_2(PC_11, PC_10); // UART2 +#endif -#elif defined (TARGET_NUMAKER_PFM_M453) +#elif defined (TARGET_NUMAKER_PFM_M453) || defined(TARGET_NUMAKER_PFM_NANO130) || defined(TARGET_NUMAKER_PFM_M2351) #error The board has no Ethernet. #else @@ -61,14 +73,12 @@ #endif }; -/* UART port to output debug message */ -RawSerial output(USBTX, USBRX); // UART3 on NuMaker-PFM-NUC472 EthernetInterface eth; -#ifdef ENABLE_WEB_CONFIG +#if ENABLE_WEB_CONFIG /* Declare the SD card as storage */ -NuSDBlockDevice bd; +NuSDBlockDevice *bd = new NuSDBlockDevice(); FATFileSystem fs("fs"); bool SD_Card_Mounted = FALSE; @@ -86,80 +96,92 @@ unsigned char s_buf[256]; int n_len = 0, n_index = 0; int s_len = 0, s_index = 0; + unsigned int eth_tx_count = 0; while(1) { /*** Network to Serial ***/ - if (n_len < 0 || n_len == n_index) + if (n_len == 0) { // 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) + if (n_len == 0) { + eth_tx_count += 3; + } + else if (n_len == NSAPI_ERROR_WOULD_BLOCK) + { + n_len = 0; } 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++) + n_index += pmap->pserial->write(n_buf+n_index, n_len-n_index); + if (n_index == n_len) { - pmap->pserial->putc(n_buf[n_index]); + n_len = 0; + n_index = 0; } } /*** Serial to Network ***/ - + + // try to get more data from serial port +#if MBED_MAJOR_VERSION <= 5 + for(; s_index < sizeof(s_buf) && pmap->pserial->readable(); s_index++) + s_buf[s_index] = pmap->pserial->getc(); +#else 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 = pmap->pserial->read(s_buf+s_index, sizeof(s_buf)-s_index); + if (s_len > 0) + s_index += s_len; + } +#endif + + if (s_index >= 240 || (s_index != 0 && ++eth_tx_count >= 5)) + { + 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) { - 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; - } + printf("Socket Send Err (%d)\r\n", s_len); + break; } - } + else // s_len >= s_index + { + unsigned int i; + + // move remain data if existed. + for(i=0; s_len < s_index; i++, s_len++) + s_buf[i] = s_buf[s_len]; + + s_index = i; + eth_tx_count = 0; + } + } } } - + void bridge_net_client(S_PORT_CONFIG *pmap) { TCPSocket socket; - SocketAddress server_address; + SocketAddress server_ipaddr; nsapi_error_t err; printf("Thread %x in TCP client mode.\r\n", (unsigned int)pmap); - if ((err=socket.open(ð)) < 0) + if ((err=socket.open(ð)) != NSAPI_ERROR_OK) { printf("TCP socket can't open (%d)(%x).\r\n", err, (unsigned int)pmap); return; @@ -168,31 +190,35 @@ 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) + server_ipaddr.set_ip_address(pmap->server_addr); + server_ipaddr.set_port(pmap->server_port); + if ((err=socket.connect(server_ipaddr)) >= 0) + { + printf("\r\nConnected."); break; + } } - printf("\r\nConnected."); - socket.set_timeout(1); exchange_data(pmap, &socket); + socket.close(); } void bridge_net_server(S_PORT_CONFIG *pmap) { - TCPServer tcp_server; - TCPSocket client_socket; - SocketAddress client_address; + TCPSocket tcp_server; + TCPSocket *client_socket; + SocketAddress client_ipaddr; nsapi_error_t err; printf("Thread %x in TCP server mode.\r\n", (unsigned int)pmap); - if ((err=tcp_server.open(ð)) < 0) + if ((err=tcp_server.open(ð)) != NSAPI_ERROR_OK) { 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) + if ((err=tcp_server.bind(pmap->port)) != NSAPI_ERROR_OK) { printf("TCP server can't bind address and port (%d)(%x).\r\n", err, (unsigned int)pmap); return; @@ -203,36 +229,46 @@ return; } - client_socket.set_timeout(1); - while(1) { - if ((err=tcp_server.accept(&client_socket, &client_address)) < 0) + client_socket = tcp_server.accept(&err); + if (err != NSAPI_ERROR_OK && err != NSAPI_ERROR_WOULD_BLOCK) { 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); + else + { + client_socket->getpeername(&client_ipaddr); + printf("Connect (%d) from %s:%d ...\r\n", pmap->port, client_ipaddr.get_ip_address(), client_ipaddr.get_port()); + + client_socket->set_timeout(1); + exchange_data(pmap, client_socket); + client_socket->close(); + } } } int main() { - /* Set the console baud-rate */ - output.baud(115200); - printf("\r\nmbed OS version is %d.\r\n", MBED_VERSION); + SocketAddress ip_addr; + SocketAddress ip_mask; + SocketAddress ip_gwaddr; + +#ifdef MBED_MAJOR_VERSION + printf("Mbed OS version %d.%d.%d\n\n", MBED_MAJOR_VERSION, MBED_MINOR_VERSION, MBED_PATCH_VERSION); +#endif printf("Start Serial-to-Ethernet...\r\n"); -#ifdef ENABLE_WEB_CONFIG +#if ENABLE_WEB_CONFIG /* Restore configuration from SD card */ - SD_Card_Mounted = (fs.mount(&bd) >= 0); + printf("Mounting SD card...\r\n"); + SD_Card_Mounted = (fs.mount(bd) == 0); if (SD_Card_Mounted) { + printf("SD card mounted. Read configuration file...\r\n"); FILE *fd = fopen(SER_CONFIG_FILE, "r"); if (fd != NULL) { @@ -276,6 +312,7 @@ #endif + /* Configure serial ports */ printf("Configure UART ports...\r\n"); for(int i=0; i<MAX_UART_PORTS; i++) { @@ -283,21 +320,27 @@ port_config[i].pserial->format(port_config[i].data, port_config[i].parity, port_config[i].stop); } + /* Configure network IP address */ 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); + + ip_addr.set_ip_address(net_config.ip); + ip_mask.set_ip_address(net_config.mask); + ip_gwaddr.set_ip_address(net_config.gateway); + ((NetworkInterface *)ð)->set_network(ip_addr, ip_mask, ip_gwaddr); } else printf("Start Ethernet in DHCP mode.\r\n"); eth.connect(); - printf("IP Address is %s\r\n", eth.get_ip_address()); - + eth.get_ip_address(&ip_addr); + printf("IP Address is %s\r\n", ip_addr.get_ip_address()); + Thread thread[MAX_UART_PORTS]; - // Folk thread for each port + /* Folk thread for each serial port */ for(int i=0; i<MAX_UART_PORTS; i++) { if (port_config[i].mode == NET_SERVER_MODE) @@ -310,7 +353,7 @@ } } -#ifdef ENABLE_WEB_CONFIG +#if ENABLE_WEB_CONFIG /*** main thread to be a web server for configuration ***/ start_httpd();
--- a/mbed-os.lib Thu Apr 19 14:03:33 2018 +0800 +++ b/mbed-os.lib Tue Mar 02 10:09:10 2021 +0800 @@ -1,1 +1,1 @@ -https://github.com/ARMmbed/mbed-os/#f9ee4e849f8cbd64f1ec5fdd4ad256585a208360 +https://github.com/ARMmbed/mbed-os/#b114a9c878519d6489ac3426697196bbea34c8ea
--- a/ste_config.h Thu Apr 19 14:03:33 2018 +0800 +++ b/ste_config.h Tue Mar 02 10:09:10 2021 +0800 @@ -10,37 +10,44 @@ #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. +#include "BufferSerial.h" + -/* Maximum UART ports supported */ +/* A simple web server for network and UART configuration + 0: Disable the web server. + 1: Enable the web server +*/ +#define ENABLE_WEB_CONFIG 1 + +/* Maximum UART ports supported. + Must define enough tuples of mapping table "port_config[]" in main.c +*/ #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. */ + 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 */ +/* Files in SD card to store settings via web configuration */ #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 */ +/* Maximum size of server domain name or address for web configuration */ #define MAX_SERVER_ADDRESS_SIZE 63 -/* Maximum size of IP address */ +/* Maximum size of IP address for web configuration */ #define MAX_IPV4_ADDRESS_SIZE 15 + /* Functions and global variables declaration. */ typedef enum { @@ -62,8 +69,8 @@ typedef struct { E_NetMode mode; // Network server or client mode - int port; // Network port number - BufferedSerial *pserial; // UART number + int port; // Network port number (Server mode) + BufferSerial *pserial; // UART number int baud; // UART baud int data; // UART data bits int stop; // UART stop bits @@ -72,7 +79,7 @@ unsigned short server_port; // Server port for TCP client mode } S_PORT_CONFIG; -extern RawSerial output; // for debug output +//extern RawSerial output; // for debug output extern EthernetInterface eth; extern S_PORT_CONFIG port_config[MAX_UART_PORTS]; extern S_NET_CONFIG net_config;
--- a/uweb_server.cpp Thu Apr 19 14:03:33 2018 +0800 +++ b/uweb_server.cpp Tue Mar 02 10:09:10 2021 +0800 @@ -5,11 +5,11 @@ * * */ - + #include <string.h> #include "ste_config.h" -#ifdef ENABLE_WEB_CONFIG +#if ENABLE_WEB_CONFIG #define PAGE_HEADER \ "<html><head>\r\n" \ @@ -408,10 +408,10 @@ send_web_body(socket, 4); printf("Restart system...\r\n"); - wait(1); // wait 1 second + ThisThread::sleep_for(1000); // wait 1 second // SYS_ResetCPU(); SYS_ResetChip(); - wait(100); + ThisThread::sleep_for(100000); } void process_http_resetconf_html(TCPSocket *socket, char *pbuf) @@ -497,16 +497,17 @@ void start_httpd(void) { - TCPServer http_server; - TCPSocket http_socket; + TCPSocket http_server; + TCPSocket *http_socket; SocketAddress http_address; + nsapi_error_t err_t; if (http_server.open(ð) < 0) { - printf("http server can't open.\r\n"); + printf("http server can't be created.\r\n"); return; } - if (http_server.bind(eth.get_ip_address(), 80) < 0) + if (http_server.bind(80) < 0) { printf("http server can't bind address and port.\r\n"); return; @@ -521,15 +522,17 @@ while(1) { - if (http_server.accept(&http_socket, &http_address) < 0) + http_socket = http_server.accept(&err_t); + if (err_t < 0) { printf("http server fail to accept connection.\r\n"); return; } + http_socket->getpeername(&http_address); printf("http from %s:%d ...\r\n", http_address.get_ip_address(), http_address.get_port()); - process_http_request(&http_socket); - http_socket.close(); + process_http_request(http_socket); + http_socket->close(); } }