-
Notifications
You must be signed in to change notification settings - Fork 3k
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
Cellular feature br #4119
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 fb7cbdf
Tighten mbed_retarget.cpp error handling
kjbracey b2408d8
Extending FileHandle & introducing mbed_poll
09ae609
Stream class should use mbed::fdopen() to attach a stream
2790d44
Introducing a BufferedSerial
4a04c9c
Extending ATParser to use FileHandle
ea117e5
Memory Optimizations and simplifications in ATParser
7f136d5
PPP Interface for LWIP using FileHandle stream
kjbracey d0820d1
Cope with different LWIP configurations
kjbracey f37f265
Add more LWIP JSON configuration, including PPP
kjbracey ae7fd61
RAM optimizations
kjbracey be00c17
Separate LWIP core and Ethernet interface initialisation
kjbracey 091396d
Adding mbed_trace to ppp_lwip
2abb078
Adding PPP link status callback
7e3c529
Unify LWIP Ethernet and PPP initialisation
kjbracey 87a4580
Bug fixes & state machine corrections
93f436e
Using DCD line to invoke poll() HUP
3b44f47
Adding support for APN lookup
f602c93
Redirecting LWIP debug trace to mbed-trace
0108864
Finalizing the public API for Cellular
658ddf7
ARMCC link errors fixed, nsapi_ppp glue layer changed
925f54b
Heap size reduced to 64k for IAR
fcbcfaf
Preparing grounds for modem api
ccbf005
Introducing hal/modem_api.h
1afc7bf
A Reference CellularInterface driver
c65f81b
Remove sigio implementation from FileHandle
c8933e4
Removing _poll_change() for now
b51fbe8
mbedtls md5 or lwip internal crypt Fudge
24de27c
Major Refactoring & extensions
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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() | ||
{ | ||
return SerialBase::readable(); | ||
} | ||
bool writable() | ||
{ | ||
return SerialBase::writeable(); | ||
} | ||
bool writeable() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should be deprecated There was a problem hiding this comment. Choose a reason for hiding this commentThe 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); | ||
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
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 restxxxable
also? Filehandle defines it as suchThere was a problem hiding this comment.
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.There was a problem hiding this comment.
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-functioningbool 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.
There was a problem hiding this comment.
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 *
orconst 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.
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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).