mirror of https://github.com/ARMmbed/mbed-os.git
Merge pull request #10924 from ghseb/free-serial-resources-2
Free serial resources if not needed anymorepull/11775/head
commit
2203549b37
|
@ -19,7 +19,8 @@
|
||||||
|
|
||||||
namespace mbed {
|
namespace mbed {
|
||||||
|
|
||||||
SerialBase::SerialBase(PinName tx, PinName rx, int baud)
|
SerialBase::SerialBase(PinName tx, PinName rx, int baud) :
|
||||||
|
_tx_pin(tx), _rx_pin(rx)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -155,6 +155,30 @@ public:
|
||||||
*/
|
*/
|
||||||
void send_break();
|
void send_break();
|
||||||
|
|
||||||
|
/** Enable serial input
|
||||||
|
*
|
||||||
|
* If both serial input and serial output are disabled, the
|
||||||
|
* peripheral is freed. If either serial input or serial
|
||||||
|
* output is re-enabled, the peripheral is reinitialized.
|
||||||
|
*
|
||||||
|
* On re-initialization rx interrupts will be enabled if a
|
||||||
|
* rx handler is attached. The rx handler is called once
|
||||||
|
* during re-initialization.
|
||||||
|
*/
|
||||||
|
void enable_input(bool enable = true);
|
||||||
|
|
||||||
|
/** Enable serial output
|
||||||
|
*
|
||||||
|
* If both serial input and serial output are disabled, the
|
||||||
|
* peripheral is freed. If either serial input or serial
|
||||||
|
* output is re-enabled, the peripheral is reinitialized.
|
||||||
|
*
|
||||||
|
* On re-initialization tx interrupts will be enabled if a
|
||||||
|
* tx handler is attached. The tx handler is called once
|
||||||
|
* during re-initialization.
|
||||||
|
*/
|
||||||
|
void enable_output(bool enable = true);
|
||||||
|
|
||||||
#if !defined(DOXYGEN_ONLY)
|
#if !defined(DOXYGEN_ONLY)
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
@ -295,6 +319,14 @@ protected:
|
||||||
|
|
||||||
int _base_putc(int c);
|
int _base_putc(int c);
|
||||||
|
|
||||||
|
/** Initialize serial port
|
||||||
|
*/
|
||||||
|
void _init();
|
||||||
|
|
||||||
|
/** Deinitialize serial port
|
||||||
|
*/
|
||||||
|
void _deinit();
|
||||||
|
|
||||||
#if DEVICE_SERIAL_ASYNCH
|
#if DEVICE_SERIAL_ASYNCH
|
||||||
CThunk<SerialBase> _thunk_irq;
|
CThunk<SerialBase> _thunk_irq;
|
||||||
DMAUsage _tx_usage;
|
DMAUsage _tx_usage;
|
||||||
|
@ -308,6 +340,17 @@ protected:
|
||||||
serial_t _serial;
|
serial_t _serial;
|
||||||
Callback<void()> _irq[IrqCnt];
|
Callback<void()> _irq[IrqCnt];
|
||||||
int _baud;
|
int _baud;
|
||||||
|
bool _rx_enabled;
|
||||||
|
bool _tx_enabled;
|
||||||
|
const PinName _tx_pin;
|
||||||
|
const PinName _rx_pin;
|
||||||
|
|
||||||
|
#if DEVICE_SERIAL_FC
|
||||||
|
Flow _flow_type;
|
||||||
|
PinName _flow1;
|
||||||
|
PinName _flow2;
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,17 @@ SerialBase::SerialBase(PinName tx, PinName rx, int baud) :
|
||||||
_rx_callback(NULL), _tx_asynch_set(false),
|
_rx_callback(NULL), _tx_asynch_set(false),
|
||||||
_rx_asynch_set(false),
|
_rx_asynch_set(false),
|
||||||
#endif
|
#endif
|
||||||
_serial(), _baud(baud)
|
_serial(),
|
||||||
|
_baud(baud),
|
||||||
|
#if DEVICE_SERIAL_FC
|
||||||
|
_flow_type(Disabled),
|
||||||
|
_flow1(NC),
|
||||||
|
_flow2(NC),
|
||||||
|
#endif
|
||||||
|
_rx_enabled(true),
|
||||||
|
_tx_enabled(true),
|
||||||
|
_tx_pin(tx),
|
||||||
|
_rx_pin(rx)
|
||||||
{
|
{
|
||||||
// No lock needed in the constructor
|
// No lock needed in the constructor
|
||||||
|
|
||||||
|
@ -38,9 +48,7 @@ SerialBase::SerialBase(PinName tx, PinName rx, int baud) :
|
||||||
_irq[i] = NULL;
|
_irq[i] = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
serial_init(&_serial, tx, rx);
|
_init();
|
||||||
serial_baud(&_serial, _baud);
|
|
||||||
serial_irq_handler(&_serial, SerialBase::_irq_handler, (uint32_t)this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SerialBase::baud(int baudrate)
|
void SerialBase::baud(int baudrate)
|
||||||
|
@ -78,6 +86,11 @@ int SerialBase::writeable()
|
||||||
void SerialBase::attach(Callback<void()> func, IrqType type)
|
void SerialBase::attach(Callback<void()> func, IrqType type)
|
||||||
{
|
{
|
||||||
lock();
|
lock();
|
||||||
|
const bool enabled { (_rx_enabled &&(type == RxIrq)) || (_tx_enabled &&(type == TxIrq)) };
|
||||||
|
// If corresponding direction is not enabled only update the handler
|
||||||
|
if (!enabled) {
|
||||||
|
_irq[type] = func;
|
||||||
|
} else {
|
||||||
// Disable interrupts when attaching interrupt handler
|
// Disable interrupts when attaching interrupt handler
|
||||||
core_util_critical_section_enter();
|
core_util_critical_section_enter();
|
||||||
if (func) {
|
if (func) {
|
||||||
|
@ -96,6 +109,7 @@ void SerialBase::attach(Callback<void()> func, IrqType type)
|
||||||
serial_irq_set(&_serial, (SerialIrq)type, 0);
|
serial_irq_set(&_serial, (SerialIrq)type, 0);
|
||||||
}
|
}
|
||||||
core_util_critical_section_exit();
|
core_util_critical_section_exit();
|
||||||
|
}
|
||||||
unlock();
|
unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,6 +134,95 @@ int SerialBase::_base_putc(int c)
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SerialBase::_init()
|
||||||
|
{
|
||||||
|
serial_init(&_serial, _tx_pin, _rx_pin);
|
||||||
|
#if DEVICE_SERIAL_FC
|
||||||
|
set_flow_control(_flow_type, _flow1, _flow2);
|
||||||
|
#endif
|
||||||
|
serial_baud(&_serial, _baud);
|
||||||
|
serial_irq_handler(&_serial, SerialBase::_irq_handler, (uint32_t)this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SerialBase::_deinit()
|
||||||
|
{
|
||||||
|
serial_free(&_serial);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SerialBase::enable_input(bool enable)
|
||||||
|
{
|
||||||
|
lock();
|
||||||
|
if (_rx_enabled != enable) {
|
||||||
|
if (enable && !_tx_enabled) {
|
||||||
|
_init();
|
||||||
|
}
|
||||||
|
|
||||||
|
core_util_critical_section_enter();
|
||||||
|
if (enable) {
|
||||||
|
// Enable rx IRQ and lock deep sleep if a rx handler is attached
|
||||||
|
// (indicated by rx IRQ callback not NULL)
|
||||||
|
if (_irq[RxIrq]) {
|
||||||
|
_irq[RxIrq].call();
|
||||||
|
sleep_manager_lock_deep_sleep();
|
||||||
|
serial_irq_set(&_serial, (SerialIrq)RxIrq, 1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Disable rx IRQ
|
||||||
|
serial_irq_set(&_serial, (SerialIrq)RxIrq, 0);
|
||||||
|
// Unlock deep sleep if a rx handler is attached
|
||||||
|
// (indicated by rx IRQ callback not NULL)
|
||||||
|
if (_irq[RxIrq]) {
|
||||||
|
sleep_manager_unlock_deep_sleep();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
core_util_critical_section_exit();
|
||||||
|
|
||||||
|
_rx_enabled = enable;
|
||||||
|
|
||||||
|
if (!enable && !_tx_enabled) {
|
||||||
|
_deinit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SerialBase::enable_output(bool enable)
|
||||||
|
{
|
||||||
|
lock();
|
||||||
|
if (_tx_enabled != enable) {
|
||||||
|
if (enable && !_rx_enabled) {
|
||||||
|
_init();
|
||||||
|
}
|
||||||
|
|
||||||
|
core_util_critical_section_enter();
|
||||||
|
if (enable) {
|
||||||
|
// Enable tx IRQ and lock deep sleep if a tx handler is attached
|
||||||
|
// (indicated by tx IRQ callback not NULL)
|
||||||
|
if (_irq[TxIrq]) {
|
||||||
|
_irq[TxIrq].call();
|
||||||
|
sleep_manager_lock_deep_sleep();
|
||||||
|
serial_irq_set(&_serial, (SerialIrq)TxIrq, 1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Disable tx IRQ
|
||||||
|
serial_irq_set(&_serial, (SerialIrq)TxIrq, 0);
|
||||||
|
// Unlock deep sleep if a tx handler is attached
|
||||||
|
// (indicated by tx IRQ callback not NULL)
|
||||||
|
if (_irq[TxIrq]) {
|
||||||
|
sleep_manager_unlock_deep_sleep();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
core_util_critical_section_exit();
|
||||||
|
|
||||||
|
_tx_enabled = enable;
|
||||||
|
|
||||||
|
if (!enable && !_rx_enabled) {
|
||||||
|
_deinit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
unlock();
|
||||||
|
}
|
||||||
|
|
||||||
void SerialBase::set_break()
|
void SerialBase::set_break()
|
||||||
{
|
{
|
||||||
lock();
|
lock();
|
||||||
|
@ -175,6 +278,11 @@ SerialBase::~SerialBase()
|
||||||
void SerialBase::set_flow_control(Flow type, PinName flow1, PinName flow2)
|
void SerialBase::set_flow_control(Flow type, PinName flow1, PinName flow2)
|
||||||
{
|
{
|
||||||
lock();
|
lock();
|
||||||
|
|
||||||
|
_flow_type = type;
|
||||||
|
_flow1 = flow1;
|
||||||
|
_flow2 = flow2;
|
||||||
|
|
||||||
FlowControl flow_type = (FlowControl)type;
|
FlowControl flow_type = (FlowControl)type;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case RTS:
|
case RTS:
|
||||||
|
|
|
@ -366,38 +366,18 @@ void UARTSerial::disable_tx_irq()
|
||||||
|
|
||||||
int UARTSerial::enable_input(bool enabled)
|
int UARTSerial::enable_input(bool enabled)
|
||||||
{
|
{
|
||||||
core_util_critical_section_enter();
|
api_lock();
|
||||||
if (_rx_enabled != enabled) {
|
SerialBase::enable_input(enabled);
|
||||||
if (enabled) {
|
api_unlock();
|
||||||
UARTSerial::rx_irq();
|
|
||||||
if (!_rxbuf.full()) {
|
|
||||||
enable_rx_irq();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
disable_rx_irq();
|
|
||||||
}
|
|
||||||
_rx_enabled = enabled;
|
|
||||||
}
|
|
||||||
core_util_critical_section_exit();
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int UARTSerial::enable_output(bool enabled)
|
int UARTSerial::enable_output(bool enabled)
|
||||||
{
|
{
|
||||||
core_util_critical_section_enter();
|
api_lock();
|
||||||
if (_tx_enabled != enabled) {
|
SerialBase::enable_output(enabled);
|
||||||
if (enabled) {
|
api_unlock();
|
||||||
UARTSerial::tx_irq();
|
|
||||||
if (!_txbuf.empty()) {
|
|
||||||
enable_tx_irq();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
disable_tx_irq();
|
|
||||||
}
|
|
||||||
_tx_enabled = enabled;
|
|
||||||
}
|
|
||||||
core_util_critical_section_exit();
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,6 +96,12 @@ void serial_init(serial_t *obj, PinName tx, PinName rx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//******************************************************************************
|
||||||
|
void serial_free(serial_t *obj)
|
||||||
|
{
|
||||||
|
serial_irq_ids[obj->index];
|
||||||
|
}
|
||||||
|
|
||||||
//******************************************************************************
|
//******************************************************************************
|
||||||
void serial_baud(serial_t *obj, int baudrate)
|
void serial_baud(serial_t *obj, int baudrate)
|
||||||
{
|
{
|
||||||
|
|
|
@ -418,3 +418,8 @@ const PinMap *serial_rts_pinmap()
|
||||||
{
|
{
|
||||||
return PinMap_UART_RTS;
|
return PinMap_UART_RTS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void serial_free(serial_t *obj)
|
||||||
|
{
|
||||||
|
// Not implemented
|
||||||
|
}
|
||||||
|
|
|
@ -115,6 +115,13 @@ void serial_init(serial_t *obj, PinName tx, PinName rx)
|
||||||
MBED_ASSERT(retval == E_NO_ERROR);
|
MBED_ASSERT(retval == E_NO_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//******************************************************************************
|
||||||
|
void serial_free(serial_t *obj)
|
||||||
|
{
|
||||||
|
UART_Shutdown(obj->uart);
|
||||||
|
objs[obj->index] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
//******************************************************************************
|
//******************************************************************************
|
||||||
void serial_baud(serial_t *obj, int baudrate)
|
void serial_baud(serial_t *obj, int baudrate)
|
||||||
{
|
{
|
||||||
|
|
|
@ -115,6 +115,13 @@ void serial_init(serial_t *obj, PinName tx, PinName rx)
|
||||||
MBED_ASSERT(retval == E_NO_ERROR);
|
MBED_ASSERT(retval == E_NO_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//******************************************************************************
|
||||||
|
void serial_free(serial_t *obj)
|
||||||
|
{
|
||||||
|
UART_Shutdown(obj->uart);
|
||||||
|
objs[obj->index] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
//******************************************************************************
|
//******************************************************************************
|
||||||
void serial_baud(serial_t *obj, int baudrate)
|
void serial_baud(serial_t *obj, int baudrate)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue