Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Revision 1:32ac89dcd434, committed 2018-10-03
- Comitter:
- marcel1691
- Date:
- Wed Oct 03 14:07:46 2018 +0000
- Parent:
- 0:62e55edab701
- Commit message:
- ATParser doppelt
Changed in this revision
diff -r 62e55edab701 -r 32ac89dcd434 ATParser/ATParser.cpp --- a/ATParser/ATParser.cpp Wed Oct 03 14:03:01 2018 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,454 +0,0 @@ -/* Copyright (c) 2015 ARM Limited - * - * 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. - * - * @section DESCRIPTION - * - * Parser for the AT command syntax - * - */ - -#include "ATParser.h" -#include "mbed_debug.h" - -#ifdef LF -#undef LF -#define LF 10 -#else -#define LF 10 -#endif - -#ifdef CR -#undef CR -#define CR 13 -#else -#define CR 13 -#endif -#define MIN(a,b) (((a)<(b))?(a):(b)) - -// activate / de-activate debug -#define dbg_on 0 -#define AT_DATA_PRINT 0 -#define AT_COMMAND_PRINT 0 -#define AT_HEXA_DATA 0 - -ATParser::ATParser(BufferedSpi &serial_spi, const char *delimiter, int buffer_size, int timeout) : - _serial_spi(&serial_spi), - _buffer_size(buffer_size), _in_prev(0), _oobs(NULL) -{ - _buffer = new char[buffer_size]; - setTimeout(timeout); - setDelimiter(delimiter); -} - - -// getc/putc handling with timeouts -int ATParser::putc(char c) -{ - return _serial_spi->putc(c); -} - -int ATParser::getc() -{ - return _serial_spi->getc(); -} - -void ATParser::flush() -{ - _bufferMutex.lock(); - while (_serial_spi->readable()) { - _serial_spi->getc(); - } - _bufferMutex.unlock(); -} - -// read/write handling with timeouts -int ATParser::write(const char *data, int size_of_data, int size_in_buff) -{ - int i = 0; - _bufferMutex.lock(); - debug_if(dbg_on, "ATParser write: %d BYTES\r\n", size_of_data); - debug_if(AT_DATA_PRINT, "ATParser write: (ASCII) ", size_of_data); - for (; i < size_of_data; i++) { - debug_if(AT_DATA_PRINT, "%c", data[i]); - if (putc(data[i]) < 0) { - debug_if(AT_DATA_PRINT, "\r\n"); - _bufferMutex.unlock(); - return -1; - } - } - debug_if(AT_DATA_PRINT, "\r\n"); - - _serial_spi->buffsend(size_of_data + size_in_buff); - _bufferMutex.unlock(); - - return (size_of_data + size_in_buff); -} - -int ATParser::read(char *data) -{ - int readsize; - int i = 0; - - _bufferMutex.lock(); - - //this->flush(); - if (!_serial_spi->readable()) { - readsize = _serial_spi->read(); - } else { - debug_if(dbg_on, "Pending data when reading from WIFI\r\n"); - return -1; - } - - debug_if(dbg_on, "ATParser read: %d data avail in SPI\r\n", readsize); - - if (readsize < 0) { - _bufferMutex.unlock(); - return -1; - } - - for (i = 0 ; i < readsize; i++) { - int c = getc(); - if (c < 0) { - _bufferMutex.unlock(); - return -1; - } - data[i] = c; - } - -#if AT_HEXA_DATA - debug_if(AT_DATA_PRINT, "ATParser read: (HEXA) "); - for (i = 0; i < readsize; i++) { - debug_if(AT_DATA_PRINT, "%2X ", data[i]); - if ((i + 1) % 20 == 0) { - debug_if(AT_DATA_PRINT, "\r\n"); - } - } - debug_if(AT_DATA_PRINT, "\r\n"); -#endif - debug_if(AT_DATA_PRINT, "ATParser read: (ASCII) "); - for (i = 0; i < readsize; i++) { - debug_if(AT_DATA_PRINT, "%c", data[i]); - } - debug_if(AT_DATA_PRINT, "\r\n"); - - _bufferMutex.unlock(); - - return (readsize); -} - -// printf/scanf handling -int ATParser::vprintf(const char *format, va_list args) -{ - _bufferMutex.lock(); - if (vsprintf(_buffer, format, args) < 0) { - _bufferMutex.unlock(); - return false; - } - - int i = 0; - for (; _buffer[i]; i++) { - if (putc(_buffer[i]) < 0) { - _bufferMutex.unlock(); - return -1; - } - } - _bufferMutex.unlock(); - - return i; -} - -int ATParser::vscanf(const char *format, va_list args) -{ - // Since format is const, we need to copy it into our buffer to - // add the line's null terminator and clobber value-matches with asterisks. - // - // We just use the beginning of the buffer to avoid unnecessary allocations. - int i = 0; - int offset = 0; - - _bufferMutex.lock(); - - while (format[i]) { - if (format[i] == '%' && format[i + 1] != '%' && format[i + 1] != '*') { - _buffer[offset++] = '%'; - _buffer[offset++] = '*'; - i++; - } else { - _buffer[offset++] = format[i++]; - } - } - - // Scanf has very poor support for catching errors - // fortunately, we can abuse the %n specifier to determine - // if the entire string was matched. - _buffer[offset++] = '%'; - _buffer[offset++] = 'n'; - _buffer[offset++] = 0; - - // To workaround scanf's lack of error reporting, we actually - // make two passes. One checks the validity with the modified - // format string that only stores the matched characters (%n). - // The other reads in the actual matched values. - // - // We keep trying the match until we succeed or some other error - // derails us. - int j = 0; - - while (true) { - // Ran out of space - if (j + 1 >= _buffer_size - offset) { - _bufferMutex.unlock(); - return false; - } - // Recieve next character - int c = getc(); - if (c < 0) { - _bufferMutex.unlock(); - return -1; - } - _buffer[offset + j++] = c; - _buffer[offset + j] = 0; - - // Check for match - int count = -1; - sscanf(_buffer + offset, _buffer, &count); - - // We only succeed if all characters in the response are matched - if (count == j) { - // Store the found results - vsscanf(_buffer + offset, format, args); - _bufferMutex.unlock(); - return j; - } - } -} - - -// Command parsing with line handling -bool ATParser::vsend(const char *command, va_list args) -{ - int i = 0, j = 0; - _bufferMutex.lock(); - // Create and send command - if (vsprintf(_buffer, command, args) < 0) { - _bufferMutex.unlock(); - return false; - } - /* get buffer length */ - for (i = 0; _buffer[i]; i++) { - } - - for (j = 0; _delimiter[j]; j++) { - _buffer[i + j] = _delimiter[j]; - } - _buffer[i + j] = 0; // only to get a clean debug log - - bool ret = !(_serial_spi->buffwrite(_buffer, i + j) < 0); - - debug_if(AT_COMMAND_PRINT, "AT> %s\n", _buffer); - _bufferMutex.unlock(); - return ret; -} - -bool ATParser::vrecv(const char *response, va_list args) -{ - _bufferMutex.lock(); - - if (!_serial_spi->readable()) { - // debug_if(dbg_on, "NO DATA, read again\r\n"); - if (_serial_spi->read() < 0) { - return false; - } - } - // else { - // debug_if(dbg_on, "Pending data\r\n"); - // } - -restart: - _aborted = false; - // Iterate through each line in the expected response - while (response[0]) { - // Since response is const, we need to copy it into our buffer to - // add the line's null terminator and clobber value-matches with asterisks. - // - // We just use the beginning of the buffer to avoid unnecessary allocations. - int i = 0; - int offset = 0; - bool whole_line_wanted = false; - - while (response[i]) { - if (response[i] == '%' && response[i + 1] != '%' && response[i + 1] != '*') { - _buffer[offset++] = '%'; - _buffer[offset++] = '*'; - i++; - } else { - _buffer[offset++] = response[i++]; - // Find linebreaks, taking care not to be fooled if they're in a %[^\n] conversion specification - if (response[i - 1] == '\n' && !(i >= 3 && response[i - 3] == '[' && response[i - 2] == '^')) { - whole_line_wanted = true; - break; - } - } - } - - // Scanf has very poor support for catching errors - // fortunately, we can abuse the %n specifier to determine - // if the entire string was matched. - _buffer[offset++] = '%'; - _buffer[offset++] = 'n'; - _buffer[offset++] = 0; - - // debug_if(dbg_on, "ATParser vrecv: AT? ====%s====\n", _buffer); - // To workaround scanf's lack of error reporting, we actually - // make two passes. One checks the validity with the modified - // format string that only stores the matched characters (%n). - // The other reads in the actual matched values. - // - // We keep trying the match until we succeed or some other error - // derails us. - int j = 0; - - while (true) { - // Recieve next character - int c = getc(); - if (c < 0) { - debug_if(dbg_on, "AT(Timeout)\n"); - _bufferMutex.unlock(); - return false; - } - - // debug_if(AT_DATA_PRINT, "%2X ", c); - - _buffer[offset + j++] = c; - _buffer[offset + j] = 0; - - // Check for oob data - for (struct oob *oob = _oobs; oob; oob = oob->next) { - if ((unsigned)j == oob->len && memcmp( - oob->prefix, _buffer + offset, oob->len) == 0) { - debug_if(dbg_on, "AT! %s\n", oob->prefix); - oob->cb(); - - if (_aborted) { - debug_if(dbg_on, "AT(Aborted)\n"); - _bufferMutex.unlock(); - return false; - } - // oob may have corrupted non-reentrant buffer, - // so we need to set it up again - goto restart; - } - } - - // Check for match - int count = -1; - if (whole_line_wanted && c != '\n') { - // Don't attempt scanning until we get delimiter if they included it in format - // This allows recv("Foo: %s\n") to work, and not match with just the first character of a string - // (scanf does not itself match whitespace in its format string, so \n is not significant to it) - } else { - sscanf(_buffer + offset, _buffer, &count); - } - - // We only succeed if all characters in the response are matched - if (count == j) { - debug_if(AT_COMMAND_PRINT, "AT= ====%s====\n", _buffer + offset); - // Reuse the front end of the buffer - memcpy(_buffer, response, i); - _buffer[i] = 0; - - // Store the found results - vsscanf(_buffer + offset, _buffer, args); - - // Jump to next line and continue parsing - response += i; - break; - } - - // Clear the buffer when we hit a newline or ran out of space - // running out of space usually means we ran into binary data - if ((c == '\n')) { - // debug_if(dbg_on, "New line AT<<< %s", _buffer+offset); - j = 0; - } - if ((j + 1 >= (_buffer_size - offset))) { - - debug_if(dbg_on, "Out of space AT<<< %s, j=%d", _buffer + offset, j); - j = 0; - } - } - } - - _bufferMutex.unlock(); - - return true; -} - - -// Mapping to vararg functions -int ATParser::printf(const char *format, ...) -{ - va_list args; - va_start(args, format); - int res = vprintf(format, args); - va_end(args); - return res; -} - -int ATParser::scanf(const char *format, ...) -{ - va_list args; - va_start(args, format); - int res = vscanf(format, args); - va_end(args); - return res; -} - -bool ATParser::send(const char *command, ...) -{ - va_list args; - va_start(args, command); - bool res = vsend(command, args); - va_end(args); - return res; -} - -bool ATParser::recv(const char *response, ...) -{ - va_list args; - va_start(args, response); - bool res = vrecv(response, args); - va_end(args); - return res; -} - - -// oob registration -void ATParser::oob(const char *prefix, Callback<void()> cb) -{ - struct oob *oob = new struct oob; - oob->len = strlen(prefix); - oob->prefix = prefix; - oob->cb = cb; - oob->next = _oobs; - _oobs = oob; -} - -void ATParser::abort() -{ - _aborted = true; -} - - -
diff -r 62e55edab701 -r 32ac89dcd434 ATParser/ATParser.h --- a/ATParser/ATParser.h Wed Oct 03 14:03:01 2018 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,246 +0,0 @@ -/* Copyright (c) 2015 ARM Limited - * - * 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. - * - * @section DESCRIPTION - * - * Parser for the AT command syntax - * - */ -#ifndef AT_PARSER_H -#define AT_PARSER_H - -#include "mbed.h" -#include <cstdarg> -#include <vector> -#include "BufferedSpi.h" -#include "Callback.h" - -#define DEFAULT_SPI_TIMEOUT 60000 /* 1 minute */ - -/** -* Parser class for parsing AT commands -* -* Here are some examples: -* @code -* ATParser at = ATParser(serial, "\r\n"); -* int value; -* char buffer[100]; -* -* at.send("AT") && at.recv("OK"); -* at.send("AT+CWMODE=%d", 3) && at.recv("OK"); -* at.send("AT+CWMODE?") && at.recv("+CWMODE:%d\r\nOK", &value); -* at.recv("+IPD,%d:", &value); -* at.read(buffer, value); -* at.recv("OK"); -* @endcode -*/ -class ATParser { -private: - // Serial information - BufferedSpi *_serial_spi; - int _buffer_size; - char *_buffer; - Mutex _bufferMutex; - - // Parsing information - const char *_delimiter; - int _delim_size; - char _in_prev; - volatile bool _aborted; - - struct oob { - unsigned len; - const char *prefix; - mbed::Callback<void()> cb; - oob *next; - }; - oob *_oobs; - -public: - /** - * Constructor - * - * @param serial spi interface to use for AT commands - * @param buffer_size size of internal buffer for transaction - * @param timeout timeout of the connection - * @param delimiter string of characters to use as line delimiters - */ - ATParser(BufferedSpi &serial_spi, const char *delimiter = "\r\n", int buffer_size = 1440, int timeout = DEFAULT_SPI_TIMEOUT); - - /** - * Destructor - */ - ~ATParser() - { - while (_oobs) { - struct oob *oob = _oobs; - _oobs = oob->next; - delete oob; - } - delete[] _buffer; - } - - /** - * Allows timeout to be changed between commands - * - * @param timeout timeout of the connection - */ - void setTimeout(int timeout) - { - _serial_spi->setTimeout(timeout); - } - - /** - * Sets string of characters to use as line delimiters - * - * @param delimiter string of characters to use as line delimiters - */ - void setDelimiter(const char *delimiter) - { - _delimiter = delimiter; - _delim_size = strlen(delimiter); - } - - /** - * Sends an AT command - * - * Sends a formatted command using printf style formatting - * @see printf - * - * @param command printf-like format string of command to send which - * is appended with a newline - * @param ... all printf-like arguments to insert into command - * @return true only if command is successfully sent - */ - bool send(const char *command, ...); - - bool vsend(const char *command, va_list args); - - /** - * Receive an AT response - * - * Receives a formatted response using scanf style formatting - * @see scanf - * - * Responses are parsed line at a time. - * Any received data that does not match the response is ignored until - * a timeout occurs. - * - * @param response scanf-like format string of response to expect - * @param ... all scanf-like arguments to extract from response - * @return true only if response is successfully matched - */ - bool recv(const char *response, ...); - bool vrecv(const char *response, va_list args); - - - /** - * Write a single byte to the underlying stream - * - * @param c The byte to write - * @return The byte that was written or -1 during a timeout - */ - int putc(char c); - - /** - * Get a single byte from the underlying stream - * - * @return The byte that was read or -1 during a timeout - */ - int getc(); - - /** - * Write an array of bytes to the underlying stream - * assuming the header of the command is already in _txbuffer - * - * @param data the array of bytes to write - * @param size_of_data number of bytes in data array - * @param size_in_buff number of bytes already in the internal buff - * @return number of bytes written or -1 on failure - */ - int write(const char *data, int size_of_data, int size_in_buff); - - /** - * Read an array of bytes from the underlying stream - * - * @param data the destination for the read bytes - * @param size number of bytes to read - * @return number of bytes read or -1 on failure - */ - int read(char *data); - - /** - * Direct printf to underlying stream - * @see printf - * - * @param format format string to pass to printf - * @param ... arguments to printf - * @return number of bytes written or -1 on failure - */ - int printf(const char *format, ...); - int vprintf(const char *format, va_list args); - - /** - * Direct scanf on underlying stream - * @see ::scanf - * - * @param format format string to pass to scanf - * @param ... arguments to scanf - * @return number of bytes read or -1 on failure - */ - int scanf(const char *format, ...); - - int vscanf(const char *format, va_list args); - - /** - * Attach a callback for out-of-band data - * - * @param prefix string on when to initiate callback - * @param func callback to call when string is read - * @note out-of-band data is only processed during a scanf call - */ - void oob(const char *prefix, mbed::Callback<void()> func); - - /** - * Flushes the underlying stream - */ - void flush(); - - /** - * Abort current recv - * - * Can be called from oob handler to interrupt the current - * recv operation. - */ - void abort(); - - /** - * Process out-of-band data - * - * Process out-of-band data in the receive buffer. This function - * returns immediately if there is no data to process. - * - * @return true if oob data processed, false otherwise - */ - bool process_oob(void); - /** - * Get buffer_size - */ - int get_size(void) - { - return _buffer_size; - } - -}; -#endif
diff -r 62e55edab701 -r 32ac89dcd434 ATParser/BufferedSpi/Buffer/MyBuffer.cpp --- a/ATParser/BufferedSpi/Buffer/MyBuffer.cpp Wed Oct 03 14:03:01 2018 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,86 +0,0 @@ - -/** - * @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> -uint32_t MyBuffer<T>::getNbAvailable() -{ - if (_wloc >= _rloc) { - return (_wloc - _rloc); - } else { - return (_size - _rloc + _wloc); - } -} - -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>;
diff -r 62e55edab701 -r 32ac89dcd434 ATParser/BufferedSpi/Buffer/MyBuffer.h --- a/ATParser/BufferedSpi/Buffer/MyBuffer.h Wed Oct 03 14:03:01 2018 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,164 +0,0 @@ - -/** - * @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(); - uint32_t getNbAvailable(); - - /** 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; - //return 1; -} - -#endif -
diff -r 62e55edab701 -r 32ac89dcd434 ATParser/BufferedSpi/BufferedPrint.c --- a/ATParser/BufferedSpi/BufferedPrint.c Wed Oct 03 14:03:01 2018 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2014-2015 ARM Limited. All rights reserved. - * 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 <stdarg.h> -#include <stdint.h> -#include <stdio.h> -#include <string.h> - -#include "mbed_error.h" - -size_t BufferedSpiThunk(void *buf_serial, const void *s, size_t length); - -int BufferedPrintfC(void *stream, int size, const char* format, va_list arg) -{ - int r; - char buffer[512]; - if (size >= 512) { - return -1; - } - memset(buffer, 0, size); - r = vsprintf(buffer, format, arg); - // this may not hit the heap but should alert the user anyways - if(r > (int32_t) size) { - error("%s %d buffer overwrite (max_buf_size: %d exceeded: %d)!\r\n", __FILE__, __LINE__, size, r); - return 0; - } - if ( r > 0 ) { - BufferedSpiThunk(stream, buffer, r); - } - return r; -}
diff -r 62e55edab701 -r 32ac89dcd434 ATParser/BufferedSpi/BufferedSpi.cpp --- a/ATParser/BufferedSpi/BufferedSpi.cpp Wed Oct 03 14:03:01 2018 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,333 +0,0 @@ -/** - * @file BufferedSpi.cpp - * @brief Software Buffer - Extends mbed SPI functionallity - * @author Armelle Duboc - * @version 1.0 - * @see - * - * Copyright (c) STMicroelectronics 2017 - * - * 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 "BufferedSpi.h" -#include <stdarg.h> -#include "mbed_debug.h" -#include "mbed_error.h" - -// change to true to add few SPI debug lines -#define local_debug false - -extern "C" int BufferedPrintfC(void *stream, int size, const char *format, va_list arg); - -void BufferedSpi::DatareadyRising(void) -{ - if (_cmddata_rdy_rising_event == 1) { - _cmddata_rdy_rising_event = 0; - } -} - -int BufferedSpi::wait_cmddata_rdy_high(void) -{ - Timer timer; - timer.start(); - - /* wait for dataready = 1 */ - while (dataready.read() == 0) { - if (timer.read_ms() > _timeout) { - debug_if(local_debug, "ERROR: SPI write timeout\r\n"); - return -1; - } - } - - _cmddata_rdy_rising_event = 1; - - return 0; -} - -int BufferedSpi::wait_cmddata_rdy_rising_event(void) -{ - Timer timer; - timer.start(); - - while (_cmddata_rdy_rising_event == 1) { - if (timer.read_ms() > _timeout) { - _cmddata_rdy_rising_event = 0; - if (dataready.read() == 1) { - debug_if(local_debug, "ERROR: We missed rising event !! (timemout=%d)\r\n", _timeout); - } - debug_if(local_debug, "ERROR: SPI read timeout\r\n"); - return -1; - } - } - - return 0; -} - -BufferedSpi::BufferedSpi(PinName mosi, PinName miso, PinName sclk, PinName _nss, PinName _datareadypin, - uint32_t buf_size, uint32_t tx_multiple, const char *name) - : SPI(mosi, miso, sclk, NC), nss(_nss), _txbuf((uint32_t)(tx_multiple * buf_size)), _rxbuf(buf_size), dataready(_datareadypin) -{ - this->_buf_size = buf_size; - this->_tx_multiple = tx_multiple; - this->_sigio_event = 0; - - _datareadyInt = new InterruptIn(_datareadypin); - _datareadyInt->rise(callback(this, &BufferedSpi::DatareadyRising)); - - _cmddata_rdy_rising_event = 1; - - return; -} - -BufferedSpi::~BufferedSpi(void) -{ - - return; -} - -void BufferedSpi::frequency(int hz) -{ - SPI::frequency(hz); -} - -void BufferedSpi::format(int bits, int mode) -{ - SPI::format(bits, mode); -} - -void BufferedSpi::disable_nss() -{ - nss = 1; - wait_us(15); -} - -void BufferedSpi::enable_nss() -{ - nss = 0; - wait_us(15); -} - -int BufferedSpi::readable(void) -{ - return _rxbuf.available(); // note: look if things are in the buffer -} - -int BufferedSpi::writeable(void) -{ - return 1; // buffer allows overwriting by design, always true -} - -int BufferedSpi::getc(void) -{ - if (_rxbuf.available()) { - return _rxbuf; - } else { - return -1; - } -} - -int BufferedSpi::putc(int c) -{ - _txbuf = (char)c; - - return c; -} - -void BufferedSpi::flush_txbuf(void) -{ - _txbuf.clear(); -} - -int BufferedSpi::puts(const char *s) -{ - if (s != NULL) { - const char *ptr = s; - - while (*(ptr) != 0) { - _txbuf = *(ptr++); - } - _txbuf = '\n'; // done per puts definition - BufferedSpi::txIrq(); // only write to hardware in one place - return (ptr - s) + 1; - } - return 0; -} - -extern "C" size_t BufferedSpiThunk(void *buf_spi, const void *s, size_t length) -{ - BufferedSpi *buffered_spi = (BufferedSpi *)buf_spi; - return buffered_spi->buffwrite(s, length); -} - -int BufferedSpi::printf(const char *format, ...) -{ - va_list arg; - va_start(arg, format); - int r = BufferedPrintfC((void *)this, this->_buf_size, format, arg); - va_end(arg); - return r; -} - -ssize_t BufferedSpi::buffwrite(const void *s, size_t length) -{ - /* flush buffer from previous message */ - this->flush_txbuf(); - - if (wait_cmddata_rdy_high() < 0) { - debug_if(local_debug, "BufferedSpi::buffwrite timeout (%d)\r\n", _timeout); - return -1; - } - - this->enable_nss(); - - if (s != NULL && length > 0) { - /* 1st fill _txbuf */ - const char *ptr = (const char *)s; - const char *end = ptr + length; - - while (ptr != end) { - _txbuf = *(ptr++); - } - if (length & 1) { /* padding to send the last char */ - _txbuf = '\n'; - length++; - } - - /* 2nd write in SPI */ - BufferedSpi::txIrq(); // only write to hardware in one place - - this->disable_nss(); - return ptr - (const char *)s; - } - this->disable_nss(); - - return 0; -} - -ssize_t BufferedSpi::buffsend(size_t length) -{ - /* wait for dataready = 1 */ - if (wait_cmddata_rdy_high() < 0) { - debug_if(local_debug, "BufferedSpi::buffsend timeout (%d)\r\n", _timeout); - return -1; - } - - this->enable_nss(); - - /* _txbuffer is already filled with data to send */ - /* check if _txbuffer needs padding to send the last char */ - if (length & 1) { - _txbuf = '\n'; - length++; - } - BufferedSpi::txIrq(); // only write to hardware in one place - - this->disable_nss(); - - return length; -} - -ssize_t BufferedSpi::read() -{ - return this->read(0); -} - -ssize_t BufferedSpi::read(uint32_t max) -{ - uint32_t len = 0; - uint8_t FirstRemoved = 1; - int tmp; - - disable_nss(); - - /* wait for data ready is up */ - if (wait_cmddata_rdy_rising_event() != 0) { - debug_if(local_debug, "BufferedSpi::read timeout (%d)\r\n", _timeout); - return -1; - } - - enable_nss(); - while (dataready.read() == 1 && (len < (_buf_size - 2))) { - tmp = SPI::write(0xAA); // dummy write to receive 2 bytes - - if (!((len == 0) && (tmp == 0x0A0D) && (FirstRemoved))) { - /* do not take into account the 2 firts \r \n char in the buffer */ - if ((max == 0) || (len < max)) { - _rxbuf = (char)(tmp & 0x00FF); - _rxbuf = (char)((tmp >> 8) & 0xFF); - len += 2; - } - } else { - FirstRemoved = 0; - } - } - disable_nss(); - - if (len >= _buf_size) { - debug_if(local_debug, "firmware ERROR ES_WIFI_ERROR_STUFFING_FOREVER\r\n"); - return -1; - } - - debug_if(local_debug, "SPI READ %d BYTES\r\n", len); - - return len; -} - -void BufferedSpi::txIrq(void) -{ - /* write everything available in the _txbuffer */ - int value = 0; - int dbg_cnt = 0; - while (_txbuf.available() && (_txbuf.getNbAvailable() > 0)) { - value = _txbuf.get(); - if (_txbuf.available() && ((_txbuf.getNbAvailable() % 2) != 0)) { - value |= ((_txbuf.get() << 8) & 0XFF00); - SPI::write(value); - dbg_cnt++; - } - } - debug_if(local_debug, "SPI Sent %d BYTES\r\n", 2 * dbg_cnt); - // disable the TX interrupt when there is nothing left to send - BufferedSpi::attach(NULL, BufferedSpi::TxIrq); - // trigger callback if necessary - if (_cbs[TxIrq]) { - _cbs[TxIrq](); - } - return; -} - -void BufferedSpi::prime(void) -{ - BufferedSpi::txIrq(); // only write to hardware in one place - return; -} - -void BufferedSpi::attach(Callback<void()> func, IrqType type) -{ - _cbs[type] = func; -} - -void BufferedSpi::sigio(Callback<void()> func) -{ - core_util_critical_section_enter(); - _sigio_cb = func; - if (_sigio_cb) { - if (_sigio_event == 1) { - _sigio_cb(); - _sigio_event = 0; - } - } - core_util_critical_section_exit(); -} -
diff -r 62e55edab701 -r 32ac89dcd434 ATParser/BufferedSpi/BufferedSpi.h --- a/ATParser/BufferedSpi/BufferedSpi.h Wed Oct 03 14:03:01 2018 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,234 +0,0 @@ - -/** - * @file BufferedSpi.h - * @brief Software Buffer - Extends mbed SPI functionallity - * @author Armelle Duboc - * @version 1.0 - * @see - * - * Copyright (c) STMicroelectronics 2017 - * - * 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 BUFFEREDSPI_H -#define BUFFEREDSPI_H - -#include "mbed.h" -#include "MyBuffer.h" - -/** A spi port (SPI) for communication with wifi device - * - * Can be used for Full Duplex communication, or Simplex by specifying - * one pin as NC (Not Connected) - * - * Example: - * @code - * #include "mbed.h" - * #include "BufferedSerial.h" - * - * BufferedSerial pc(USBTX, USBRX); - * - * int main() - * { - * while(1) - * { - * Timer s; - * - * s.start(); - * pc.printf("Hello World - buffered\n"); - * int buffered_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 buffered took %d us\n", buffered_time); - * pc.printf("printf blocking took %d us\n", polled_time); - * wait(0.5f); - * } - * } - * @endcode - */ - -/** - * @class BufferedSpi - * @brief Software buffers and interrupt driven tx and rx for Serial - */ -class BufferedSpi : public SPI { -private: - DigitalOut nss; - MyBuffer <char> _txbuf; - uint32_t _buf_size; - uint32_t _tx_multiple; - volatile int _timeout; - void txIrq(void); - void prime(void); - - InterruptIn *_datareadyInt; - volatile int _cmddata_rdy_rising_event; - void DatareadyRising(void); - int wait_cmddata_rdy_rising_event(void); - int wait_cmddata_rdy_high(void); - - - Callback<void()> _cbs[2]; - - Callback<void()> _sigio_cb; - uint8_t _sigio_event; - -public: - MyBuffer <char> _rxbuf; - DigitalIn dataready; - enum IrqType { - RxIrq = 0, - TxIrq, - - IrqCnt - }; - - /** Create a BufferedSpi Port, connected to the specified transmit and receive pins - * @param SPI mosi pin - * @param SPI miso pin - * @param SPI sclk pin - * @param SPI nss pin - * @param Dataready 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 - */ - BufferedSpi(PinName mosi, PinName miso, PinName sclk, PinName nss, PinName datareadypin, uint32_t buf_size = 2500, uint32_t tx_multiple = 1, const char *name = NULL); - - /** Destroy a BufferedSpi Port - */ - virtual ~BufferedSpi(void); - - /** call to SPI frequency Function - */ - virtual void frequency(int hz); - - /** clear the transmit buffer - */ - virtual void flush_txbuf(void); - - /** call to SPI format function - */ - virtual void format(int bits, int mode); - - virtual void enable_nss(void); - - virtual void disable_nss(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 BufferedSpi Port. - * Should check readable() before calling this. - * @return A byte that came in on the SPI Port - */ - virtual int getc(void); - - /** Write a single byte to the BufferedSpi Port. - * @param c The byte to write to the SPI Port - * @return The byte that was written to the SPI Port Buffer - */ - virtual int putc(int c); - - /** Write a string to the BufferedSpi Port. Must be NULL terminated - * @param s The string to write to the Spi Port - * @return The number of bytes written to the Spi Port Buffer - */ - virtual int puts(const char *s); - - /** Write a formatted string to the BufferedSpi Port. - * @param format The string + format specifiers to write to the Spi Port - * @return The number of bytes written to the Spi Port Buffer - */ - virtual int printf(const char *format, ...); - - /** Write data to the Buffered Spi 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 Spi Port Buffer - */ - virtual ssize_t buffwrite(const void *s, std::size_t length); - - /** Send datas to the Spi port that are already present - * in the internal _txbuffer - * @param length - * @return the number of bytes written on the SPI port - */ - virtual ssize_t buffsend(size_t length); - - /** Read data from the Spi Port to the _rxbuf - * @param max: optional. = max sieze of the input read - * @return The number of bytes read from the SPI port and written to the _rxbuf - */ - virtual ssize_t read(); - virtual ssize_t read(uint32_t max); - - /** - * Allows timeout to be changed between commands - * - * @param timeout timeout of the connection in ms - */ - void setTimeout(int timeout) - { - /* this is a safe guard timeout at SPI level in case module is stuck */ - _timeout = timeout; - } - - /** Register a callback once any data is ready for sockets - * @param func Function to call on state change - */ - virtual void sigio(Callback<void()> func); - - /** Attach a function to call whenever a serial interrupt is generated - * @param func A pointer to a void function, or 0 to set as none - * @param type Which serial interrupt to attach the member function to (Serial::RxIrq for receive, TxIrq for transmit buffer empty) - */ - virtual void attach(Callback<void()> func, IrqType type = RxIrq); - - /** Attach a member function to call whenever a serial interrupt is generated - * @param obj pointer to the object to call the member function on - * @param method pointer to the member function to call - * @param type Which serial interrupt to attach the member function to (Serial::RxIrq for receive, TxIrq for transmit buffer empty) - */ - template <typename T> - void attach(T *obj, void (T::*method)(), IrqType type = RxIrq) - { - attach(Callback<void()>(obj, method), type); - } - - /** Attach a member function to call whenever a serial interrupt is generated - * @param obj pointer to the object to call the member function on - * @param method pointer to the member function to call - * @param type Which serial interrupt to attach the member function to (Serial::RxIrq for receive, TxIrq for transmit buffer empty) - */ - template <typename T> - void attach(T *obj, void (*method)(T *), IrqType type = RxIrq) - { - attach(Callback<void()>(obj, method), type); - } -}; -#endif