@@ -30,17 +30,25 @@ SerialBase::SerialBase(PinName tx, PinName rx, int baud) :
3030 _rx_callback(NULL ), _tx_asynch_set(false ),
3131 _rx_asynch_set(false ),
3232#endif
33- _serial (), _baud(baud)
33+ _serial (),
34+ _baud (baud),
35+ #if DEVICE_SERIAL_FC
36+ _flow_type (Disabled),
37+ _flow1(NC),
38+ _flow2(NC),
39+ #endif
40+ _rx_enabled (true ),
41+ _tx_enabled (true ),
42+ _tx_pin (tx),
43+ _rx_pin (rx)
3444{
3545 // No lock needed in the constructor
3646
3747 for (size_t i = 0 ; i < sizeof _irq / sizeof _irq[0 ]; i++) {
3848 _irq[i] = NULL ;
3949 }
4050
41- serial_init (&_serial, tx, rx);
42- serial_baud (&_serial, _baud);
43- serial_irq_handler (&_serial, SerialBase::_irq_handler, (uint32_t )this );
51+ _init ();
4452}
4553
4654void SerialBase::baud (int baudrate)
@@ -78,24 +86,30 @@ int SerialBase::writeable()
7886void SerialBase::attach (Callback<void ()> func, IrqType type)
7987{
8088 lock ();
81- // Disable interrupts when attaching interrupt handler
82- core_util_critical_section_enter ();
83- if (func) {
84- // lock deep sleep only the first time
85- if (!_irq[type]) {
86- sleep_manager_lock_deep_sleep ();
87- }
89+ const bool enabled { (_rx_enabled &&(type == RxIrq)) || (_tx_enabled &&(type == TxIrq)) };
90+ // If corresponding direction is not enabled only update the handler
91+ if (!enabled) {
8892 _irq[type] = func;
89- serial_irq_set (&_serial, (SerialIrq)type, 1 );
9093 } else {
91- // unlock deep sleep only the first time
92- if (_irq[type]) {
93- sleep_manager_unlock_deep_sleep ();
94+ // Disable interrupts when attaching interrupt handler
95+ core_util_critical_section_enter ();
96+ if (func) {
97+ // lock deep sleep only the first time
98+ if (!_irq[type]) {
99+ sleep_manager_lock_deep_sleep ();
100+ }
101+ _irq[type] = func;
102+ serial_irq_set (&_serial, (SerialIrq)type, 1 );
103+ } else {
104+ // unlock deep sleep only the first time
105+ if (_irq[type]) {
106+ sleep_manager_unlock_deep_sleep ();
107+ }
108+ _irq[type] = NULL ;
109+ serial_irq_set (&_serial, (SerialIrq)type, 0 );
94110 }
95- _irq[type] = NULL ;
96- serial_irq_set (&_serial, (SerialIrq)type, 0 );
111+ core_util_critical_section_exit ();
97112 }
98- core_util_critical_section_exit ();
99113 unlock ();
100114}
101115
@@ -120,6 +134,95 @@ int SerialBase::_base_putc(int c)
120134 return c;
121135}
122136
137+ void SerialBase::_init ()
138+ {
139+ serial_init (&_serial, _tx_pin, _rx_pin);
140+ #if DEVICE_SERIAL_FC
141+ set_flow_control (_flow_type, _flow1, _flow2);
142+ #endif
143+ serial_baud (&_serial, _baud);
144+ serial_irq_handler (&_serial, SerialBase::_irq_handler, (uint32_t )this );
145+ }
146+
147+ void SerialBase::_deinit ()
148+ {
149+ serial_free (&_serial);
150+ }
151+
152+ void SerialBase::enable_input (bool enable)
153+ {
154+ lock ();
155+ if (_rx_enabled != enable) {
156+ if (enable && !_tx_enabled) {
157+ _init ();
158+ }
159+
160+ core_util_critical_section_enter ();
161+ if (enable) {
162+ // Enable rx IRQ and lock deep sleep if a rx handler is attached
163+ // (indicated by rx IRQ callback not NULL)
164+ if (_irq[RxIrq]) {
165+ _irq[RxIrq].call ();
166+ sleep_manager_lock_deep_sleep ();
167+ serial_irq_set (&_serial, (SerialIrq)RxIrq, 1 );
168+ }
169+ } else {
170+ // Disable rx IRQ
171+ serial_irq_set (&_serial, (SerialIrq)RxIrq, 0 );
172+ // Unlock deep sleep if a rx handler is attached
173+ // (indicated by rx IRQ callback not NULL)
174+ if (_irq[RxIrq]) {
175+ sleep_manager_unlock_deep_sleep ();
176+ }
177+ }
178+ core_util_critical_section_exit ();
179+
180+ _rx_enabled = enable;
181+
182+ if (!enable && !_tx_enabled) {
183+ _deinit ();
184+ }
185+ }
186+ unlock ();
187+ }
188+
189+ void SerialBase::enable_output (bool enable)
190+ {
191+ lock ();
192+ if (_tx_enabled != enable) {
193+ if (enable && !_rx_enabled) {
194+ _init ();
195+ }
196+
197+ core_util_critical_section_enter ();
198+ if (enable) {
199+ // Enable tx IRQ and lock deep sleep if a tx handler is attached
200+ // (indicated by tx IRQ callback not NULL)
201+ if (_irq[TxIrq]) {
202+ _irq[TxIrq].call ();
203+ sleep_manager_lock_deep_sleep ();
204+ serial_irq_set (&_serial, (SerialIrq)TxIrq, 1 );
205+ }
206+ } else {
207+ // Disable tx IRQ
208+ serial_irq_set (&_serial, (SerialIrq)TxIrq, 0 );
209+ // Unlock deep sleep if a tx handler is attached
210+ // (indicated by tx IRQ callback not NULL)
211+ if (_irq[TxIrq]) {
212+ sleep_manager_unlock_deep_sleep ();
213+ }
214+ }
215+ core_util_critical_section_exit ();
216+
217+ _tx_enabled = enable;
218+
219+ if (!enable && !_rx_enabled) {
220+ _deinit ();
221+ }
222+ }
223+ unlock ();
224+ }
225+
123226void SerialBase::set_break ()
124227{
125228 lock ();
@@ -175,6 +278,11 @@ SerialBase::~SerialBase()
175278void SerialBase::set_flow_control (Flow type, PinName flow1, PinName flow2)
176279{
177280 lock ();
281+
282+ _flow_type = type;
283+ _flow1 = flow1;
284+ _flow2 = flow2;
285+
178286 FlowControl flow_type = (FlowControl)type;
179287 switch (type) {
180288 case RTS:
0 commit comments