From 67e14adc4f0dfbaef4762e383a5328add42f6cf5 Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Sun, 5 Dec 2021 18:52:59 -0500 Subject: [posix] 按照高级unix环境编程整理IO类别 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/drivers/serial/serial.c | 2 +- components/libc/compilers/common/poll.h | 49 --- components/libc/compilers/common/sys/termios.h | 8 - components/libc/compilers/common/termios.h | 19 - components/libc/posix/Kconfig | 32 +- components/libc/posix/aio/SConscript | 11 - components/libc/posix/aio/posix_aio.c | 459 ------------------------- components/libc/posix/aio/posix_aio.h | 47 --- components/libc/posix/io/SConscript | 34 ++ components/libc/posix/io/aio/SConscript | 11 + components/libc/posix/io/aio/aio.c | 459 +++++++++++++++++++++++++ components/libc/posix/io/aio/aio.h | 47 +++ components/libc/posix/io/libc.c | 147 ++++++++ components/libc/posix/io/libc.h | 29 ++ components/libc/posix/io/mmap.c | 67 ++++ components/libc/posix/io/poll/SConscript | 11 + components/libc/posix/io/poll/poll.c | 226 ++++++++++++ components/libc/posix/io/poll/poll.h | 49 +++ components/libc/posix/io/select.c | 176 ++++++++++ components/libc/posix/io/termios/SConscript | 11 + components/libc/posix/io/termios/termios.c | 129 +++++++ components/libc/posix/io/termios/termios.h | 213 ++++++++++++ components/libc/posix/src/SConscript | 16 - components/libc/posix/src/libc.c | 147 -------- components/libc/posix/src/libc.h | 29 -- components/libc/posix/src/mmap.c | 67 ---- components/libc/posix/src/poll.c | 226 ------------ components/libc/posix/src/select.c | 176 ---------- components/libc/posix/termios/SConscript | 11 - components/libc/posix/termios/posix_termios.c | 129 ------- components/libc/posix/termios/posix_termios.h | 213 ------------ 31 files changed, 1626 insertions(+), 1624 deletions(-) delete mode 100644 components/libc/compilers/common/poll.h delete mode 100644 components/libc/compilers/common/sys/termios.h delete mode 100644 components/libc/compilers/common/termios.h delete mode 100644 components/libc/posix/aio/SConscript delete mode 100644 components/libc/posix/aio/posix_aio.c delete mode 100644 components/libc/posix/aio/posix_aio.h create mode 100644 components/libc/posix/io/SConscript create mode 100644 components/libc/posix/io/aio/SConscript create mode 100644 components/libc/posix/io/aio/aio.c create mode 100644 components/libc/posix/io/aio/aio.h create mode 100644 components/libc/posix/io/libc.c create mode 100644 components/libc/posix/io/libc.h create mode 100644 components/libc/posix/io/mmap.c create mode 100644 components/libc/posix/io/poll/SConscript create mode 100644 components/libc/posix/io/poll/poll.c create mode 100644 components/libc/posix/io/poll/poll.h create mode 100644 components/libc/posix/io/select.c create mode 100644 components/libc/posix/io/termios/SConscript create mode 100644 components/libc/posix/io/termios/termios.c create mode 100644 components/libc/posix/io/termios/termios.h delete mode 100644 components/libc/posix/src/libc.c delete mode 100644 components/libc/posix/src/libc.h delete mode 100644 components/libc/posix/src/mmap.c delete mode 100644 components/libc/posix/src/poll.c delete mode 100644 components/libc/posix/src/select.c delete mode 100644 components/libc/posix/termios/SConscript delete mode 100644 components/libc/posix/termios/posix_termios.c delete mode 100644 components/libc/posix/termios/posix_termios.h (limited to 'components') diff --git a/components/drivers/serial/serial.c b/components/drivers/serial/serial.c index 0e944b5e95..6f7e7d5b2b 100644 --- a/components/drivers/serial/serial.c +++ b/components/drivers/serial/serial.c @@ -42,7 +42,7 @@ #include #ifdef RT_USING_POSIX_TERMIOS -#include +#include #endif /* it's possible the 'getc/putc' is defined by stdio.h in gcc/newlib. */ diff --git a/components/libc/compilers/common/poll.h b/components/libc/compilers/common/poll.h deleted file mode 100644 index aea73d6eaf..0000000000 --- a/components/libc/compilers/common/poll.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2021-09-11 Meco Man First version - */ -#ifndef __POLL_H__ -#define __POLL_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#if !defined(POLLIN) && !defined(POLLOUT) -#define POLLIN (0x01) -#define POLLRDNORM (0x01) -#define POLLRDBAND (0x01) -#define POLLPRI (0x01) - -#define POLLOUT (0x02) -#define POLLWRNORM (0x02) -#define POLLWRBAND (0x02) - -#define POLLERR (0x04) -#define POLLHUP (0x08) -#define POLLNVAL (0x10) - -typedef unsigned int nfds_t; - -struct pollfd -{ - int fd; - short events; - short revents; -}; -#endif /* !defined(POLLIN) && !defined(POLLOUT) */ - -#define POLLMASK_DEFAULT (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM) - -int poll(struct pollfd *fds, nfds_t nfds, int timeout); - -#ifdef __cplusplus -} -#endif - -#endif /* __POLL_H__ */ diff --git a/components/libc/compilers/common/sys/termios.h b/components/libc/compilers/common/sys/termios.h deleted file mode 100644 index c4b42083c4..0000000000 --- a/components/libc/compilers/common/sys/termios.h +++ /dev/null @@ -1,8 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - */ diff --git a/components/libc/compilers/common/termios.h b/components/libc/compilers/common/termios.h deleted file mode 100644 index 2960d52c58..0000000000 --- a/components/libc/compilers/common/termios.h +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - */ -#ifndef _TERMIOS_H__ -#define _TERMIOS_H__ - -#include - -#ifdef RT_USING_POSIX_TERMIOS -#include -#include -#endif - -#endif diff --git a/components/libc/posix/Kconfig b/components/libc/posix/Kconfig index 0afff161ff..db83269dd0 100644 --- a/components/libc/posix/Kconfig +++ b/components/libc/posix/Kconfig @@ -1,7 +1,7 @@ menu "POSIX (Portable Operating System Interface) layer" config RT_USING_POSIX_FS - bool "Enable POSIX file system, open()/read()/write()/close() etc" + bool "Enable POSIX file system and I/O" select RT_USING_DFS select DFS_USING_POSIX default n @@ -13,13 +13,26 @@ if RT_USING_POSIX_FS default n config RT_USING_POSIX_POLL - bool "Enable poll()" + bool "Enable I/O Multiplexing poll() " default n config RT_USING_POSIX_SELECT - bool "Enable select()" + bool "Enable I/O Multiplexing select() " select RT_USING_POSIX_POLL default n + + config RT_USING_POSIX_TERMIOS + bool "Enable Terminal I/O " + select RT_USING_POSIX_DEVIO + default n + + config RT_USING_POSIX_AIO + bool "Enable Asynchronous I/O " + default n + + config RT_USING_POSIX_MMAP + bool "Enable Memory-Mapped I/O " + default n endif config RT_USING_POSIX_DELAY @@ -32,19 +45,6 @@ config RT_USING_POSIX_GETLINE select RT_LIBC_USING_FILEIO default n -config RT_USING_POSIX_MMAP - bool "Enable mmap()" - select RT_USING_POSIX_FS - default n - -config RT_USING_POSIX_TERMIOS - bool "Enable termios APIs" - default n - -config RT_USING_POSIX_AIO - bool "Enable AIO APIs" - default n - config RT_USING_PTHREADS bool "Enable pthreads APIs" default n diff --git a/components/libc/posix/aio/SConscript b/components/libc/posix/aio/SConscript deleted file mode 100644 index 139bc45749..0000000000 --- a/components/libc/posix/aio/SConscript +++ /dev/null @@ -1,11 +0,0 @@ -# RT-Thread building script for component - -from building import * - -cwd = GetCurrentDir() -src = Glob('*.c') -CPPPATH = [cwd] - -group = DefineGroup('POSIX', src, depend = ['RT_USING_POSIX_AIO'], CPPPATH = CPPPATH) - -Return('group') diff --git a/components/libc/posix/aio/posix_aio.c b/components/libc/posix/aio/posix_aio.c deleted file mode 100644 index 66cced8687..0000000000 --- a/components/libc/posix/aio/posix_aio.c +++ /dev/null @@ -1,459 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2017/12/30 Bernard The first version. - */ - -#include -#include -#include -#include "posix_aio.h" - -struct rt_workqueue* aio_queue = NULL; - -/** - * The aio_cancel() function shall attempt to cancel one or more asynchronous I/O - * requests currently outstanding against file descriptor fildes. The aiocbp - * argument points to the asynchronous I/O control block for a particular request - * to be canceled. If aiocbp is NULL, then all outstanding cancelable asynchronous - * I/O requests against fildes shall be canceled. - * - * Normal asynchronous notification shall occur for asynchronous I/O operations - * that are successfully canceled. If there are requests that cannot be canceled, - * then the normal asynchronous completion process shall take place for those - * requests when they are completed. - * - * For requested operations that are successfully canceled, the associated error - * status shall be set to [ECANCELED] and the return status shall be -1. For - * requested operations that are not successfully canceled, the aiocbp shall not - * be modified by aio_cancel(). - * - * If aiocbp is not NULL, then if fildes does not have the same value as the file - * descriptor with which the asynchronous operation was initiated, unspecified results occur. - * - * Which operations are cancelable is implementation-defined. - */ -int aio_cancel(int fd, struct aiocb *cb) -{ - rt_err_t ret; - - if (!cb) return -EINVAL; - if (cb->aio_fildes != fd) return -EINVAL; - - ret = rt_workqueue_cancel_work_sync(aio_queue, &(cb->aio_work)); - if (ret == RT_EOK) - { - errno = -ECANCELED; - return -1; - } - - return 0; -} - -/** - * The aio_error() function shall return the error status associated with the - * aiocb structure referenced by the aiocbp argument. The error status for an - * asynchronous I/O operation is the errno value that would be set by the corresponding - * read(), write(), - */ -int aio_error (const struct aiocb *cb) -{ - if (cb) - { - return cb->aio_result; - } - - return -EINVAL; -} - -/** - * The aio_fsync() function shall asynchronously perform a file synchronization - * operation, as specified by the op argument, for I/O operations associated with - * the file indicated by the file descriptor aio_fildes member of the aiocb - * structure referenced by the aiocbp argument and queued at the time of the - * call to aio_fsync(). The function call shall return when the synchronization - * request has been initiated or queued to the file or device (even when the data - * cannot be synchronized immediately). - * - * option: If op is O_DSYNC, all currently queued I/O operations shall be completed - * as if by a call to fdatasync(); that is, as defined for synchronized I/O data - * integrity completion. - * - * option: If op is O_SYNC, all currently queued I/O operations shall be completed - * as if by a call to fsync(); that is, as defined for synchronized I/O file integrity - * completion. If the aio_fsync() function fails, or if the operation queued by - * aio_fsync() fails, then outstanding I/O operations are not guaranteed to have - * been completed. - * - * If aio_fsync() succeeds, then it is only the I/O that was queued at the time - * of the call to aio_fsync() that is guaranteed to be forced to the relevant - * completion state. The completion of subsequent I/O on the file descriptor is - * not guaranteed to be completed in a synchronized fashion. - * - * The aiocbp argument refers to an asynchronous I/O control block. The aiocbp - * value may be used as an argument to aio_error() and aio_return() in order to - * determine the error status and return status, respectively, of the asynchronous - * operation while it is proceeding. When the request is queued, the error status - * for the operation is [EINPROGRESS]. When all data has been successfully transferred, - * the error status shall be reset to reflect the success or failure of the operation. - * If the operation does not complete successfully, the error status for the - * operation shall be set to indicate the error. The aio_sigevent member determines - * the asynchronous notification to occur as specified in Signal Generation and - * Delivery when all operations have achieved synchronized I/O completion. All - * other members of the structure referenced by aiocbp are ignored. If the control - * block referenced by aiocbp becomes an illegal address prior to asynchronous - * I/O completion, then the behavior is undefined. - * - * If the aio_fsync() function fails or aiocbp indicates an error condition, - * data is not guaranteed to have been successfully transferred. - */ -static void aio_fync_work(struct rt_work* work, void* work_data) -{ - int result; - rt_ubase_t level; - struct aiocb *cb = (struct aiocb*)work_data; - - RT_ASSERT(cb != RT_NULL); - - result = fsync(cb->aio_fildes); - /* modify result */ - level = rt_hw_interrupt_disable(); - if (result < 0) - cb->aio_result = errno; - else - cb->aio_result = 0; - rt_hw_interrupt_enable(level); - - return ; -} - -int aio_fsync(int op, struct aiocb *cb) -{ - rt_ubase_t level; - if (!cb) return -EINVAL; - - level = rt_hw_interrupt_disable(); - cb->aio_result = -EINPROGRESS; - rt_hw_interrupt_enable(level); - - rt_work_init(&(cb->aio_work), aio_fync_work, cb); - rt_workqueue_dowork(aio_queue, &(cb->aio_work)); - - return 0; -} - -static void aio_read_work(struct rt_work* work, void* work_data) -{ - int len; - rt_ubase_t level; - uint8_t *buf_ptr; - struct aiocb *cb = (struct aiocb*)work_data; - - buf_ptr = (uint8_t*)cb->aio_buf; - - /* seek to offset */ - lseek(cb->aio_fildes, cb->aio_offset, SEEK_SET); - len = read(cb->aio_fildes, &buf_ptr[cb->aio_offset], cb->aio_nbytes); - - /* modify result */ - level = rt_hw_interrupt_disable(); - if (len <= 0) - cb->aio_result = errno; - else - cb->aio_result = len; - rt_hw_interrupt_enable(level); - - return ; -} - -/** - * The aio_read() function shall read aiocbp->aio_nbytes from the file associated - * with aiocbp->aio_fildes into the buffer pointed to by aiocbp->aio_buf. The - * function call shall return when the read request has been initiated or queued - * to the file or device (even when the data cannot be delivered immediately). - * - * If prioritized I/O is supported for this file, then the asynchronous operation - * shall be submitted at a priority equal to a base scheduling priority minus - * aiocbp->aio_reqprio. If Thread Execution Scheduling is not supported, then - * the base scheduling priority is that of the calling process; - * - * otherwise, the base scheduling priority is that of the calling thread. - * - * The aiocbp value may be used as an argument to aio_error() and aio_return() - * in order to determine the error status and return status, respectively, of - * the asynchronous operation while it is proceeding. If an error condition is - * encountered during queuing, the function call shall return without having - * initiated or queued the request. The requested operation takes place at the - * absolute position in the file as given by aio_offset, as if lseek() were called - * immediately prior to the operation with an offset equal to aio_offset and a - * whence equal to SEEK_SET. After a successful call to enqueue an asynchronous - * I/O operation, the value of the file offset for the file is unspecified. - * - * The aio_sigevent member specifies the notification which occurs when the - * request is completed. - * - * The aiocbp->aio_lio_opcode field shall be ignored by aio_read(). - * - * The aiocbp argument points to an aiocb structure. If the buffer pointed to by - * aiocbp->aio_buf or the control block pointed to by aiocbp becomes an illegal - * address prior to asynchronous I/O completion, then the behavior is undefined. - * - * Simultaneous asynchronous operations using the same aiocbp produce undefined - * results. - * - * If synchronized I/O is enabled on the file associated with aiocbp->aio_fildes, - * the behavior of this function shall be according to the definitions of synchronized - * I/O data integrity completion and synchronized I/O file integrity completion. - * - * For any system action that changes the process memory space while an asynchronous - * I/O is outstanding to the address range being changed, the result of that action - * is undefined. - * - * For regular files, no data transfer shall occur past the offset maximum - * established in the open file description associated with aiocbp->aio_fildes. - * - */ -int aio_read(struct aiocb *cb) -{ - rt_ubase_t level; - - if (!cb) return -EINVAL; - if (cb->aio_offset < 0) return -EINVAL; - - level = rt_hw_interrupt_disable(); - cb->aio_result = -EINPROGRESS; - rt_hw_interrupt_enable(level); - - /* en-queue read work */ - rt_work_init(&(cb->aio_work), aio_read_work, cb); - rt_workqueue_dowork(aio_queue, &(cb->aio_work)); - - return 0; -} - -/** - * The aio_return() function shall return the return status associated with the - * aiocb structure referenced by the aiocbp argument. The return status for an - * asynchronous I/O operation is the value that would be returned by the corresponding - * read(), write(), or fsync() function call. If the error status for the operation - * is equal to [EINPROGRESS], then the return status for the operation is undefined. - * The aio_return() function may be called exactly once to retrieve the return - * status of a given asynchronous operation; thereafter, if the same aiocb structure - * is used in a call to aio_return() or aio_error(), an error may be returned. - * When the aiocb structure referred to by aiocbp is used to submit another asynchronous - * operation, then aio_return() may be successfully used to retrieve the return - * status of that operation. - */ -ssize_t aio_return(struct aiocb *cb) -{ - if (cb) - { - if (cb->aio_result < 0) - rt_set_errno(cb->aio_result); - - return cb->aio_result; - } - - return -EINVAL; -} - -/** - * The aio_suspend() function shall suspend the calling thread until at least - * one of the asynchronous I/O operations referenced by the list argument has - * completed, until a signal interrupts the function, or, if timeout is not NULL, - * until the time interval specified by timeout has passed. If any of the aiocb - * structures in the list correspond to completed asynchronous I/O operations - * (that is, the error status for the operation is not equal to [EINPROGRESS]) - * at the time of the call, the function shall return without suspending the - * calling thread. The list argument is an array of pointers to asynchronous I/O - * control blocks. The nent argument indicates the number of elements in the - * array. Each aiocb structure pointed to has been used in initiating an asynchronous - * I/O request via aio_read(), aio_write(), or lio_listio(). This array may - * contain null pointers, which are ignored. If this array contains pointers - * that refer to aiocb structures that have not been used in submitting asynchronous - * I/O, the effect is undefined. - * - * If the time interval indicated in the timespec structure pointed to by timeout - * passes before any of the I/O operations referenced by list are completed, then - * aio_suspend() shall return with an error. - */ -int aio_suspend(const struct aiocb *const list[], int nent, - const struct timespec *timeout) -{ - return -ENOSYS; -} - -static void aio_write_work(struct rt_work* work, void* work_data) -{ - int len, oflags, level; - uint8_t *buf_ptr; - struct aiocb *cb = (struct aiocb*)work_data; - - buf_ptr = (uint8_t*)cb->aio_buf; - - /* whether seek offset */ - oflags = fcntl(cb->aio_fildes, F_GETFL, 0); - if ((oflags & O_APPEND) == 0) - { - lseek(cb->aio_fildes, SEEK_SET, cb->aio_offset); - } - - /* write data */ - len = write(cb->aio_fildes, buf_ptr, cb->aio_nbytes); - - /* modify result */ - level = rt_hw_interrupt_disable(); - if (len <= 0) - cb->aio_result = errno; - else - cb->aio_result = len; - rt_hw_interrupt_enable(level); - - return; -} - -/** - * The aio_write() function shall write aiocbp->aio_nbytes to the file associated - * with aiocbp->aio_fildes from the buffer pointed to by aiocbp->aio_buf. The - * function shall return when the write request has been initiated or, at a minimum, - * queued to the file or device. - * - * The aiocbp argument may be used as an argument to aio_error() and aio_return() - * in order to determine the error status and return status, respectively, of the - * asynchronous operation while it is proceeding. - * - * The aiocbp argument points to an aiocb structure. If the buffer pointed to by - * aiocbp->aio_buf or the control block pointed to by aiocbp becomes an illegal - * address prior to asynchronous I/O completion, then the behavior is undefined. - * - * If O_APPEND is not set for the file descriptor aio_fildes, then the requested - * operation shall take place at the absolute position in the file as given by - * aio_offset, as if lseek() were called immediately prior to the operation with - * an offset equal to aio_offset and a whence equal to SEEK_SET. If O_APPEND is - * set for the file descriptor, or if aio_fildes is associated with a device that - * is incapable of seeking, write operations append to the file in the same order - * as the calls were made, except under circumstances described in Asynchronous - * I/O. After a successful call to enqueue an asynchronous I/O operation, the value - * of the file offset for the file is unspecified. - * - * The aio_sigevent member specifies the notification which occurs when the request - * is completed. - * - * The aiocbp->aio_lio_opcode field shall be ignored by aio_write(). - * - * Simultaneous asynchronous operations using the same aiocbp produce undefined - * results. - * - * If synchronized I/O is enabled on the file associated with aiocbp->aio_fildes, - * the behavior of this function shall be according to the definitions of synchronized - * I/O data integrity completion, and synchronized I/O file integrity completion. - * - * For regular files, no data transfer shall occur past the offset maximum established - * in the open file description associated with aiocbp->aio_fildes. - */ -int aio_write(struct aiocb *cb) -{ - int oflags; - rt_ubase_t level; - - if (!cb || (cb->aio_buf == NULL)) return -EINVAL; - - /* check access mode */ - oflags = fcntl(cb->aio_fildes, F_GETFL, 0); - if ((oflags & O_ACCMODE) != O_WRONLY || - (oflags & O_ACCMODE) != O_RDWR) - return -EINVAL; - - level = rt_hw_interrupt_disable(); - cb->aio_result = -EINPROGRESS; - rt_hw_interrupt_enable(level); - - rt_work_init(&(cb->aio_work), aio_write_work, cb); - rt_workqueue_dowork(aio_queue, &(cb->aio_work)); - - return 0; -} - -/** - * The lio_listio() function shall initiate a list of I/O requests with a single - * function call. - * - * The mode argument takes one of the values LIO_WAIT or LIO_NOWAIT declared in - * and determines whether the function returns when the I/O operations - * have been completed, or as soon as the operations have been queued. If the - * mode argument is LIO_WAIT, the function shall wait until all I/O is complete - * and the sig argument shall be ignored. - * - * If the mode argument is LIO_NOWAIT, the function shall return immediately, and - * asynchronous notification shall occur, according to the sig argument, when all - * the I/O operations complete. If sig is NULL, then no asynchronous notification - * shall occur. If sig is not NULL, asynchronous notification occurs as specified - * in Signal Generation and Delivery when all the requests in list have completed. - * - * The I/O requests enumerated by list are submitted in an unspecified order. - * - * The list argument is an array of pointers to aiocb structures. The array contains - * nent elements. The array may contain NULL elements, which shall be ignored. - * - * If the buffer pointed to by list or the aiocb structures pointed to by the - * elements of the array list become illegal addresses before all asynchronous I/O - * completed and, if necessary, the notification is sent, then the behavior is - * undefined. If the buffers pointed to by the aio_buf member of the aiocb structure - * pointed to by the elements of the array list become illegal addresses prior to - * the asynchronous I/O associated with that aiocb structure being completed, the - * behavior is undefined. - * - * The aio_lio_opcode field of each aiocb structure specifies the operation to be - * performed. The supported operations are LIO_READ, LIO_WRITE, and LIO_NOP; these - * symbols are defined in . The LIO_NOP operation causes the list entry to - * be ignored. If the aio_lio_opcode element is equal to LIO_READ, then an I/O operation - * is submitted as if by a call to aio_read() with the aiocbp equal to the address - * of the aiocb structure. If the aio_lio_opcode element is equal to LIO_WRITE, then - * an I/O operation is submitted as if by a call to aio_write() with the aiocbp equal - * to the address of the aiocb structure. - * - * The aio_fildes member specifies the file descriptor on which the operation is to - * be performed. - * - * The aio_buf member specifies the address of the buffer to or from which the data - * is transferred. - * - * The aio_nbytes member specifies the number of bytes of data to be transferred. - * - * The members of the aiocb structure further describe the I/O operation to be - * performed, in a manner identical to that of the corresponding aiocb structure - * when used by the aio_read() and aio_write() functions. - * - * The nent argument specifies how many elements are members of the list; that is, - * the length of the array. - * - * The behavior of this function is altered according to the definitions of synchronized - * I/O data integrity completion and synchronized I/O file integrity completion if - * synchronized I/O is enabled on the file associated with aio_fildes. - * - * For regular files, no data transfer shall occur past the offset maximum established - * in the open file description associated with aiocbp->aio_fildes. - * - * If sig->sigev_notify is SIGEV_THREAD and sig->sigev_notify_attributes is a - * non-null pointer and the block pointed to by this pointer becomes an illegal - * address prior to all asynchronous I/O being completed, then the behavior is - * undefined. - */ -int lio_listio(int mode, struct aiocb * const list[], int nent, - struct sigevent *sig) -{ - return -ENOSYS; -} - -int aio_system_init(void) -{ - aio_queue = rt_workqueue_create("aio", 2048, RT_THREAD_PRIORITY_MAX/2); - RT_ASSERT(aio_queue != NULL); - - return 0; -} -INIT_COMPONENT_EXPORT(aio_system_init); diff --git a/components/libc/posix/aio/posix_aio.h b/components/libc/posix/aio/posix_aio.h deleted file mode 100644 index 4e25e1d15b..0000000000 --- a/components/libc/posix/aio/posix_aio.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2017/12/30 Bernard The first version. - */ - -#ifndef POSIX_AIO_H__ -#define POSIX_AIO_H__ - -#include -#include -#include - -struct aiocb -{ - int aio_fildes; /* File descriptor. */ - off_t aio_offset; /* File offset. */ - - volatile void *aio_buf; /* Location of buffer. */ - size_t aio_nbytes; /* Length of transfer. */ - int aio_reqprio; /* Request priority offset. */ - struct sigevent aio_sigevent; /* Signal number and value. */ - int aio_lio_opcode; /* Operation to be performed. */ - - int aio_result; - struct rt_work aio_work; -}; - -int aio_cancel(int fd, struct aiocb *cb); -int aio_error (const struct aiocb *cb); - -int aio_fsync(int op, struct aiocb *cb); - -int aio_read(struct aiocb *cb); -ssize_t aio_return(struct aiocb *cb); -int aio_suspend(const struct aiocb *const list[], int nent, - const struct timespec *timeout); -int aio_write(struct aiocb *cb); - -int lio_listio(int mode, struct aiocb * const list[], int nent, - struct sigevent *sig); - -#endif diff --git a/components/libc/posix/io/SConscript b/components/libc/posix/io/SConscript new file mode 100644 index 0000000000..2a7cd76ded --- /dev/null +++ b/components/libc/posix/io/SConscript @@ -0,0 +1,34 @@ +# RT-Thread building script for component + +import os +from building import * + +src = [] +cwd = GetCurrentDir() +CPPPATH = [cwd] +group = [] + +flag = False + +if GetDepend('RT_USING_POSIX_DEVIO'): + src += ['libc.c'] + flag = True + +if GetDepend('RT_USING_POSIX_SELECT'): + src += ['select.c'] + flag = True + +if GetDepend('RT_USING_POSIX_MMAP'): + src += ['mmap.c'] + flag = True + +if flag == True: + group = DefineGroup('POSIX', src, depend = [], CPPPATH = CPPPATH) + +list = os.listdir(cwd) +for d in list: + path = os.path.join(cwd, d) + if os.path.isfile(os.path.join(path, 'SConscript')): + group = group + SConscript(os.path.join(d, 'SConscript')) + +Return('group') diff --git a/components/libc/posix/io/aio/SConscript b/components/libc/posix/io/aio/SConscript new file mode 100644 index 0000000000..6d4014311c --- /dev/null +++ b/components/libc/posix/io/aio/SConscript @@ -0,0 +1,11 @@ +# RT-Thread building script for component + +from building import * + +cwd = GetCurrentDir() +src = ['aio.c'] +CPPPATH = [cwd] + +group = DefineGroup('POSIX', src, depend = ['RT_USING_POSIX_AIO'], CPPPATH = CPPPATH) + +Return('group') diff --git a/components/libc/posix/io/aio/aio.c b/components/libc/posix/io/aio/aio.c new file mode 100644 index 0000000000..08ef4c634a --- /dev/null +++ b/components/libc/posix/io/aio/aio.c @@ -0,0 +1,459 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2017/12/30 Bernard The first version. + */ + +#include +#include +#include +#include "aio.h" + +struct rt_workqueue* aio_queue = NULL; + +/** + * The aio_cancel() function shall attempt to cancel one or more asynchronous I/O + * requests currently outstanding against file descriptor fildes. The aiocbp + * argument points to the asynchronous I/O control block for a particular request + * to be canceled. If aiocbp is NULL, then all outstanding cancelable asynchronous + * I/O requests against fildes shall be canceled. + * + * Normal asynchronous notification shall occur for asynchronous I/O operations + * that are successfully canceled. If there are requests that cannot be canceled, + * then the normal asynchronous completion process shall take place for those + * requests when they are completed. + * + * For requested operations that are successfully canceled, the associated error + * status shall be set to [ECANCELED] and the return status shall be -1. For + * requested operations that are not successfully canceled, the aiocbp shall not + * be modified by aio_cancel(). + * + * If aiocbp is not NULL, then if fildes does not have the same value as the file + * descriptor with which the asynchronous operation was initiated, unspecified results occur. + * + * Which operations are cancelable is implementation-defined. + */ +int aio_cancel(int fd, struct aiocb *cb) +{ + rt_err_t ret; + + if (!cb) return -EINVAL; + if (cb->aio_fildes != fd) return -EINVAL; + + ret = rt_workqueue_cancel_work_sync(aio_queue, &(cb->aio_work)); + if (ret == RT_EOK) + { + errno = -ECANCELED; + return -1; + } + + return 0; +} + +/** + * The aio_error() function shall return the error status associated with the + * aiocb structure referenced by the aiocbp argument. The error status for an + * asynchronous I/O operation is the errno value that would be set by the corresponding + * read(), write(), + */ +int aio_error (const struct aiocb *cb) +{ + if (cb) + { + return cb->aio_result; + } + + return -EINVAL; +} + +/** + * The aio_fsync() function shall asynchronously perform a file synchronization + * operation, as specified by the op argument, for I/O operations associated with + * the file indicated by the file descriptor aio_fildes member of the aiocb + * structure referenced by the aiocbp argument and queued at the time of the + * call to aio_fsync(). The function call shall return when the synchronization + * request has been initiated or queued to the file or device (even when the data + * cannot be synchronized immediately). + * + * option: If op is O_DSYNC, all currently queued I/O operations shall be completed + * as if by a call to fdatasync(); that is, as defined for synchronized I/O data + * integrity completion. + * + * option: If op is O_SYNC, all currently queued I/O operations shall be completed + * as if by a call to fsync(); that is, as defined for synchronized I/O file integrity + * completion. If the aio_fsync() function fails, or if the operation queued by + * aio_fsync() fails, then outstanding I/O operations are not guaranteed to have + * been completed. + * + * If aio_fsync() succeeds, then it is only the I/O that was queued at the time + * of the call to aio_fsync() that is guaranteed to be forced to the relevant + * completion state. The completion of subsequent I/O on the file descriptor is + * not guaranteed to be completed in a synchronized fashion. + * + * The aiocbp argument refers to an asynchronous I/O control block. The aiocbp + * value may be used as an argument to aio_error() and aio_return() in order to + * determine the error status and return status, respectively, of the asynchronous + * operation while it is proceeding. When the request is queued, the error status + * for the operation is [EINPROGRESS]. When all data has been successfully transferred, + * the error status shall be reset to reflect the success or failure of the operation. + * If the operation does not complete successfully, the error status for the + * operation shall be set to indicate the error. The aio_sigevent member determines + * the asynchronous notification to occur as specified in Signal Generation and + * Delivery when all operations have achieved synchronized I/O completion. All + * other members of the structure referenced by aiocbp are ignored. If the control + * block referenced by aiocbp becomes an illegal address prior to asynchronous + * I/O completion, then the behavior is undefined. + * + * If the aio_fsync() function fails or aiocbp indicates an error condition, + * data is not guaranteed to have been successfully transferred. + */ +static void aio_fync_work(struct rt_work* work, void* work_data) +{ + int result; + rt_ubase_t level; + struct aiocb *cb = (struct aiocb*)work_data; + + RT_ASSERT(cb != RT_NULL); + + result = fsync(cb->aio_fildes); + /* modify result */ + level = rt_hw_interrupt_disable(); + if (result < 0) + cb->aio_result = errno; + else + cb->aio_result = 0; + rt_hw_interrupt_enable(level); + + return ; +} + +int aio_fsync(int op, struct aiocb *cb) +{ + rt_ubase_t level; + if (!cb) return -EINVAL; + + level = rt_hw_interrupt_disable(); + cb->aio_result = -EINPROGRESS; + rt_hw_interrupt_enable(level); + + rt_work_init(&(cb->aio_work), aio_fync_work, cb); + rt_workqueue_dowork(aio_queue, &(cb->aio_work)); + + return 0; +} + +static void aio_read_work(struct rt_work* work, void* work_data) +{ + int len; + rt_ubase_t level; + uint8_t *buf_ptr; + struct aiocb *cb = (struct aiocb*)work_data; + + buf_ptr = (uint8_t*)cb->aio_buf; + + /* seek to offset */ + lseek(cb->aio_fildes, cb->aio_offset, SEEK_SET); + len = read(cb->aio_fildes, &buf_ptr[cb->aio_offset], cb->aio_nbytes); + + /* modify result */ + level = rt_hw_interrupt_disable(); + if (len <= 0) + cb->aio_result = errno; + else + cb->aio_result = len; + rt_hw_interrupt_enable(level); + + return ; +} + +/** + * The aio_read() function shall read aiocbp->aio_nbytes from the file associated + * with aiocbp->aio_fildes into the buffer pointed to by aiocbp->aio_buf. The + * function call shall return when the read request has been initiated or queued + * to the file or device (even when the data cannot be delivered immediately). + * + * If prioritized I/O is supported for this file, then the asynchronous operation + * shall be submitted at a priority equal to a base scheduling priority minus + * aiocbp->aio_reqprio. If Thread Execution Scheduling is not supported, then + * the base scheduling priority is that of the calling process; + * + * otherwise, the base scheduling priority is that of the calling thread. + * + * The aiocbp value may be used as an argument to aio_error() and aio_return() + * in order to determine the error status and return status, respectively, of + * the asynchronous operation while it is proceeding. If an error condition is + * encountered during queuing, the function call shall return without having + * initiated or queued the request. The requested operation takes place at the + * absolute position in the file as given by aio_offset, as if lseek() were called + * immediately prior to the operation with an offset equal to aio_offset and a + * whence equal to SEEK_SET. After a successful call to enqueue an asynchronous + * I/O operation, the value of the file offset for the file is unspecified. + * + * The aio_sigevent member specifies the notification which occurs when the + * request is completed. + * + * The aiocbp->aio_lio_opcode field shall be ignored by aio_read(). + * + * The aiocbp argument points to an aiocb structure. If the buffer pointed to by + * aiocbp->aio_buf or the control block pointed to by aiocbp becomes an illegal + * address prior to asynchronous I/O completion, then the behavior is undefined. + * + * Simultaneous asynchronous operations using the same aiocbp produce undefined + * results. + * + * If synchronized I/O is enabled on the file associated with aiocbp->aio_fildes, + * the behavior of this function shall be according to the definitions of synchronized + * I/O data integrity completion and synchronized I/O file integrity completion. + * + * For any system action that changes the process memory space while an asynchronous + * I/O is outstanding to the address range being changed, the result of that action + * is undefined. + * + * For regular files, no data transfer shall occur past the offset maximum + * established in the open file description associated with aiocbp->aio_fildes. + * + */ +int aio_read(struct aiocb *cb) +{ + rt_ubase_t level; + + if (!cb) return -EINVAL; + if (cb->aio_offset < 0) return -EINVAL; + + level = rt_hw_interrupt_disable(); + cb->aio_result = -EINPROGRESS; + rt_hw_interrupt_enable(level); + + /* en-queue read work */ + rt_work_init(&(cb->aio_work), aio_read_work, cb); + rt_workqueue_dowork(aio_queue, &(cb->aio_work)); + + return 0; +} + +/** + * The aio_return() function shall return the return status associated with the + * aiocb structure referenced by the aiocbp argument. The return status for an + * asynchronous I/O operation is the value that would be returned by the corresponding + * read(), write(), or fsync() function call. If the error status for the operation + * is equal to [EINPROGRESS], then the return status for the operation is undefined. + * The aio_return() function may be called exactly once to retrieve the return + * status of a given asynchronous operation; thereafter, if the same aiocb structure + * is used in a call to aio_return() or aio_error(), an error may be returned. + * When the aiocb structure referred to by aiocbp is used to submit another asynchronous + * operation, then aio_return() may be successfully used to retrieve the return + * status of that operation. + */ +ssize_t aio_return(struct aiocb *cb) +{ + if (cb) + { + if (cb->aio_result < 0) + rt_set_errno(cb->aio_result); + + return cb->aio_result; + } + + return -EINVAL; +} + +/** + * The aio_suspend() function shall suspend the calling thread until at least + * one of the asynchronous I/O operations referenced by the list argument has + * completed, until a signal interrupts the function, or, if timeout is not NULL, + * until the time interval specified by timeout has passed. If any of the aiocb + * structures in the list correspond to completed asynchronous I/O operations + * (that is, the error status for the operation is not equal to [EINPROGRESS]) + * at the time of the call, the function shall return without suspending the + * calling thread. The list argument is an array of pointers to asynchronous I/O + * control blocks. The nent argument indicates the number of elements in the + * array. Each aiocb structure pointed to has been used in initiating an asynchronous + * I/O request via aio_read(), aio_write(), or lio_listio(). This array may + * contain null pointers, which are ignored. If this array contains pointers + * that refer to aiocb structures that have not been used in submitting asynchronous + * I/O, the effect is undefined. + * + * If the time interval indicated in the timespec structure pointed to by timeout + * passes before any of the I/O operations referenced by list are completed, then + * aio_suspend() shall return with an error. + */ +int aio_suspend(const struct aiocb *const list[], int nent, + const struct timespec *timeout) +{ + return -ENOSYS; +} + +static void aio_write_work(struct rt_work* work, void* work_data) +{ + int len, oflags, level; + uint8_t *buf_ptr; + struct aiocb *cb = (struct aiocb*)work_data; + + buf_ptr = (uint8_t*)cb->aio_buf; + + /* whether seek offset */ + oflags = fcntl(cb->aio_fildes, F_GETFL, 0); + if ((oflags & O_APPEND) == 0) + { + lseek(cb->aio_fildes, SEEK_SET, cb->aio_offset); + } + + /* write data */ + len = write(cb->aio_fildes, buf_ptr, cb->aio_nbytes); + + /* modify result */ + level = rt_hw_interrupt_disable(); + if (len <= 0) + cb->aio_result = errno; + else + cb->aio_result = len; + rt_hw_interrupt_enable(level); + + return; +} + +/** + * The aio_write() function shall write aiocbp->aio_nbytes to the file associated + * with aiocbp->aio_fildes from the buffer pointed to by aiocbp->aio_buf. The + * function shall return when the write request has been initiated or, at a minimum, + * queued to the file or device. + * + * The aiocbp argument may be used as an argument to aio_error() and aio_return() + * in order to determine the error status and return status, respectively, of the + * asynchronous operation while it is proceeding. + * + * The aiocbp argument points to an aiocb structure. If the buffer pointed to by + * aiocbp->aio_buf or the control block pointed to by aiocbp becomes an illegal + * address prior to asynchronous I/O completion, then the behavior is undefined. + * + * If O_APPEND is not set for the file descriptor aio_fildes, then the requested + * operation shall take place at the absolute position in the file as given by + * aio_offset, as if lseek() were called immediately prior to the operation with + * an offset equal to aio_offset and a whence equal to SEEK_SET. If O_APPEND is + * set for the file descriptor, or if aio_fildes is associated with a device that + * is incapable of seeking, write operations append to the file in the same order + * as the calls were made, except under circumstances described in Asynchronous + * I/O. After a successful call to enqueue an asynchronous I/O operation, the value + * of the file offset for the file is unspecified. + * + * The aio_sigevent member specifies the notification which occurs when the request + * is completed. + * + * The aiocbp->aio_lio_opcode field shall be ignored by aio_write(). + * + * Simultaneous asynchronous operations using the same aiocbp produce undefined + * results. + * + * If synchronized I/O is enabled on the file associated with aiocbp->aio_fildes, + * the behavior of this function shall be according to the definitions of synchronized + * I/O data integrity completion, and synchronized I/O file integrity completion. + * + * For regular files, no data transfer shall occur past the offset maximum established + * in the open file description associated with aiocbp->aio_fildes. + */ +int aio_write(struct aiocb *cb) +{ + int oflags; + rt_ubase_t level; + + if (!cb || (cb->aio_buf == NULL)) return -EINVAL; + + /* check access mode */ + oflags = fcntl(cb->aio_fildes, F_GETFL, 0); + if ((oflags & O_ACCMODE) != O_WRONLY || + (oflags & O_ACCMODE) != O_RDWR) + return -EINVAL; + + level = rt_hw_interrupt_disable(); + cb->aio_result = -EINPROGRESS; + rt_hw_interrupt_enable(level); + + rt_work_init(&(cb->aio_work), aio_write_work, cb); + rt_workqueue_dowork(aio_queue, &(cb->aio_work)); + + return 0; +} + +/** + * The lio_listio() function shall initiate a list of I/O requests with a single + * function call. + * + * The mode argument takes one of the values LIO_WAIT or LIO_NOWAIT declared in + * and determines whether the function returns when the I/O operations + * have been completed, or as soon as the operations have been queued. If the + * mode argument is LIO_WAIT, the function shall wait until all I/O is complete + * and the sig argument shall be ignored. + * + * If the mode argument is LIO_NOWAIT, the function shall return immediately, and + * asynchronous notification shall occur, according to the sig argument, when all + * the I/O operations complete. If sig is NULL, then no asynchronous notification + * shall occur. If sig is not NULL, asynchronous notification occurs as specified + * in Signal Generation and Delivery when all the requests in list have completed. + * + * The I/O requests enumerated by list are submitted in an unspecified order. + * + * The list argument is an array of pointers to aiocb structures. The array contains + * nent elements. The array may contain NULL elements, which shall be ignored. + * + * If the buffer pointed to by list or the aiocb structures pointed to by the + * elements of the array list become illegal addresses before all asynchronous I/O + * completed and, if necessary, the notification is sent, then the behavior is + * undefined. If the buffers pointed to by the aio_buf member of the aiocb structure + * pointed to by the elements of the array list become illegal addresses prior to + * the asynchronous I/O associated with that aiocb structure being completed, the + * behavior is undefined. + * + * The aio_lio_opcode field of each aiocb structure specifies the operation to be + * performed. The supported operations are LIO_READ, LIO_WRITE, and LIO_NOP; these + * symbols are defined in . The LIO_NOP operation causes the list entry to + * be ignored. If the aio_lio_opcode element is equal to LIO_READ, then an I/O operation + * is submitted as if by a call to aio_read() with the aiocbp equal to the address + * of the aiocb structure. If the aio_lio_opcode element is equal to LIO_WRITE, then + * an I/O operation is submitted as if by a call to aio_write() with the aiocbp equal + * to the address of the aiocb structure. + * + * The aio_fildes member specifies the file descriptor on which the operation is to + * be performed. + * + * The aio_buf member specifies the address of the buffer to or from which the data + * is transferred. + * + * The aio_nbytes member specifies the number of bytes of data to be transferred. + * + * The members of the aiocb structure further describe the I/O operation to be + * performed, in a manner identical to that of the corresponding aiocb structure + * when used by the aio_read() and aio_write() functions. + * + * The nent argument specifies how many elements are members of the list; that is, + * the length of the array. + * + * The behavior of this function is altered according to the definitions of synchronized + * I/O data integrity completion and synchronized I/O file integrity completion if + * synchronized I/O is enabled on the file associated with aio_fildes. + * + * For regular files, no data transfer shall occur past the offset maximum established + * in the open file description associated with aiocbp->aio_fildes. + * + * If sig->sigev_notify is SIGEV_THREAD and sig->sigev_notify_attributes is a + * non-null pointer and the block pointed to by this pointer becomes an illegal + * address prior to all asynchronous I/O being completed, then the behavior is + * undefined. + */ +int lio_listio(int mode, struct aiocb * const list[], int nent, + struct sigevent *sig) +{ + return -ENOSYS; +} + +int aio_system_init(void) +{ + aio_queue = rt_workqueue_create("aio", 2048, RT_THREAD_PRIORITY_MAX/2); + RT_ASSERT(aio_queue != NULL); + + return 0; +} +INIT_COMPONENT_EXPORT(aio_system_init); diff --git a/components/libc/posix/io/aio/aio.h b/components/libc/posix/io/aio/aio.h new file mode 100644 index 0000000000..35a5c194db --- /dev/null +++ b/components/libc/posix/io/aio/aio.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2017/12/30 Bernard The first version. + */ + +#ifndef __AIO_H__ +#define __AIO_H__ + +#include +#include +#include + +struct aiocb +{ + int aio_fildes; /* File descriptor. */ + off_t aio_offset; /* File offset. */ + + volatile void *aio_buf; /* Location of buffer. */ + size_t aio_nbytes; /* Length of transfer. */ + int aio_reqprio; /* Request priority offset. */ + struct sigevent aio_sigevent; /* Signal number and value. */ + int aio_lio_opcode; /* Operation to be performed. */ + + int aio_result; + struct rt_work aio_work; +}; + +int aio_cancel(int fd, struct aiocb *cb); +int aio_error (const struct aiocb *cb); + +int aio_fsync(int op, struct aiocb *cb); + +int aio_read(struct aiocb *cb); +ssize_t aio_return(struct aiocb *cb); +int aio_suspend(const struct aiocb *const list[], int nent, + const struct timespec *timeout); +int aio_write(struct aiocb *cb); + +int lio_listio(int mode, struct aiocb * const list[], int nent, + struct sigevent *sig); + +#endif diff --git a/components/libc/posix/io/libc.c b/components/libc/posix/io/libc.c new file mode 100644 index 0000000000..c324d84ef8 --- /dev/null +++ b/components/libc/posix/io/libc.c @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2017/10/15 bernard the first version + */ +#include +#include +#include +#include +#include +#include +#include +#include "libc.h" +#include +#include +#ifdef RT_USING_PTHREADS +#include +#endif + +int libc_system_init(void) +{ +#ifdef RT_USING_POSIX_DEVIO + rt_device_t dev_console; + + dev_console = rt_console_get_device(); + if (dev_console) + { + libc_stdio_set_console(dev_console->parent.name, O_RDWR); + } +#endif /* RT_USING_POSIX_DEVIO */ + +#if defined RT_USING_PTHREADS && !defined RT_USING_COMPONENTS_INIT + pthread_system_init(); +#endif + + return 0; +} +INIT_COMPONENT_EXPORT(libc_system_init); + +#ifdef RT_USING_POSIX_DEVIO +#if defined(RT_USING_LIBC) && defined(RT_USING_NEWLIB) +#define STDIO_DEVICE_NAME_MAX 32 +static FILE* std_console = NULL; +int libc_stdio_set_console(const char* device_name, int mode) +{ + FILE *fp; + char name[STDIO_DEVICE_NAME_MAX]; + char *file_mode; + + snprintf(name, sizeof(name) - 1, "/dev/%s", device_name); + name[STDIO_DEVICE_NAME_MAX - 1] = '\0'; + + if (mode == O_RDWR) + { + file_mode = "r+"; + } + else if (mode == O_WRONLY) + { + file_mode = "wb"; + } + else + { + file_mode = "rb"; + } + + fp = fopen(name, file_mode); + if (fp) + { + setvbuf(fp, NULL, _IONBF, 0); + + if (std_console) + { + fclose(std_console); + std_console = NULL; + } + std_console = fp; + + if (mode == O_RDWR) + { + _GLOBAL_REENT->_stdin = std_console; + } + else + { + _GLOBAL_REENT->_stdin = NULL; + } + + if (mode == O_RDONLY) + { + _GLOBAL_REENT->_stdout = NULL; + _GLOBAL_REENT->_stderr = NULL; + } + else + { + _GLOBAL_REENT->_stdout = std_console; + _GLOBAL_REENT->_stderr = std_console; + } + + _GLOBAL_REENT->__sdidinit = 1; + } + + if (std_console) + return fileno(std_console); + + return -1; +} + +int libc_stdio_get_console(void) +{ + if (std_console) + return fileno(std_console); + else + return -1; +} + +#else +#define STDIO_DEVICE_NAME_MAX 32 +static int std_fd = -1; +int libc_stdio_set_console(const char* device_name, int mode) +{ + int fd; + char name[STDIO_DEVICE_NAME_MAX]; + + snprintf(name, sizeof(name) - 1, "/dev/%s", device_name); + name[STDIO_DEVICE_NAME_MAX - 1] = '\0'; + + fd = open(name, mode, 0); + if (fd >= 0) + { + if (std_fd >= 0) + { + close(std_fd); + } + std_fd = fd; + } + + return std_fd; +} + +int libc_stdio_get_console(void) { + return std_fd; +} +#endif /* defined(RT_USING_LIBC) && defined(RT_USING_NEWLIB) */ +#endif /* RT_USING_POSIX_DEVIO */ diff --git a/components/libc/posix/io/libc.h b/components/libc/posix/io/libc.h new file mode 100644 index 0000000000..b019267926 --- /dev/null +++ b/components/libc/posix/io/libc.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2017/10/15 bernard the first version + */ +#ifndef __RTT_LIBC_H__ +#define __RTT_LIBC_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +int libc_system_init(void); +#ifdef RT_USING_POSIX_DEVIO +int libc_stdio_get_console(void); +int libc_stdio_set_console(const char* device_name, int mode); +#endif /* RT_USING_POSIX_DEVIO */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/components/libc/posix/io/mmap.c b/components/libc/posix/io/mmap.c new file mode 100644 index 0000000000..e68b82e640 --- /dev/null +++ b/components/libc/posix/io/mmap.c @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2017/11/30 Bernard The first version. + */ + +#include +#include + +#include +#include + +#include + +void *mmap(void *addr, size_t length, int prot, int flags, + int fd, off_t offset) +{ + uint8_t *mem; + + if (addr) + { + mem = addr; + } + else mem = (uint8_t *)malloc(length); + + if (mem) + { + off_t cur; + size_t read_bytes; + + cur = lseek(fd, 0, SEEK_SET); + + lseek(fd, offset, SEEK_SET); + read_bytes = read(fd, mem, length); + if (read_bytes != length) + { + if (addr == RT_NULL) + { + /* read failed */ + free(mem); + mem = RT_NULL; + } + } + lseek(fd, cur, SEEK_SET); + + return mem; + } + + errno = ENOMEM; + + return MAP_FAILED; +} + +int munmap(void *addr, size_t length) +{ + if (addr) + { + free(addr); + return 0; + } + + return -1; +} diff --git a/components/libc/posix/io/poll/SConscript b/components/libc/posix/io/poll/SConscript new file mode 100644 index 0000000000..47f1722ed3 --- /dev/null +++ b/components/libc/posix/io/poll/SConscript @@ -0,0 +1,11 @@ +# RT-Thread building script for component + +from building import * + +cwd = GetCurrentDir() +src = ['poll.c'] +CPPPATH = [cwd] + +group = DefineGroup('POSIX', src, depend = ['RT_USING_POSIX_POLL'], CPPPATH = CPPPATH) + +Return('group') diff --git a/components/libc/posix/io/poll/poll.c b/components/libc/posix/io/poll/poll.c new file mode 100644 index 0000000000..0c773b306c --- /dev/null +++ b/components/libc/posix/io/poll/poll.c @@ -0,0 +1,226 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2016-12-28 Bernard first version + * 2018-03-09 Bernard Add protection for pt->triggered. + */ +#include +#include +#include +#include +#include + +struct rt_poll_node; + +struct rt_poll_table +{ + rt_pollreq_t req; + rt_uint32_t triggered; /* the waited thread whether triggered */ + rt_thread_t polling_thread; + struct rt_poll_node *nodes; +}; + +struct rt_poll_node +{ + struct rt_wqueue_node wqn; + struct rt_poll_table *pt; + struct rt_poll_node *next; +}; + +static int __wqueue_pollwake(struct rt_wqueue_node *wait, void *key) +{ + struct rt_poll_node *pn; + + if (key && !((rt_ubase_t)key & wait->key)) + return -1; + + pn = rt_container_of(wait, struct rt_poll_node, wqn); + pn->pt->triggered = 1; + + return __wqueue_default_wake(wait, key); +} + +static void _poll_add(rt_wqueue_t *wq, rt_pollreq_t *req) +{ + struct rt_poll_table *pt; + struct rt_poll_node *node; + + node = (struct rt_poll_node *)rt_malloc(sizeof(struct rt_poll_node)); + if (node == RT_NULL) + return; + + pt = rt_container_of(req, struct rt_poll_table, req); + + node->wqn.key = req->_key; + rt_list_init(&(node->wqn.list)); + node->wqn.polling_thread = pt->polling_thread; + node->wqn.wakeup = __wqueue_pollwake; + node->next = pt->nodes; + node->pt = pt; + pt->nodes = node; + rt_wqueue_add(wq, &node->wqn); +} + +static void poll_table_init(struct rt_poll_table *pt) +{ + pt->req._proc = _poll_add; + pt->triggered = 0; + pt->nodes = RT_NULL; + pt->polling_thread = rt_thread_self(); +} + +static int poll_wait_timeout(struct rt_poll_table *pt, int msec) +{ + rt_int32_t timeout; + int ret = 0; + struct rt_thread *thread; + rt_base_t level; + + thread = pt->polling_thread; + + timeout = rt_tick_from_millisecond(msec); + + level = rt_hw_interrupt_disable(); + + if (timeout != 0 && !pt->triggered) + { + rt_thread_suspend(thread); + if (timeout > 0) + { + rt_timer_control(&(thread->thread_timer), + RT_TIMER_CTRL_SET_TIME, + &timeout); + rt_timer_start(&(thread->thread_timer)); + } + + rt_hw_interrupt_enable(level); + + rt_schedule(); + + level = rt_hw_interrupt_disable(); + } + + ret = !pt->triggered; + rt_hw_interrupt_enable(level); + + return ret; +} + +static int do_pollfd(struct pollfd *pollfd, rt_pollreq_t *req) +{ + int mask = 0; + int fd; + + fd = pollfd->fd; + + if (fd >= 0) + { + struct dfs_fd *f = fd_get(fd); + mask = POLLNVAL; + + if (f) + { + mask = POLLMASK_DEFAULT; + if (f->fops->poll) + { + req->_key = pollfd->events | POLLERR | POLLHUP; + + mask = f->fops->poll(f, req); + + /* dealwith the device return error -1*/ + if (mask < 0) + { + fd_put(f); + pollfd->revents = 0; + return mask; + } + } + /* Mask out unneeded events. */ + mask &= pollfd->events | POLLERR | POLLHUP; + fd_put(f); + } + } + pollfd->revents = mask; + + return mask; +} + +static int poll_do(struct pollfd *fds, nfds_t nfds, struct rt_poll_table *pt, int msec) +{ + int num; + int istimeout = 0; + int n; + struct pollfd *pf; + int ret = 0; + + if (msec == 0) + { + pt->req._proc = RT_NULL; + istimeout = 1; + } + + while (1) + { + pf = fds; + num = 0; + + for (n = 0; n < nfds; n ++) + { + ret = do_pollfd(pf, &pt->req); + if(ret < 0) + { + /*dealwith the device return error -1 */ + pt->req._proc = RT_NULL; + return ret; + } + else if(ret > 0) + { + num ++; + pt->req._proc = RT_NULL; + } + pf ++; + } + + pt->req._proc = RT_NULL; + + if (num || istimeout) + break; + + if (poll_wait_timeout(pt, msec)) + istimeout = 1; + } + + return num; +} + +static void poll_teardown(struct rt_poll_table *pt) +{ + struct rt_poll_node *node, *next; + + next = pt->nodes; + while (next) + { + node = next; + rt_wqueue_remove(&node->wqn); + next = node->next; + rt_free(node); + } +} + +int poll(struct pollfd *fds, nfds_t nfds, int timeout) +{ + int num; + struct rt_poll_table table; + + poll_table_init(&table); + + num = poll_do(fds, nfds, &table, timeout); + + poll_teardown(&table); + + return num; +} diff --git a/components/libc/posix/io/poll/poll.h b/components/libc/posix/io/poll/poll.h new file mode 100644 index 0000000000..aea73d6eaf --- /dev/null +++ b/components/libc/posix/io/poll/poll.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-09-11 Meco Man First version + */ +#ifndef __POLL_H__ +#define __POLL_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(POLLIN) && !defined(POLLOUT) +#define POLLIN (0x01) +#define POLLRDNORM (0x01) +#define POLLRDBAND (0x01) +#define POLLPRI (0x01) + +#define POLLOUT (0x02) +#define POLLWRNORM (0x02) +#define POLLWRBAND (0x02) + +#define POLLERR (0x04) +#define POLLHUP (0x08) +#define POLLNVAL (0x10) + +typedef unsigned int nfds_t; + +struct pollfd +{ + int fd; + short events; + short revents; +}; +#endif /* !defined(POLLIN) && !defined(POLLOUT) */ + +#define POLLMASK_DEFAULT (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM) + +int poll(struct pollfd *fds, nfds_t nfds, int timeout); + +#ifdef __cplusplus +} +#endif + +#endif /* __POLL_H__ */ diff --git a/components/libc/posix/io/select.c b/components/libc/posix/io/select.c new file mode 100644 index 0000000000..55d320e921 --- /dev/null +++ b/components/libc/posix/io/select.c @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2016-12-28 Bernard first version + */ +#include +#include +#include + +static void fdszero(fd_set *set, int nfds) +{ + fd_mask *m; + int n; + + /* + The 'sizeof(fd_set)' of the system space may differ from user space, + so the actual size of the 'fd_set' is determined here with the parameter 'nfds' + */ + m = (fd_mask *)set; + for (n = 0; n < nfds; n += (sizeof(fd_mask) * 8)) + { + rt_memset(m, 0, sizeof(fd_mask)); + m ++; + } +} + +int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout) +{ + int fd; + int npfds; + int msec; + int ndx; + int ret; + struct pollfd *pollset = RT_NULL; + + /* How many pollfd structures do we need to allocate? */ + for (fd = 0, npfds = 0; fd < nfds; fd++) + { + /* Check if any monitor operation is requested on this fd */ + if ((readfds && FD_ISSET(fd, readfds)) || + (writefds && FD_ISSET(fd, writefds)) || + (exceptfds && FD_ISSET(fd, exceptfds))) + { + npfds++; + } + } + + /* Allocate the descriptor list for poll() */ + if (npfds > 0) + { + pollset = (struct pollfd *)rt_calloc(npfds, sizeof(struct pollfd)); + if (!pollset) + { + return -1; + } + } + + /* Initialize the descriptor list for poll() */ + for (fd = 0, ndx = 0; fd < nfds; fd++) + { + int incr = 0; + + /* The readfs set holds the set of FDs that the caller can be assured + * of reading from without blocking. Note that POLLHUP is included as + * a read-able condition. POLLHUP will be reported at the end-of-file + * or when a connection is lost. In either case, the read() can then + * be performed without blocking. + */ + + if (readfds && FD_ISSET(fd, readfds)) + { + pollset[ndx].fd = fd; + pollset[ndx].events |= POLLIN; + incr = 1; + } + + if (writefds && FD_ISSET(fd, writefds)) + { + pollset[ndx].fd = fd; + pollset[ndx].events |= POLLOUT; + incr = 1; + } + + if (exceptfds && FD_ISSET(fd, exceptfds)) + { + pollset[ndx].fd = fd; + incr = 1; + } + + ndx += incr; + } + + RT_ASSERT(ndx == npfds); + + /* Convert the timeout to milliseconds */ + if (timeout) + { + msec = timeout->tv_sec * 1000 + timeout->tv_usec / 1000; + } + else + { + msec = -1; + } + + /* Then let poll do all of the real work. */ + + ret = poll(pollset, npfds, msec); + + /* Now set up the return values */ + if (readfds) + { + fdszero(readfds, nfds); + } + + if (writefds) + { + fdszero(writefds, nfds); + } + + if (exceptfds) + { + fdszero(exceptfds, nfds); + } + + /* Convert the poll descriptor list back into selects 3 bitsets */ + + if (ret > 0) + { + ret = 0; + for (ndx = 0; ndx < npfds; ndx++) + { + /* Check for read conditions. Note that POLLHUP is included as a + * read condition. POLLHUP will be reported when no more data will + * be available (such as when a connection is lost). In either + * case, the read() can then be performed without blocking. + */ + + if (readfds) + { + if (pollset[ndx].revents & (POLLIN | POLLHUP)) + { + FD_SET(pollset[ndx].fd, readfds); + ret++; + } + } + + /* Check for write conditions */ + if (writefds) + { + if (pollset[ndx].revents & POLLOUT) + { + FD_SET(pollset[ndx].fd, writefds); + ret++; + } + } + + /* Check for exceptions */ + if (exceptfds) + { + if (pollset[ndx].revents & POLLERR) + { + FD_SET(pollset[ndx].fd, exceptfds); + ret++; + } + } + } + } + + if (pollset) rt_free(pollset); + + return ret; +} diff --git a/components/libc/posix/io/termios/SConscript b/components/libc/posix/io/termios/SConscript new file mode 100644 index 0000000000..68bd9d81c9 --- /dev/null +++ b/components/libc/posix/io/termios/SConscript @@ -0,0 +1,11 @@ +# RT-Thread building script for component + +from building import * + +cwd = GetCurrentDir() +src = ['termios.c'] +CPPPATH = [cwd] + +group = DefineGroup('POSIX', src, depend = ['RT_USING_POSIX_TERMIOS'], CPPPATH = CPPPATH) + +Return('group') diff --git a/components/libc/posix/io/termios/termios.c b/components/libc/posix/io/termios/termios.c new file mode 100644 index 0000000000..d7d869d67f --- /dev/null +++ b/components/libc/posix/io/termios/termios.c @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2017/08/30 Bernard The first version + */ +#include +#include +#include +#include +#include "termios.h" + +int tcgetattr(int fd, struct termios *tio) +{ + /* Get the current serial port settings. */ + if (ioctl(fd, TCGETA, tio)) + return -1; + + return 0; +} + +int tcsetattr(int fd, int act, const struct termios *tio) +{ + switch (act) + { + case TCSANOW: + /* make the change immediately */ + return (ioctl(fd, TCSETA, (void*)tio)); + case TCSADRAIN: + /* + * Don't make the change until all currently written data + * has been transmitted. + */ + return (ioctl(fd, TCSETAW, (void*)tio)); + case TCSAFLUSH: + /* Don't make the change until all currently written data + * has been transmitted, at which point any received but + * unread data is also discarded. + */ + return (ioctl(fd, TCSETAF, (void*)tio)); + default: + errno = EINVAL; + return (-1); + } +} + +/** + * this function gets process group ID for session leader for controlling + * terminal + * + * @return always 0 + */ +pid_t tcgetsid(int fd) +{ + return 0; +} + +speed_t cfgetospeed(const struct termios *tio) +{ + return tio->c_cflag & CBAUD; +} + +speed_t cfgetispeed(const struct termios *tio) +{ + return cfgetospeed(tio); +} + +int cfsetospeed(struct termios *tio, speed_t speed) +{ + if (speed & ~CBAUD) + { + errno = EINVAL; + return -1; + } + + tio->c_cflag &= ~CBAUD; + tio->c_cflag |= speed; + return 0; +} + +int cfsetispeed(struct termios *tio, speed_t speed) +{ + return speed ? cfsetospeed(tio, speed) : 0; +} + +int tcsendbreak(int fd, int dur) +{ + /* nonzero duration is implementation-defined, so ignore it */ + return 0; +} + +int tcflush(int fd, int queue) +{ + return ioctl(fd, TCFLSH, (void*)queue); +} + +int tcflow(int fd, int action) +{ + return ioctl(fd, TCXONC, (void*)action); +} + +/** + * this function waits for transmission of output + */ +int tcdrain(int fd) +{ + return 0; +} + +#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) +void cfmakeraw(struct termios *t) +{ + t->c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON); + t->c_oflag &= ~OPOST; + t->c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN); + t->c_cflag &= ~(CSIZE|PARENB); + t->c_cflag |= CS8; + t->c_cc[VMIN] = 1; + t->c_cc[VTIME] = 0; +} + +int cfsetspeed(struct termios *tio, speed_t speed) +{ + return cfsetospeed(tio, speed); +} +#endif diff --git a/components/libc/posix/io/termios/termios.h b/components/libc/posix/io/termios/termios.h new file mode 100644 index 0000000000..b647fa0728 --- /dev/null +++ b/components/libc/posix/io/termios/termios.h @@ -0,0 +1,213 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2017/08/30 Bernard The first version + */ +#ifndef __TERMIOS_H__ +#define __TERMIOS_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef unsigned char cc_t; +typedef unsigned int speed_t; +typedef unsigned int tcflag_t; + +#define NCCS 32 + +struct termios { + tcflag_t c_iflag; + tcflag_t c_oflag; + tcflag_t c_cflag; + tcflag_t c_lflag; + cc_t c_line; + cc_t c_cc[NCCS]; + speed_t __c_ispeed; + speed_t __c_ospeed; +}; + +#define VINTR 0 +#define VQUIT 1 +#define VERASE 2 +#define VKILL 3 +#define VEOF 4 +#define VTIME 5 +#define VMIN 6 +#define VSWTC 7 +#define VSTART 8 +#define VSTOP 9 +#define VSUSP 10 +#define VEOL 11 +#define VREPRINT 12 +#define VDISCARD 13 +#define VWERASE 14 +#define VLNEXT 15 +#define VEOL2 16 + +#define IGNBRK 0000001 +#define BRKINT 0000002 +#define IGNPAR 0000004 +#define PARMRK 0000010 +#define INPCK 0000020 +#define ISTRIP 0000040 +#define INLCR 0000100 +#define IGNCR 0000200 +#define ICRNL 0000400 +#define IUCLC 0001000 +#define IXON 0002000 +#define IXANY 0004000 +#define IXOFF 0010000 +#define IMAXBEL 0020000 +#define IUTF8 0040000 + +#define OPOST 0000001 +#define OLCUC 0000002 +#define ONLCR 0000004 +#define OCRNL 0000010 +#define ONOCR 0000020 +#define ONLRET 0000040 +#define OFILL 0000100 +#define OFDEL 0000200 +#define NLDLY 0000400 +#define NL0 0000000 +#define NL1 0000400 +#define CRDLY 0003000 +#define CR0 0000000 +#define CR1 0001000 +#define CR2 0002000 +#define CR3 0003000 +#define TABDLY 0014000 +#define TAB0 0000000 +#define TAB1 0004000 +#define TAB2 0010000 +#define TAB3 0014000 +#define BSDLY 0020000 +#define BS0 0000000 +#define BS1 0020000 +#define FFDLY 0100000 +#define FF0 0000000 +#define FF1 0100000 + +#define VTDLY 0040000 +#define VT0 0000000 +#define VT1 0040000 + +#define B0 0000000 +#define B50 0000001 +#define B75 0000002 +#define B110 0000003 +#define B134 0000004 +#define B150 0000005 +#define B200 0000006 +#define B300 0000007 +#define B600 0000010 +#define B1200 0000011 +#define B1800 0000012 +#define B2400 0000013 +#define B4800 0000014 +#define B9600 0000015 +#define B19200 0000016 +#define B38400 0000017 + +#define B57600 0010001 +#define B115200 0010002 +#define B230400 0010003 +#define B460800 0010004 +#define B500000 0010005 +#define B576000 0010006 +#define B921600 0010007 +#define B1000000 0010010 +#define B1152000 0010011 +#define B1500000 0010012 +#define B2000000 0010013 +#define B2500000 0010014 +#define B3000000 0010015 +#define B3500000 0010016 +#define B4000000 0010017 + +#define CSIZE 0000060 +#define CS5 0000000 +#define CS6 0000020 +#define CS7 0000040 +#define CS8 0000060 +#define CSTOPB 0000100 +#define CREAD 0000200 +#define PARENB 0000400 +#define PARODD 0001000 +#define HUPCL 0002000 +#define CLOCAL 0004000 + +#define ISIG 0000001 +#define ICANON 0000002 +#define ECHO 0000010 +#define ECHOE 0000020 +#define ECHOK 0000040 +#define ECHONL 0000100 +#define NOFLSH 0000200 +#define TOSTOP 0000400 +#define IEXTEN 0100000 + +#define TCOOFF 0 +#define TCOON 1 +#define TCIOFF 2 +#define TCION 3 + +#define TCIFLUSH 0 +#define TCOFLUSH 1 +#define TCIOFLUSH 2 + +#define TCSANOW 0 +#define TCSADRAIN 1 +#define TCSAFLUSH 2 + +#define EXTA 0000016 +#define EXTB 0000017 +#define CBAUD 0010017 +#define CBAUDEX 0010000 +#define CIBAUD 002003600000 +#define CMSPAR 010000000000 +#define CRTSCTS 020000000000 + +#define XCASE 0000004 +#define ECHOCTL 0001000 +#define ECHOPRT 0002000 +#define ECHOKE 0004000 +#define FLUSHO 0010000 +#define PENDIN 0040000 +#define EXTPROC 0200000 + +#define XTABS 0014000 + +speed_t cfgetospeed (const struct termios *); +speed_t cfgetispeed (const struct termios *); +int cfsetospeed (struct termios *, speed_t); +int cfsetispeed (struct termios *, speed_t); + +int tcgetattr (int, struct termios *); +int tcsetattr (int, int, const struct termios *); + +int tcsendbreak (int, int); +int tcdrain (int); +int tcflush (int, int); +int tcflow (int, int); + +pid_t tcgetsid (int); + +#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) +void cfmakeraw(struct termios *); +int cfsetspeed(struct termios *, speed_t); +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/components/libc/posix/src/SConscript b/components/libc/posix/src/SConscript index 4be5ac83cc..87be6b6a06 100644 --- a/components/libc/posix/src/SConscript +++ b/components/libc/posix/src/SConscript @@ -10,26 +10,10 @@ group = [] flag = False src += ['unistd.c'] #TODO -if GetDepend('RT_USING_POSIX_DEVIO'): - src += ['libc.c'] - flag = True - if GetDepend('RT_USING_POSIX_DELAY'): src += ['delay.c'] flag = True -if GetDepend('RT_USING_POSIX_POLL'): - src += ['poll.c'] - flag = True - -if GetDepend('RT_USING_POSIX_SELECT'): - src += ['select.c'] - flag = True - -if GetDepend('RT_USING_POSIX_MMAP'): - src += ['mmap.c'] - flag = True - if flag == True: group = DefineGroup('POSIX', src, depend = [], CPPPATH = CPPPATH) diff --git a/components/libc/posix/src/libc.c b/components/libc/posix/src/libc.c deleted file mode 100644 index c324d84ef8..0000000000 --- a/components/libc/posix/src/libc.c +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2017/10/15 bernard the first version - */ -#include -#include -#include -#include -#include -#include -#include -#include "libc.h" -#include -#include -#ifdef RT_USING_PTHREADS -#include -#endif - -int libc_system_init(void) -{ -#ifdef RT_USING_POSIX_DEVIO - rt_device_t dev_console; - - dev_console = rt_console_get_device(); - if (dev_console) - { - libc_stdio_set_console(dev_console->parent.name, O_RDWR); - } -#endif /* RT_USING_POSIX_DEVIO */ - -#if defined RT_USING_PTHREADS && !defined RT_USING_COMPONENTS_INIT - pthread_system_init(); -#endif - - return 0; -} -INIT_COMPONENT_EXPORT(libc_system_init); - -#ifdef RT_USING_POSIX_DEVIO -#if defined(RT_USING_LIBC) && defined(RT_USING_NEWLIB) -#define STDIO_DEVICE_NAME_MAX 32 -static FILE* std_console = NULL; -int libc_stdio_set_console(const char* device_name, int mode) -{ - FILE *fp; - char name[STDIO_DEVICE_NAME_MAX]; - char *file_mode; - - snprintf(name, sizeof(name) - 1, "/dev/%s", device_name); - name[STDIO_DEVICE_NAME_MAX - 1] = '\0'; - - if (mode == O_RDWR) - { - file_mode = "r+"; - } - else if (mode == O_WRONLY) - { - file_mode = "wb"; - } - else - { - file_mode = "rb"; - } - - fp = fopen(name, file_mode); - if (fp) - { - setvbuf(fp, NULL, _IONBF, 0); - - if (std_console) - { - fclose(std_console); - std_console = NULL; - } - std_console = fp; - - if (mode == O_RDWR) - { - _GLOBAL_REENT->_stdin = std_console; - } - else - { - _GLOBAL_REENT->_stdin = NULL; - } - - if (mode == O_RDONLY) - { - _GLOBAL_REENT->_stdout = NULL; - _GLOBAL_REENT->_stderr = NULL; - } - else - { - _GLOBAL_REENT->_stdout = std_console; - _GLOBAL_REENT->_stderr = std_console; - } - - _GLOBAL_REENT->__sdidinit = 1; - } - - if (std_console) - return fileno(std_console); - - return -1; -} - -int libc_stdio_get_console(void) -{ - if (std_console) - return fileno(std_console); - else - return -1; -} - -#else -#define STDIO_DEVICE_NAME_MAX 32 -static int std_fd = -1; -int libc_stdio_set_console(const char* device_name, int mode) -{ - int fd; - char name[STDIO_DEVICE_NAME_MAX]; - - snprintf(name, sizeof(name) - 1, "/dev/%s", device_name); - name[STDIO_DEVICE_NAME_MAX - 1] = '\0'; - - fd = open(name, mode, 0); - if (fd >= 0) - { - if (std_fd >= 0) - { - close(std_fd); - } - std_fd = fd; - } - - return std_fd; -} - -int libc_stdio_get_console(void) { - return std_fd; -} -#endif /* defined(RT_USING_LIBC) && defined(RT_USING_NEWLIB) */ -#endif /* RT_USING_POSIX_DEVIO */ diff --git a/components/libc/posix/src/libc.h b/components/libc/posix/src/libc.h deleted file mode 100644 index b019267926..0000000000 --- a/components/libc/posix/src/libc.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2017/10/15 bernard the first version - */ -#ifndef __RTT_LIBC_H__ -#define __RTT_LIBC_H__ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -int libc_system_init(void); -#ifdef RT_USING_POSIX_DEVIO -int libc_stdio_get_console(void); -int libc_stdio_set_console(const char* device_name, int mode); -#endif /* RT_USING_POSIX_DEVIO */ - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/components/libc/posix/src/mmap.c b/components/libc/posix/src/mmap.c deleted file mode 100644 index e68b82e640..0000000000 --- a/components/libc/posix/src/mmap.c +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2017/11/30 Bernard The first version. - */ - -#include -#include - -#include -#include - -#include - -void *mmap(void *addr, size_t length, int prot, int flags, - int fd, off_t offset) -{ - uint8_t *mem; - - if (addr) - { - mem = addr; - } - else mem = (uint8_t *)malloc(length); - - if (mem) - { - off_t cur; - size_t read_bytes; - - cur = lseek(fd, 0, SEEK_SET); - - lseek(fd, offset, SEEK_SET); - read_bytes = read(fd, mem, length); - if (read_bytes != length) - { - if (addr == RT_NULL) - { - /* read failed */ - free(mem); - mem = RT_NULL; - } - } - lseek(fd, cur, SEEK_SET); - - return mem; - } - - errno = ENOMEM; - - return MAP_FAILED; -} - -int munmap(void *addr, size_t length) -{ - if (addr) - { - free(addr); - return 0; - } - - return -1; -} diff --git a/components/libc/posix/src/poll.c b/components/libc/posix/src/poll.c deleted file mode 100644 index 0c773b306c..0000000000 --- a/components/libc/posix/src/poll.c +++ /dev/null @@ -1,226 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2016-12-28 Bernard first version - * 2018-03-09 Bernard Add protection for pt->triggered. - */ -#include -#include -#include -#include -#include - -struct rt_poll_node; - -struct rt_poll_table -{ - rt_pollreq_t req; - rt_uint32_t triggered; /* the waited thread whether triggered */ - rt_thread_t polling_thread; - struct rt_poll_node *nodes; -}; - -struct rt_poll_node -{ - struct rt_wqueue_node wqn; - struct rt_poll_table *pt; - struct rt_poll_node *next; -}; - -static int __wqueue_pollwake(struct rt_wqueue_node *wait, void *key) -{ - struct rt_poll_node *pn; - - if (key && !((rt_ubase_t)key & wait->key)) - return -1; - - pn = rt_container_of(wait, struct rt_poll_node, wqn); - pn->pt->triggered = 1; - - return __wqueue_default_wake(wait, key); -} - -static void _poll_add(rt_wqueue_t *wq, rt_pollreq_t *req) -{ - struct rt_poll_table *pt; - struct rt_poll_node *node; - - node = (struct rt_poll_node *)rt_malloc(sizeof(struct rt_poll_node)); - if (node == RT_NULL) - return; - - pt = rt_container_of(req, struct rt_poll_table, req); - - node->wqn.key = req->_key; - rt_list_init(&(node->wqn.list)); - node->wqn.polling_thread = pt->polling_thread; - node->wqn.wakeup = __wqueue_pollwake; - node->next = pt->nodes; - node->pt = pt; - pt->nodes = node; - rt_wqueue_add(wq, &node->wqn); -} - -static void poll_table_init(struct rt_poll_table *pt) -{ - pt->req._proc = _poll_add; - pt->triggered = 0; - pt->nodes = RT_NULL; - pt->polling_thread = rt_thread_self(); -} - -static int poll_wait_timeout(struct rt_poll_table *pt, int msec) -{ - rt_int32_t timeout; - int ret = 0; - struct rt_thread *thread; - rt_base_t level; - - thread = pt->polling_thread; - - timeout = rt_tick_from_millisecond(msec); - - level = rt_hw_interrupt_disable(); - - if (timeout != 0 && !pt->triggered) - { - rt_thread_suspend(thread); - if (timeout > 0) - { - rt_timer_control(&(thread->thread_timer), - RT_TIMER_CTRL_SET_TIME, - &timeout); - rt_timer_start(&(thread->thread_timer)); - } - - rt_hw_interrupt_enable(level); - - rt_schedule(); - - level = rt_hw_interrupt_disable(); - } - - ret = !pt->triggered; - rt_hw_interrupt_enable(level); - - return ret; -} - -static int do_pollfd(struct pollfd *pollfd, rt_pollreq_t *req) -{ - int mask = 0; - int fd; - - fd = pollfd->fd; - - if (fd >= 0) - { - struct dfs_fd *f = fd_get(fd); - mask = POLLNVAL; - - if (f) - { - mask = POLLMASK_DEFAULT; - if (f->fops->poll) - { - req->_key = pollfd->events | POLLERR | POLLHUP; - - mask = f->fops->poll(f, req); - - /* dealwith the device return error -1*/ - if (mask < 0) - { - fd_put(f); - pollfd->revents = 0; - return mask; - } - } - /* Mask out unneeded events. */ - mask &= pollfd->events | POLLERR | POLLHUP; - fd_put(f); - } - } - pollfd->revents = mask; - - return mask; -} - -static int poll_do(struct pollfd *fds, nfds_t nfds, struct rt_poll_table *pt, int msec) -{ - int num; - int istimeout = 0; - int n; - struct pollfd *pf; - int ret = 0; - - if (msec == 0) - { - pt->req._proc = RT_NULL; - istimeout = 1; - } - - while (1) - { - pf = fds; - num = 0; - - for (n = 0; n < nfds; n ++) - { - ret = do_pollfd(pf, &pt->req); - if(ret < 0) - { - /*dealwith the device return error -1 */ - pt->req._proc = RT_NULL; - return ret; - } - else if(ret > 0) - { - num ++; - pt->req._proc = RT_NULL; - } - pf ++; - } - - pt->req._proc = RT_NULL; - - if (num || istimeout) - break; - - if (poll_wait_timeout(pt, msec)) - istimeout = 1; - } - - return num; -} - -static void poll_teardown(struct rt_poll_table *pt) -{ - struct rt_poll_node *node, *next; - - next = pt->nodes; - while (next) - { - node = next; - rt_wqueue_remove(&node->wqn); - next = node->next; - rt_free(node); - } -} - -int poll(struct pollfd *fds, nfds_t nfds, int timeout) -{ - int num; - struct rt_poll_table table; - - poll_table_init(&table); - - num = poll_do(fds, nfds, &table, timeout); - - poll_teardown(&table); - - return num; -} diff --git a/components/libc/posix/src/select.c b/components/libc/posix/src/select.c deleted file mode 100644 index 55d320e921..0000000000 --- a/components/libc/posix/src/select.c +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2016-12-28 Bernard first version - */ -#include -#include -#include - -static void fdszero(fd_set *set, int nfds) -{ - fd_mask *m; - int n; - - /* - The 'sizeof(fd_set)' of the system space may differ from user space, - so the actual size of the 'fd_set' is determined here with the parameter 'nfds' - */ - m = (fd_mask *)set; - for (n = 0; n < nfds; n += (sizeof(fd_mask) * 8)) - { - rt_memset(m, 0, sizeof(fd_mask)); - m ++; - } -} - -int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout) -{ - int fd; - int npfds; - int msec; - int ndx; - int ret; - struct pollfd *pollset = RT_NULL; - - /* How many pollfd structures do we need to allocate? */ - for (fd = 0, npfds = 0; fd < nfds; fd++) - { - /* Check if any monitor operation is requested on this fd */ - if ((readfds && FD_ISSET(fd, readfds)) || - (writefds && FD_ISSET(fd, writefds)) || - (exceptfds && FD_ISSET(fd, exceptfds))) - { - npfds++; - } - } - - /* Allocate the descriptor list for poll() */ - if (npfds > 0) - { - pollset = (struct pollfd *)rt_calloc(npfds, sizeof(struct pollfd)); - if (!pollset) - { - return -1; - } - } - - /* Initialize the descriptor list for poll() */ - for (fd = 0, ndx = 0; fd < nfds; fd++) - { - int incr = 0; - - /* The readfs set holds the set of FDs that the caller can be assured - * of reading from without blocking. Note that POLLHUP is included as - * a read-able condition. POLLHUP will be reported at the end-of-file - * or when a connection is lost. In either case, the read() can then - * be performed without blocking. - */ - - if (readfds && FD_ISSET(fd, readfds)) - { - pollset[ndx].fd = fd; - pollset[ndx].events |= POLLIN; - incr = 1; - } - - if (writefds && FD_ISSET(fd, writefds)) - { - pollset[ndx].fd = fd; - pollset[ndx].events |= POLLOUT; - incr = 1; - } - - if (exceptfds && FD_ISSET(fd, exceptfds)) - { - pollset[ndx].fd = fd; - incr = 1; - } - - ndx += incr; - } - - RT_ASSERT(ndx == npfds); - - /* Convert the timeout to milliseconds */ - if (timeout) - { - msec = timeout->tv_sec * 1000 + timeout->tv_usec / 1000; - } - else - { - msec = -1; - } - - /* Then let poll do all of the real work. */ - - ret = poll(pollset, npfds, msec); - - /* Now set up the return values */ - if (readfds) - { - fdszero(readfds, nfds); - } - - if (writefds) - { - fdszero(writefds, nfds); - } - - if (exceptfds) - { - fdszero(exceptfds, nfds); - } - - /* Convert the poll descriptor list back into selects 3 bitsets */ - - if (ret > 0) - { - ret = 0; - for (ndx = 0; ndx < npfds; ndx++) - { - /* Check for read conditions. Note that POLLHUP is included as a - * read condition. POLLHUP will be reported when no more data will - * be available (such as when a connection is lost). In either - * case, the read() can then be performed without blocking. - */ - - if (readfds) - { - if (pollset[ndx].revents & (POLLIN | POLLHUP)) - { - FD_SET(pollset[ndx].fd, readfds); - ret++; - } - } - - /* Check for write conditions */ - if (writefds) - { - if (pollset[ndx].revents & POLLOUT) - { - FD_SET(pollset[ndx].fd, writefds); - ret++; - } - } - - /* Check for exceptions */ - if (exceptfds) - { - if (pollset[ndx].revents & POLLERR) - { - FD_SET(pollset[ndx].fd, exceptfds); - ret++; - } - } - } - } - - if (pollset) rt_free(pollset); - - return ret; -} diff --git a/components/libc/posix/termios/SConscript b/components/libc/posix/termios/SConscript deleted file mode 100644 index 3615926251..0000000000 --- a/components/libc/posix/termios/SConscript +++ /dev/null @@ -1,11 +0,0 @@ -# RT-Thread building script for component - -from building import * - -cwd = GetCurrentDir() -src = Glob('*.c') + Glob('*.cpp') -CPPPATH = [cwd] - -group = DefineGroup('POSIX', src, depend = ['RT_USING_LIBC', 'RT_USING_POSIX_TERMIOS'], CPPPATH = CPPPATH) - -Return('group') diff --git a/components/libc/posix/termios/posix_termios.c b/components/libc/posix/termios/posix_termios.c deleted file mode 100644 index 9f33c857e6..0000000000 --- a/components/libc/posix/termios/posix_termios.c +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2017/08/30 Bernard The first version - */ -#include -#include -#include -#include -#include - -int tcgetattr(int fd, struct termios *tio) -{ - /* Get the current serial port settings. */ - if (ioctl(fd, TCGETA, tio)) - return -1; - - return 0; -} - -int tcsetattr(int fd, int act, const struct termios *tio) -{ - switch (act) - { - case TCSANOW: - /* make the change immediately */ - return (ioctl(fd, TCSETA, (void*)tio)); - case TCSADRAIN: - /* - * Don't make the change until all currently written data - * has been transmitted. - */ - return (ioctl(fd, TCSETAW, (void*)tio)); - case TCSAFLUSH: - /* Don't make the change until all currently written data - * has been transmitted, at which point any received but - * unread data is also discarded. - */ - return (ioctl(fd, TCSETAF, (void*)tio)); - default: - errno = EINVAL; - return (-1); - } -} - -/** - * this function gets process group ID for session leader for controlling - * terminal - * - * @return always 0 - */ -pid_t tcgetsid(int fd) -{ - return 0; -} - -speed_t cfgetospeed(const struct termios *tio) -{ - return tio->c_cflag & CBAUD; -} - -speed_t cfgetispeed(const struct termios *tio) -{ - return cfgetospeed(tio); -} - -int cfsetospeed(struct termios *tio, speed_t speed) -{ - if (speed & ~CBAUD) - { - errno = EINVAL; - return -1; - } - - tio->c_cflag &= ~CBAUD; - tio->c_cflag |= speed; - return 0; -} - -int cfsetispeed(struct termios *tio, speed_t speed) -{ - return speed ? cfsetospeed(tio, speed) : 0; -} - -int tcsendbreak(int fd, int dur) -{ - /* nonzero duration is implementation-defined, so ignore it */ - return 0; -} - -int tcflush(int fd, int queue) -{ - return ioctl(fd, TCFLSH, (void*)queue); -} - -int tcflow(int fd, int action) -{ - return ioctl(fd, TCXONC, (void*)action); -} - -/** - * this function waits for transmission of output - */ -int tcdrain(int fd) -{ - return 0; -} - -#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) -void cfmakeraw(struct termios *t) -{ - t->c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON); - t->c_oflag &= ~OPOST; - t->c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN); - t->c_cflag &= ~(CSIZE|PARENB); - t->c_cflag |= CS8; - t->c_cc[VMIN] = 1; - t->c_cc[VTIME] = 0; -} - -int cfsetspeed(struct termios *tio, speed_t speed) -{ - return cfsetospeed(tio, speed); -} -#endif diff --git a/components/libc/posix/termios/posix_termios.h b/components/libc/posix/termios/posix_termios.h deleted file mode 100644 index 6dc5531955..0000000000 --- a/components/libc/posix/termios/posix_termios.h +++ /dev/null @@ -1,213 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2017/08/30 Bernard The first version - */ -#ifndef TERMIOS_H__ -#define TERMIOS_H__ - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -typedef unsigned char cc_t; -typedef unsigned int speed_t; -typedef unsigned int tcflag_t; - -#define NCCS 32 - -struct termios { - tcflag_t c_iflag; - tcflag_t c_oflag; - tcflag_t c_cflag; - tcflag_t c_lflag; - cc_t c_line; - cc_t c_cc[NCCS]; - speed_t __c_ispeed; - speed_t __c_ospeed; -}; - -#define VINTR 0 -#define VQUIT 1 -#define VERASE 2 -#define VKILL 3 -#define VEOF 4 -#define VTIME 5 -#define VMIN 6 -#define VSWTC 7 -#define VSTART 8 -#define VSTOP 9 -#define VSUSP 10 -#define VEOL 11 -#define VREPRINT 12 -#define VDISCARD 13 -#define VWERASE 14 -#define VLNEXT 15 -#define VEOL2 16 - -#define IGNBRK 0000001 -#define BRKINT 0000002 -#define IGNPAR 0000004 -#define PARMRK 0000010 -#define INPCK 0000020 -#define ISTRIP 0000040 -#define INLCR 0000100 -#define IGNCR 0000200 -#define ICRNL 0000400 -#define IUCLC 0001000 -#define IXON 0002000 -#define IXANY 0004000 -#define IXOFF 0010000 -#define IMAXBEL 0020000 -#define IUTF8 0040000 - -#define OPOST 0000001 -#define OLCUC 0000002 -#define ONLCR 0000004 -#define OCRNL 0000010 -#define ONOCR 0000020 -#define ONLRET 0000040 -#define OFILL 0000100 -#define OFDEL 0000200 -#define NLDLY 0000400 -#define NL0 0000000 -#define NL1 0000400 -#define CRDLY 0003000 -#define CR0 0000000 -#define CR1 0001000 -#define CR2 0002000 -#define CR3 0003000 -#define TABDLY 0014000 -#define TAB0 0000000 -#define TAB1 0004000 -#define TAB2 0010000 -#define TAB3 0014000 -#define BSDLY 0020000 -#define BS0 0000000 -#define BS1 0020000 -#define FFDLY 0100000 -#define FF0 0000000 -#define FF1 0100000 - -#define VTDLY 0040000 -#define VT0 0000000 -#define VT1 0040000 - -#define B0 0000000 -#define B50 0000001 -#define B75 0000002 -#define B110 0000003 -#define B134 0000004 -#define B150 0000005 -#define B200 0000006 -#define B300 0000007 -#define B600 0000010 -#define B1200 0000011 -#define B1800 0000012 -#define B2400 0000013 -#define B4800 0000014 -#define B9600 0000015 -#define B19200 0000016 -#define B38400 0000017 - -#define B57600 0010001 -#define B115200 0010002 -#define B230400 0010003 -#define B460800 0010004 -#define B500000 0010005 -#define B576000 0010006 -#define B921600 0010007 -#define B1000000 0010010 -#define B1152000 0010011 -#define B1500000 0010012 -#define B2000000 0010013 -#define B2500000 0010014 -#define B3000000 0010015 -#define B3500000 0010016 -#define B4000000 0010017 - -#define CSIZE 0000060 -#define CS5 0000000 -#define CS6 0000020 -#define CS7 0000040 -#define CS8 0000060 -#define CSTOPB 0000100 -#define CREAD 0000200 -#define PARENB 0000400 -#define PARODD 0001000 -#define HUPCL 0002000 -#define CLOCAL 0004000 - -#define ISIG 0000001 -#define ICANON 0000002 -#define ECHO 0000010 -#define ECHOE 0000020 -#define ECHOK 0000040 -#define ECHONL 0000100 -#define NOFLSH 0000200 -#define TOSTOP 0000400 -#define IEXTEN 0100000 - -#define TCOOFF 0 -#define TCOON 1 -#define TCIOFF 2 -#define TCION 3 - -#define TCIFLUSH 0 -#define TCOFLUSH 1 -#define TCIOFLUSH 2 - -#define TCSANOW 0 -#define TCSADRAIN 1 -#define TCSAFLUSH 2 - -#define EXTA 0000016 -#define EXTB 0000017 -#define CBAUD 0010017 -#define CBAUDEX 0010000 -#define CIBAUD 002003600000 -#define CMSPAR 010000000000 -#define CRTSCTS 020000000000 - -#define XCASE 0000004 -#define ECHOCTL 0001000 -#define ECHOPRT 0002000 -#define ECHOKE 0004000 -#define FLUSHO 0010000 -#define PENDIN 0040000 -#define EXTPROC 0200000 - -#define XTABS 0014000 - -speed_t cfgetospeed (const struct termios *); -speed_t cfgetispeed (const struct termios *); -int cfsetospeed (struct termios *, speed_t); -int cfsetispeed (struct termios *, speed_t); - -int tcgetattr (int, struct termios *); -int tcsetattr (int, int, const struct termios *); - -int tcsendbreak (int, int); -int tcdrain (int); -int tcflush (int, int); -int tcflow (int, int); - -pid_t tcgetsid (int); - -#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) -void cfmakeraw(struct termios *); -int cfsetspeed(struct termios *, speed_t); -#endif - -#ifdef __cplusplus -} -#endif - -#endif -- cgit v1.3.1 From 7e06b6c50448bc7c082e9235bb90263970468ad3 Mon Sep 17 00:00:00 2001 From: jonas Date: Thu, 9 Dec 2021 18:11:55 +0800 Subject: [fix]修复AT组件在CLI模式下,指令输入过长导致数组越界的问题 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/net/at/src/at_cli.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'components') diff --git a/components/net/at/src/at_cli.c b/components/net/at/src/at_cli.c index c589bb68a0..d51358d863 100644 --- a/components/net/at/src/at_cli.c +++ b/components/net/at/src/at_cli.c @@ -264,6 +264,10 @@ static void client_cli_parser(at_client_t client) } else { + if(cur_line_len >= FINSH_CMD_SIZE) + { + continue; + } rt_kprintf("%c", ch); cur_line[cur_line_len++] = ch; } -- cgit v1.3.1 From 7ff976dab392a82f4307b58b36c6551612fa7e5f Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Tue, 7 Dec 2021 02:18:58 -0500 Subject: [posix] [pipe] add IPC for POSIX and add pipe for it --- components/drivers/Kconfig | 6 +----- components/drivers/include/ipc/pipe.h | 6 ------ components/drivers/src/pipe.c | 26 +++++++++++++------------- components/libc/posix/Kconfig | 2 ++ components/libc/posix/ipc/Kconfig | 17 +++++++++++++++++ 5 files changed, 33 insertions(+), 24 deletions(-) create mode 100644 components/libc/posix/ipc/Kconfig (limited to 'components') diff --git a/components/drivers/Kconfig b/components/drivers/Kconfig index 159a6cbda3..8d340da3f5 100755 --- a/components/drivers/Kconfig +++ b/components/drivers/Kconfig @@ -5,10 +5,6 @@ config RT_USING_DEVICE_IPC default y if RT_USING_DEVICE_IPC - config RT_PIPE_BUFSZ - int "Set pipe buffer size" - default 512 - config RT_USING_SYSTEM_WORKQUEUE bool "Using system default workqueue" default n @@ -18,7 +14,7 @@ if RT_USING_DEVICE_IPC int "The stack size for system workqueue thread" default 2048 - config RT_SYSTEM_WORKQUEUE_PRIORITY + config RT_SYSTEM_WORKQUEUE_PRIORITY int "The priority level of system workqueue thread" default 23 endif diff --git a/components/drivers/include/ipc/pipe.h b/components/drivers/include/ipc/pipe.h index a45e8ae002..7d271c3a04 100644 --- a/components/drivers/include/ipc/pipe.h +++ b/components/drivers/include/ipc/pipe.h @@ -15,12 +15,6 @@ #include #include -#ifndef RT_PIPE_BUFSZ -#define PIPE_BUFSZ 512 -#else -#define PIPE_BUFSZ RT_PIPE_BUFSZ -#endif - struct rt_pipe_device { struct rt_device parent; diff --git a/components/drivers/src/pipe.c b/components/drivers/src/pipe.c index 89b544bc4e..8f9a62e05b 100644 --- a/components/drivers/src/pipe.c +++ b/components/drivers/src/pipe.c @@ -13,7 +13,7 @@ #include #include -#ifdef RT_USING_POSIX_DEVIO +#if defined(RT_USING_POSIX_DEVIO) && defined(RT_USING_POSIX_PIPE) #include #include #include @@ -320,9 +320,9 @@ static const struct dfs_file_ops pipe_fops = RT_NULL, pipe_fops_poll, }; -#endif /* RT_USING_POSIX_DEVIO */ +#endif /* defined(RT_USING_POSIX_DEVIO) && defined(RT_USING_POSIX_PIPE) */ -rt_err_t rt_pipe_open(rt_device_t device, rt_uint16_t oflag) +static rt_err_t rt_pipe_open(rt_device_t device, rt_uint16_t oflag) { rt_pipe_t *pipe = (rt_pipe_t *)device; rt_err_t ret = RT_EOK; @@ -350,7 +350,7 @@ __exit: return ret; } -rt_err_t rt_pipe_close(rt_device_t device) +static rt_err_t rt_pipe_close(rt_device_t device) { rt_pipe_t *pipe = (rt_pipe_t *)device; @@ -368,7 +368,7 @@ rt_err_t rt_pipe_close(rt_device_t device) return RT_EOK; } -rt_size_t rt_pipe_read(rt_device_t device, rt_off_t pos, void *buffer, rt_size_t count) +static rt_size_t rt_pipe_read(rt_device_t device, rt_off_t pos, void *buffer, rt_size_t count) { uint8_t *pbuf; rt_size_t read_bytes = 0; @@ -396,7 +396,7 @@ rt_size_t rt_pipe_read(rt_device_t device, rt_off_t pos, void *buffer, rt_size_t return read_bytes; } -rt_size_t rt_pipe_write(rt_device_t device, rt_off_t pos, const void *buffer, rt_size_t count) +static rt_size_t rt_pipe_write(rt_device_t device, rt_off_t pos, const void *buffer, rt_size_t count) { uint8_t *pbuf; rt_size_t write_bytes = 0; @@ -424,7 +424,7 @@ rt_size_t rt_pipe_write(rt_device_t device, rt_off_t pos, const void *buffer, rt return write_bytes; } -rt_err_t rt_pipe_control(rt_device_t dev, int cmd, void *args) +static rt_err_t rt_pipe_control(rt_device_t dev, int cmd, void *args) { return RT_EOK; } @@ -479,9 +479,9 @@ rt_pipe_t *rt_pipe_create(const char *name, int bufsz) rt_free(pipe); return RT_NULL; } -#ifdef RT_USING_POSIX_DEVIO +#if defined(RT_USING_POSIX_DEVIO) && defined(RT_USING_POSIX_PIPE) dev->fops = (void*)&pipe_fops; -#endif /* RT_USING_POSIX_DEVIO */ +#endif return pipe; } @@ -529,7 +529,7 @@ int rt_pipe_delete(const char *name) return result; } -#ifdef RT_USING_POSIX_DEVIO +#if defined(RT_USING_POSIX_DEVIO) && defined(RT_USING_POSIX_PIPE) int pipe(int fildes[2]) { rt_pipe_t *pipe; @@ -539,7 +539,7 @@ int pipe(int fildes[2]) rt_snprintf(dname, sizeof(dname), "pipe%d", pipeno++); - pipe = rt_pipe_create(dname, PIPE_BUFSZ); + pipe = rt_pipe_create(dname, RT_USING_POSIX_PIPE_SIZE); if (pipe == RT_NULL) { return -1; @@ -567,7 +567,7 @@ int mkfifo(const char *path, mode_t mode) { rt_pipe_t *pipe; - pipe = rt_pipe_create(path, PIPE_BUFSZ); + pipe = rt_pipe_create(path, RT_USING_POSIX_PIPE_SIZE); if (pipe == RT_NULL) { return -1; @@ -575,4 +575,4 @@ int mkfifo(const char *path, mode_t mode) return 0; } -#endif /* RT_USING_POSIX_DEVIO */ +#endif /* defined(RT_USING_POSIX_DEVIO) && defined(RT_USING_POSIX_PIPE) */ diff --git a/components/libc/posix/Kconfig b/components/libc/posix/Kconfig index db83269dd0..52b5fdc948 100644 --- a/components/libc/posix/Kconfig +++ b/components/libc/posix/Kconfig @@ -55,4 +55,6 @@ if RT_USING_PTHREADS default 8 endif +source "$RTT_DIR/components/libc/posix/ipc/Kconfig" + endmenu diff --git a/components/libc/posix/ipc/Kconfig b/components/libc/posix/ipc/Kconfig new file mode 100644 index 0000000000..f5ec6ad040 --- /dev/null +++ b/components/libc/posix/ipc/Kconfig @@ -0,0 +1,17 @@ +menu "Interprocess Communication (IPC)" + +config RT_USING_POSIX_PIPE + bool "Enable pipe and FIFO" + select RT_USING_POSIX_FS + select RT_USING_POSIX_DEVIO + select RT_USING_POSIX_POLL + default n + +config RT_USING_POSIX_PIPE_SIZE + int "Set pipe buffer size" + depends on RT_USING_POSIX_PIPE + default 512 + +comment "Socket is in the 'Network' category" + +endmenu -- cgit v1.3.1 From ce8085befa161f9940157df6b41190aaf531a5cc Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Tue, 7 Dec 2021 15:42:06 -0500 Subject: [posix][ipc] add ipc header files --- components/libc/posix/ipc/sys/ipc.h | 15 +++++++++++++++ components/libc/posix/ipc/sys/msg.h | 15 +++++++++++++++ components/libc/posix/ipc/sys/sem.h | 15 +++++++++++++++ components/libc/posix/ipc/sys/shm.h | 15 +++++++++++++++ 4 files changed, 60 insertions(+) create mode 100644 components/libc/posix/ipc/sys/ipc.h create mode 100644 components/libc/posix/ipc/sys/msg.h create mode 100644 components/libc/posix/ipc/sys/sem.h create mode 100644 components/libc/posix/ipc/sys/shm.h (limited to 'components') diff --git a/components/libc/posix/ipc/sys/ipc.h b/components/libc/posix/ipc/sys/ipc.h new file mode 100644 index 0000000000..03b5458d51 --- /dev/null +++ b/components/libc/posix/ipc/sys/ipc.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-12-07 Meco Man First version + */ +#ifndef __SYS_IPC_H__ +#define __SYS_IPC_H__ + + + +#endif diff --git a/components/libc/posix/ipc/sys/msg.h b/components/libc/posix/ipc/sys/msg.h new file mode 100644 index 0000000000..c030c9e8cb --- /dev/null +++ b/components/libc/posix/ipc/sys/msg.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-12-07 Meco Man First version + */ +#ifndef __SYS_MSG_H__ +#define __SYS_MSG_H__ + + + +#endif diff --git a/components/libc/posix/ipc/sys/sem.h b/components/libc/posix/ipc/sys/sem.h new file mode 100644 index 0000000000..b849bd687d --- /dev/null +++ b/components/libc/posix/ipc/sys/sem.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-12-07 Meco Man First version + */ +#ifndef __SYS_SEM_H__ +#define __SYS_SEM_H__ + + + +#endif diff --git a/components/libc/posix/ipc/sys/shm.h b/components/libc/posix/ipc/sys/shm.h new file mode 100644 index 0000000000..762d68891a --- /dev/null +++ b/components/libc/posix/ipc/sys/shm.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-12-07 Meco Man First version + */ +#ifndef __SYS_SHM_H__ +#define __SYS_SHM_H__ + + + +#endif -- cgit v1.3.1 From 15435b68507e0a5b6b90341d7c53945487aaf0de Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Tue, 7 Dec 2021 15:47:00 -0500 Subject: [posix][mmap] create the mman folder --- components/libc/compilers/common/sys/ioctl.h | 4 +- components/libc/compilers/common/sys/mman.h | 60 ------------------------- components/libc/posix/Kconfig | 2 +- components/libc/posix/io/SConscript | 4 -- components/libc/posix/io/mman/SConscript | 11 +++++ components/libc/posix/io/mman/mman.c | 67 ++++++++++++++++++++++++++++ components/libc/posix/io/mman/sys/mman.h | 60 +++++++++++++++++++++++++ components/libc/posix/io/mmap.c | 67 ---------------------------- components/libc/posix/io/poll/poll.c | 2 +- 9 files changed, 142 insertions(+), 135 deletions(-) delete mode 100644 components/libc/compilers/common/sys/mman.h create mode 100644 components/libc/posix/io/mman/SConscript create mode 100644 components/libc/posix/io/mman/mman.c create mode 100644 components/libc/posix/io/mman/sys/mman.h delete mode 100644 components/libc/posix/io/mmap.c (limited to 'components') diff --git a/components/libc/compilers/common/sys/ioctl.h b/components/libc/compilers/common/sys/ioctl.h index 29ed3a8b84..a1642199b1 100644 --- a/components/libc/compilers/common/sys/ioctl.h +++ b/components/libc/compilers/common/sys/ioctl.h @@ -7,8 +7,8 @@ * Date Author Notes * 2020-09-01 Meco Man First Version */ -#ifndef _SYS_IOCTL_H -#define _SYS_IOCTL_H +#ifndef __SYS_IOCTL_H__ +#define __SYS_IOCTL_H__ #include #include diff --git a/components/libc/compilers/common/sys/mman.h b/components/libc/compilers/common/sys/mman.h deleted file mode 100644 index 2da2ddf716..0000000000 --- a/components/libc/compilers/common/sys/mman.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2017/11/30 Bernard The first version. - */ - -#ifndef _SYS_MMAN_H -#define _SYS_MMAN_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -#define MAP_FAILED ((void *) -1) - -#define MAP_SHARED 0x01 -#define MAP_PRIVATE 0x02 -#define MAP_TYPE 0x0f -#define MAP_FIXED 0x10 -#define MAP_ANON 0x20 -#define MAP_ANONYMOUS MAP_ANON -#define MAP_NORESERVE 0x4000 -#define MAP_GROWSDOWN 0x0100 -#define MAP_DENYWRITE 0x0800 -#define MAP_EXECUTABLE 0x1000 -#define MAP_LOCKED 0x2000 -#define MAP_POPULATE 0x8000 -#define MAP_NONBLOCK 0x10000 -#define MAP_STACK 0x20000 -#define MAP_HUGETLB 0x40000 -#define MAP_FILE 0 - -#define PROT_NONE 0 -#define PROT_READ 1 -#define PROT_WRITE 2 -#define PROT_EXEC 4 -#define PROT_GROWSDOWN 0x01000000 -#define PROT_GROWSUP 0x02000000 - -#define MS_ASYNC 1 -#define MS_INVALIDATE 2 -#define MS_SYNC 4 - -#define MCL_CURRENT 1 -#define MCL_FUTURE 2 -#define MCL_ONFAULT 4 - -void *mmap (void *start, size_t len, int prot, int flags, int fd, off_t off); -int munmap (void *start, size_t len); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/components/libc/posix/Kconfig b/components/libc/posix/Kconfig index 52b5fdc948..4534da7118 100644 --- a/components/libc/posix/Kconfig +++ b/components/libc/posix/Kconfig @@ -30,7 +30,7 @@ if RT_USING_POSIX_FS bool "Enable Asynchronous I/O " default n - config RT_USING_POSIX_MMAP + config RT_USING_POSIX_MMAN bool "Enable Memory-Mapped I/O " default n endif diff --git a/components/libc/posix/io/SConscript b/components/libc/posix/io/SConscript index 2a7cd76ded..32654674e8 100644 --- a/components/libc/posix/io/SConscript +++ b/components/libc/posix/io/SConscript @@ -18,10 +18,6 @@ if GetDepend('RT_USING_POSIX_SELECT'): src += ['select.c'] flag = True -if GetDepend('RT_USING_POSIX_MMAP'): - src += ['mmap.c'] - flag = True - if flag == True: group = DefineGroup('POSIX', src, depend = [], CPPPATH = CPPPATH) diff --git a/components/libc/posix/io/mman/SConscript b/components/libc/posix/io/mman/SConscript new file mode 100644 index 0000000000..7dd096c998 --- /dev/null +++ b/components/libc/posix/io/mman/SConscript @@ -0,0 +1,11 @@ +# RT-Thread building script for component + +from building import * + +cwd = GetCurrentDir() +src = ['mman.c'] +CPPPATH = [cwd] + +group = DefineGroup('POSIX', src, depend = ['RT_USING_POSIX_MMAN'], CPPPATH = CPPPATH) + +Return('group') diff --git a/components/libc/posix/io/mman/mman.c b/components/libc/posix/io/mman/mman.c new file mode 100644 index 0000000000..827f2cbb14 --- /dev/null +++ b/components/libc/posix/io/mman/mman.c @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2017/11/30 Bernard The first version. + */ + +#include +#include + +#include +#include + +#include "sys/mman.h" + +void *mmap(void *addr, size_t length, int prot, int flags, + int fd, off_t offset) +{ + uint8_t *mem; + + if (addr) + { + mem = addr; + } + else mem = (uint8_t *)malloc(length); + + if (mem) + { + off_t cur; + size_t read_bytes; + + cur = lseek(fd, 0, SEEK_SET); + + lseek(fd, offset, SEEK_SET); + read_bytes = read(fd, mem, length); + if (read_bytes != length) + { + if (addr == RT_NULL) + { + /* read failed */ + free(mem); + mem = RT_NULL; + } + } + lseek(fd, cur, SEEK_SET); + + return mem; + } + + errno = ENOMEM; + + return MAP_FAILED; +} + +int munmap(void *addr, size_t length) +{ + if (addr) + { + free(addr); + return 0; + } + + return -1; +} diff --git a/components/libc/posix/io/mman/sys/mman.h b/components/libc/posix/io/mman/sys/mman.h new file mode 100644 index 0000000000..a730f33b6b --- /dev/null +++ b/components/libc/posix/io/mman/sys/mman.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2017/11/30 Bernard The first version. + */ + +#ifndef __SYS_MMAN_H__ +#define __SYS_MMAN_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#define MAP_FAILED ((void *) -1) + +#define MAP_SHARED 0x01 +#define MAP_PRIVATE 0x02 +#define MAP_TYPE 0x0f +#define MAP_FIXED 0x10 +#define MAP_ANON 0x20 +#define MAP_ANONYMOUS MAP_ANON +#define MAP_NORESERVE 0x4000 +#define MAP_GROWSDOWN 0x0100 +#define MAP_DENYWRITE 0x0800 +#define MAP_EXECUTABLE 0x1000 +#define MAP_LOCKED 0x2000 +#define MAP_POPULATE 0x8000 +#define MAP_NONBLOCK 0x10000 +#define MAP_STACK 0x20000 +#define MAP_HUGETLB 0x40000 +#define MAP_FILE 0 + +#define PROT_NONE 0 +#define PROT_READ 1 +#define PROT_WRITE 2 +#define PROT_EXEC 4 +#define PROT_GROWSDOWN 0x01000000 +#define PROT_GROWSUP 0x02000000 + +#define MS_ASYNC 1 +#define MS_INVALIDATE 2 +#define MS_SYNC 4 + +#define MCL_CURRENT 1 +#define MCL_FUTURE 2 +#define MCL_ONFAULT 4 + +void *mmap (void *start, size_t len, int prot, int flags, int fd, off_t off); +int munmap (void *start, size_t len); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/components/libc/posix/io/mmap.c b/components/libc/posix/io/mmap.c deleted file mode 100644 index e68b82e640..0000000000 --- a/components/libc/posix/io/mmap.c +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2017/11/30 Bernard The first version. - */ - -#include -#include - -#include -#include - -#include - -void *mmap(void *addr, size_t length, int prot, int flags, - int fd, off_t offset) -{ - uint8_t *mem; - - if (addr) - { - mem = addr; - } - else mem = (uint8_t *)malloc(length); - - if (mem) - { - off_t cur; - size_t read_bytes; - - cur = lseek(fd, 0, SEEK_SET); - - lseek(fd, offset, SEEK_SET); - read_bytes = read(fd, mem, length); - if (read_bytes != length) - { - if (addr == RT_NULL) - { - /* read failed */ - free(mem); - mem = RT_NULL; - } - } - lseek(fd, cur, SEEK_SET); - - return mem; - } - - errno = ENOMEM; - - return MAP_FAILED; -} - -int munmap(void *addr, size_t length) -{ - if (addr) - { - free(addr); - return 0; - } - - return -1; -} diff --git a/components/libc/posix/io/poll/poll.c b/components/libc/posix/io/poll/poll.c index 0c773b306c..a1500ba109 100644 --- a/components/libc/posix/io/poll/poll.c +++ b/components/libc/posix/io/poll/poll.c @@ -12,7 +12,7 @@ #include #include #include -#include +#include "poll.h" struct rt_poll_node; -- cgit v1.3.1 From 153ab5c2382b90dab1b2f2cbbb99e82f235208f0 Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Wed, 8 Dec 2021 09:13:57 -0500 Subject: update poll sconscript --- components/libc/posix/io/poll/SConscript | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'components') diff --git a/components/libc/posix/io/poll/SConscript b/components/libc/posix/io/poll/SConscript index 47f1722ed3..7d82ade035 100644 --- a/components/libc/posix/io/poll/SConscript +++ b/components/libc/posix/io/poll/SConscript @@ -3,9 +3,12 @@ from building import * cwd = GetCurrentDir() -src = ['poll.c'] +src = [] CPPPATH = [cwd] -group = DefineGroup('POSIX', src, depend = ['RT_USING_POSIX_POLL'], CPPPATH = CPPPATH) +if GetDepend('RT_USING_POSIX_POLL'): + src += ['poll.c'] + +group = DefineGroup('POSIX', src, depend = [], CPPPATH = CPPPATH) Return('group') -- cgit v1.3.1 From 7455e2487bd420c06ba7198228b0dcca297f83cc Mon Sep 17 00:00:00 2001 From: 张世争 Date: Sun, 5 Dec 2021 09:07:23 +0800 Subject: [components] PM框架更新 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bsp/stm32/stm32l475-atk-pandora/board/pm_cfg.h | 25 ++ components/drivers/Kconfig | 36 +++ components/drivers/include/drivers/lptimer.h | 38 +++ components/drivers/include/drivers/pm.h | 38 ++- components/drivers/pm/SConscript | 1 + components/drivers/pm/lptimer.c | 176 ++++++++++ components/drivers/pm/pm.c | 427 +++++++++++++++++++++++-- 7 files changed, 700 insertions(+), 41 deletions(-) create mode 100644 bsp/stm32/stm32l475-atk-pandora/board/pm_cfg.h create mode 100644 components/drivers/include/drivers/lptimer.h create mode 100644 components/drivers/pm/lptimer.c (limited to 'components') diff --git a/bsp/stm32/stm32l475-atk-pandora/board/pm_cfg.h b/bsp/stm32/stm32l475-atk-pandora/board/pm_cfg.h new file mode 100644 index 0000000000..bb4c3cf22d --- /dev/null +++ b/bsp/stm32/stm32l475-atk-pandora/board/pm_cfg.h @@ -0,0 +1,25 @@ +#ifndef __PM_CFG_H__ +#define __PM_CFG_H__ + +enum pm_module_id +{ + PM_NONE_ID = 0, + PM_POWER_ID, + PM_BOARD_ID, + PM_LCD_ID, + PM_KEY_ID, + PM_TP_ID, + PM_OTA_ID, + PM_SPI_ID, + PM_I2C_ID, + PM_ADC_ID, + PM_RTC_ID, + PM_GPIO_ID, + PM_UART_ID, + PM_SENSOR_ID, + PM_ALARM_ID, + PM_BLE_ID, + PM_MODULE_MAX_ID, /* enum must! */ +}; + +#endif diff --git a/components/drivers/Kconfig b/components/drivers/Kconfig index 8d340da3f5..d197bd246e 100755 --- a/components/drivers/Kconfig +++ b/components/drivers/Kconfig @@ -145,6 +145,42 @@ config RT_USING_PM bool "Using Power Management device drivers" default n + if RT_USING_PM + config PM_TICKLESS_THRESHOLD_TIME + int "PM tickless threashold time" + default 2 + + config PM_USING_CUSTOM_CONFIG + bool "PM using custom pm config" + default n + + config PM_ENABLE_DEBUG + bool "PM Enable Debug" + default n + + config PM_ENABLE_SUSPEND_SLEEP_MODE + bool "PM Device suspend change sleep mode" + default n + + config PM_ENABLE_THRESHOLD_SLEEP_MODE + bool "PM using threshold time change sleep mode" + default n + + if PM_ENABLE_THRESHOLD_SLEEP_MODE + config PM_LIGHT_THRESHOLD_TIME + int "PM light mode threashold time" + default 5 + + config PM_DEEP_THRESHOLD_TIME + int "PM deep mode threashold time" + default 20 + + config PM_STANDBY_THRESHOLD_TIME + int "PM standby mode threashold time" + default 100 + endif + endif + config RT_USING_RTC bool "Using RTC device drivers" default n diff --git a/components/drivers/include/drivers/lptimer.h b/components/drivers/include/drivers/lptimer.h new file mode 100644 index 0000000000..e59ce61d22 --- /dev/null +++ b/components/drivers/include/drivers/lptimer.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-10-11 zhangsz the first version + */ + +#ifndef __LPTIMER_H__ +#define __LPTIMER_H__ + +#include + +struct rt_lptimer +{ + struct rt_timer timer; + rt_list_t list; +}; +typedef struct rt_lptimer *rt_lptimer_t; + +void rt_lptimer_init(rt_lptimer_t timer, + const char *name, + void (*timeout)(void *parameter), + void *parameter, + rt_tick_t time, + rt_uint8_t flag); + +rt_err_t rt_lptimer_detach(rt_lptimer_t timer); +rt_err_t rt_lptimer_start(rt_lptimer_t timer); +rt_err_t rt_lptimer_stop(rt_lptimer_t timer); + +rt_err_t rt_lptimer_control(rt_lptimer_t timer, int cmd, void *arg); + +rt_tick_t rt_lptimer_next_timeout_tick(void); + +#endif diff --git a/components/drivers/include/drivers/pm.h b/components/drivers/include/drivers/pm.h index d38c0a4e2a..2deee83692 100644 --- a/components/drivers/include/drivers/pm.h +++ b/components/drivers/include/drivers/pm.h @@ -17,8 +17,7 @@ #include #include - -#ifndef PM_HAS_CUSTOM_CONFIG +#include /* All modes used for rt_pm_request() and rt_pm_release() */ enum @@ -48,10 +47,6 @@ enum RT_PM_FREQUENCY_PENDING = 0x01, }; -#define RT_PM_DEFAULT_SLEEP_MODE PM_SLEEP_MODE_NONE -#define RT_PM_DEFAULT_DEEPSLEEP_MODE PM_SLEEP_MODE_DEEP -#define RT_PM_DEFAULT_RUN_MODE PM_RUN_MODE_NORMAL_SPEED - /* The name of all modes used in the msh command "pm_dump" */ #define PM_SLEEP_MODE_NAMES \ { \ @@ -71,6 +66,7 @@ enum "Low Mode", \ } +#ifndef PM_USING_CUSTOM_CONFIG /** * Modules used for * pm_module_request(PM_BOARD_ID, PM_SLEEP_MODE_IDLE) @@ -98,11 +94,23 @@ enum pm_module_id { PM_MODULE_MAX_ID, /* enum must! */ }; -#else /* PM_HAS_CUSTOM_CONFIG */ +#else #include -#endif /* PM_HAS_CUSTOM_CONFIG */ +#endif /* PM_USING_CUSTOM_CONFIG */ + +#ifndef RT_PM_DEFAULT_SLEEP_MODE +#define RT_PM_DEFAULT_SLEEP_MODE PM_SLEEP_MODE_NONE +#endif + +#ifndef RT_PM_DEFAULT_DEEPSLEEP_MODE +#define RT_PM_DEFAULT_DEEPSLEEP_MODE PM_SLEEP_MODE_DEEP +#endif + +#ifndef RT_PM_DEFAULT_RUN_MODE +#define RT_PM_DEFAULT_RUN_MODE PM_RUN_MODE_NORMAL_SPEED +#endif /** * device control flag to request or release power @@ -160,6 +168,9 @@ struct rt_pm /* modules request status*/ struct rt_pm_module module_status[PM_MODULE_MAX_ID]; + /* sleep request table */ + rt_uint32_t sleep_status[PM_SLEEP_MODE_MAX - 1][(PM_MODULE_MAX_ID + 31) / 32]; + /* the list of device, which has PM feature */ rt_uint8_t device_pm_number; struct rt_device_pm *device_pm; @@ -203,5 +214,16 @@ void rt_pm_module_release_all(uint8_t module_id, rt_uint8_t sleep_mode); void rt_pm_module_delay_sleep(rt_uint8_t module_id, rt_tick_t timeout); rt_uint32_t rt_pm_module_get_status(void); rt_uint8_t rt_pm_get_sleep_mode(void); +struct rt_pm *rt_pm_get_handle(void); + +/* sleep : request or release */ +void rt_pm_sleep_request(rt_uint16_t module_id, rt_uint8_t mode); +void rt_pm_sleep_release(rt_uint16_t module_id, rt_uint8_t mode); +void rt_pm_sleep_none_request(rt_uint16_t module_id); +void rt_pm_sleep_none_release(rt_uint16_t module_id); +void rt_pm_sleep_idle_request(rt_uint16_t module_id); +void rt_pm_sleep_idle_release(rt_uint16_t module_id); +void rt_pm_sleep_light_request(rt_uint16_t module_id); +void rt_pm_sleep_light_release(rt_uint16_t module_id); #endif /* __PM_H__ */ diff --git a/components/drivers/pm/SConscript b/components/drivers/pm/SConscript index a94fc11f57..fd23e8293c 100644 --- a/components/drivers/pm/SConscript +++ b/components/drivers/pm/SConscript @@ -7,6 +7,7 @@ group = [] if GetDepend(['RT_USING_PM']): src = src + ['pm.c'] + src = src + ['lptimer.c'] if len(src): group = DefineGroup('DeviceDrivers', src, depend = [''], CPPPATH = CPPPATH) diff --git a/components/drivers/pm/lptimer.c b/components/drivers/pm/lptimer.c new file mode 100644 index 0000000000..144270cf7f --- /dev/null +++ b/components/drivers/pm/lptimer.c @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-10-11 zhangsz the first version + */ + +#include +#include +#include + +static rt_list_t rt_soft_lptimer_list = RT_LIST_OBJECT_INIT(rt_soft_lptimer_list); + +/* lptimer init */ +void rt_lptimer_init(rt_lptimer_t timer, + const char *name, + void (*timeout)(void *parameter), + void *parameter, + rt_tick_t time, + rt_uint8_t flag) +{ + rt_timer_init(&timer->timer, name, timeout, parameter, time, flag); + rt_list_init(&timer->list); +} + +/* lptimer detach */ +rt_err_t rt_lptimer_detach(rt_lptimer_t timer) +{ + rt_base_t level; + rt_err_t ret = RT_EOK; + RT_ASSERT(timer != RT_NULL); + + /* disable interrupt */ + level = rt_hw_interrupt_disable(); + + ret = rt_timer_detach(&timer->timer); + rt_list_remove(&timer->list); + + /* enable interrupt */ + rt_hw_interrupt_enable(level); + return ret; +} + +/* lptimer start */ +rt_err_t rt_lptimer_start(rt_lptimer_t timer) +{ + rt_base_t level; + + RT_ASSERT(timer != RT_NULL); + + /* disable interrupt */ + level = rt_hw_interrupt_disable(); + rt_list_remove(&timer->list); /* remove first */ + if (rt_timer_start(&timer->timer) == RT_EOK) + { + /* insert to lptimer list */ + rt_list_insert_after(&rt_soft_lptimer_list, &(timer->list)); + } + else + { + /* enable interrupt */ + rt_hw_interrupt_enable(level); + return -RT_ERROR; + } + + /* enable interrupt */ + rt_hw_interrupt_enable(level); + return RT_EOK; +} + +/* lptimer stop */ +rt_err_t rt_lptimer_stop(rt_lptimer_t timer) +{ + rt_base_t level; + RT_ASSERT(timer != RT_NULL); + + /* disable interrupt */ + level = rt_hw_interrupt_disable(); + rt_list_remove(&timer->list); + if (rt_timer_stop(&timer->timer) == RT_EOK) + { + /* enable interrupt */ + rt_hw_interrupt_enable(level); + return RT_EOK; + } + else + { + /* enable interrupt */ + rt_hw_interrupt_enable(level); + return -RT_ERROR; + } +} + +rt_err_t rt_lptimer_control(rt_lptimer_t timer, int cmd, void *arg) +{ + RT_ASSERT(timer != RT_NULL); + + return rt_timer_control(&timer->timer, cmd, arg); +} + +/* get the next soft lptimer timeout */ +rt_tick_t rt_lptimer_next_timeout_tick(void) +{ + struct rt_lptimer *timer; + rt_base_t level; + rt_tick_t timeout_tick = RT_TICK_MAX; + struct rt_list_node *node = RT_NULL; + rt_tick_t temp_tick = 0; + rt_tick_t min_tick = RT_TICK_MAX; + rt_tick_t cur_tick = rt_tick_get(); + + /* disable interrupt */ + level = rt_hw_interrupt_disable(); + + if (!rt_list_isempty(&rt_soft_lptimer_list)) + { + /* find the first active timer's timeout */ + rt_list_for_each(node, &rt_soft_lptimer_list) + { + timer = rt_list_entry(node, struct rt_lptimer, list); + if (timer->timer.parent.flag & RT_TIMER_FLAG_ACTIVATED) + { + temp_tick = timer->timer.timeout_tick - cur_tick; + + /* find the least timeout_tick */ + if (min_tick > temp_tick) + { + min_tick = temp_tick; + timeout_tick = timer->timer.timeout_tick; + } + } + } + } + + /* enable interrupt */ + rt_hw_interrupt_enable(level); + + return timeout_tick; +} + +void lptimer_dump(void) +{ + struct rt_lptimer *timer; + rt_base_t level; + struct rt_list_node *node = RT_NULL; + + /* disable interrupt */ + level = rt_hw_interrupt_disable(); + + rt_kprintf("| lptimer | periodic | timeout | flag |\n"); + rt_kprintf("+---------------+------------+------------+-------------+\n"); + + if (!rt_list_isempty(&rt_soft_lptimer_list)) + { + rt_list_for_each(node, &rt_soft_lptimer_list) + { + timer = rt_list_entry(node, struct rt_lptimer, list); + rt_kprintf("| %-13s | 0x%08x | 0x%08x |", + timer->timer.parent.name, timer->timer.init_tick, + timer->timer.timeout_tick); + if (timer->timer.parent.flag & RT_TIMER_FLAG_ACTIVATED) + rt_kprintf(" activated |\n"); + else + rt_kprintf(" deactivated |\n"); + } + } + + /* enable interrupt */ + rt_hw_interrupt_enable(level); + rt_kprintf("+---------------+------------+------------+-------------+\n"); +} + +MSH_CMD_EXPORT(lptimer_dump, soft lptimer dump); diff --git a/components/drivers/pm/pm.c b/components/drivers/pm/pm.c index cf488a9ce1..b3ebbeb078 100644 --- a/components/drivers/pm/pm.c +++ b/components/drivers/pm/pm.c @@ -15,9 +15,44 @@ #include #include #include +#include #ifdef RT_USING_PM +/* tickless threshold time */ +#ifndef PM_TICKLESS_THRESHOLD_TIME +#define PM_TICKLESS_THRESHOLD_TIME 2 +#endif + +/* tickless threshold : sleep mode */ +#ifndef PM_TICKLESS_THRESHOLD_MODE +#define PM_TICKLESS_THRESHOLD_MODE PM_SLEEP_MODE_IDLE +#endif + +/* busy : sleep mode */ +#ifndef PM_BUSY_SLEEP_MODE +#define PM_BUSY_SLEEP_MODE PM_SLEEP_MODE_IDLE +#endif + +/* suspend : suspend sleep mode */ +#ifndef PM_SUSPEND_SLEEP_MODE +#define PM_SUSPEND_SLEEP_MODE PM_SLEEP_MODE_IDLE +#endif + +#ifdef PM_ENABLE_THRESHOLD_SLEEP_MODE +#ifndef PM_LIGHT_THRESHOLD_TIME +#define PM_LIGHT_THRESHOLD_TIME 5 +#endif + +#ifndef PM_DEEP_THRESHOLD_TIME +#define PM_DEEP_THRESHOLD_TIME 20 +#endif + +#ifndef PM_STANDBY_THRESHOLD_TIME +#define PM_STANDBY_THRESHOLD_TIME 100 +#endif +#endif + static struct rt_pm _pm; /* default mode : system power on */ @@ -29,8 +64,6 @@ static rt_uint8_t _pm_default_deepsleep = RT_PM_DEFAULT_DEEPSLEEP_MODE; static struct rt_pm_notify _pm_notify; static rt_uint8_t _pm_init_flag = 0; -#define RT_PM_TICKLESS_THRESH (2) - RT_WEAK rt_uint32_t rt_pm_enter_critical(rt_uint8_t sleep_mode) { return rt_hw_interrupt_disable(); @@ -41,6 +74,48 @@ RT_WEAK void rt_pm_exit_critical(rt_uint32_t ctx, rt_uint8_t sleep_mode) rt_hw_interrupt_enable(ctx); } +/* lptimer start */ +static void pm_lptimer_start(struct rt_pm *pm, uint32_t timeout) +{ + if (_pm.ops == RT_NULL) + return; + + if (_pm.ops->timer_start != RT_NULL) + _pm.ops->timer_start(pm, timeout); +} + +/* lptimer stop */ +static void pm_lptimer_stop(struct rt_pm *pm) +{ + if (_pm.ops == RT_NULL) + return; + + if (_pm.ops->timer_stop != RT_NULL) + _pm.ops->timer_stop(pm); +} + +/* lptimer get timeout tick */ +static rt_tick_t pm_lptimer_get_timeout(struct rt_pm *pm) +{ + if (_pm.ops == RT_NULL) + return RT_TICK_MAX; + + if (_pm.ops->timer_get_tick != RT_NULL) + return _pm.ops->timer_get_tick(pm); + + return RT_TICK_MAX; +} + +/* enter sleep mode */ +static void pm_sleep(struct rt_pm *pm, uint8_t sleep_mode) +{ + if (_pm.ops == RT_NULL) + return; + + if (_pm.ops->sleep != RT_NULL) + _pm.ops->sleep(pm, sleep_mode); +} + /** * This function will suspend all registered devices */ @@ -111,6 +186,30 @@ static void _pm_frequency_scaling(struct rt_pm *pm) } } +/** + * judge sleep mode from sleep request + * + * @param none + * + * @return sleep mode + */ +static rt_uint8_t _judge_sleep_mode(void) +{ + rt_uint16_t index; + rt_uint16_t len; + + for (index = 0; index < PM_SLEEP_MODE_MAX -1; index++) + { + for (len = 0; len < ((PM_MODULE_MAX_ID + 31) / 32); len++) + { + if (_pm.sleep_status[index][len] != 0x00) + return index; + } + } + + return PM_SLEEP_MODE_MAX; /* default sleep mode */ +} + /** * This function selects the sleep mode according to the rt_pm_request/rt_pm_release count. */ @@ -120,6 +219,7 @@ static rt_uint8_t _pm_select_sleep_mode(struct rt_pm *pm) rt_uint8_t mode; mode = _pm_default_deepsleep; + rt_uint8_t request_mode = _judge_sleep_mode(); for (index = PM_SLEEP_MODE_NONE; index < PM_SLEEP_MODE_MAX; index ++) { if (pm->modes[index]) @@ -128,7 +228,10 @@ static rt_uint8_t _pm_select_sleep_mode(struct rt_pm *pm) break; } } - pm->sleep_mode = mode; + + /* select the high power mode */ + if (request_mode < mode) + mode = request_mode; return mode; } @@ -185,6 +288,72 @@ static rt_bool_t _pm_device_check_idle(void) return RT_TRUE; } +RT_WEAK rt_tick_t pm_timer_next_timeout_tick(rt_uint8_t mode) +{ + switch (mode) + { + case PM_SLEEP_MODE_LIGHT: + return rt_timer_next_timeout_tick(); + case PM_SLEEP_MODE_DEEP: + case PM_SLEEP_MODE_STANDBY: + return rt_lptimer_next_timeout_tick(); + } + + return RT_TICK_MAX; +} + +/** + * This function will judge sleep mode from threshold timeout. + * + * @param cur_mode the current pm sleep mode + * @param timeout_tick the threshold timeout + * + * @return none + */ +RT_WEAK rt_uint8_t pm_get_sleep_threshold_mode(rt_uint8_t cur_mode, rt_tick_t timeout_tick) +{ + rt_uint8_t sleep_mode = cur_mode; + + if (_pm_init_flag == 0) + return sleep_mode; + + if (cur_mode >= PM_SLEEP_MODE_MAX) + return sleep_mode; + +#ifdef PM_ENABLE_THRESHOLD_SLEEP_MODE + switch (cur_mode) + { + case PM_SLEEP_MODE_NONE: + case PM_SLEEP_MODE_IDLE: + break; + case PM_SLEEP_MODE_LIGHT: + if (timeout_tick < PM_LIGHT_THRESHOLD_TIME) + sleep_mode = PM_SLEEP_MODE_IDLE; + break; + case PM_SLEEP_MODE_DEEP: + if (timeout_tick < PM_LIGHT_THRESHOLD_TIME) + sleep_mode = PM_SLEEP_MODE_IDLE; + else if (timeout_tick < PM_DEEP_THRESHOLD_TIME) + sleep_mode = PM_SLEEP_MODE_LIGHT; + break; + case PM_SLEEP_MODE_STANDBY: + if (timeout_tick < PM_LIGHT_THRESHOLD_TIME) + sleep_mode = PM_SLEEP_MODE_IDLE; + else if (timeout_tick < PM_DEEP_THRESHOLD_TIME) + sleep_mode = PM_SLEEP_MODE_LIGHT; + else if (timeout_tick < PM_STANDBY_THRESHOLD_TIME) + sleep_mode = PM_SLEEP_MODE_DEEP; + } +#else + if (timeout_tick < PM_TICKLESS_THRESHOLD_TIME) + { + cur_mode = PM_SLEEP_MODE_IDLE; + } +#endif + + return cur_mode; +} + /** * This function changes the power sleep mode base on the result of selection */ @@ -192,16 +361,21 @@ static void _pm_change_sleep_mode(struct rt_pm *pm) { rt_tick_t timeout_tick, delta_tick; rt_base_t level; - int ret = RT_EOK; + uint8_t sleep_mode = PM_SLEEP_MODE_DEEP; level = rt_pm_enter_critical(pm->sleep_mode); - /* module busy request */ + /* judge sleep mode from module request */ + pm->sleep_mode = _pm_select_sleep_mode(pm); + + /* module busy request check */ if (_pm_device_check_idle() == RT_FALSE) { - pm->ops->sleep(pm, PM_SLEEP_MODE_NONE); - rt_pm_exit_critical(level, pm->sleep_mode); - return; + sleep_mode = PM_BUSY_SLEEP_MODE; + if (sleep_mode < pm->sleep_mode) + { + pm->sleep_mode = sleep_mode; /* judge the highest sleep mode */ + } } if (_pm.sleep_mode == PM_SLEEP_MODE_NONE) @@ -216,50 +390,54 @@ static void _pm_change_sleep_mode(struct rt_pm *pm) _pm_notify.notify(RT_PM_ENTER_SLEEP, pm->sleep_mode, _pm_notify.data); /* Suspend all peripheral device */ - ret = _pm_device_suspend(pm->sleep_mode); +#ifdef PM_ENABLE_SUSPEND_SLEEP_MODE + int ret = _pm_device_suspend(pm->sleep_mode); if (ret != RT_EOK) { _pm_device_resume(pm->sleep_mode); if (_pm_notify.notify) _pm_notify.notify(RT_PM_EXIT_SLEEP, pm->sleep_mode, _pm_notify.data); + if (pm->sleep_mode > PM_SUSPEND_SLEEP_MODE) + { + pm->sleep_mode = PM_SUSPEND_SLEEP_MODE; + } + pm->ops->sleep(pm, pm->sleep_mode); /* suspend failed */ rt_pm_exit_critical(level, pm->sleep_mode); - return; } - +#else + _pm_device_suspend(pm->sleep_mode); +#endif /* Tickless*/ if (pm->timer_mask & (0x01 << pm->sleep_mode)) { - timeout_tick = rt_timer_next_timeout_tick(); - if (timeout_tick == RT_TICK_MAX) - { - if (pm->ops->timer_start) - { - pm->ops->timer_start(pm, RT_TICK_MAX); - } - } - else + timeout_tick = pm_timer_next_timeout_tick(pm->sleep_mode); + timeout_tick = timeout_tick - rt_tick_get(); + + /* Judge sleep_mode from threshold time */ + pm->sleep_mode = pm_get_sleep_threshold_mode(pm->sleep_mode, timeout_tick); + + if (pm->timer_mask & (0x01 << pm->sleep_mode)) { - timeout_tick = timeout_tick - rt_tick_get(); - if (timeout_tick < RT_PM_TICKLESS_THRESH) + if (timeout_tick == RT_TICK_MAX) { - pm->sleep_mode = PM_SLEEP_MODE_IDLE; + pm_lptimer_start(pm, RT_TICK_MAX); } else { - pm->ops->timer_start(pm, timeout_tick); + pm_lptimer_start(pm, timeout_tick); } } } /* enter lower power state */ - pm->ops->sleep(pm, pm->sleep_mode); + pm_sleep(pm, pm->sleep_mode); /* wake up from lower power state*/ if (pm->timer_mask & (0x01 << pm->sleep_mode)) { - delta_tick = pm->ops->timer_get_tick(pm); - pm->ops->timer_stop(pm); + delta_tick = pm_lptimer_get_timeout(pm); + pm_lptimer_stop(pm); if (delta_tick) { rt_tick_set(rt_tick_get() + delta_tick); @@ -320,7 +498,6 @@ void rt_pm_request(rt_uint8_t mode) pm = &_pm; if (pm->modes[mode] < 255) pm->modes[mode] ++; - _pm_select_sleep_mode(pm); rt_hw_interrupt_enable(level); } @@ -346,7 +523,6 @@ void rt_pm_release(rt_uint8_t mode) pm = &_pm; if (pm->modes[mode] > 0) pm->modes[mode] --; - _pm_select_sleep_mode(pm); rt_hw_interrupt_enable(level); } @@ -371,7 +547,6 @@ void rt_pm_release_all(rt_uint8_t mode) level = rt_hw_interrupt_disable(); pm = &_pm; pm->modes[mode] = 0; - _pm_select_sleep_mode(pm); rt_hw_interrupt_enable(level); } @@ -401,7 +576,6 @@ void rt_pm_module_request(uint8_t module_id, rt_uint8_t mode) pm->module_status[module_id].req_status = 0x01; if (pm->modes[mode] < 255) pm->modes[mode] ++; - _pm_select_sleep_mode(pm); rt_hw_interrupt_enable(level); } @@ -433,7 +607,6 @@ void rt_pm_module_release(uint8_t module_id, rt_uint8_t mode) pm->modes[mode] --; if (pm->modes[mode] == 0) pm->module_status[module_id].req_status = 0x00; - _pm_select_sleep_mode(pm); rt_hw_interrupt_enable(level); } @@ -460,10 +633,135 @@ void rt_pm_module_release_all(uint8_t module_id, rt_uint8_t mode) pm = &_pm; pm->modes[mode] = 0; pm->module_status[module_id].req_status = 0x00; - _pm_select_sleep_mode(pm); rt_hw_interrupt_enable(level); } +/** + * This function will let current module work with specified sleep mode. + * + * @param module_id the pm module id + * @param mode the pm sleep mode + * + * @return none + */ +void rt_pm_sleep_request(rt_uint16_t module_id, rt_uint8_t mode) +{ + rt_uint32_t level; + + if (module_id >= PM_MODULE_MAX_ID) + { + return; + } + + if (mode >= (PM_SLEEP_MODE_MAX - 1)) + { + return; + } + + level = rt_hw_interrupt_disable(); + _pm.sleep_status[mode][module_id / 32] |= 1 << (module_id % 32); + rt_hw_interrupt_enable(level); +} + +/** + * This function will let current module work with PM_SLEEP_MODE_NONE mode. + * + * @param module_id the pm module id + * + * @return NULL + */ +void rt_pm_sleep_none_request(rt_uint16_t module_id) +{ + rt_pm_sleep_request(module_id, PM_SLEEP_MODE_NONE); +} + +/** + * This function will let current module work with PM_SLEEP_MODE_IDLE mode. + * + * @param module_id the pm module id + * + * @return NULL + */ +void rt_pm_sleep_idle_request(rt_uint16_t module_id) +{ + rt_pm_sleep_request(module_id, PM_SLEEP_MODE_IDLE); +} + +/** + * This function will let current module work with PM_SLEEP_MODE_LIGHT mode. + * + * @param module_id the pm module id + * + * @return NULL + */ +void rt_pm_sleep_light_request(rt_uint16_t module_id) +{ + rt_pm_sleep_request(module_id, PM_SLEEP_MODE_LIGHT); +} + +/** + * When current module don't work, release requested sleep mode. + * + * @param module_id the pm module id + * @param mode the pm sleep mode + * + * @return NULL + */ +void rt_pm_sleep_release(rt_uint16_t module_id, rt_uint8_t mode) +{ + rt_uint32_t level; + + if (module_id >= PM_MODULE_MAX_ID) + { + return; + } + + if (mode >= (PM_SLEEP_MODE_MAX - 1)) + { + return; + } + + level = rt_hw_interrupt_disable(); + _pm.sleep_status[mode][module_id / 32] &= ~(1 << (module_id % 32)); + rt_hw_interrupt_enable(level); +} + +/** + * The specified module release the requested PM_SLEEP_MODE_NONE mode + * + * @param module_id the pm module id + * + * @return none + */ +void rt_pm_sleep_none_release(rt_uint16_t module_id) +{ + rt_pm_sleep_release(module_id, PM_SLEEP_MODE_NONE); +} + +/** + * The specified module release the requested PM_SLEEP_MODE_IDLE mode + * + * @param module_id the pm module id + * + * @return none + */ +void rt_pm_sleep_idle_release(rt_uint16_t module_id) +{ + rt_pm_sleep_release(module_id, PM_SLEEP_MODE_IDLE); +} + +/** + * The specified module release the requested PM_SLEEP_MODE_LIGHT mode + * + * @param module_id the pm module id + * + * @return none + */ +void rt_pm_sleep_light_release(rt_uint16_t module_id) +{ + rt_pm_sleep_release(module_id, PM_SLEEP_MODE_LIGHT); +} + /** * Register a device with PM feature * @@ -853,6 +1151,69 @@ rt_uint8_t rt_pm_get_sleep_mode(void) return pm->sleep_mode; } +/* get pm entity pointer */ +struct rt_pm *rt_pm_get_handle(void) +{ + return &_pm; +} + +#ifdef PM_ENABLE_DEBUG +/** + * print current module sleep request list + * + * @param none + * + * @return none + */ +void pm_sleep_dump(void) +{ + uint8_t index; + uint16_t len; + + rt_kprintf("+-------------+--------------+\n"); + rt_kprintf("| Sleep Mode | Request List |\n"); + rt_kprintf("+-------------+--------------+\n"); + for (index = 0; index < PM_SLEEP_MODE_MAX -1; index++) + { + for (len = 0; len < ((PM_MODULE_MAX_ID + 31) / 32); len++) + { + rt_kprintf("| Mode[%d] : %d | 0x%08x |\n", index, len, + _pm.sleep_status[index][len]); + } + } + rt_kprintf("+-------------+--------------+\n"); +} +MSH_CMD_EXPORT(pm_sleep_dump, dump pm request list); + +static void pm_sleep_request(int argc, char **argv) +{ + int module = 0; + int mode = 0; + + if (argc >= 3) + { + module = atoi(argv[1]); + mode = atoi(argv[2]); + rt_pm_sleep_request(module, mode); + } +} +MSH_CMD_EXPORT(pm_sleep_request, pm_sleep_request module sleep_mode); + +static void pm_sleep_release(int argc, char **argv) +{ + int module = 0; + int mode = 0; + + if (argc >= 3) + { + module = atoi(argv[1]); + mode = atoi(argv[2]); + rt_pm_sleep_release(module, mode); + } +} +MSH_CMD_EXPORT(pm_sleep_release, pm_sleep_release module sleep_mode); +#endif + static void rt_pm_dump_status(void) { rt_uint32_t index; -- cgit v1.3.1