Generic Pelion Device Management example for various Advantech modules.

This example is known to work great on the following platforms:

Example Functionality

This example showcases the following device functionality:

  • On timer button increment, simulate Pelion LWM2M button resource change

Use this example with Mbed CLI

1. Import the application into your desktop:

mbed import https://os.mbed.com/teams/Advantech/code/pelion-example-common
cd pelion-example-common

2. Download your developer certificate from pelion portal

3. Compile the program

mbed compile -t <toolchain> -m <TARGET_BOARD>

(supported toolchains : GCC_ARM / ARM / IAR)

4. Copy the binary file pelion-example-common.bin to your mbed device.

Committer:
chuanga
Date:
Tue Mar 12 13:48:39 2019 +0800
Revision:
0:43ff9e3bc244
copying sources from github repository

Who changed what in which revision?

UserRevisionLine numberNew contents of line
chuanga 0:43ff9e3bc244 1 /**
chuanga 0:43ff9e3bc244 2 * @file BufferedSpi.cpp
chuanga 0:43ff9e3bc244 3 * @brief Software Buffer - Extends mbed SPI functionallity
chuanga 0:43ff9e3bc244 4 * @author Armelle Duboc
chuanga 0:43ff9e3bc244 5 * @version 1.0
chuanga 0:43ff9e3bc244 6 * @see
chuanga 0:43ff9e3bc244 7 *
chuanga 0:43ff9e3bc244 8 * Copyright (c) STMicroelectronics 2017
chuanga 0:43ff9e3bc244 9 *
chuanga 0:43ff9e3bc244 10 * Licensed under the Apache License, Version 2.0 (the "License");
chuanga 0:43ff9e3bc244 11 * you may not use this file except in compliance with the License.
chuanga 0:43ff9e3bc244 12 * You may obtain a copy of the License at
chuanga 0:43ff9e3bc244 13 *
chuanga 0:43ff9e3bc244 14 * http://www.apache.org/licenses/LICENSE-2.0
chuanga 0:43ff9e3bc244 15 *
chuanga 0:43ff9e3bc244 16 * Unless required by applicable law or agreed to in writing, software
chuanga 0:43ff9e3bc244 17 * distributed under the License is distributed on an "AS IS" BASIS,
chuanga 0:43ff9e3bc244 18 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
chuanga 0:43ff9e3bc244 19 * See the License for the specific language governing permissions and
chuanga 0:43ff9e3bc244 20 * limitations under the License.
chuanga 0:43ff9e3bc244 21 */
chuanga 0:43ff9e3bc244 22
chuanga 0:43ff9e3bc244 23 #include "BufferedSpi.h"
chuanga 0:43ff9e3bc244 24 #include <stdarg.h>
chuanga 0:43ff9e3bc244 25 #include "mbed_debug.h"
chuanga 0:43ff9e3bc244 26 #include "mbed_error.h"
chuanga 0:43ff9e3bc244 27
chuanga 0:43ff9e3bc244 28 // change to true to add few SPI debug lines
chuanga 0:43ff9e3bc244 29 #define local_debug false
chuanga 0:43ff9e3bc244 30
chuanga 0:43ff9e3bc244 31 extern "C" int BufferedPrintfC(void *stream, int size, const char *format, va_list arg);
chuanga 0:43ff9e3bc244 32
chuanga 0:43ff9e3bc244 33 void BufferedSpi::DatareadyRising(void)
chuanga 0:43ff9e3bc244 34 {
chuanga 0:43ff9e3bc244 35 if (_cmddata_rdy_rising_event == 1) {
chuanga 0:43ff9e3bc244 36 _cmddata_rdy_rising_event = 0;
chuanga 0:43ff9e3bc244 37 }
chuanga 0:43ff9e3bc244 38 }
chuanga 0:43ff9e3bc244 39
chuanga 0:43ff9e3bc244 40 int BufferedSpi::wait_cmddata_rdy_high(void)
chuanga 0:43ff9e3bc244 41 {
chuanga 0:43ff9e3bc244 42 Timer timer;
chuanga 0:43ff9e3bc244 43 timer.start();
chuanga 0:43ff9e3bc244 44
chuanga 0:43ff9e3bc244 45 /* wait for dataready = 1 */
chuanga 0:43ff9e3bc244 46 while (dataready.read() == 0) {
chuanga 0:43ff9e3bc244 47 if (timer.read_ms() > _timeout) {
chuanga 0:43ff9e3bc244 48 debug_if(local_debug, "ERROR: SPI write timeout\r\n");
chuanga 0:43ff9e3bc244 49 return -1;
chuanga 0:43ff9e3bc244 50 }
chuanga 0:43ff9e3bc244 51 }
chuanga 0:43ff9e3bc244 52
chuanga 0:43ff9e3bc244 53 _cmddata_rdy_rising_event = 1;
chuanga 0:43ff9e3bc244 54
chuanga 0:43ff9e3bc244 55 return 0;
chuanga 0:43ff9e3bc244 56 }
chuanga 0:43ff9e3bc244 57
chuanga 0:43ff9e3bc244 58 int BufferedSpi::wait_cmddata_rdy_rising_event(void)
chuanga 0:43ff9e3bc244 59 {
chuanga 0:43ff9e3bc244 60 Timer timer;
chuanga 0:43ff9e3bc244 61 timer.start();
chuanga 0:43ff9e3bc244 62
chuanga 0:43ff9e3bc244 63 while (_cmddata_rdy_rising_event == 1) {
chuanga 0:43ff9e3bc244 64 if (timer.read_ms() > _timeout) {
chuanga 0:43ff9e3bc244 65 _cmddata_rdy_rising_event = 0;
chuanga 0:43ff9e3bc244 66 if (dataready.read() == 1) {
chuanga 0:43ff9e3bc244 67 debug_if(local_debug, "ERROR: We missed rising event !! (timemout=%d)\r\n", _timeout);
chuanga 0:43ff9e3bc244 68 }
chuanga 0:43ff9e3bc244 69 debug_if(local_debug, "ERROR: SPI read timeout\r\n");
chuanga 0:43ff9e3bc244 70 return -1;
chuanga 0:43ff9e3bc244 71 }
chuanga 0:43ff9e3bc244 72 }
chuanga 0:43ff9e3bc244 73
chuanga 0:43ff9e3bc244 74 return 0;
chuanga 0:43ff9e3bc244 75 }
chuanga 0:43ff9e3bc244 76
chuanga 0:43ff9e3bc244 77 BufferedSpi::BufferedSpi(PinName mosi, PinName miso, PinName sclk, PinName _nss, PinName _datareadypin,
chuanga 0:43ff9e3bc244 78 uint32_t buf_size, uint32_t tx_multiple, const char *name)
chuanga 0:43ff9e3bc244 79 : SPI(mosi, miso, sclk, NC), nss(_nss), _txbuf((uint32_t)(tx_multiple * buf_size)), _rxbuf(buf_size), dataready(_datareadypin)
chuanga 0:43ff9e3bc244 80 {
chuanga 0:43ff9e3bc244 81 this->_buf_size = buf_size;
chuanga 0:43ff9e3bc244 82 this->_tx_multiple = tx_multiple;
chuanga 0:43ff9e3bc244 83 this->_sigio_event = 0;
chuanga 0:43ff9e3bc244 84
chuanga 0:43ff9e3bc244 85 _datareadyInt = new InterruptIn(_datareadypin);
chuanga 0:43ff9e3bc244 86 _datareadyInt->rise(callback(this, &BufferedSpi::DatareadyRising));
chuanga 0:43ff9e3bc244 87
chuanga 0:43ff9e3bc244 88 _cmddata_rdy_rising_event = 1;
chuanga 0:43ff9e3bc244 89 nss = 1;
chuanga 0:43ff9e3bc244 90 wait_us(15);
chuanga 0:43ff9e3bc244 91
chuanga 0:43ff9e3bc244 92 return;
chuanga 0:43ff9e3bc244 93 }
chuanga 0:43ff9e3bc244 94
chuanga 0:43ff9e3bc244 95 BufferedSpi::~BufferedSpi(void)
chuanga 0:43ff9e3bc244 96 {
chuanga 0:43ff9e3bc244 97
chuanga 0:43ff9e3bc244 98 return;
chuanga 0:43ff9e3bc244 99 }
chuanga 0:43ff9e3bc244 100
chuanga 0:43ff9e3bc244 101 void BufferedSpi::frequency(int hz)
chuanga 0:43ff9e3bc244 102 {
chuanga 0:43ff9e3bc244 103 SPI::frequency(hz);
chuanga 0:43ff9e3bc244 104 }
chuanga 0:43ff9e3bc244 105
chuanga 0:43ff9e3bc244 106 void BufferedSpi::format(int bits, int mode)
chuanga 0:43ff9e3bc244 107 {
chuanga 0:43ff9e3bc244 108 SPI::format(bits, mode);
chuanga 0:43ff9e3bc244 109 }
chuanga 0:43ff9e3bc244 110
chuanga 0:43ff9e3bc244 111 void BufferedSpi::disable_nss()
chuanga 0:43ff9e3bc244 112 {
chuanga 0:43ff9e3bc244 113 nss = 1;
chuanga 0:43ff9e3bc244 114 wait_us(15);
chuanga 0:43ff9e3bc244 115 unlock();
chuanga 0:43ff9e3bc244 116 }
chuanga 0:43ff9e3bc244 117
chuanga 0:43ff9e3bc244 118 void BufferedSpi::enable_nss()
chuanga 0:43ff9e3bc244 119 {
chuanga 0:43ff9e3bc244 120 lock();
chuanga 0:43ff9e3bc244 121 nss = 0;
chuanga 0:43ff9e3bc244 122 wait_us(15);
chuanga 0:43ff9e3bc244 123 }
chuanga 0:43ff9e3bc244 124
chuanga 0:43ff9e3bc244 125 int BufferedSpi::readable(void)
chuanga 0:43ff9e3bc244 126 {
chuanga 0:43ff9e3bc244 127 return _rxbuf.available(); // note: look if things are in the buffer
chuanga 0:43ff9e3bc244 128 }
chuanga 0:43ff9e3bc244 129
chuanga 0:43ff9e3bc244 130 int BufferedSpi::writeable(void)
chuanga 0:43ff9e3bc244 131 {
chuanga 0:43ff9e3bc244 132 return 1; // buffer allows overwriting by design, always true
chuanga 0:43ff9e3bc244 133 }
chuanga 0:43ff9e3bc244 134
chuanga 0:43ff9e3bc244 135 int BufferedSpi::getc(void)
chuanga 0:43ff9e3bc244 136 {
chuanga 0:43ff9e3bc244 137 if (_rxbuf.available()) {
chuanga 0:43ff9e3bc244 138 return _rxbuf;
chuanga 0:43ff9e3bc244 139 } else {
chuanga 0:43ff9e3bc244 140 return -1;
chuanga 0:43ff9e3bc244 141 }
chuanga 0:43ff9e3bc244 142 }
chuanga 0:43ff9e3bc244 143
chuanga 0:43ff9e3bc244 144 int BufferedSpi::putc(int c)
chuanga 0:43ff9e3bc244 145 {
chuanga 0:43ff9e3bc244 146 _txbuf = (char)c;
chuanga 0:43ff9e3bc244 147
chuanga 0:43ff9e3bc244 148 return c;
chuanga 0:43ff9e3bc244 149 }
chuanga 0:43ff9e3bc244 150
chuanga 0:43ff9e3bc244 151 void BufferedSpi::flush_txbuf(void)
chuanga 0:43ff9e3bc244 152 {
chuanga 0:43ff9e3bc244 153 _txbuf.clear();
chuanga 0:43ff9e3bc244 154 }
chuanga 0:43ff9e3bc244 155
chuanga 0:43ff9e3bc244 156 int BufferedSpi::puts(const char *s)
chuanga 0:43ff9e3bc244 157 {
chuanga 0:43ff9e3bc244 158 if (s != NULL) {
chuanga 0:43ff9e3bc244 159 const char *ptr = s;
chuanga 0:43ff9e3bc244 160
chuanga 0:43ff9e3bc244 161 while (*(ptr) != 0) {
chuanga 0:43ff9e3bc244 162 _txbuf = *(ptr++);
chuanga 0:43ff9e3bc244 163 }
chuanga 0:43ff9e3bc244 164 _txbuf = '\n'; // done per puts definition
chuanga 0:43ff9e3bc244 165 BufferedSpi::txIrq(); // only write to hardware in one place
chuanga 0:43ff9e3bc244 166 return (ptr - s) + 1;
chuanga 0:43ff9e3bc244 167 }
chuanga 0:43ff9e3bc244 168 return 0;
chuanga 0:43ff9e3bc244 169 }
chuanga 0:43ff9e3bc244 170
chuanga 0:43ff9e3bc244 171 extern "C" size_t BufferedSpiThunk(void *buf_spi, const void *s, size_t length)
chuanga 0:43ff9e3bc244 172 {
chuanga 0:43ff9e3bc244 173 BufferedSpi *buffered_spi = (BufferedSpi *)buf_spi;
chuanga 0:43ff9e3bc244 174 return buffered_spi->buffwrite(s, length);
chuanga 0:43ff9e3bc244 175 }
chuanga 0:43ff9e3bc244 176
chuanga 0:43ff9e3bc244 177 int BufferedSpi::printf(const char *format, ...)
chuanga 0:43ff9e3bc244 178 {
chuanga 0:43ff9e3bc244 179 va_list arg;
chuanga 0:43ff9e3bc244 180 va_start(arg, format);
chuanga 0:43ff9e3bc244 181 int r = BufferedPrintfC((void *)this, this->_buf_size, format, arg);
chuanga 0:43ff9e3bc244 182 va_end(arg);
chuanga 0:43ff9e3bc244 183 return r;
chuanga 0:43ff9e3bc244 184 }
chuanga 0:43ff9e3bc244 185
chuanga 0:43ff9e3bc244 186 ssize_t BufferedSpi::buffwrite(const void *s, size_t length)
chuanga 0:43ff9e3bc244 187 {
chuanga 0:43ff9e3bc244 188 /* flush buffer from previous message */
chuanga 0:43ff9e3bc244 189 this->flush_txbuf();
chuanga 0:43ff9e3bc244 190
chuanga 0:43ff9e3bc244 191 if (wait_cmddata_rdy_high() < 0) {
chuanga 0:43ff9e3bc244 192 debug_if(local_debug, "BufferedSpi::buffwrite timeout (%d)\r\n", _timeout);
chuanga 0:43ff9e3bc244 193 return -1;
chuanga 0:43ff9e3bc244 194 }
chuanga 0:43ff9e3bc244 195
chuanga 0:43ff9e3bc244 196 this->enable_nss();
chuanga 0:43ff9e3bc244 197
chuanga 0:43ff9e3bc244 198 if (s != NULL && length > 0) {
chuanga 0:43ff9e3bc244 199 /* 1st fill _txbuf */
chuanga 0:43ff9e3bc244 200 const char *ptr = (const char *)s;
chuanga 0:43ff9e3bc244 201 const char *end = ptr + length;
chuanga 0:43ff9e3bc244 202
chuanga 0:43ff9e3bc244 203 while (ptr != end) {
chuanga 0:43ff9e3bc244 204 _txbuf = *(ptr++);
chuanga 0:43ff9e3bc244 205 }
chuanga 0:43ff9e3bc244 206 if (length & 1) { /* padding to send the last char */
chuanga 0:43ff9e3bc244 207 _txbuf = '\n';
chuanga 0:43ff9e3bc244 208 length++;
chuanga 0:43ff9e3bc244 209 }
chuanga 0:43ff9e3bc244 210
chuanga 0:43ff9e3bc244 211 /* 2nd write in SPI */
chuanga 0:43ff9e3bc244 212 BufferedSpi::txIrq(); // only write to hardware in one place
chuanga 0:43ff9e3bc244 213
chuanga 0:43ff9e3bc244 214 this->disable_nss();
chuanga 0:43ff9e3bc244 215 return ptr - (const char *)s;
chuanga 0:43ff9e3bc244 216 }
chuanga 0:43ff9e3bc244 217 this->disable_nss();
chuanga 0:43ff9e3bc244 218
chuanga 0:43ff9e3bc244 219 return 0;
chuanga 0:43ff9e3bc244 220 }
chuanga 0:43ff9e3bc244 221
chuanga 0:43ff9e3bc244 222 ssize_t BufferedSpi::buffsend(size_t length)
chuanga 0:43ff9e3bc244 223 {
chuanga 0:43ff9e3bc244 224 /* wait for dataready = 1 */
chuanga 0:43ff9e3bc244 225 if (wait_cmddata_rdy_high() < 0) {
chuanga 0:43ff9e3bc244 226 debug_if(local_debug, "BufferedSpi::buffsend timeout (%d)\r\n", _timeout);
chuanga 0:43ff9e3bc244 227 return -1;
chuanga 0:43ff9e3bc244 228 }
chuanga 0:43ff9e3bc244 229
chuanga 0:43ff9e3bc244 230 this->enable_nss();
chuanga 0:43ff9e3bc244 231
chuanga 0:43ff9e3bc244 232 /* _txbuffer is already filled with data to send */
chuanga 0:43ff9e3bc244 233 /* check if _txbuffer needs padding to send the last char */
chuanga 0:43ff9e3bc244 234 if (length & 1) {
chuanga 0:43ff9e3bc244 235 _txbuf = '\n';
chuanga 0:43ff9e3bc244 236 length++;
chuanga 0:43ff9e3bc244 237 }
chuanga 0:43ff9e3bc244 238 BufferedSpi::txIrq(); // only write to hardware in one place
chuanga 0:43ff9e3bc244 239
chuanga 0:43ff9e3bc244 240 this->disable_nss();
chuanga 0:43ff9e3bc244 241
chuanga 0:43ff9e3bc244 242 return length;
chuanga 0:43ff9e3bc244 243 }
chuanga 0:43ff9e3bc244 244
chuanga 0:43ff9e3bc244 245 ssize_t BufferedSpi::read()
chuanga 0:43ff9e3bc244 246 {
chuanga 0:43ff9e3bc244 247 return this->read(0);
chuanga 0:43ff9e3bc244 248 }
chuanga 0:43ff9e3bc244 249
chuanga 0:43ff9e3bc244 250 ssize_t BufferedSpi::read(uint32_t max)
chuanga 0:43ff9e3bc244 251 {
chuanga 0:43ff9e3bc244 252 uint32_t len = 0;
chuanga 0:43ff9e3bc244 253 uint8_t FirstRemoved = 1;
chuanga 0:43ff9e3bc244 254 int tmp;
chuanga 0:43ff9e3bc244 255
chuanga 0:43ff9e3bc244 256 /* wait for data ready is up */
chuanga 0:43ff9e3bc244 257 if (wait_cmddata_rdy_rising_event() != 0) {
chuanga 0:43ff9e3bc244 258 debug_if(local_debug, "BufferedSpi::read timeout (%d)\r\n", _timeout);
chuanga 0:43ff9e3bc244 259 return -1;
chuanga 0:43ff9e3bc244 260 }
chuanga 0:43ff9e3bc244 261
chuanga 0:43ff9e3bc244 262 enable_nss();
chuanga 0:43ff9e3bc244 263 while (dataready.read() == 1 && (len < (_buf_size - 2))) {
chuanga 0:43ff9e3bc244 264 tmp = SPI::write(0xAA); // dummy write to receive 2 bytes
chuanga 0:43ff9e3bc244 265
chuanga 0:43ff9e3bc244 266 if (!((len == 0) && (tmp == 0x0A0D) && (FirstRemoved))) {
chuanga 0:43ff9e3bc244 267 /* do not take into account the 2 firts \r \n char in the buffer */
chuanga 0:43ff9e3bc244 268 if ((max == 0) || (len < max)) {
chuanga 0:43ff9e3bc244 269 _rxbuf = (char)(tmp & 0x00FF);
chuanga 0:43ff9e3bc244 270 _rxbuf = (char)((tmp >> 8) & 0xFF);
chuanga 0:43ff9e3bc244 271 len += 2;
chuanga 0:43ff9e3bc244 272 }
chuanga 0:43ff9e3bc244 273 } else {
chuanga 0:43ff9e3bc244 274 FirstRemoved = 0;
chuanga 0:43ff9e3bc244 275 }
chuanga 0:43ff9e3bc244 276 }
chuanga 0:43ff9e3bc244 277 disable_nss();
chuanga 0:43ff9e3bc244 278
chuanga 0:43ff9e3bc244 279 if (len >= _buf_size) {
chuanga 0:43ff9e3bc244 280 debug_if(local_debug, "firmware ERROR ES_WIFI_ERROR_STUFFING_FOREVER\r\n");
chuanga 0:43ff9e3bc244 281 return -1;
chuanga 0:43ff9e3bc244 282 }
chuanga 0:43ff9e3bc244 283
chuanga 0:43ff9e3bc244 284 debug_if(local_debug, "SPI READ %d BYTES\r\n", len);
chuanga 0:43ff9e3bc244 285
chuanga 0:43ff9e3bc244 286 return len;
chuanga 0:43ff9e3bc244 287 }
chuanga 0:43ff9e3bc244 288
chuanga 0:43ff9e3bc244 289 void BufferedSpi::txIrq(void)
chuanga 0:43ff9e3bc244 290 {
chuanga 0:43ff9e3bc244 291 /* write everything available in the _txbuffer */
chuanga 0:43ff9e3bc244 292 int value = 0;
chuanga 0:43ff9e3bc244 293 int dbg_cnt = 0;
chuanga 0:43ff9e3bc244 294 while (_txbuf.available() && (_txbuf.getNbAvailable() > 0)) {
chuanga 0:43ff9e3bc244 295 value = _txbuf.get();
chuanga 0:43ff9e3bc244 296 if (_txbuf.available() && ((_txbuf.getNbAvailable() % 2) != 0)) {
chuanga 0:43ff9e3bc244 297 value |= ((_txbuf.get() << 8) & 0XFF00);
chuanga 0:43ff9e3bc244 298 SPI::write(value);
chuanga 0:43ff9e3bc244 299 dbg_cnt++;
chuanga 0:43ff9e3bc244 300 }
chuanga 0:43ff9e3bc244 301 }
chuanga 0:43ff9e3bc244 302 debug_if(local_debug, "SPI Sent %d BYTES\r\n", 2 * dbg_cnt);
chuanga 0:43ff9e3bc244 303 // disable the TX interrupt when there is nothing left to send
chuanga 0:43ff9e3bc244 304 BufferedSpi::attach(NULL, BufferedSpi::TxIrq);
chuanga 0:43ff9e3bc244 305 // trigger callback if necessary
chuanga 0:43ff9e3bc244 306 if (_cbs[TxIrq]) {
chuanga 0:43ff9e3bc244 307 _cbs[TxIrq]();
chuanga 0:43ff9e3bc244 308 }
chuanga 0:43ff9e3bc244 309 return;
chuanga 0:43ff9e3bc244 310 }
chuanga 0:43ff9e3bc244 311
chuanga 0:43ff9e3bc244 312 void BufferedSpi::prime(void)
chuanga 0:43ff9e3bc244 313 {
chuanga 0:43ff9e3bc244 314 BufferedSpi::txIrq(); // only write to hardware in one place
chuanga 0:43ff9e3bc244 315 return;
chuanga 0:43ff9e3bc244 316 }
chuanga 0:43ff9e3bc244 317
chuanga 0:43ff9e3bc244 318 void BufferedSpi::attach(Callback<void()> func, IrqType type)
chuanga 0:43ff9e3bc244 319 {
chuanga 0:43ff9e3bc244 320 _cbs[type] = func;
chuanga 0:43ff9e3bc244 321 }
chuanga 0:43ff9e3bc244 322
chuanga 0:43ff9e3bc244 323 void BufferedSpi::sigio(Callback<void()> func)
chuanga 0:43ff9e3bc244 324 {
chuanga 0:43ff9e3bc244 325 core_util_critical_section_enter();
chuanga 0:43ff9e3bc244 326 _sigio_cb = func;
chuanga 0:43ff9e3bc244 327 if (_sigio_cb) {
chuanga 0:43ff9e3bc244 328 if (_sigio_event == 1) {
chuanga 0:43ff9e3bc244 329 _sigio_cb();
chuanga 0:43ff9e3bc244 330 _sigio_event = 0;
chuanga 0:43ff9e3bc244 331 }
chuanga 0:43ff9e3bc244 332 }
chuanga 0:43ff9e3bc244 333 core_util_critical_section_exit();
chuanga 0:43ff9e3bc244 334 }
chuanga 0:43ff9e3bc244 335