Skip to content

Cellular feature br #4119

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 29 commits into from
Jun 1, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
533910c
Correct return type of FileHandle::size()
kjbracey Mar 28, 2017
fb7cbdf
Tighten mbed_retarget.cpp error handling
kjbracey Mar 28, 2017
b2408d8
Extending FileHandle & introducing mbed_poll
Feb 15, 2017
09ae609
Stream class should use mbed::fdopen() to attach a stream
Feb 16, 2017
2790d44
Introducing a BufferedSerial
Feb 15, 2017
4a04c9c
Extending ATParser to use FileHandle
Feb 15, 2017
ea117e5
Memory Optimizations and simplifications in ATParser
Feb 16, 2017
7f136d5
PPP Interface for LWIP using FileHandle stream
kjbracey Feb 16, 2017
d0820d1
Cope with different LWIP configurations
kjbracey Feb 16, 2017
f37f265
Add more LWIP JSON configuration, including PPP
kjbracey Feb 16, 2017
ae7fd61
RAM optimizations
kjbracey Feb 16, 2017
be00c17
Separate LWIP core and Ethernet interface initialisation
kjbracey Feb 16, 2017
091396d
Adding mbed_trace to ppp_lwip
Feb 15, 2017
2abb078
Adding PPP link status callback
Feb 15, 2017
7e3c529
Unify LWIP Ethernet and PPP initialisation
kjbracey Feb 17, 2017
87a4580
Bug fixes & state machine corrections
Feb 22, 2017
93f436e
Using DCD line to invoke poll() HUP
Feb 22, 2017
3b44f47
Adding support for APN lookup
Feb 16, 2017
f602c93
Redirecting LWIP debug trace to mbed-trace
Mar 13, 2017
0108864
Finalizing the public API for Cellular
Mar 13, 2017
658ddf7
ARMCC link errors fixed, nsapi_ppp glue layer changed
Mar 14, 2017
925f54b
Heap size reduced to 64k for IAR
Apr 6, 2017
fcbcfaf
Preparing grounds for modem api
May 1, 2017
ccbf005
Introducing hal/modem_api.h
Apr 28, 2017
1afc7bf
A Reference CellularInterface driver
Apr 28, 2017
c65f81b
Remove sigio implementation from FileHandle
May 8, 2017
c8933e4
Removing _poll_change() for now
May 10, 2017
b51fbe8
mbedtls md5 or lwip internal crypt Fudge
May 16, 2017
24de27c
Major Refactoring & extensions
May 23, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions drivers/RawSerial.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,10 @@
*/
#include "drivers/RawSerial.h"
#include "platform/mbed_wait_api.h"
#include <stdio.h>
#include <cstdarg>


#if DEVICE_SERIAL

#define STRING_STACK_LIMIT 120
Expand Down
17 changes: 17 additions & 0 deletions drivers/Serial.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,23 @@ class Serial : public SerialBase, public Stream {
*/
Serial(PinName tx, PinName rx, int baud);

/* Stream gives us a FileHandle with non-functional poll()/readable()/writable. Pass through
* the calls from the SerialBase instead for backwards compatibility. This problem is
* part of why Stream and Serial should be deprecated.
*/
bool readable()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should be bool readable() const , and the rest xxxable also? Filehandle defines it as such

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Quite right. Will need a const_cast because SerialBase lacks a const.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, no, that doesn't really work out.

The issue here is that SerialBase has int readable() and Stream has non-functioning bool readable() const.

Attempting to call readable() on a Serial would cause an ambiguity error. Adding any definition of readable in Serial, whether const or not, shadows both of those, solving the ambiguity. As we are passing through to SerialBase's non-const method, then Serial's readable is non-const.

SerialBase's readable is non-const because it calls lock() - I see consensus that built-in locks can be mutable, but not on constness of lock methods in combined function+lock objects. Because overriding lock() is part of SerialBase's API, I don't think it could be easily changed anyway.

I don't particularly fancy the const_cast, and there is no need for this to be const to shadow FileHandle::readable() as intended.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In practice, I think const-correctness on these sort of device objects doesn't serve that much purpose anyway - no-one is ever going to be passing around const FileHandle * or const Serial * pointers. There's basically nothing you could do with such a pointer apart from check readability...

I put in the consts when adding those new methods to FileHandle, because why not, but I don't see any pressing reason to try to retrofit const to all the device objects. Serial's readable and writable are currently non-const, via SerialBase, and this preserves that.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @kjbracey-arm for the explanation

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Possibly should be returning int for backwards compatibility though? This does change Serial::readable() to return bool. Although I struggle to think of anything that would break, we are trying to avoid changing the things we're deprecating (Serial and Stream).

{
return SerialBase::readable();
}
bool writable()
{
return SerialBase::writeable();
}
bool writeable()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be deprecated

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This whole class should be deprecated. But this is beyond this PR.

{
return SerialBase::writeable();
}

protected:
virtual int _getc();
virtual int _putc(int c);
Expand Down
1 change: 0 additions & 1 deletion drivers/SerialBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@

#if defined (DEVICE_SERIAL) || defined(DOXYGEN_ONLY)

#include "Stream.h"
#include "Callback.h"
#include "serial_api.h"
#include "mbed_toolchain.h"
Expand Down
265 changes: 265 additions & 0 deletions drivers/UARTSerial.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,265 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2017 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.
*/

#if DEVICE_SERIAL

#include <errno.h>
#include "UARTSerial.h"
#include "platform/mbed_poll.h"
#include "platform/mbed_wait_api.h"

namespace mbed {

UARTSerial::UARTSerial(PinName tx, PinName rx, int baud) :
SerialBase(tx, rx, baud),
_blocking(true),
_tx_irq_enabled(false),
_dcd_irq(NULL)
{
/* Attatch IRQ routines to the serial device. */
SerialBase::attach(callback(this, &UARTSerial::rx_irq), RxIrq);
}

UARTSerial::~UARTSerial()
{
delete _dcd_irq;
}

void UARTSerial::dcd_irq()
{
wake();
}

void UARTSerial::set_data_carrier_detect(PinName dcd_pin, bool active_high)
{
delete _dcd_irq;
_dcd_irq = NULL;

if (dcd_pin != NC) {
_dcd_irq = new InterruptIn(dcd_pin);
if (active_high) {
_dcd_irq->fall(callback(this, &UARTSerial::dcd_irq));
} else {
_dcd_irq->rise(callback(this, &UARTSerial::dcd_irq));
}
}
}

int UARTSerial::close()
{
/* Does not let us pass a file descriptor. So how to close ?
* Also, does it make sense to close a device type file descriptor*/
return 0;
}

int UARTSerial::isatty()
{
return 1;

}

off_t UARTSerial::seek(off_t offset, int whence)
{
/*XXX lseek can be done theoratically, but is it sane to mark positions on a dynamically growing/shrinking
* buffer system (from an interrupt context) */
return -ESPIPE;
}

int UARTSerial::sync()
{
lock();

while (!_txbuf.empty()) {
unlock();
// Doing better than wait would require TxIRQ to also do wake() when becoming empty. Worth it?
wait_ms(1);
lock();
}

unlock();

return 0;
}

void UARTSerial::sigio(Callback<void()> func) {
core_util_critical_section_enter();
_sigio_cb = func;
if (_sigio_cb) {
short current_events = poll(0x7FFF);
if (current_events) {
_sigio_cb();
}
}
core_util_critical_section_exit();
}

ssize_t UARTSerial::write(const void* buffer, size_t length)
{
size_t data_written = 0;
const char *buf_ptr = static_cast<const char *>(buffer);

lock();

while (_txbuf.full()) {
if (!_blocking) {
unlock();
return -EAGAIN;
}
unlock();
wait_ms(1); // XXX todo - proper wait, WFE for non-rtos ?
lock();
}

while (data_written < length && !_txbuf.full()) {
_txbuf.push(*buf_ptr++);
data_written++;
}

core_util_critical_section_enter();
if (!_tx_irq_enabled) {
UARTSerial::tx_irq(); // only write to hardware in one place
if (!_txbuf.empty()) {
SerialBase::attach(callback(this, &UARTSerial::tx_irq), TxIrq);
_tx_irq_enabled = true;
}
}
core_util_critical_section_exit();

unlock();

return data_written;
}

ssize_t UARTSerial::read(void* buffer, size_t length)
{
size_t data_read = 0;

char *ptr = static_cast<char *>(buffer);

lock();

while (_rxbuf.empty()) {
if (!_blocking) {
unlock();
return -EAGAIN;
}
unlock();
wait_ms(1); // XXX todo - proper wait, WFE for non-rtos ?
lock();
}

while (data_read < length && !_rxbuf.empty()) {
_rxbuf.pop(*ptr++);
data_read++;
}

unlock();

return data_read;
}

bool UARTSerial::hup() const
{
return _dcd_irq && _dcd_irq->read() != 0;
}

void UARTSerial::wake()
{
if (_sigio_cb) {
_sigio_cb();
}
}

short UARTSerial::poll(short events) const {

short revents = 0;
/* Check the Circular Buffer if space available for writing out */


if (!_rxbuf.empty()) {
revents |= POLLIN;
}

/* POLLHUP and POLLOUT are mutually exclusive */
if (hup()) {
revents |= POLLHUP;
} else if (!_txbuf.full()) {
revents |= POLLOUT;
}

/*TODO Handle other event types */

return revents;
}

void UARTSerial::lock(void)
{
_mutex.lock();
}

void UARTSerial::unlock(void)
{
_mutex.unlock();
}

void UARTSerial::rx_irq(void)
{
bool was_empty = _rxbuf.empty();

/* Fill in the receive buffer if the peripheral is readable
* and receive buffer is not full. */
while (SerialBase::readable()) {
char data = SerialBase::_base_getc();
if (!_rxbuf.full()) {
_rxbuf.push(data);
} else {
/* Drop - can we report in some way? */
}
}

/* Report the File handler that data is ready to be read from the buffer. */
if (was_empty && !_rxbuf.empty()) {
wake();
}
}

// Also called from write to start transfer
void UARTSerial::tx_irq(void)
{
bool was_full = _txbuf.full();

/* Write to the peripheral if there is something to write
* and if the peripheral is available to write. */
while (!_txbuf.empty() && SerialBase::writeable()) {
char data;
_txbuf.pop(data);
SerialBase::_base_putc(data);
}

if (_tx_irq_enabled && _txbuf.empty()) {
SerialBase::attach(NULL, TxIrq);
_tx_irq_enabled = false;
}

/* Report the File handler that data can be written to peripheral. */
if (was_full && !_txbuf.full() && !hup()) {
wake();
}
}

} //namespace mbed

#endif //DEVICE_SERIAL
Loading