Skip to content

Commit 596b9f7

Browse files
authored
Merge pull request #9797 from ARMmbed/fh_enable
API to temporarily enable/disable FileHandles
2 parents 857cd9f + 7098f1b commit 596b9f7

File tree

6 files changed

+192
-28
lines changed

6 files changed

+192
-28
lines changed

UNITTESTS/stubs/UARTSerial_stub.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,16 @@ void UARTSerial::tx_irq(void)
120120
{
121121
}
122122

123+
int UARTSerial::enable_input(bool enabled)
124+
{
125+
return 0;
126+
}
127+
128+
int UARTSerial::enable_output(bool enabled)
129+
{
130+
return 0;
131+
}
132+
123133
void UARTSerial::wait_ms(uint32_t millisec)
124134
{
125135

drivers/UARTSerial.cpp

Lines changed: 73 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,13 @@ UARTSerial::UARTSerial(PinName tx, PinName rx, int baud) :
3232
SerialBase(tx, rx, baud),
3333
_blocking(true),
3434
_tx_irq_enabled(false),
35-
_rx_irq_enabled(true),
35+
_rx_irq_enabled(false),
36+
_tx_enabled(true),
37+
_rx_enabled(true),
3638
_dcd_irq(NULL)
3739
{
3840
/* Attatch IRQ routines to the serial device. */
39-
SerialBase::attach(callback(this, &UARTSerial::rx_irq), RxIrq);
41+
enable_rx_irq();
4042
}
4143

4244
UARTSerial::~UARTSerial()
@@ -188,11 +190,10 @@ ssize_t UARTSerial::write(const void *buffer, size_t length)
188190
}
189191

190192
core_util_critical_section_enter();
191-
if (!_tx_irq_enabled) {
193+
if (_tx_enabled && !_tx_irq_enabled) {
192194
UARTSerial::tx_irq(); // only write to hardware in one place
193195
if (!_txbuf.empty()) {
194-
SerialBase::attach(callback(this, &UARTSerial::tx_irq), TxIrq);
195-
_tx_irq_enabled = true;
196+
enable_tx_irq();
196197
}
197198
}
198199
core_util_critical_section_exit();
@@ -231,11 +232,10 @@ ssize_t UARTSerial::read(void *buffer, size_t length)
231232
}
232233

233234
core_util_critical_section_enter();
234-
if (!_rx_irq_enabled) {
235+
if (_rx_enabled && !_rx_irq_enabled) {
235236
UARTSerial::rx_irq(); // only read from hardware in one place
236237
if (!_rxbuf.full()) {
237-
SerialBase::attach(callback(this, &UARTSerial::rx_irq), RxIrq);
238-
_rx_irq_enabled = true;
238+
enable_rx_irq();
239239
}
240240
}
241241
core_util_critical_section_exit();
@@ -314,8 +314,7 @@ void UARTSerial::rx_irq(void)
314314
}
315315

316316
if (_rx_irq_enabled && _rxbuf.full()) {
317-
SerialBase::attach(NULL, RxIrq);
318-
_rx_irq_enabled = false;
317+
disable_rx_irq();
319318
}
320319

321320
/* Report the File handler that data is ready to be read from the buffer. */
@@ -337,8 +336,7 @@ void UARTSerial::tx_irq(void)
337336
}
338337

339338
if (_tx_irq_enabled && _txbuf.empty()) {
340-
SerialBase::attach(NULL, TxIrq);
341-
_tx_irq_enabled = false;
339+
disable_tx_irq();
342340
}
343341

344342
/* Report the File handler that data can be written to peripheral. */
@@ -347,6 +345,69 @@ void UARTSerial::tx_irq(void)
347345
}
348346
}
349347

348+
/* These are all called from critical section */
349+
void UARTSerial::enable_rx_irq()
350+
{
351+
SerialBase::attach(callback(this, &UARTSerial::rx_irq), RxIrq);
352+
_rx_irq_enabled = true;
353+
}
354+
355+
void UARTSerial::disable_rx_irq()
356+
{
357+
SerialBase::attach(NULL, RxIrq);
358+
_rx_irq_enabled = false;
359+
}
360+
361+
void UARTSerial::enable_tx_irq()
362+
{
363+
SerialBase::attach(callback(this, &UARTSerial::tx_irq), TxIrq);
364+
_tx_irq_enabled = true;
365+
}
366+
367+
void UARTSerial::disable_tx_irq()
368+
{
369+
SerialBase::attach(NULL, TxIrq);
370+
_tx_irq_enabled = false;
371+
}
372+
373+
int UARTSerial::enable_input(bool enabled)
374+
{
375+
core_util_critical_section_enter();
376+
if (_rx_enabled != enabled) {
377+
if (enabled) {
378+
UARTSerial::rx_irq();
379+
if (!_rxbuf.full()) {
380+
enable_rx_irq();
381+
}
382+
} else {
383+
disable_rx_irq();
384+
}
385+
_rx_enabled = enabled;
386+
}
387+
core_util_critical_section_exit();
388+
389+
return 0;
390+
}
391+
392+
int UARTSerial::enable_output(bool enabled)
393+
{
394+
core_util_critical_section_enter();
395+
if (_tx_enabled != enabled) {
396+
if (enabled) {
397+
UARTSerial::tx_irq();
398+
if (!_txbuf.empty()) {
399+
enable_tx_irq();
400+
}
401+
} else {
402+
disable_tx_irq();
403+
}
404+
_tx_enabled = enabled;
405+
}
406+
core_util_critical_section_exit();
407+
408+
return 0;
409+
}
410+
350411
void UARTSerial::wait_ms(uint32_t millisec)
351412
{
352413
/* wait_ms implementation for RTOS spins until exact microseconds - we

drivers/UARTSerial.h

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,36 @@ class UARTSerial : private SerialBase, public FileHandle, private NonCopyable<UA
152152
return _blocking;
153153
}
154154

155+
/** Enable or disable input
156+
*
157+
* Control enabling of device for input. This is primarily intended
158+
* for temporary power-saving; the overall ability of the device to operate for
159+
* input and/or output may be fixed at creation time, but this call can
160+
* allow input to be temporarily disabled to permit power saving without
161+
* losing device state.
162+
*
163+
* @param enabled true to enable input, false to disable.
164+
*
165+
* @return 0 on success
166+
* @return Negative error code on failure
167+
*/
168+
virtual int enable_input(bool enabled);
169+
170+
/** Enable or disable output
171+
*
172+
* Control enabling of device for output. This is primarily intended
173+
* for temporary power-saving; the overall ability of the device to operate for
174+
* input and/or output may be fixed at creation time, but this call can
175+
* allow output to be temporarily disabled to permit power saving without
176+
* losing device state.
177+
*
178+
* @param enabled true to enable output, false to disable.
179+
*
180+
* @return 0 on success
181+
* @return Negative error code on failure
182+
*/
183+
virtual int enable_output(bool enabled);
184+
155185
/** Register a callback on state change of the file.
156186
*
157187
* The specified callback will be called on state changes such as when
@@ -242,6 +272,11 @@ class UARTSerial : private SerialBase, public FileHandle, private NonCopyable<UA
242272
/** Unbuffered write - invoked when write called from critical section */
243273
ssize_t write_unbuffered(const char *buf_ptr, size_t length);
244274

275+
void enable_rx_irq();
276+
void disable_rx_irq();
277+
void enable_tx_irq();
278+
void disable_tx_irq();
279+
245280
/** Software serial buffers
246281
* By default buffer size is 256 for TX and 256 for RX. Configurable through mbed_app.json
247282
*/
@@ -255,6 +290,8 @@ class UARTSerial : private SerialBase, public FileHandle, private NonCopyable<UA
255290
bool _blocking;
256291
bool _tx_irq_enabled;
257292
bool _rx_irq_enabled;
293+
bool _tx_enabled;
294+
bool _rx_enabled;
258295
InterruptIn *_dcd_irq;
259296

260297
/** Device Hanged up

platform/FileHandle.h

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,42 @@ class FileHandle : private NonCopyable<FileHandle> {
220220
return true;
221221
}
222222

223+
/** Enable or disable input
224+
*
225+
* Control enabling of device for input. This is primarily intended
226+
* for temporary power-saving; the overall ability of the device to operate for
227+
* input and/or output may be fixed at creation time, but this call can
228+
* allow input to be temporarily disabled to permit power saving without
229+
* losing device state.
230+
*
231+
* @param enabled true to enable input, false to disable.
232+
*
233+
* @return 0 on success
234+
* @return Negative error code on failure
235+
*/
236+
virtual int enable_input(bool enabled)
237+
{
238+
return -EINVAL;
239+
}
240+
241+
/** Enable or disable output
242+
*
243+
* Control enabling of device for output. This is primarily intended
244+
* for temporary power-saving; the overall ability of the device to operate for
245+
* input and/or output may be fixed at creation time, but this call can
246+
* allow output to be temporarily disabled to permit power saving without
247+
* losing device state.
248+
*
249+
* @param enabled true to enable output, false to disable.
250+
*
251+
* @return 0 on success
252+
* @return Negative error code on failure
253+
*/
254+
virtual int enable_output(bool enabled)
255+
{
256+
return -EINVAL;
257+
}
258+
223259
/** Check for poll event flags
224260
* You can use or ignore the input parameter. You can return all events
225261
* or check just the events listed in events.

platform/mbed_retarget.cpp

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,7 @@ static FileHandle *get_console(int fd)
291291
}
292292

293293
/* Deal with the fact C library may not _open descriptors 0, 1, 2 - auto bind */
294-
static FileHandle *get_fhc(int fd)
294+
FileHandle *mbed::mbed_file_handle(int fd)
295295
{
296296
if (fd >= OPEN_MAX) {
297297
return NULL;
@@ -491,13 +491,13 @@ extern "C" FILEHANDLE PREFIX(_open)(const char *name, int openflags)
491491
/* Use the posix convention that stdin,out,err are filehandles 0,1,2.
492492
*/
493493
if (std::strcmp(name, __stdin_name) == 0) {
494-
get_fhc(STDIN_FILENO);
494+
mbed_file_handle(STDIN_FILENO);
495495
return STDIN_FILENO;
496496
} else if (std::strcmp(name, __stdout_name) == 0) {
497-
get_fhc(STDOUT_FILENO);
497+
mbed_file_handle(STDOUT_FILENO);
498498
return STDOUT_FILENO;
499499
} else if (std::strcmp(name, __stderr_name) == 0) {
500-
get_fhc(STDERR_FILENO);
500+
mbed_file_handle(STDERR_FILENO);
501501
return STDERR_FILENO;
502502
}
503503
#endif
@@ -556,7 +556,7 @@ extern "C" int PREFIX(_close)(FILEHANDLE fh)
556556

557557
extern "C" int close(int fildes)
558558
{
559-
FileHandle *fhc = get_fhc(fildes);
559+
FileHandle *fhc = mbed_file_handle(fildes);
560560
filehandles[fildes] = NULL;
561561
if (fhc == NULL) {
562562
errno = EBADF;
@@ -668,7 +668,7 @@ extern "C" int PREFIX(_write)(FILEHANDLE fh, const unsigned char *buffer, unsign
668668
extern "C" ssize_t write(int fildes, const void *buf, size_t length)
669669
{
670670

671-
FileHandle *fhc = get_fhc(fildes);
671+
FileHandle *fhc = mbed_file_handle(fildes);
672672
if (fhc == NULL) {
673673
errno = EBADF;
674674
return -1;
@@ -762,8 +762,7 @@ extern "C" int PREFIX(_read)(FILEHANDLE fh, unsigned char *buffer, unsigned int
762762

763763
extern "C" ssize_t read(int fildes, void *buf, size_t length)
764764
{
765-
766-
FileHandle *fhc = get_fhc(fildes);
765+
FileHandle *fhc = mbed_file_handle(fildes);
767766
if (fhc == NULL) {
768767
errno = EBADF;
769768
return -1;
@@ -790,7 +789,7 @@ extern "C" int _isatty(FILEHANDLE fh)
790789

791790
extern "C" int isatty(int fildes)
792791
{
793-
FileHandle *fhc = get_fhc(fildes);
792+
FileHandle *fhc = mbed_file_handle(fildes);
794793
if (fhc == NULL) {
795794
errno = EBADF;
796795
return 0;
@@ -829,7 +828,7 @@ int _lseek(FILEHANDLE fh, int offset, int whence)
829828

830829
extern "C" off_t lseek(int fildes, off_t offset, int whence)
831830
{
832-
FileHandle *fhc = get_fhc(fildes);
831+
FileHandle *fhc = mbed_file_handle(fildes);
833832
if (fhc == NULL) {
834833
errno = EBADF;
835834
return -1;
@@ -845,7 +844,7 @@ extern "C" off_t lseek(int fildes, off_t offset, int whence)
845844

846845
extern "C" int ftruncate(int fildes, off_t length)
847846
{
848-
FileHandle *fhc = get_fhc(fildes);
847+
FileHandle *fhc = mbed_file_handle(fildes);
849848
if (fhc == NULL) {
850849
errno = EBADF;
851850
return -1;
@@ -869,7 +868,7 @@ extern "C" int PREFIX(_ensure)(FILEHANDLE fh)
869868

870869
extern "C" int fsync(int fildes)
871870
{
872-
FileHandle *fhc = get_fhc(fildes);
871+
FileHandle *fhc = mbed_file_handle(fildes);
873872
if (fhc == NULL) {
874873
errno = EBADF;
875874
return -1;
@@ -887,7 +886,7 @@ extern "C" int fsync(int fildes)
887886
#ifdef __ARMCC_VERSION
888887
extern "C" long PREFIX(_flen)(FILEHANDLE fh)
889888
{
890-
FileHandle *fhc = get_fhc(fh);
889+
FileHandle *fhc = mbed_file_handle(fh);
891890
if (fhc == NULL) {
892891
errno = EBADF;
893892
return -1;
@@ -965,7 +964,7 @@ extern "C" int _fstat(int fh, struct stat *st)
965964

966965
extern "C" int fstat(int fildes, struct stat *st)
967966
{
968-
FileHandle *fhc = get_fhc(fildes);
967+
FileHandle *fhc = mbed_file_handle(fildes);
969968
if (fhc == NULL) {
970969
errno = EBADF;
971970
return -1;
@@ -978,7 +977,7 @@ extern "C" int fstat(int fildes, struct stat *st)
978977

979978
extern "C" int fcntl(int fildes, int cmd, ...)
980979
{
981-
FileHandle *fhc = get_fhc(fildes);
980+
FileHandle *fhc = mbed_file_handle(fildes);
982981
if (fhc == NULL) {
983982
errno = EBADF;
984983
return -1;
@@ -1023,7 +1022,7 @@ extern "C" int poll(struct pollfd fds[], nfds_t nfds, int timeout)
10231022
for (nfds_t n = 0; n < nfds; n++) {
10241023
// Underlying FileHandle poll returns POLLNVAL if given NULL, so
10251024
// we don't need to take special action.
1026-
fhs[n].fh = get_fhc(fds[n].fd);
1025+
fhs[n].fh = mbed_file_handle(fds[n].fd);
10271026
fhs[n].events = fds[n].events;
10281027
}
10291028
int ret = poll(fhs, nfds, timeout);

0 commit comments

Comments
 (0)