@@ -30,17 +30,25 @@ SerialBase::SerialBase(PinName tx, PinName rx, int baud) :
30
30
_rx_callback(NULL ), _tx_asynch_set(false ),
31
31
_rx_asynch_set(false ),
32
32
#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)
34
44
{
35
45
// No lock needed in the constructor
36
46
37
47
for (size_t i = 0 ; i < sizeof _irq / sizeof _irq[0 ]; i++) {
38
48
_irq[i] = NULL ;
39
49
}
40
50
41
- serial_init (&_serial, tx, rx);
42
- serial_baud (&_serial, _baud);
43
- serial_irq_handler (&_serial, SerialBase::_irq_handler, (uint32_t )this );
51
+ _init ();
44
52
}
45
53
46
54
void SerialBase::baud (int baudrate)
@@ -78,24 +86,30 @@ int SerialBase::writeable()
78
86
void SerialBase::attach (Callback<void ()> func, IrqType type)
79
87
{
80
88
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) {
88
92
_irq[type] = func;
89
- serial_irq_set (&_serial, (SerialIrq)type, 1 );
90
93
} 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 );
94
110
}
95
- _irq[type] = NULL ;
96
- serial_irq_set (&_serial, (SerialIrq)type, 0 );
111
+ core_util_critical_section_exit ();
97
112
}
98
- core_util_critical_section_exit ();
99
113
unlock ();
100
114
}
101
115
@@ -120,6 +134,95 @@ int SerialBase::_base_putc(int c)
120
134
return c;
121
135
}
122
136
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
+
123
226
void SerialBase::set_break ()
124
227
{
125
228
lock ();
@@ -175,6 +278,11 @@ SerialBase::~SerialBase()
175
278
void SerialBase::set_flow_control (Flow type, PinName flow1, PinName flow2)
176
279
{
177
280
lock ();
281
+
282
+ _flow_type = type;
283
+ _flow1 = flow1;
284
+ _flow2 = flow2;
285
+
178
286
FlowControl flow_type = (FlowControl)type;
179
287
switch (type) {
180
288
case RTS:
0 commit comments