Skip to content

Cellular: added setting of data carrier support for UART. #8971

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
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,6 @@ set(unittest-test-sources
stubs/randLIB_stub.cpp
stubs/Semaphore_stub.cpp
stubs/us_ticker_stub.cpp
stubs/UARTSerial_stub.cpp
stubs/SerialBase_stub.cpp
)
8 changes: 8 additions & 0 deletions UNITTESTS/stubs/AT_CellularContext_stub.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,14 @@ AT_CellularContext::~AT_CellularContext()
{
}

void AT_CellularContext::set_file_handle(UARTSerial *serial, PinName dcd_pin, bool active_high)
{
}

void AT_CellularContext::enable_hup(bool enable)
{
}

void AT_CellularContext::set_file_handle(FileHandle *fh)
{
}
Expand Down
7 changes: 6 additions & 1 deletion UNITTESTS/stubs/AT_CellularDevice_stub.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,12 @@ void AT_CellularDevice::release_at_handler(ATHandler *at_handler)
{
}

CellularContext *create_context(FileHandle *fh = NULL, const char *apn = MBED_CONF_NSAPI_DEFAULT_CELLULAR_APN)
CellularContext *AT_CellularDevice::create_context(UARTSerial *serial, const char *const apn, PinName dcd_pin,
bool active_high)
{
}

CellularContext *create_context(FileHandle *fh, const char *apn)
{
}

Expand Down
6 changes: 6 additions & 0 deletions UNITTESTS/target_h/myCellularDevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,12 @@ class myCellularDevice : public CellularDevice {
return NSAPI_ERROR_OK;
}

virtual CellularContext *create_context(UARTSerial *serial, const char *const apn, PinName dcd_pin,
bool active_high)
{
return NULL;
}

virtual CellularContext *create_context(FileHandle *fh = NULL, const char *apn = NULL)
{
EventQueue que;
Expand Down
21 changes: 20 additions & 1 deletion features/cellular/framework/API/CellularContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,6 @@ class CellularContext : public CellularBase {
// friend of CellularDevice so that it's the only way to close/delete this class.
friend class CellularDevice;
virtual ~CellularContext() {}

public: // from NetworkInterface
virtual nsapi_error_t set_blocking(bool blocking) = 0;
virtual NetworkStack *get_stack() = 0;
Expand Down Expand Up @@ -211,6 +210,15 @@ class CellularContext : public CellularBase {
*/
virtual void set_file_handle(FileHandle *fh) = 0;

/** Set the UART serial used to communicate with the modem. Can be used to change default file handle.
* File handle set with this method will use data carrier detect to be able to detect disconnection much faster in PPP mode.
*
* @param serial UARTSerial used in communication to modem. If null then the default file handle is used.
* @param dcd_pin Pin used to set data carrier detect on/off for the given UART
* @param active_high a boolean set to true if DCD polarity is active low
*/
virtual void set_file_handle(UARTSerial *serial, PinName dcd_pin = NC, bool active_high = false) = 0;

protected: // Device specific implementations might need these so protected
enum ContextOperation {
OP_INVALID = -1,
Expand All @@ -230,6 +238,15 @@ class CellularContext : public CellularBase {
*/
virtual void cellular_callback(nsapi_event_t ev, intptr_t ptr) = 0;

/** Enable or disable hang-up detection
*
* When in PPP data pump mode, it is helpful if the FileHandle will signal hang-up via
* POLLHUP, e.g., if the DCD line is deasserted on a UART. During command mode, this
* signaling is not desired. enable_hup() controls whether this function should be
* active.
*/
virtual void enable_hup(bool enable) = 0;

// member variables needed in target override methods
NetworkStack *_stack; // must be pointer because of PPP
nsapi_ip_stack_t _ip_stack_type;
Expand All @@ -244,6 +261,8 @@ class CellularContext : public CellularBase {
const char *_apn;
const char *_uname;
const char *_pwd;
PinName _dcd_pin;
bool _active_high;
};

} // namespace mbed
Expand Down
23 changes: 22 additions & 1 deletion features/cellular/framework/API/CellularDevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "CellularTargets.h"
#include "CellularStateMachine.h"
#include "Callback.h"
#include "UARTSerial.h"

namespace mbed {

Expand All @@ -29,7 +30,6 @@ class CellularSMS;
class CellularInformation;
class CellularNetwork;
class CellularContext;
class FileHandle;

const int MAX_PIN_SIZE = 8;
const int MAX_PLMN_SIZE = 16;
Expand Down Expand Up @@ -96,6 +96,21 @@ class CellularDevice {
*/
virtual CellularContext *create_context(FileHandle *fh = NULL, const char *apn = NULL) = 0;

/** Creates a new CellularContext interface. This API should be used if serial is UART and PPP mode used.
* CellularContext created will use data carrier detect to be able to detect disconnection much faster in PPP mode.
* UARTSerial usually is the same which was given for the CellularDevice.
*
* @param serial UARTSerial used in communication to modem. If null then the default file handle is used.
* @param apn access point to use with context, can be null.
* @param dcd_pin Pin used to set data carrier detect on/off for the given UART
* @param active_high a boolean set to true if DCD polarity is active low
*
* @return new instance of class CellularContext or NULL in case of failure
*
*/
virtual CellularContext *create_context(UARTSerial *serial, const char *apn, PinName dcd_pin = NC,
Copy link
Contributor

Choose a reason for hiding this comment

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

This and the other declaration should also still have the = NULL default on apn I assume?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yep, added.

bool active_high = false) = 0;

/** Deletes the given CellularContext instance
*
* @param context CellularContext to delete
Expand All @@ -107,6 +122,12 @@ class CellularDevice {
*/
void stop();

/** Get the current FileHandle item used when communicating with the modem.
*
* @return reference to FileHandle
*/
FileHandle &get_file_handle() const;

/** Get event queue that can be chained to main event queue.
* @return event queue
*/
Expand Down
4 changes: 4 additions & 0 deletions features/cellular/framework/AT/ATHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,10 @@ void ATHandler::set_file_handle(FileHandle *fh)
void ATHandler::set_is_filehandle_usable(bool usable)
{
_is_fh_usable = usable;
if (usable) {
// set file handle sigio and blocking mode back
set_file_handle(_fileHandle);
}
}

nsapi_error_t ATHandler::set_urc_handler(const char *prefix, mbed::Callback<void()> callback)
Expand Down
56 changes: 44 additions & 12 deletions features/cellular/framework/AT/AT_CellularContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,13 @@ AT_CellularContext::AT_CellularContext(ATHandler &at, CellularDevice *device, co
_cid = -1;
_new_context_set = false;
_next = NULL;
_dcd_pin = NC;
_active_high = false;
}

AT_CellularContext::~AT_CellularContext()
{
tr_info("Delete CellularContext %s (%p)", _apn ? _apn : "", this);
tr_info("Delete CellularContext with apn: [%s] (%p)", _apn ? _apn : "", this);

(void)disconnect();

Expand All @@ -79,6 +81,23 @@ void AT_CellularContext::set_file_handle(FileHandle *fh)
_at.set_file_handle(_fh);
}

void AT_CellularContext::set_file_handle(UARTSerial *serial, PinName dcd_pin, bool active_high)
{
tr_info("CellularContext serial %p", serial);
_dcd_pin = dcd_pin;
_active_high = active_high;
_fh = serial;
_at.set_file_handle(static_cast<FileHandle *>(serial));
enable_hup(false);
Copy link
Contributor

Choose a reason for hiding this comment

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

I'd be inclined to call set_file_handle(static_cast<FileHandle *>(serial)) here too for consistency of logic with the create_context, even though it doesn't really save anything.

And hey, if you do that explicit upcast in two places it becomes a recognisable pattern!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fixed

Copy link
Contributor

Choose a reason for hiding this comment

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

No, I meant call AT_CellularContext::set_file_handle(FileHandle *)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Do'h, I need to sleep more :) Fixed.

}

void AT_CellularContext::enable_hup(bool enable)
{
if (_dcd_pin != NC) {
static_cast<UARTSerial *>(_fh)->set_data_carrier_detect(enable ? _dcd_pin : NC, _active_high);
}
}

nsapi_error_t AT_CellularContext::connect()
{
tr_info("CellularContext connect");
Expand Down Expand Up @@ -592,18 +611,25 @@ nsapi_error_t AT_CellularContext::open_data_channel()
}

_at.set_is_filehandle_usable(false);

enable_hup(true);
/* Initialize PPP
* If blocking: mbed_ppp_init() is a blocking call, it will block until
connected, or timeout after 30 seconds*/
return nsapi_ppp_connect(_at.get_file_handle(), callback(this, &AT_CellularContext::ppp_status_cb), _uname, _pwd, _ip_stack_type);
nsapi_error_t err = nsapi_ppp_connect(_at.get_file_handle(), callback(this, &AT_CellularContext::ppp_status_cb), _uname, _pwd, _ip_stack_type);
if (err) {
ppp_disconnected();
}

return err;
}

void AT_CellularContext::ppp_status_cb(nsapi_event_t ev, intptr_t ptr)
{
tr_debug("ppp_status_cb: event %d, ptr %d", ev, ptr);
if (ev == NSAPI_EVENT_CONNECTION_STATUS_CHANGE && ptr == NSAPI_STATUS_GLOBAL_UP) {
_is_connected = true;
} else if (ev == NSAPI_EVENT_CONNECTION_STATUS_CHANGE && ptr == NSAPI_STATUS_DISCONNECTED) {
ppp_disconnected();
} else {
_is_connected = false;
}
Expand All @@ -614,6 +640,20 @@ void AT_CellularContext::ppp_status_cb(nsapi_event_t ev, intptr_t ptr)
_device->cellular_callback(ev, ptr);
}

void AT_CellularContext::ppp_disconnected()
{
enable_hup(false);

// after ppp disconnect if we wan't to use same at handler we need to set filehandle again to athandler so it
// will set the correct sigio and nonblocking
_at.lock();
_at.set_is_filehandle_usable(true);
if (!_at.sync(AT_SYNC_TIMEOUT)) { // consume extra characters after ppp disconnect, also it may take a while until modem listens AT commands
tr_error("AT sync failed after PPP Disconnect");
}
_at.unlock();
}

#endif //#if NSAPI_PPP_AVAILABLE

nsapi_error_t AT_CellularContext::disconnect()
Expand All @@ -628,15 +668,7 @@ nsapi_error_t AT_CellularContext::disconnect()
tr_error("CellularContext disconnect failed!");
// continue even in failure due to ppp disconnect in any case releases filehandle
}
// after ppp disconnect if we wan't to use same at handler we need to set filehandle again to athandler so it
// will set the correct sigio and nonblocking
_at.lock();
_at.set_file_handle(_at.get_file_handle());
_at.set_is_filehandle_usable(true);
if (!_at.sync(AT_SYNC_TIMEOUT)) { // consume extra characters after ppp disconnect, also it may take a while until modem listens AT commands
tr_error("AT sync failed after PPP Disconnect");
}
_at.unlock();
ppp_disconnected();
#endif // NSAPI_PPP_AVAILABLE
_at.lock();

Expand Down
3 changes: 3 additions & 0 deletions features/cellular/framework/AT/AT_CellularContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ class AT_CellularContext : public CellularContext, public AT_CellularBase {
virtual nsapi_error_t register_to_network();
virtual nsapi_error_t attach_to_network();
virtual void set_file_handle(FileHandle *fh);
virtual void set_file_handle(UARTSerial *serial, PinName dcd_pin = NC, bool active_high = false);
virtual void enable_hup(bool enable);

protected:
virtual void cellular_callback(nsapi_event_t ev, intptr_t ptr);
Expand Down Expand Up @@ -99,6 +101,7 @@ class AT_CellularContext : public CellularContext, public AT_CellularBase {
#if NSAPI_PPP_AVAILABLE
nsapi_error_t open_data_channel();
void ppp_status_cb(nsapi_event_t ev, intptr_t ptr);
void ppp_disconnected();
#endif // #if NSAPI_PPP_AVAILABLE
nsapi_error_t do_activate_context();
bool set_new_context(int cid);
Expand Down
11 changes: 11 additions & 0 deletions features/cellular/framework/AT/AT_CellularDevice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,17 @@ CellularContext *AT_CellularDevice::get_context_list() const
return _context_list;
}

CellularContext *AT_CellularDevice::create_context(UARTSerial *serial, const char *const apn, PinName dcd_pin,
bool active_high)
{
// Call FileHandle base version - explict upcast to avoid recursing into ourselves
CellularContext *ctx = create_context(static_cast<FileHandle *>(serial), apn);
if (serial) {
ctx->set_file_handle(serial, dcd_pin, active_high);
}
return ctx;
}

CellularContext *AT_CellularDevice::create_context(FileHandle *fh, const char *apn)
{
ATHandler *atHandler = get_at_handler(fh);
Expand Down
2 changes: 2 additions & 0 deletions features/cellular/framework/AT/AT_CellularDevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ class AT_CellularDevice : public CellularDevice {

virtual CellularContext *create_context(FileHandle *fh = NULL, const char *apn = NULL);

virtual CellularContext *create_context(UARTSerial *serial, const char *const apn, PinName dcd_pin = NC, bool active_high = false);

virtual void delete_context(CellularContext *context);

virtual CellularNetwork *open_network(FileHandle *fh = NULL);
Expand Down
3 changes: 3 additions & 0 deletions features/cellular/framework/device/CellularContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ MBED_WEAK CellularContext *CellularContext::get_default_instance()
return NULL;
}
static CellularContext *context = dev->create_context();
#if defined(MDMDCD) && defined(MDM_PIN_POLARITY)
context->set_file_handle(static_cast<UARTSerial *>(&dev->get_file_handle()), MDMDCD, MDM_PIN_POLARITY);
#endif // #if defined(MDMDCD) && defined(MDM_PIN_POLARITY)
return context;
}
#else
Expand Down
7 changes: 6 additions & 1 deletion features/cellular/framework/device/CellularDevice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
#include "CellularLog.h"
#include "CellularTargets.h"
#include "EventQueue.h"
#include "UARTSerial.h"

#ifdef CELLULAR_DEVICE
#include CELLULAR_STRINGIFY(CELLULAR_DEVICE.h)
Expand Down Expand Up @@ -52,6 +51,7 @@ MBED_WEAK CellularDevice *CellularDevice::get_default_instance()
CellularDevice::CellularDevice(FileHandle *fh) : _network_ref_count(0), _sms_ref_count(0), _power_ref_count(0),
_info_ref_count(0), _fh(fh), _queue(5 * EVENTS_EVENT_SIZE), _state_machine(0), _nw(0), _status_cb(0)
{
MBED_ASSERT(fh);
set_sim_pin(NULL);
set_plmn(NULL);
}
Expand All @@ -66,6 +66,11 @@ void CellularDevice::stop()
_state_machine->stop();
}

FileHandle &CellularDevice::get_file_handle() const
{
return *_fh;
}

events::EventQueue *CellularDevice::get_queue()
{
return &_queue;
Expand Down