diff --git a/bsp/qemu-vexpress-a9/drivers/drv_clcd.c b/bsp/qemu-vexpress-a9/drivers/drv_clcd.c index 543924e7181d97afe7a1391351b31cc6363fd807..4444d338c33b514c8fcc207930b06d88364d3231 100644 --- a/bsp/qemu-vexpress-a9/drivers/drv_clcd.c +++ b/bsp/qemu-vexpress-a9/drivers/drv_clcd.c @@ -5,8 +5,8 @@ #include #include "drv_clcd.h" -#define CLCD_WIDTH 480 -#define CLCD_HEIGHT 320 +#define CLCD_WIDTH 640 +#define CLCD_HEIGHT 480 #define CLCD_DEVICE(dev) (struct drv_clcd_device*)(dev) @@ -78,6 +78,18 @@ static rt_err_t drv_clcd_control(struct rt_device *device, int cmd, void *args) return RT_EOK; } +#ifdef RT_USING_DEVICE_OPS +const static struct rt_device_ops clcd_ops = +{ + drv_clcd_init, + RT_NULL, + RT_NULL, + RT_NULL, + RT_NULL, + drv_clcd_control +}; +#endif + int drv_clcd_hw_init(void) { PL111MMIO *plio; @@ -107,8 +119,13 @@ int drv_clcd_hw_init(void) plio->control = 0x1921 | (0x6 << 1); device->type = RT_Device_Class_Graphic; +#ifdef RT_USING_DEVICE_OPS + device->ops = &clcd_ops; +#else device->init = drv_clcd_init; device->control = drv_clcd_control; +#endif + rt_device_register(device, "lcd", RT_DEVICE_FLAG_RDWR); return 0; diff --git a/bsp/qemu-vexpress-a9/drivers/drv_smc911x.c b/bsp/qemu-vexpress-a9/drivers/drv_smc911x.c index a5a7df3b0690e32d7e25da0bfee29819758ddb7e..4b33cc42157692abc4dc4e1daeda7abb619665f2 100644 --- a/bsp/qemu-vexpress-a9/drivers/drv_smc911x.c +++ b/bsp/qemu-vexpress-a9/drivers/drv_smc911x.c @@ -485,6 +485,18 @@ struct pbuf *smc911x_emac_rx(rt_device_t dev) return p; } +#ifdef RT_USING_DEVICE_OPS +const static struct rt_device_ops smc911x_emac_ops = +{ + smc911x_emac_init, + RT_NULL, + RT_NULL, + RT_NULL, + RT_NULL, + smc911x_emac_control +}; +#endif + int smc911x_emac_hw_init(void) { _emac.iobase = VEXPRESS_ETH_BASE; @@ -507,12 +519,16 @@ int smc911x_emac_hw_init(void) _emac.enetaddr[4] = 0x22; _emac.enetaddr[5] = 0x33; +#ifdef RT_USING_DEVICE_OPS + _emac.parent.parent.ops = &smc911x_emac_ops; +#else _emac.parent.parent.init = smc911x_emac_init; _emac.parent.parent.open = RT_NULL; _emac.parent.parent.close = RT_NULL; _emac.parent.parent.read = RT_NULL; _emac.parent.parent.write = RT_NULL; _emac.parent.parent.control = smc911x_emac_control; +#endif _emac.parent.parent.user_data = RT_NULL; _emac.parent.eth_rx = smc911x_emac_rx; _emac.parent.eth_tx = smc911x_emac_tx; @@ -540,12 +556,3 @@ int smc911x_emac_hw_init(void) return 0; } INIT_APP_EXPORT(smc911x_emac_hw_init); - -#include -int emac(int argc, char** argv) -{ - rt_hw_interrupt_umask(_emac.irqno); - - return 0; -} -MSH_CMD_EXPORT(emac, emac dump); diff --git a/bsp/stm32f411-nucleo/Kconfig b/bsp/stm32f411-nucleo/Kconfig index dbc6403e945347ac82ffa116057ebfef15b1b2ef..eccda0aefe58b6c75ac829aa06dbaea173aa1f87 100644 --- a/bsp/stm32f411-nucleo/Kconfig +++ b/bsp/stm32f411-nucleo/Kconfig @@ -15,6 +15,11 @@ config $PKGS_DIR option env="PKGS_ROOT" default "packages" +config BOARD_STM32F411_NUCLEO + bool + select ARCH_ARM_CORTEX_M4 + default y + source "$RTT_DIR/Kconfig" source "$PKGS_DIR/Kconfig" diff --git a/bsp/stm32f411-nucleo/drivers/stm32f4xx_it.c b/bsp/stm32f411-nucleo/drivers/stm32f4xx_it.c index c2dd528276892ad7e2cb1b3563ac3ed27ecb43ee..7b5660001d8294e8501fa8d1b9752127ad6eeb6f 100644 --- a/bsp/stm32f411-nucleo/drivers/stm32f4xx_it.c +++ b/bsp/stm32f411-nucleo/drivers/stm32f4xx_it.c @@ -93,15 +93,6 @@ void UsageFault_Handler(void) } } -/** - * @brief This function handles SVCall exception. - * @param None - * @retval None - */ -void SVC_Handler(void) -{ -} - /** * @} */ diff --git a/bsp/stm32f411-nucleo/stm32_rom.ld b/bsp/stm32f411-nucleo/stm32_rom.ld index 9db59b5fb268d06fa339b672667214604d9b5798..9045a9195ca928118372380f81bb3652277700ca 100644 --- a/bsp/stm32f411-nucleo/stm32_rom.ld +++ b/bsp/stm32f411-nucleo/stm32_rom.ld @@ -39,6 +39,12 @@ SECTIONS __vsymtab_end = .; . = ALIGN(4); + /* section information for modules */ + . = ALIGN(4); + __rtmsymtab_start = .; + KEEP(*(RTMSymTab)) + __rtmsymtab_end = .; + /* section information for initial. */ . = ALIGN(4); __rt_init_start = .; diff --git a/components/Kconfig b/components/Kconfig index ed5c137d374dc25133d479c84fe0749a796cd72b..3bcae8e1631c559d01560a8b23a8a7d8d03d425b 100644 --- a/components/Kconfig +++ b/components/Kconfig @@ -26,6 +26,8 @@ source "$RTT_DIR/components/drivers/Kconfig" source "$RTT_DIR/components/libc/Kconfig" +source "$RTT_DIR/components/lwp/Kconfig" + source "$RTT_DIR/components/net/Kconfig" source "$RTT_DIR/components/vbus/Kconfig" diff --git a/components/dfs/include/dfs.h b/components/dfs/include/dfs.h index 91ef42ab56e1bb4de2d4ebbca9fb8e544ad09a57..f17458bd69b7656cda923dae6d03dc6c148c9bee 100644 --- a/components/dfs/include/dfs.h +++ b/components/dfs/include/dfs.h @@ -95,6 +95,12 @@ struct dirent char d_name[DFS_PATH_MAX]; /* The null-terminated file name */ }; +struct dfs_fdtable +{ + uint32_t maxfd; + struct dfs_fd **fds; +}; + /* Initialization of dfs */ int dfs_init(void); @@ -110,6 +116,8 @@ struct dfs_fd *fd_get(int fd); void fd_put(struct dfs_fd *fd); int fd_is_open(const char *pathname); +struct dfs_fdtable* dfs_fdtable_get(void); + #ifdef __cplusplus } #endif diff --git a/components/dfs/src/dfs.c b/components/dfs/src/dfs.c index 858399fd137c79f8d8f7a160a9967d62ca01c7c1..f613168a4c0371375d921272fbccfaaeb1de0197 100644 --- a/components/dfs/src/dfs.c +++ b/components/dfs/src/dfs.c @@ -21,12 +21,16 @@ * Date Author Notes * 2005-02-22 Bernard The first version. * 2017-12-11 Bernard Use rt_free to instead of free in fd_is_open(). + * 2018-03-20 Heyuanjie dynamic allocation FD */ #include #include #include #include "dfs_private.h" +#ifdef RT_USING_LWP +#include +#endif /* Global variables */ const struct dfs_filesystem_ops *filesystem_operation_table[DFS_FILESYSTEM_TYPES_MAX]; @@ -39,7 +43,8 @@ static struct rt_mutex fslock; char working_directory[DFS_PATH_MAX] = {"/"}; #endif -struct dfs_fd fd_table[DFS_FD_MAX]; +static struct dfs_fdtable _fdtab; +static int fd_alloc(struct dfs_fdtable *fdt, int startfd); /** * @addtogroup DFS @@ -57,7 +62,7 @@ int dfs_init(void) /* clear filesystem table */ memset(filesystem_table, 0, sizeof(filesystem_table)); /* clean fd table */ - memset(fd_table, 0, sizeof(fd_table)); + memset(&_fdtab, 0, sizeof(_fdtab)); /* create device filesystem lock */ rt_mutex_init(&fslock, "fslock", RT_IPC_FLAG_FIFO); @@ -90,9 +95,13 @@ INIT_PREV_EXPORT(dfs_init); */ void dfs_lock(void) { - rt_err_t result; + rt_err_t result = -RT_EBUSY; + + while (result == -RT_EBUSY) + { + result = rt_mutex_take(&fslock, RT_WAITING_FOREVER); + } - result = rt_mutex_take(&fslock, RT_WAITING_FOREVER); if (result != RT_EOK) { RT_ASSERT(0); @@ -109,6 +118,54 @@ void dfs_unlock(void) rt_mutex_release(&fslock); } +static int fd_alloc(struct dfs_fdtable *fdt, int startfd) +{ + int idx; + + /* find an empty fd entry */ + for (idx = startfd; idx < fdt->maxfd; idx++) + { + if (fdt->fds[idx] == RT_NULL) + break; + if (fdt->fds[idx]->ref_count == 0) + break; + } + + /* allocate a larger FD container */ + if (idx == fdt->maxfd && fdt->maxfd < DFS_FD_MAX) + { + int cnt, index; + struct dfs_fd **fds; + + /* increase the number of FD with 4 step length */ + cnt = fdt->maxfd + 4; + cnt = cnt > DFS_FD_MAX? DFS_FD_MAX : cnt; + + fds = rt_realloc(fdt->fds, cnt * sizeof(struct dfs_fd *)); + if (fds == NULL) goto __out; /* return fdt->maxfd */ + + /* clean the new allocated fds */ + for (index = fdt->maxfd; index < cnt; index ++) + { + fds[index] = NULL; + } + + fdt->fds = fds; + fdt->maxfd = cnt; + } + + /* allocate 'struct dfs_fd' */ + if (idx < fdt->maxfd &&fdt->fds[idx] == RT_NULL) + { + fdt->fds[idx] = rt_malloc(sizeof(struct dfs_fd)); + if (fdt->fds[idx] == RT_NULL) + idx = fdt->maxfd; + } + +__out: + return idx; +} + /** * @ingroup Fd * This function will allocate a file descriptor. @@ -119,21 +176,23 @@ int fd_new(void) { struct dfs_fd *d; int idx; + struct dfs_fdtable *fdt; + fdt = dfs_fdtable_get(); /* lock filesystem */ dfs_lock(); /* find an empty fd entry */ - for (idx = 0; idx < DFS_FD_MAX && fd_table[idx].ref_count > 0; idx++); + idx = fd_alloc(fdt, 0); /* can't find an empty fd entry */ - if (idx == DFS_FD_MAX) + if (idx == fdt->maxfd) { idx = -(1 + DFS_FD_OFFSET); goto __result; } - d = &(fd_table[idx]); + d = fdt->fds[idx]; d->ref_count = 1; d->magic = DFS_FD_MAGIC; @@ -154,13 +213,15 @@ __result: struct dfs_fd *fd_get(int fd) { struct dfs_fd *d; + struct dfs_fdtable *fdt; + fdt = dfs_fdtable_get(); fd = fd - DFS_FD_OFFSET; - if (fd < 0 || fd >= DFS_FD_MAX) + if (fd < 0 || fd >= fdt->maxfd) return NULL; dfs_lock(); - d = &fd_table[fd]; + d = fdt->fds[fd]; /* check dfs_fd valid or not */ if (d->magic != DFS_FD_MAGIC) @@ -186,12 +247,25 @@ void fd_put(struct dfs_fd *fd) RT_ASSERT(fd != NULL); dfs_lock(); + fd->ref_count --; /* clear this fd entry */ if (fd->ref_count == 0) { - memset(fd, 0, sizeof(struct dfs_fd)); + int index; + struct dfs_fdtable *fdt; + + fdt = dfs_fdtable_get(); + for (index = 0; index < fdt->maxfd; index ++) + { + if (fdt->fds[index] == fd) + { + rt_free(fd); + fdt->fds[index] = 0; + break; + } + } } dfs_unlock(); } @@ -211,7 +285,9 @@ int fd_is_open(const char *pathname) unsigned int index; struct dfs_filesystem *fs; struct dfs_fd *fd; + struct dfs_fdtable *fdt; + fdt = dfs_fdtable_get(); fullpath = dfs_normalize_path(NULL, pathname); if (fullpath != NULL) { @@ -233,11 +309,10 @@ int fd_is_open(const char *pathname) dfs_lock(); - for (index = 0; index < DFS_FD_MAX; index++) + for (index = 0; index < fdt->maxfd; index++) { - fd = &(fd_table[index]); - if (fd->fops == NULL) - continue; + fd = fdt->fds[index]; + if (fd == NULL) continue; if (fd->fops == fs->ops->fops && strcmp(fd->path, mountpath) == 0) { @@ -414,17 +489,43 @@ up_one: return fullpath; } RTM_EXPORT(dfs_normalize_path); + +/** + * This function will get the file descriptor table of current process. + */ +struct dfs_fdtable* dfs_fdtable_get(void) +{ + struct dfs_fdtable *fdt; +#ifdef RT_USING_LWP + struct rt_lwp *lwp; + + lwp = (struct rt_lwp *)rt_thread_self()->user_data; + if (lwp) + fdt = &lwp->fdt; + else + fdt = &_fdtab; +#else + fdt = &_fdtab; +#endif + + return fdt; +} + #ifdef RT_USING_FINSH #include int list_fd(void) { int index; + struct dfs_fdtable *fd_table; + + fd_table = dfs_fdtable_get(); + if (!fd_table) return -1; rt_enter_critical(); - for (index = 0; index < DFS_FD_MAX; index ++) + for (index = 0; index < fd_table->maxfd; index ++) { - struct dfs_fd *fd = &(fd_table[index]); + struct dfs_fd *fd = fd_table->fds[index]; if (fd->fops) { diff --git a/components/drivers/audio/audio.c b/components/drivers/audio/audio.c index 87bb7260580fef7227192c99ac1d34eee0e9aeeb..220a000df1a9acf0b838884c0cc74fa96c7b78f1 100644 --- a/components/drivers/audio/audio.c +++ b/components/drivers/audio/audio.c @@ -421,6 +421,18 @@ static rt_err_t _audio_dev_control(struct rt_device *dev, int cmd, void *args) return result; } +#ifdef RT_USING_DEVICE_OPS +const static struct rt_device_ops audio_ops = +{ + _audio_dev_init, + _audio_dev_open, + _audio_dev_close, + _audio_dev_read, + _audio_dev_write, + _audio_dev_control +}; +#endif + rt_err_t rt_audio_register(struct rt_audio_device *audio, const char *name, rt_uint32_t flag, void *data) { struct rt_device *device; @@ -431,12 +443,16 @@ rt_err_t rt_audio_register(struct rt_audio_device *audio, const char *name, rt_u device->rx_indicate = RT_NULL; device->tx_complete = RT_NULL; - device->init = _audio_dev_init; - device->open = _audio_dev_open; - device->close = _audio_dev_close; - device->read = _audio_dev_read; - device->write = _audio_dev_write; +#ifdef RT_USING_DEVICE_OPS + device->ops = &audio_ops; +#else + device->init = _audio_dev_init; + device->open = _audio_dev_open; + device->close = _audio_dev_close; + device->read = _audio_dev_read; + device->write = _audio_dev_write; device->control = _audio_dev_control; +#endif device->user_data = data; //init memory pool for replay diff --git a/components/drivers/audio/audio_pipe.c b/components/drivers/audio/audio_pipe.c index abef1557a4754c7dd26430cdd93cb695238033fe..9dc296831ee18d47dc80a6fbeaed9475209ce9ec 100644 --- a/components/drivers/audio/audio_pipe.c +++ b/components/drivers/audio/audio_pipe.c @@ -193,14 +193,26 @@ static rt_size_t rt_pipe_write(rt_device_t dev, static rt_err_t rt_pipe_control(rt_device_t dev, int cmd, void *args) { struct rt_audio_pipe *pipe; - + pipe = (struct rt_audio_pipe *)dev; - + if (cmd == PIPE_CTRL_GET_SPACE && args) *(rt_size_t*)args = rt_ringbuffer_space_len(&pipe->ringbuffer); return RT_EOK; } +#ifdef RT_USING_DEVICE_OPS +const static struct rt_device_ops audio_pipe_ops +{ + RT_NULL, + RT_NULL, + RT_NULL, + rt_pipe_read, + rt_pipe_write, + rt_pipe_control +}; +#endif + /** * This function will initialize a pipe device and put it under control of * resource management. @@ -233,12 +245,16 @@ rt_err_t rt_audio_pipe_init(struct rt_audio_pipe *pipe, /* create pipe */ pipe->parent.type = RT_Device_Class_Pipe; +#ifdef RT_USING_DEVICE_OPS + pipe->parent.ops = &audio_pipe_ops; +#else pipe->parent.init = RT_NULL; pipe->parent.open = RT_NULL; pipe->parent.close = RT_NULL; pipe->parent.read = rt_pipe_read; pipe->parent.write = rt_pipe_write; pipe->parent.control = rt_pipe_control; +#endif return rt_device_register(&(pipe->parent), name, RT_DEVICE_FLAG_RDWR); } diff --git a/components/drivers/can/can.c b/components/drivers/can/can.c index 000745514c3e110b887b00f5b50ffc87a23c472a..98d76cd5b306f8ae308d580c4feaf0c8ddc92551 100644 --- a/components/drivers/can/can.c +++ b/components/drivers/can/can.c @@ -687,6 +687,18 @@ static void cantimeout(void *arg) } } +#ifdef RT_USING_DEVICE_OPS +const static struct rt_device_ops can_device_ops = +{ + rt_can_init, + rt_can_open, + rt_can_close, + rt_can_read, + rt_can_write, + rt_can_control +}; +#endif + /* * can register */ @@ -712,12 +724,17 @@ rt_err_t rt_hw_can_register(struct rt_can_device *can, #ifdef RT_CAN_USING_BUS_HOOK can->bus_hook = RT_NULL; #endif /*RT_CAN_USING_BUS_HOOK*/ + +#ifdef RT_USING_DEVICE_OPS + device->ops = &can_device_ops; +#else device->init = rt_can_init; device->open = rt_can_open; device->close = rt_can_close; device->read = rt_can_read; device->write = rt_can_write; device->control = rt_can_control; +#endif can->ops = ops; can->status_indicate.ind = RT_NULL; diff --git a/components/drivers/hwtimer/hwtimer.c b/components/drivers/hwtimer/hwtimer.c index 066c5f6f6c6c0fbf21a26d449507e7b55e946577..c3e50763432fd28675ec72b49e694cb36ecdf416 100644 --- a/components/drivers/hwtimer/hwtimer.c +++ b/components/drivers/hwtimer/hwtimer.c @@ -35,13 +35,13 @@ rt_inline rt_uint32_t timeout_calc(rt_hwtimer_t *timer, rt_hwtimerval_t *tv) float devi_min = 1; float devi; - /* 把定时器溢出时间和定时时间换算成秒 */ + /* changed to second */ overflow = timer->info->maxcnt/(float)timer->freq; tv_sec = tv->sec + tv->usec/(float)1000000; if (tv_sec < (1/(float)timer->freq)) { - /* 定时时间小于计数周期 */ + /* little timeout */ i = 0; timeout = 1/(float)timer->freq; } @@ -55,7 +55,7 @@ rt_inline rt_uint32_t timeout_calc(rt_hwtimer_t *timer, rt_hwtimerval_t *tv) { counter = timeout*timer->freq; devi = tv_sec - (counter/(float)timer->freq)*i; - /* 计算最小误差 */ + /* Minimum calculation error */ if (devi > devi_min) { i = index; @@ -89,7 +89,7 @@ static rt_err_t rt_hwtimer_init(struct rt_device *dev) rt_hwtimer_t *timer; timer = (rt_hwtimer_t *)dev; - /* 尝试将默认计数频率设为1Mhz */ + /* try to change to 1MHz */ if ((1000000 <= timer->info->maxfreq) && (1000000 >= timer->info->minfreq)) { timer->freq = 1000000; @@ -330,6 +330,18 @@ void rt_device_hwtimer_isr(rt_hwtimer_t *timer) } } +#ifdef RT_USING_DEVICE_OPS +const static struct rt_device_ops hwtimer_ops = +{ + rt_hwtimer_init, + rt_hwtimer_open, + rt_hwtimer_close, + rt_hwtimer_read, + rt_hwtimer_write, + rt_hwtimer_control +}; +#endif + rt_err_t rt_device_hwtimer_register(rt_hwtimer_t *timer, const char *name, void *user_data) { struct rt_device *device; @@ -344,12 +356,16 @@ rt_err_t rt_device_hwtimer_register(rt_hwtimer_t *timer, const char *name, void device->rx_indicate = RT_NULL; device->tx_complete = RT_NULL; +#ifdef RT_USING_DEVICE_OPS + device->ops = &hwtimer_ops; +#else device->init = rt_hwtimer_init; device->open = rt_hwtimer_open; device->close = rt_hwtimer_close; device->read = rt_hwtimer_read; device->write = rt_hwtimer_write; device->control = rt_hwtimer_control; +#endif device->user_data = user_data; return rt_device_register(device, name, RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_STANDALONE); diff --git a/components/drivers/i2c/fm24clxx.c b/components/drivers/i2c/fm24clxx.c index c37a62973a5e7284d18bcc4017e491dad59b2a12..bb77d707bf318727d822a1e4877248a414548caa 100644 --- a/components/drivers/i2c/fm24clxx.c +++ b/components/drivers/i2c/fm24clxx.c @@ -132,6 +132,18 @@ static rt_size_t fm24clxx_write(rt_device_t dev, rt_off_t pos, const void *buffe return (ret == 2) ? size : 0; } +#ifdef RT_USING_DEVICE_OPS +const static struct rt_device fm24clxx_ops = +{ + fm24clxx_init, + fm24clxx_open, + fm24clxx_close, + fm24clxx_read, + fm24clxx_write, + fm24clxx_control +}; +#endif + rt_err_t fm24clxx_register(const char *fm_device_name, const char *i2c_bus, void *user_data) { static struct fm24clxx_device fm24clxx_drv; @@ -145,12 +157,17 @@ rt_err_t fm24clxx_register(const char *fm_device_name, const char *i2c_bus, void fm24clxx_drv.bus = bus; fm24clxx_drv.parent.type = RT_Device_Class_Block; +#ifdef RT_USING_DEVICE_OPS + fm24clxx_drv.parent.ops = &fm24clxx_ops; +#else fm24clxx_drv.parent.init = fm24clxx_init; fm24clxx_drv.parent.open = fm24clxx_open; fm24clxx_drv.parent.close = fm24clxx_close; fm24clxx_drv.parent.read = fm24clxx_read; fm24clxx_drv.parent.write = fm24clxx_write; fm24clxx_drv.parent.control = fm24clxx_control; +#endif + fm24clxx_drv.parent.user_data = user_data; return rt_device_register(&fm24clxx_drv.parent, fm_device_name, RT_DEVICE_FLAG_RDWR); diff --git a/components/drivers/i2c/i2c_dev.c b/components/drivers/i2c/i2c_dev.c index 5713a289365ab188b303b1c8da1e3d9ba72b6cd6..042b7b743a5dcbf0d940674deddbff4a1680c9be 100644 --- a/components/drivers/i2c/i2c_dev.c +++ b/components/drivers/i2c/i2c_dev.c @@ -102,6 +102,18 @@ static rt_err_t i2c_bus_device_control(rt_device_t dev, return RT_EOK; } +#ifdef RT_USING_DEVICE_OPS +const static struct rt_device_ops i2c_ops = +{ + RT_NULL, + RT_NULL, + RT_NULL, + i2c_bus_device_read, + i2c_bus_device_write, + i2c_bus_device_control +}; +#endif + rt_err_t rt_i2c_bus_device_device_init(struct rt_i2c_bus_device *bus, const char *name) { @@ -115,12 +127,16 @@ rt_err_t rt_i2c_bus_device_device_init(struct rt_i2c_bus_device *bus, /* set device type */ device->type = RT_Device_Class_I2CBUS; /* initialize device interface */ +#ifdef RT_USING_DEVICE_OPS + device->ops = &i2c_ops; +#else device->init = RT_NULL; device->open = RT_NULL; device->close = RT_NULL; device->read = i2c_bus_device_read; device->write = i2c_bus_device_write; device->control = i2c_bus_device_control; +#endif /* register to device manager */ rt_device_register(device, name, RT_DEVICE_FLAG_RDWR); diff --git a/components/drivers/misc/pin.c b/components/drivers/misc/pin.c index 9ed827f0b59e8f57930565b00f81ca713e16212b..dc2137eb17d65c40720d0fb91bdf084092deccd7 100644 --- a/components/drivers/misc/pin.c +++ b/components/drivers/misc/pin.c @@ -76,18 +76,34 @@ static rt_err_t _pin_control(rt_device_t dev, int cmd, void *args) return 0; } +#ifdef RT_USING_DEVICE_OPS +const static struct rt_device_ops pin_ops = +{ + RT_NULL, + RT_NULL, + RT_NULL, + _pin_read, + _pin_write, + _pin_control +}; +#endif + int rt_device_pin_register(const char *name, const struct rt_pin_ops *ops, void *user_data) { _hw_pin.parent.type = RT_Device_Class_Miscellaneous; _hw_pin.parent.rx_indicate = RT_NULL; _hw_pin.parent.tx_complete = RT_NULL; +#ifdef RT_USING_DEVICE_OPS + _hw_pin.parent.ops = &pin_ops; +#else _hw_pin.parent.init = RT_NULL; _hw_pin.parent.open = RT_NULL; _hw_pin.parent.close = RT_NULL; _hw_pin.parent.read = _pin_read; _hw_pin.parent.write = _pin_write; _hw_pin.parent.control = _pin_control; +#endif _hw_pin.ops = ops; _hw_pin.parent.user_data = user_data; @@ -117,6 +133,7 @@ rt_err_t rt_pin_dettach_irq(rt_int32_t pin) } return RT_ENOSYS; } + rt_err_t rt_pin_irq_enable(rt_base_t pin, rt_uint32_t enabled) { RT_ASSERT(_hw_pin.ops != RT_NULL); @@ -126,6 +143,7 @@ rt_err_t rt_pin_irq_enable(rt_base_t pin, rt_uint32_t enabled) } return RT_ENOSYS; } + /* RT-Thread Hardware PIN APIs */ void rt_pin_mode(rt_base_t pin, rt_base_t mode) { diff --git a/components/drivers/mtd/mtd_nand.c b/components/drivers/mtd/mtd_nand.c index 8cd0a03d5d382a838eeded46f0bbcbd55d305ca9..bf22d889ce56a19b021f0388983b05d18e3e6820 100644 --- a/components/drivers/mtd/mtd_nand.c +++ b/components/drivers/mtd/mtd_nand.c @@ -69,6 +69,18 @@ static rt_err_t _mtd_control(rt_device_t dev, int cmd, void *args) return RT_EOK; } +#ifdef RT_USING_DEVICE_OPS +const static struct rt_device_ops mtd_nand_ops = +{ + _mtd_init, + _mtd_open, + _mtd_close, + _mtd_read, + _mtd_write, + _mtd_control +}; +#endif + rt_err_t rt_mtd_nand_register_device(const char *name, struct rt_mtd_nand_device *device) { @@ -79,12 +91,16 @@ rt_err_t rt_mtd_nand_register_device(const char *name, /* set device class and generic device interface */ dev->type = RT_Device_Class_MTD; +#ifdef RT_USING_DEVICE_OPS + dev->ops = &mtd_nand_ops; +#else dev->init = _mtd_init; dev->open = _mtd_open; dev->read = _mtd_read; dev->write = _mtd_write; dev->close = _mtd_close; dev->control = _mtd_control; +#endif dev->rx_indicate = RT_NULL; dev->tx_complete = RT_NULL; diff --git a/components/drivers/mtd/mtd_nor.c b/components/drivers/mtd/mtd_nor.c index 72bbc5a87321576cbbfe710131bc369393189ee7..8f37e95f0944a339fd178c603c665970defb4ded 100644 --- a/components/drivers/mtd/mtd_nor.c +++ b/components/drivers/mtd/mtd_nor.c @@ -65,6 +65,18 @@ static rt_err_t _mtd_control(rt_device_t dev, int cmd, void *args) return RT_EOK; } +#ifdef RT_USING_DEVICE_OPS +const static struct rt_device_ops mtd_nor_ops = +{ + _mtd_init, + _mtd_open, + _mtd_close, + _mtd_read, + _mtd_write, + _mtd_control +}; +#endif + rt_err_t rt_mtd_nor_register_device(const char *name, struct rt_mtd_nor_device *device) { @@ -75,12 +87,16 @@ rt_err_t rt_mtd_nor_register_device(const char *name, /* set device class and generic device interface */ dev->type = RT_Device_Class_MTD; +#ifdef RT_USING_DEVICE_OPS + dev->ops = &mtd_nor_ops; +#else dev->init = _mtd_init; dev->open = _mtd_open; dev->read = _mtd_read; dev->write = _mtd_write; dev->close = _mtd_close; dev->control = _mtd_control; +#endif dev->rx_indicate = RT_NULL; dev->tx_complete = RT_NULL; diff --git a/components/drivers/rtc/soft_rtc.c b/components/drivers/rtc/soft_rtc.c index 6db2136ad4b11567f9da32b41da307b438abd116..c828e43ebcf16c4a524d0f1c83e14e3c36413c17 100644 --- a/components/drivers/rtc/soft_rtc.c +++ b/components/drivers/rtc/soft_rtc.c @@ -68,6 +68,18 @@ static rt_err_t soft_rtc_control(rt_device_t dev, int cmd, void *args) return RT_EOK; } +#ifdef RT_USING_DEVICE_OPS +const static struct rt_device_ops soft_rtc_ops = +{ + RT_NULL, + RT_NULL, + RT_NULL, + RT_NULL, + RT_NULL, + soft_rtc_control +}; +#endif + int rt_soft_rtc_init(void) { static rt_bool_t init_ok = RT_FALSE; @@ -86,12 +98,16 @@ int rt_soft_rtc_init(void) soft_rtc_dev.type = RT_Device_Class_RTC; /* register rtc device */ +#ifdef RT_USING_DEVICE_OPS + soft_rtc_dev.ops = &soft_rtc_ops; +#else soft_rtc_dev.init = RT_NULL; soft_rtc_dev.open = RT_NULL; soft_rtc_dev.close = RT_NULL; soft_rtc_dev.read = RT_NULL; soft_rtc_dev.write = RT_NULL; soft_rtc_dev.control = soft_rtc_control; +#endif /* no private */ soft_rtc_dev.user_data = RT_NULL; diff --git a/components/drivers/sdio/block_dev.c b/components/drivers/sdio/block_dev.c index 4143272b80cc2d026f597265048c26fbd709e4a2..14a01acd90051b816343a57254f8623cfed1b479 100644 --- a/components/drivers/sdio/block_dev.c +++ b/components/drivers/sdio/block_dev.c @@ -319,6 +319,18 @@ static rt_int32_t mmcsd_set_blksize(struct rt_mmcsd_card *card) return 0; } +#ifdef RT_USING_DEVICE_OPS +const static struct rt_device_ops mmcsd_blk_ops = +{ + rt_mmcsd_init, + rt_mmcsd_open, + rt_mmcsd_close, + rt_mmcsd_read, + rt_mmcsd_write, + rt_mmcsd_control +}; +#endif + rt_int32_t rt_mmcsd_blk_probe(struct rt_mmcsd_card *card) { rt_int32_t err = 0; @@ -366,13 +378,17 @@ rt_int32_t rt_mmcsd_blk_probe(struct rt_mmcsd_card *card) blk_dev->part.lock = rt_sem_create(sname, 1, RT_IPC_FLAG_FIFO); /* register mmcsd device */ - blk_dev->dev.type = RT_Device_Class_Block; + blk_dev->dev.type = RT_Device_Class_Block; +#ifdef RT_USING_DEVICE_OPS + blk_dev->dev.ops = &mmcsd_blk_ops; +#else blk_dev->dev.init = rt_mmcsd_init; blk_dev->dev.open = rt_mmcsd_open; blk_dev->dev.close = rt_mmcsd_close; blk_dev->dev.read = rt_mmcsd_read; blk_dev->dev.write = rt_mmcsd_write; blk_dev->dev.control = rt_mmcsd_control; +#endif blk_dev->dev.user_data = blk_dev; blk_dev->card = card; @@ -396,12 +412,16 @@ rt_int32_t rt_mmcsd_blk_probe(struct rt_mmcsd_card *card) /* register mmcsd device */ blk_dev->dev.type = RT_Device_Class_Block; +#ifdef RT_USING_DEVICE_OPS + blk_dev->dev.ops = &mmcsd_blk_ops; +#else blk_dev->dev.init = rt_mmcsd_init; blk_dev->dev.open = rt_mmcsd_open; blk_dev->dev.close = rt_mmcsd_close; blk_dev->dev.read = rt_mmcsd_read; blk_dev->dev.write = rt_mmcsd_write; blk_dev->dev.control = rt_mmcsd_control; +#endif blk_dev->dev.user_data = blk_dev; blk_dev->card = card; @@ -482,6 +502,3 @@ int rt_mmcsd_blk_init(void) /* nothing */ return 0; } - -INIT_PREV_EXPORT(rt_mmcsd_blk_init); - diff --git a/components/drivers/serial/serial.c b/components/drivers/serial/serial.c index 645d083283ccb1edd91a3a16bbbdacf5c18ae578..1de13313446d20d204d080fcd77c451d92806516 100644 --- a/components/drivers/serial/serial.c +++ b/components/drivers/serial/serial.c @@ -1072,6 +1072,18 @@ static rt_err_t rt_serial_control(struct rt_device *dev, return ret; } +#ifdef RT_USING_DEVICE_OPS +const static struct rt_device_ops serial_ops = +{ + rt_serial_init, + rt_serial_open, + rt_serial_close, + rt_serial_read, + rt_serial_write, + rt_serial_control +}; +#endif + /* * serial register */ @@ -1090,12 +1102,16 @@ rt_err_t rt_hw_serial_register(struct rt_serial_device *serial, device->rx_indicate = RT_NULL; device->tx_complete = RT_NULL; +#ifdef RT_USING_DEVICE_OPS + device->ops = &serial_ops; +#else device->init = rt_serial_init; device->open = rt_serial_open; device->close = rt_serial_close; device->read = rt_serial_read; device->write = rt_serial_write; device->control = rt_serial_control; +#endif device->user_data = data; /* register a character device */ diff --git a/components/drivers/spi/enc28j60.c b/components/drivers/spi/enc28j60.c index 1daaea367a954de40fd3613aada8bbc4eff7d5f4..b37b2244e599e90279daf120b968a49f0e4414bf 100644 --- a/components/drivers/spi/enc28j60.c +++ b/components/drivers/spi/enc28j60.c @@ -741,6 +741,18 @@ static struct pbuf *enc28j60_rx(rt_device_t dev) return p; } +#ifdef RT_USING_DEVICE_OPS +const static struct rt_device_ops enc28j60_ops = +{ + enc28j60_init, + enc28j60_open, + enc28j60_close, + enc28j60_read, + enc28j60_write, + enc28j60_control +}; +#endif + rt_err_t enc28j60_attach(const char *spi_device_name) { struct rt_spi_device *spi_device; @@ -802,12 +814,16 @@ rt_err_t enc28j60_attach(const char *spi_device_name) /* init rt-thread device struct */ enc28j60_dev.parent.parent.type = RT_Device_Class_NetIf; +#ifdef RT_USING_DEVICE_OPS + enc28j60_dev.parent.parent.ops = &enc28j60_ops; +#else enc28j60_dev.parent.parent.init = enc28j60_init; enc28j60_dev.parent.parent.open = enc28j60_open; enc28j60_dev.parent.parent.close = enc28j60_close; enc28j60_dev.parent.parent.read = enc28j60_read; enc28j60_dev.parent.parent.write = enc28j60_write; enc28j60_dev.parent.parent.control = enc28j60_control; +#endif /* init rt-thread ethernet device struct */ enc28j60_dev.parent.eth_rx = enc28j60_rx; diff --git a/components/drivers/spi/spi_dev.c b/components/drivers/spi/spi_dev.c index eca971a6e75b7223c740724ccd86ea61d437ba0c..1e69ebe59106d53f02137b285e25ffa36b27f2b5 100644 --- a/components/drivers/spi/spi_dev.c +++ b/components/drivers/spi/spi_dev.c @@ -69,6 +69,18 @@ static rt_err_t _spi_bus_device_control(rt_device_t dev, return RT_EOK; } +#ifdef RT_USING_DEVICE_OPS +const static struct rt_device_ops spi_bus_ops = +{ + RT_NULL, + RT_NULL, + RT_NULL, + _spi_bus_device_read, + _spi_bus_device_write, + _spi_bus_device_control +}; +#endif + rt_err_t rt_spi_bus_device_init(struct rt_spi_bus *bus, const char *name) { struct rt_device *device; @@ -79,12 +91,16 @@ rt_err_t rt_spi_bus_device_init(struct rt_spi_bus *bus, const char *name) /* set device type */ device->type = RT_Device_Class_SPIBUS; /* initialize device interface */ +#ifdef RT_USING_DEVICE_OPS + device->ops = &spi_bus_ops; +#else device->init = RT_NULL; device->open = RT_NULL; device->close = RT_NULL; device->read = _spi_bus_device_read; device->write = _spi_bus_device_write; device->control = _spi_bus_device_control; +#endif /* register to device manager */ return rt_device_register(device, name, RT_DEVICE_FLAG_RDWR); @@ -134,6 +150,18 @@ static rt_err_t _spidev_device_control(rt_device_t dev, return RT_EOK; } +#ifdef RT_USING_DEVICE_OPS +const static struct rt_device_ops spi_device_ops = +{ + RT_NULL, + RT_NULL, + RT_NULL, + _spidev_device_read, + _spidev_device_write, + _spidev_device_control +}; +#endif + rt_err_t rt_spidev_device_init(struct rt_spi_device *dev, const char *name) { struct rt_device *device; @@ -143,13 +171,17 @@ rt_err_t rt_spidev_device_init(struct rt_spi_device *dev, const char *name) /* set device type */ device->type = RT_Device_Class_SPIDevice; +#ifdef RT_USING_DEVICE_OPS + device->ops = &spi_device_ops; +#else device->init = RT_NULL; device->open = RT_NULL; device->close = RT_NULL; device->read = _spidev_device_read; device->write = _spidev_device_write; device->control = _spidev_device_control; - +#endif + /* register to device manager */ return rt_device_register(device, name, RT_DEVICE_FLAG_RDWR); } diff --git a/components/drivers/spi/spi_flash_gd.c b/components/drivers/spi/spi_flash_gd.c index df41150a5d9115327334999228642fd368e02478..a8e8f9a4b831a41a4382cb0acca8304fe7f58650 100644 --- a/components/drivers/spi/spi_flash_gd.c +++ b/components/drivers/spi/spi_flash_gd.c @@ -1,7 +1,7 @@ /* * File : spi_flash_gd.c * This file is part of RT-Thread RTOS - * Copyright (c) 2016 Shanghai Fullhan Microelectronics Co., Ltd. + * Copyright (c) 2016 Shanghai Fullhan Microelectronics Co., Ltd. * All rights reserved * * This program is free software; you can redistribute it and/or modify @@ -254,6 +254,18 @@ static rt_size_t w25qxx_flash_write(rt_device_t dev, return size; } +#ifdef RT_USING_DEVICE_OPS +const static struct rt_device_ops gd_device_ops = +{ + w25qxx_flash_init, + w25qxx_flash_open, + w25qxx_flash_close, + w25qxx_flash_read, + w25qxx_flash_write, + w25qxx_flash_control +}; +#endif + rt_err_t gd_init(const char * flash_device_name, const char * spi_device_name) { struct rt_spi_device * rt_spi_device; @@ -330,12 +342,16 @@ rt_err_t gd_init(const char * flash_device_name, const char * spi_device_name) /* register device */ spi_flash_device.flash_device.type = RT_Device_Class_Block; +#ifdef RT_USING_DEVICE_OPS + spi_flash_device.flash_device.ops = &gd_device_ops; +#else spi_flash_device.flash_device.init = w25qxx_flash_init; spi_flash_device.flash_device.open = w25qxx_flash_open; spi_flash_device.flash_device.close = w25qxx_flash_close; spi_flash_device.flash_device.read = w25qxx_flash_read; spi_flash_device.flash_device.write = w25qxx_flash_write; spi_flash_device.flash_device.control = w25qxx_flash_control; +#endif /* no private */ spi_flash_device.flash_device.user_data = RT_NULL; diff --git a/components/drivers/spi/spi_flash_sfud.c b/components/drivers/spi/spi_flash_sfud.c index 2833f5c9a5ef7de33053130320703ce754b8d61d..94b9afc9bab80eb1186626530180e23ef56e18ca 100644 --- a/components/drivers/spi/spi_flash_sfud.c +++ b/components/drivers/spi/spi_flash_sfud.c @@ -228,6 +228,18 @@ sfud_err sfud_spi_port_init(sfud_flash *flash) { return result; } +#ifdef RT_USING_DEVICE_OPS +const static struct rt_device_ops flash_device_ops = +{ + RT_NULL, + RT_NULL, + RT_NULL, + rt_sfud_read, + rt_sfud_write, + rt_sfud_control +}; +#endif + /** * Probe SPI flash by SFUD(Serial Flash Universal Driver) driver library and though SPI device. * @@ -258,7 +270,7 @@ rt_spi_flash_device_t rt_sfud_flash_probe(const char *spi_flash_dev_name, const /* initialize lock */ rt_mutex_init(&(rtt_dev->lock), spi_flash_dev_name, RT_IPC_FLAG_FIFO); } - + if (rtt_dev && sfud_dev && spi_flash_dev_name_bak && spi_dev_name_bak) { rt_memset(sfud_dev, 0, sizeof(sfud_flash)); rt_strncpy(spi_flash_dev_name_bak, spi_flash_dev_name, rt_strlen(spi_flash_dev_name)); @@ -297,12 +309,16 @@ rt_spi_flash_device_t rt_sfud_flash_probe(const char *spi_flash_dev_name, const /* register device */ rtt_dev->flash_device.type = RT_Device_Class_Block; +#ifdef RT_USING_DEVICE_OPS + rtt_dev->flash_device.ops = &flash_device_ops; +#else rtt_dev->flash_device.init = RT_NULL; rtt_dev->flash_device.open = RT_NULL; rtt_dev->flash_device.close = RT_NULL; rtt_dev->flash_device.read = rt_sfud_read; rtt_dev->flash_device.write = rt_sfud_write; rtt_dev->flash_device.control = rt_sfud_control; +#endif rt_device_register(&(rtt_dev->flash_device), spi_flash_dev_name, RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_STANDALONE); diff --git a/components/drivers/spi/spi_flash_sst25vfxx.c b/components/drivers/spi/spi_flash_sst25vfxx.c index 3843d20ff27a9b214affa0cb116ac4c77090b03a..35dcf3fff702d6fee6ee780741404850ec16c6d5 100644 --- a/components/drivers/spi/spi_flash_sst25vfxx.c +++ b/components/drivers/spi/spi_flash_sst25vfxx.c @@ -254,6 +254,18 @@ static rt_size_t sst25vfxx_flash_write(rt_device_t dev, rt_off_t pos, const void return size; } +#ifdef RT_USING_DEVICE_OPS +const static struct rt_device_ops sst25vfxx_device_ops = +{ + sst25vfxx_flash_init, + sst25vfxx_flash_open, + sst25vfxx_flash_close, + sst25vfxx_flash_read, + sst25vfxx_flash_write, + sst25vfxx_flash_control +}; +#endif + rt_err_t sst25vfxx_init(const char * flash_device_name, const char * spi_device_name) { struct rt_spi_device * rt_spi_device; @@ -340,12 +352,16 @@ rt_err_t sst25vfxx_init(const char * flash_device_name, const char * spi_device_ /* register device */ spi_flash->flash_device.type = RT_Device_Class_Block; +#ifdef RT_USING_DEVICE_OPS + spi_flash->flash_device.ops = &sst25vfxx_device_ops; +#else spi_flash->flash_device.init = sst25vfxx_flash_init; spi_flash->flash_device.open = sst25vfxx_flash_open; spi_flash->flash_device.close = sst25vfxx_flash_close; spi_flash->flash_device.read = sst25vfxx_flash_read; spi_flash->flash_device.write = sst25vfxx_flash_write; spi_flash->flash_device.control = sst25vfxx_flash_control; +#endif /* no private */ spi_flash->flash_device.user_data = RT_NULL; diff --git a/components/drivers/spi/spi_flash_w25qxx.c b/components/drivers/spi/spi_flash_w25qxx.c index a413aec673b417f4ddc7949d075c17381f5c783b..5a16ffbae20076a52f2f563bfffa777cffee30a8 100644 --- a/components/drivers/spi/spi_flash_w25qxx.c +++ b/components/drivers/spi/spi_flash_w25qxx.c @@ -264,6 +264,18 @@ static rt_size_t w25qxx_flash_write(rt_device_t dev, return size; } +#ifdef RT_USING_DEVICE_OPS +const static struct rt_device_ops w25qxx_device_ops = +{ + w25qxx_flash_init, + w25qxx_flash_open, + w25qxx_flash_close, + w25qxx_flash_read, + w25qxx_flash_write, + w25qxx_flash_control +}; +#endif + rt_err_t w25qxx_init(const char * flash_device_name, const char * spi_device_name) { struct rt_spi_device * rt_spi_device; @@ -375,12 +387,16 @@ rt_err_t w25qxx_init(const char * flash_device_name, const char * spi_device_nam /* register device */ spi_flash_device.flash_device.type = RT_Device_Class_Block; +#ifdef RT_USING_DEVICE_OPS + spi_flash_device.flash_device.ops = &w25qxx_device_ops; +#else spi_flash_device.flash_device.init = w25qxx_flash_init; spi_flash_device.flash_device.open = w25qxx_flash_open; spi_flash_device.flash_device.close = w25qxx_flash_close; spi_flash_device.flash_device.read = w25qxx_flash_read; spi_flash_device.flash_device.write = w25qxx_flash_write; spi_flash_device.flash_device.control = w25qxx_flash_control; +#endif /* no private */ spi_flash_device.flash_device.user_data = RT_NULL; diff --git a/components/drivers/spi/spi_msd.c b/components/drivers/spi/spi_msd.c index 5e9ae6289e0df41553f0ef350ce29e354eef9e26..a3046e14ba5281d163c249b9f4d38b1d8af17283 100644 --- a/components/drivers/spi/spi_msd.c +++ b/components/drivers/spi/spi_msd.c @@ -47,10 +47,14 @@ static void MSD_release_cs(struct rt_spi_device *device); static rt_err_t _wait_token(struct rt_spi_device *device, uint8_t token); static rt_err_t _wait_ready(struct rt_spi_device *device); +static rt_err_t rt_msd_init(rt_device_t dev); +static rt_err_t rt_msd_open(rt_device_t dev, rt_uint16_t oflag); +static rt_err_t rt_msd_close(rt_device_t dev); static rt_size_t rt_msd_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size); static rt_size_t rt_msd_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size); static rt_size_t rt_msd_sdhc_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size); static rt_size_t rt_msd_sdhc_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size); +static rt_err_t rt_msd_control(rt_device_t dev, int cmd, void *args); static rt_err_t MSD_take_owner(struct rt_spi_device *spi_device) { @@ -461,6 +465,28 @@ static rt_err_t _write_block(struct rt_spi_device *device, const void *buffer, u return _wait_ready(device); } +#ifdef RT_USING_DEVICE_OPS +const static struct rt_device_ops msd_ops = +{ + rt_msd_init, + rt_msd_open, + rt_msd_close, + rt_msd_read, + rt_msd_write, + rt_msd_control +}; + +const static struct rt_device_ops msd_sdhc_ops = +{ + rt_msd_init, + rt_msd_open, + rt_msd_close, + rt_msd_sdhc_read, + rt_msd_sdhc_write, + rt_msd_control +}; +#endif + /* RT-Thread Device Driver Interface */ static rt_err_t rt_msd_init(rt_device_t dev) { @@ -893,13 +919,21 @@ static rt_err_t rt_msd_init(rt_device_t dev) if (msd->card_type == MSD_CARD_TYPE_SD_SDHC) { +#ifdef RT_USING_DEVICE_OPS + dev->ops = &msd_sdhc_ops; +#else dev->read = rt_msd_sdhc_read; dev->write = rt_msd_sdhc_write; +#endif } else { +#ifdef RT_USING_DEVICE_OPS + dev->ops = &msd_ops; +#else dev->read = rt_msd_read; dev->write = rt_msd_write; +#endif } /* set CRC */ @@ -1674,12 +1708,16 @@ rt_err_t msd_init(const char *sd_device_name, const char *spi_device_name) _msd_device.geometry.sector_count = 0; _msd_device.geometry.block_size = 0; +#ifdef RT_USING_DEVICE_OPS + _msd_device.parent.ops = &msd_ops; +#else _msd_device.parent.init = rt_msd_init; _msd_device.parent.open = rt_msd_open; _msd_device.parent.close = rt_msd_close; _msd_device.parent.read = RT_NULL; _msd_device.parent.write = RT_NULL; _msd_device.parent.control = rt_msd_control; +#endif /* no private, no callback */ _msd_device.parent.user_data = RT_NULL; diff --git a/components/drivers/spi/spi_wifi_rw009.c b/components/drivers/spi/spi_wifi_rw009.c index 5fb36f33cf5f006fb2b0e9523557c3e1ddd8f3ae..0b92802383494657a138027a254525643a6262e8 100644 --- a/components/drivers/spi/spi_wifi_rw009.c +++ b/components/drivers/spi/spi_wifi_rw009.c @@ -629,6 +629,18 @@ static void spi_wifi_data_thread_entry(void *parameter) } } +#ifdef RT_USING_DEVICE_OPS +const static struct rt_device_ops rw009_ops = +{ + rw009_wifi_init, + rw009_wifi_open, + rw009_wifi_close, + rw009_wifi_read, + rw009_wifi_write, + rw009_wifi_control +}; +#endif + rt_err_t rt_hw_wifi_init(const char *spi_device_name, wifi_mode_t mode) { /* align and struct size check. */ @@ -654,12 +666,16 @@ rt_err_t rt_hw_wifi_init(const char *spi_device_name, wifi_mode_t mode) rt_spi_configure(rw009_wifi_device.rt_spi_device, &cfg); } +#ifdef RT_USING_DEVICE_OPS + rw009_wifi_device.parent.parent.ops = &rw009_ops; +#else rw009_wifi_device.parent.parent.init = rw009_wifi_init; rw009_wifi_device.parent.parent.open = rw009_wifi_open; rw009_wifi_device.parent.parent.close = rw009_wifi_close; rw009_wifi_device.parent.parent.read = rw009_wifi_read; rw009_wifi_device.parent.parent.write = rw009_wifi_write; rw009_wifi_device.parent.parent.control = rw009_wifi_control; +#endif rw009_wifi_device.parent.parent.user_data = RT_NULL; rw009_wifi_device.parent.eth_rx = rw009_wifi_rx; diff --git a/components/drivers/src/pipe.c b/components/drivers/src/pipe.c index ee9c8ba02a331792229ab276a8eb15ee4b290f36..09264ffbe3661ffe681594512e2180d22c587ecd 100644 --- a/components/drivers/src/pipe.c +++ b/components/drivers/src/pipe.c @@ -416,6 +416,18 @@ rt_err_t rt_pipe_control(rt_device_t dev, int cmd, void *args) return RT_EOK; } +#ifdef RT_USING_DEVICE_OPS +const static struct rt_device_ops pipe_ops = +{ + RT_NULL, + rt_pipe_open, + rt_pipe_close, + rt_pipe_read, + rt_pipe_write, + rt_pipe_control, +}; +#endif + rt_pipe_t *rt_pipe_create(const char *name, int bufsz) { rt_pipe_t *pipe; @@ -434,12 +446,16 @@ rt_pipe_t *rt_pipe_create(const char *name, int bufsz) dev = &(pipe->parent); dev->type = RT_Device_Class_Pipe; +#ifdef RT_USING_DEVICE_OPS + dev->ops = &pipe_ops; +#else dev->init = RT_NULL; dev->open = rt_pipe_open; dev->read = rt_pipe_read; dev->write = rt_pipe_write; dev->close = rt_pipe_close; dev->control = rt_pipe_control; +#endif dev->rx_indicate = RT_NULL; dev->tx_complete = RT_NULL; diff --git a/components/drivers/usb/usbdevice/class/ecm.c b/components/drivers/usb/usbdevice/class/ecm.c index 0711de3f516c81ee49841ca118b6536cf7460cb5..6f19a0099ebbb7624b4a5ff8b1dc73c0e487b02b 100644 --- a/components/drivers/usb/usbdevice/class/ecm.c +++ b/components/drivers/usb/usbdevice/class/ecm.c @@ -327,6 +327,19 @@ static rt_err_t rt_ecm_eth_control(rt_device_t dev, int cmd, void *args) return RT_EOK; } + +#ifdef RT_USING_DEVICE_OPS +const static struct rt_device_ops ecm_device_ops = +{ + rt_ecm_eth_init, + rt_ecm_eth_open, + rt_ecm_eth_close, + rt_ecm_eth_read, + rt_ecm_eth_write, + rt_ecm_eth_control +}; +#endif + struct pbuf *rt_ecm_eth_rx(rt_device_t dev) { struct pbuf* p = RT_NULL; diff --git a/components/drivers/usb/usbdevice/class/hid.c b/components/drivers/usb/usbdevice/class/hid.c index 29e581d62b6c7cc45185f8f80955a64cb1446c71..fe1050e3efb4617d9b1c3f77d86df741cb1d6f2c 100644 --- a/components/drivers/usb/usbdevice/class/hid.c +++ b/components/drivers/usb/usbdevice/class/hid.c @@ -592,14 +592,33 @@ static void hid_thread_entry(void* parameter) HID_Report_Received(&report); } } + +#ifdef RT_USING_DEVICE_OPS +const static struct rt_device_ops hid_device_ops = +{ + RT_NULL, + RT_NULL, + RT_NULL, + RT_NULL, + _hid_write, + RT_NULL, +}; +#endif + static rt_uint8_t hid_mq_pool[(sizeof(struct hid_report)+sizeof(void*))*8]; static void rt_usb_hid_init(struct ufunction *func) { struct hid_s *hiddev; hiddev = (struct hid_s *)func->user_data; rt_memset(&hiddev->parent, 0, sizeof(hiddev->parent)); + +#ifdef RT_USING_DEVICE_OPS + hiddev->parent.ops = &hid_device_ops; +#else hiddev->parent.write = _hid_write; - hiddev->func = func; +#endif + hiddev->func = func; + rt_device_register(&hiddev->parent, "hidd", RT_DEVICE_FLAG_RDWR); rt_mq_init(&hiddev->hid_mq, "hiddmq", hid_mq_pool, sizeof(struct hid_report), sizeof(hid_mq_pool), RT_IPC_FLAG_FIFO); diff --git a/components/drivers/usb/usbdevice/class/rndis.c b/components/drivers/usb/usbdevice/class/rndis.c index 7e67b28bef9b1e6c2ccd45255a7edfca312bf0eb..0f680e9066d347c15404cf61773e19862fe23661 100644 --- a/components/drivers/usb/usbdevice/class/rndis.c +++ b/components/drivers/usb/usbdevice/class/rndis.c @@ -1180,6 +1180,19 @@ rt_err_t rt_rndis_eth_tx(rt_device_t dev, struct pbuf* p) return result; } + +#ifdef RT_USING_DEVICE_OPS +const static struct rt_device_ops rndis_device_ops = +{ + rt_rndis_eth_init, + rt_rndis_eth_open, + rt_rndis_eth_close, + rt_rndis_eth_read, + rt_rndis_eth_write, + rt_rndis_eth_control +}; +#endif + #endif /* RT_USING_LWIP */ #ifdef RNDIS_DELAY_LINK_UP @@ -1307,20 +1320,24 @@ ufunction_t rt_usbd_function_rndis_create(udevice_t device) _rndis->host_addr[4] = 0xEA;//*(const rt_uint8_t *)(0x0FE081F1); _rndis->host_addr[5] = 0x13;//*(const rt_uint8_t *)(0x0FE081F2); +#ifdef RT_USING_DEVICE_OPS + _rndis->parent.parent.ops = &rndis_device_ops; +#else _rndis->parent.parent.init = rt_rndis_eth_init; _rndis->parent.parent.open = rt_rndis_eth_open; _rndis->parent.parent.close = rt_rndis_eth_close; _rndis->parent.parent.read = rt_rndis_eth_read; _rndis->parent.parent.write = rt_rndis_eth_write; _rndis->parent.parent.control = rt_rndis_eth_control; +#endif _rndis->parent.parent.user_data = device; _rndis->parent.eth_rx = rt_rndis_eth_rx; _rndis->parent.eth_tx = rt_rndis_eth_tx; - /* register eth device */ + /* register eth device */ eth_device_init(&((rt_rndis_eth_t)cdc->user_data)->parent, "u0"); - + #endif /* RT_USING_LWIP */ return cdc; diff --git a/components/drivers/usb/usbdevice/class/winusb.c b/components/drivers/usb/usbdevice/class/winusb.c index 71d946fcd962c8c9ca977227bbc565014e09fe72..9e7c957e7c2851f15741865d2e808ef4c6f7a7a4 100644 --- a/components/drivers/usb/usbdevice/class/winusb.c +++ b/components/drivers/usb/usbdevice/class/winusb.c @@ -246,16 +246,34 @@ static rt_err_t win_usb_control(rt_device_t dev, int cmd, void *args) } return RT_EOK; } + +#ifdef RT_USING_DEVICE_OPS +const static struct rt_device_ops winusb_device_ops = +{ + RT_NULL, + RT_NULL, + RT_NULL, + win_usb_read, + win_usb_write, + win_usb_control, +}; +#endif + static rt_err_t rt_usb_winusb_init(ufunction_t func) { winusb_device_t winusb_device = (winusb_device_t)func->user_data; winusb_device->parent.type = RT_Device_Class_Miscellaneous; + +#ifdef RT_USING_DEVICE_OPS + winusb_device->parent.ops = &winusb_device_ops; +#else winusb_device->parent.init = RT_NULL; winusb_device->parent.open = RT_NULL; winusb_device->parent.close = RT_NULL; winusb_device->parent.read = win_usb_read; winusb_device->parent.write = win_usb_write; winusb_device->parent.control = win_usb_control; +#endif winusb_device->parent.user_data = func; diff --git a/components/drivers/usb/usbhost/class/adk.c b/components/drivers/usb/usbhost/class/adk.c index 1481d27ea6df1357fa1126b94e989225f26ce84d..e7eed45127f5c49ff97479ecdd35343c21c4d2a9 100644 --- a/components/drivers/usb/usbhost/class/adk.c +++ b/components/drivers/usb/usbhost/class/adk.c @@ -37,7 +37,7 @@ static const char* _adk_uri = RT_NULL; static const char* _adk_serial = RT_NULL; rt_err_t rt_usbh_adk_set_string(const char* manufacturer, const char* model, - const char* description, const char* _version, const char* uri, + const char* description, const char* _version, const char* uri, const char* serial) { _adk_manufacturer = manufacturer; @@ -62,31 +62,31 @@ RTM_EXPORT(rt_usbh_adk_set_string); * @param intf the interface instance. * @duration the idle period of requesting data. * @report_id the report id - * + * * @return the error code, RT_EOK on successfully. */ static rt_err_t rt_usbh_adk_get_protocol(struct uintf* intf, rt_uint16_t *protocol) { struct urequest setup; - uinst_t device; + uinst_t device; int timeout = 100; - + /* parameter check */ RT_ASSERT(intf != RT_NULL); RT_ASSERT(intf->device != RT_NULL); device = intf->device; - setup.request_type = USB_REQ_TYPE_DIR_IN | USB_REQ_TYPE_VENDOR | + setup.request_type = USB_REQ_TYPE_DIR_IN | USB_REQ_TYPE_VENDOR | USB_REQ_TYPE_DEVICE; setup.request = USB_REQ_GET_PROTOCOL; setup.index = 0; setup.length = 2; setup.value = 0; - if(rt_usb_hcd_control_xfer(device->hcd, device, &setup, (void*)protocol, 2, + if(rt_usb_hcd_control_xfer(device->hcd, device, &setup, (void*)protocol, 2, timeout) == 0) return RT_EOK; - else return -RT_FALSE; + else return -RT_FALSE; } /** @@ -95,32 +95,32 @@ static rt_err_t rt_usbh_adk_get_protocol(struct uintf* intf, rt_uint16_t *protoc * @param intf the interface instance. * @duration the idle period of requesting data. * @report_id the report id - * + * * @return the error code, RT_EOK on successfully. */ -static rt_err_t rt_usbh_adk_send_string(struct uintf* intf, rt_uint16_t index, +static rt_err_t rt_usbh_adk_send_string(struct uintf* intf, rt_uint16_t index, const char* str) { struct urequest setup; - uinst_t device; + uinst_t device; int timeout = 100; - + /* parameter check */ RT_ASSERT(intf != RT_NULL); RT_ASSERT(intf->device != RT_NULL); device = intf->device; - setup.request_type = USB_REQ_TYPE_DIR_OUT | USB_REQ_TYPE_VENDOR | + setup.request_type = USB_REQ_TYPE_DIR_OUT | USB_REQ_TYPE_VENDOR | USB_REQ_TYPE_DEVICE; setup.request = USB_REQ_SEND_STRING; setup.index = index; setup.length = rt_strlen(str) + 1; setup.value = 0; - if(rt_usb_hcd_control_xfer(device->hcd, device, &setup, (void*)str, + if(rt_usb_hcd_control_xfer(device->hcd, device, &setup, (void*)str, rt_strlen(str) + 1, timeout) == 0) return RT_EOK; - else return -RT_FALSE; + else return -RT_FALSE; } /** @@ -129,41 +129,41 @@ static rt_err_t rt_usbh_adk_send_string(struct uintf* intf, rt_uint16_t index, * @param intf the interface instance. * @duration the idle period of requesting data. * @report_id the report id - * + * * @return the error code, RT_EOK on successfully. */ static rt_err_t rt_usbh_adk_start(struct uintf* intf) { struct urequest setup; - uinst_t device; + uinst_t device; int timeout = 100; - + /* parameter check */ RT_ASSERT(intf != RT_NULL); RT_ASSERT(intf->device != RT_NULL); device = intf->device; - setup.request_type = USB_REQ_TYPE_DIR_OUT | USB_REQ_TYPE_VENDOR | + setup.request_type = USB_REQ_TYPE_DIR_OUT | USB_REQ_TYPE_VENDOR | USB_REQ_TYPE_DEVICE; setup.request = USB_REQ_START; setup.index = 0; setup.length = 0; setup.value = 0; - if(rt_usb_hcd_control_xfer(device->hcd, device, &setup, RT_NULL, 0, + if(rt_usb_hcd_control_xfer(device->hcd, device, &setup, RT_NULL, 0, timeout) == 0) return RT_EOK; - else return -RT_FALSE; + else return -RT_FALSE; } /** * This function will read data from usb adk device * * @param intf the interface instance. - * + * * @return the error code, RT_EOK on successfully. */ -static rt_size_t rt_usbh_adk_read(rt_device_t device, rt_off_t pos, void* buffer, +static rt_size_t rt_usbh_adk_read(rt_device_t device, rt_off_t pos, void* buffer, rt_size_t size) { uadk_t adk; @@ -177,9 +177,9 @@ static rt_size_t rt_usbh_adk_read(rt_device_t device, rt_off_t pos, void* buffer intf = (struct uintf*)device->user_data; adk = (uadk_t)intf->user_data; - length = rt_usb_hcd_bulk_xfer(intf->device->hcd, adk->pipe_in, + length = rt_usb_hcd_bulk_xfer(intf->device->hcd, adk->pipe_in, buffer, size, 300); - + return length; } @@ -188,33 +188,45 @@ static rt_size_t rt_usbh_adk_read(rt_device_t device, rt_off_t pos, void* buffer * This function will write data to usb adk device * * @param intf the interface instance. - * + * * @return the error code, RT_EOK on successfully. */ -static rt_size_t rt_usbh_adk_write (rt_device_t device, rt_off_t pos, const void* buffer, +static rt_size_t rt_usbh_adk_write (rt_device_t device, rt_off_t pos, const void* buffer, rt_size_t size) { uadk_t adk; rt_size_t length; struct uintf* intf; - RT_ASSERT(buffer != RT_NULL); + RT_ASSERT(buffer != RT_NULL); intf = (struct uintf*)device->user_data; adk = (uadk_t)intf->user_data; - length = rt_usb_hcd_bulk_xfer(intf->device->hcd, adk->pipe_out, + length = rt_usb_hcd_bulk_xfer(intf->device->hcd, adk->pipe_out, (void*)buffer, size, 300); - + return length; } +#ifdef RT_USING_DEVICE_OPS +const static struct rt_device_ops adk_device_ops = +{ + RT_NULL; + RT_NULL; + RT_NULL; + rt_usbh_adk_read; + rt_usbh_adk_write; + RT_NULL; +}; +#endif + /** * This function will run adk class driver when usb device is detected and identified * as a adk class device, it will continue the enumulate process. * * @param arg the argument. - * + * * @return the error code, RT_EOK on successfully. */ static rt_err_t rt_usbh_adk_enable(void* arg) @@ -224,8 +236,8 @@ static rt_err_t rt_usbh_adk_enable(void* arg) struct uintf* intf = (struct uintf*)arg; udev_desc_t dev_desc; rt_uint16_t protocol; - rt_err_t ret; - + rt_err_t ret; + /* parameter check */ if(intf == RT_NULL) { @@ -234,72 +246,72 @@ static rt_err_t rt_usbh_adk_enable(void* arg) } RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbh_adk_run\n")); - + dev_desc = &intf->device->dev_desc; - if(dev_desc->idVendor == USB_ACCESSORY_VENDOR_ID && - (dev_desc->idProduct == USB_ACCESSORY_PRODUCT_ID || + if(dev_desc->idVendor == USB_ACCESSORY_VENDOR_ID && + (dev_desc->idProduct == USB_ACCESSORY_PRODUCT_ID || dev_desc->idProduct == USB_ACCESSORY_ADB_PRODUCT_ID)) { if(intf->intf_desc->bInterfaceSubClass != 0xFF) return -RT_ERROR; - - RT_DEBUG_LOG(RT_DEBUG_USB, ("found android accessory device\n")); + + RT_DEBUG_LOG(RT_DEBUG_USB, ("found android accessory device\n")); } else { - RT_DEBUG_LOG(RT_DEBUG_USB, ("switch device\n")); - + RT_DEBUG_LOG(RT_DEBUG_USB, ("switch device\n")); + if((ret = rt_usbh_adk_get_protocol(intf, &protocol)) != RT_EOK) { rt_kprintf("rt_usbh_adk_get_protocol failed\n"); return ret; } - if(protocol != 1) + if(protocol != 1) { rt_kprintf("read protocol failed\n"); return -RT_ERROR; - } + } - rt_usbh_adk_send_string(intf, + rt_usbh_adk_send_string(intf, ACCESSORY_STRING_MANUFACTURER, _adk_manufacturer); - rt_usbh_adk_send_string(intf, + rt_usbh_adk_send_string(intf, ACCESSORY_STRING_MODEL, _adk_model); - rt_usbh_adk_send_string(intf, + rt_usbh_adk_send_string(intf, ACCESSORY_STRING_DESCRIPTION, _adk_description); - rt_usbh_adk_send_string(intf, + rt_usbh_adk_send_string(intf, ACCESSORY_STRING_VERSION, _adk_version); - rt_usbh_adk_send_string(intf, - ACCESSORY_STRING_URI, _adk_uri); - rt_usbh_adk_send_string(intf, - ACCESSORY_STRING_SERIAL, _adk_serial); + rt_usbh_adk_send_string(intf, + ACCESSORY_STRING_URI, _adk_uri); + rt_usbh_adk_send_string(intf, + ACCESSORY_STRING_SERIAL, _adk_serial); RT_DEBUG_LOG(RT_DEBUG_USB, ("manufacturer %s\n", _adk_manufacturer)); RT_DEBUG_LOG(RT_DEBUG_USB, ("model %s\n", _adk_model)); RT_DEBUG_LOG(RT_DEBUG_USB, ("description %s\n", _adk_description)); RT_DEBUG_LOG(RT_DEBUG_USB, ("version %s\n", _adk_version)); - RT_DEBUG_LOG(RT_DEBUG_USB, ("uri %s\n", _adk_uri)); - RT_DEBUG_LOG(RT_DEBUG_USB, ("serial %s\n", _adk_serial)); - + RT_DEBUG_LOG(RT_DEBUG_USB, ("uri %s\n", _adk_uri)); + RT_DEBUG_LOG(RT_DEBUG_USB, ("serial %s\n", _adk_serial)); + if((ret = rt_usbh_adk_start(intf)) != RT_EOK) { rt_kprintf("rt_usbh_adk_start failed\n"); return ret; - } + } return RT_EOK; } - + adk = rt_malloc(sizeof(struct uadkinst)); RT_ASSERT(adk != RT_NULL); /* initilize the data structure */ - rt_memset(adk, 0, sizeof(struct uadkinst)); + rt_memset(adk, 0, sizeof(struct uadkinst)); intf->user_data = (void*)adk; for(i=0; iintf_desc->bNumEndpoints; i++) - { + { uep_desc_t ep_desc; - + /* get endpoint descriptor from interface descriptor */ rt_usbh_get_endpoint_descriptor(intf->intf_desc, i, &ep_desc); if(ep_desc == RT_NULL) @@ -307,24 +319,24 @@ static rt_err_t rt_usbh_adk_enable(void* arg) rt_kprintf("rt_usb_get_endpoint_descriptor error\n"); return -RT_ERROR; } - - /* the endpoint type of adk class should be BULK */ + + /* the endpoint type of adk class should be BULK */ if((ep_desc->bmAttributes & USB_EP_ATTR_TYPE_MASK) != USB_EP_ATTR_BULK) continue; - + /* allocate pipes according to the endpoint type */ if(ep_desc->bEndpointAddress & USB_DIR_IN) { /* allocate an in pipe for the adk instance */ - ret = rt_usb_hcd_alloc_pipe(intf->device->hcd, &adk->pipe_in, + ret = rt_usb_hcd_alloc_pipe(intf->device->hcd, &adk->pipe_in, intf, ep_desc, RT_NULL); if(ret != RT_EOK) return ret; } else - { + { /* allocate an output pipe for the adk instance */ - ret = rt_usb_hcd_alloc_pipe(intf->device->hcd, &adk->pipe_out, - intf, ep_desc, RT_NULL); + ret = rt_usb_hcd_alloc_pipe(intf->device->hcd, &adk->pipe_out, + intf, ep_desc, RT_NULL); if(ret != RT_EOK) return ret; } } @@ -334,33 +346,37 @@ static rt_err_t rt_usbh_adk_enable(void* arg) { rt_kprintf("pipe error, unsupported device\n"); return -RT_ERROR; - } + } /* set configuration */ ret = rt_usbh_set_configure(intf->device, 1); if(ret != RT_EOK) return ret; /* register adk device */ - adk->device.type = RT_Device_Class_Char; - adk->device.init = RT_NULL; - adk->device.open = RT_NULL; - adk->device.close = RT_NULL; - adk->device.read = rt_usbh_adk_read; - adk->device.write = rt_usbh_adk_write; + adk->device.type = RT_Device_Class_Char; +#ifdef RT_USING_DEVICE_OPS + adk->device.ops = &adk_device_ops; +#else + adk->device.init = RT_NULL; + adk->device.open = RT_NULL; + adk->device.close = RT_NULL; + adk->device.read = rt_usbh_adk_read; + adk->device.write = rt_usbh_adk_write; adk->device.control = RT_NULL; +#endif adk->device.user_data = (void*)intf; rt_device_register(&adk->device, "adkdev", RT_DEVICE_FLAG_RDWR); - + return RT_EOK; } /** - * This function will be invoked when usb device plug out is detected and it would clean + * This function will be invoked when usb device plug out is detected and it would clean * and release all hub class related resources. * * @param arg the argument. - * + * * @return the error code, RT_EOK on successfully. */ static rt_err_t rt_usbh_adk_disable(void* arg) @@ -373,12 +389,12 @@ static rt_err_t rt_usbh_adk_disable(void* arg) RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbh_adk_stop\n")); adk = (uadk_t)intf->user_data; - if(adk == RT_NULL) + if(adk == RT_NULL) { - rt_free(intf); + rt_free(intf); return RT_EOK; } - + if(adk->pipe_in != RT_NULL) rt_usb_hcd_free_pipe(intf->device->hcd, adk->pipe_in); @@ -389,11 +405,11 @@ static rt_err_t rt_usbh_adk_disable(void* arg) rt_device_unregister(&adk->device); /* free adk instance */ - if(adk != RT_NULL) + if(adk != RT_NULL) { rt_free(adk); } - + /* free interface instance */ rt_free(intf); @@ -403,13 +419,13 @@ static rt_err_t rt_usbh_adk_disable(void* arg) /** * This function will register adk class driver to the usb class driver manager. * and it should be invoked in the usb system initialization. - * + * * @return the error code, RT_EOK on successfully. */ ucd_t rt_usbh_class_driver_adk(void) { adk_driver.class_code = USB_CLASS_ADK; - + adk_driver.enable = rt_usbh_adk_enable; adk_driver.disable = rt_usbh_adk_disable; diff --git a/components/drivers/usb/usbhost/class/udisk.c b/components/drivers/usb/usbhost/class/udisk.c index f8f47890f45bd4a8b0143365cc7ea6d8d44b13c9..cdd2551c96f9f5482ec70798d127373eaca23b43 100644 --- a/components/drivers/usb/usbhost/class/udisk.c +++ b/components/drivers/usb/usbhost/class/udisk.c @@ -31,7 +31,7 @@ static int udisk_get_id(void) if((_udisk_idset & (1 << i)) != 0) continue; else break; } - + /* it should not happen */ if(i == UDISK_MAX_COUNT) RT_ASSERT(0); @@ -43,14 +43,14 @@ static void udisk_free_id(int id) { RT_ASSERT(id < UDISK_MAX_COUNT) - _udisk_idset &= ~(1 << id); + _udisk_idset &= ~(1 << id); } /** * This function will initialize the udisk device * * @param dev the pointer of device driver structure - * + * * @return RT_EOK */ static rt_err_t rt_udisk_init(rt_device_t dev) @@ -68,7 +68,7 @@ static rt_err_t rt_udisk_init(rt_device_t dev) * * @return the actually read size on successful, otherwise negative returned. */ -static rt_size_t rt_udisk_read(rt_device_t dev, rt_off_t pos, void* buffer, +static rt_size_t rt_udisk_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size) { rt_err_t ret; @@ -81,18 +81,18 @@ static rt_size_t rt_udisk_read(rt_device_t dev, rt_off_t pos, void* buffer, RT_ASSERT(buffer != RT_NULL); if(size > 4096) timeout = 800; - + data = (struct ustor_data*)dev->user_data; intf = data->intf; ret = rt_usbh_storage_read10(intf, (rt_uint8_t*)buffer, pos, size, timeout); - + if (ret != RT_EOK) { rt_kprintf("usb mass_storage read failed\n"); return 0; } - + return size; } @@ -106,7 +106,7 @@ static rt_size_t rt_udisk_read(rt_device_t dev, rt_off_t pos, void* buffer, * * @return the actually written size on successful, otherwise negative returned. */ -static rt_size_t rt_udisk_write (rt_device_t dev, rt_off_t pos, const void* buffer, +static rt_size_t rt_udisk_write (rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size) { rt_err_t ret; @@ -129,7 +129,7 @@ static rt_size_t rt_udisk_write (rt_device_t dev, rt_off_t pos, const void* buff rt_kprintf("usb mass_storage write %d sector failed\n", size); return 0; } - + return size; } @@ -138,9 +138,9 @@ static rt_size_t rt_udisk_write (rt_device_t dev, rt_off_t pos, const void* buff * * @param intf the interface instance. * @param buffer the data buffer to save inquiry data - * + * * @return the error code, RT_EOK on successfully. - */ + */ static rt_err_t rt_udisk_control(rt_device_t dev, int cmd, void *args) { ustor_t stor; @@ -164,14 +164,26 @@ static rt_err_t rt_udisk_control(rt_device_t dev, int cmd, void *args) geometry->sector_count = stor->capicity[0]; } - return RT_EOK; + return RT_EOK; } +#ifdef RT_USING_DEVICE_OPS +const static struct rt_device_ops udisk_device_ops = +{ + rt_udisk_init, + RT_NULL, + RT_NULL, + rt_udisk_read, + rt_udisk_write, + rt_udisk_control +}; +#endif + /** * This function will run udisk driver when usb disk is detected. * * @param intf the usb interface instance. - * + * * @return the error code, RT_EOK on successfully. */ rt_err_t rt_udisk_run(struct uhintf* intf) @@ -179,10 +191,10 @@ rt_err_t rt_udisk_run(struct uhintf* intf) int i = 0; rt_err_t ret; char dname[4]; - char sname[8]; + char sname[8]; rt_uint8_t max_lun, *sector, sense[18], inquiry[36]; - struct dfs_partition part[MAX_PARTITION_COUNT]; - ustor_t stor; + struct dfs_partition part[MAX_PARTITION_COUNT]; + ustor_t stor; /* check parameter */ RT_ASSERT(intf != RT_NULL); @@ -193,40 +205,40 @@ rt_err_t rt_udisk_run(struct uhintf* intf) // rt_usbh_clear_feature(intf->device, 0, USB_FEATURE_ENDPOINT_HALT); /* reset mass storage class device */ ret = rt_usbh_storage_reset(intf); - if(ret != RT_EOK) return ret; + if(ret != RT_EOK) return ret; stor = (ustor_t)intf->user_data; - /* get max logic unit number */ + /* get max logic unit number */ ret = rt_usbh_storage_get_max_lun(intf, &max_lun); - if(ret != RT_EOK) + if(ret != RT_EOK) rt_usbh_clear_feature(intf->device, 0, USB_FEATURE_ENDPOINT_HALT); /* reset pipe in endpoint */ if(stor->pipe_in->status == UPIPE_STATUS_STALL) { - ret = rt_usbh_clear_feature(intf->device, + ret = rt_usbh_clear_feature(intf->device, stor->pipe_in->ep.bEndpointAddress, USB_FEATURE_ENDPOINT_HALT); - if(ret != RT_EOK) return ret; + if(ret != RT_EOK) return ret; } - + /* reset pipe out endpoint */ if(stor->pipe_out->status == UPIPE_STATUS_STALL) { - ret = rt_usbh_clear_feature(intf->device, + ret = rt_usbh_clear_feature(intf->device, stor->pipe_out->ep.bEndpointAddress, USB_FEATURE_ENDPOINT_HALT); - if(ret != RT_EOK) return ret; + if(ret != RT_EOK) return ret; } while((ret = rt_usbh_storage_inquiry(intf, inquiry)) != RT_EOK) - { + { if(ret == -RT_EIO) return ret; - rt_thread_delay(5); + rt_thread_delay(5); if(i++ < 10) continue; rt_kprintf("rt_usbh_storage_inquiry error\n"); - return -RT_ERROR; + return -RT_ERROR; } i = 0; @@ -235,26 +247,26 @@ rt_err_t rt_udisk_run(struct uhintf* intf) while((ret = rt_usbh_storage_test_unit_ready(intf)) != RT_EOK) { if(ret == -RT_EIO) return ret; - + ret = rt_usbh_storage_request_sense(intf, sense); if(ret == -RT_EIO) return ret; - - rt_thread_delay(10); + + rt_thread_delay(10); if(i++ < 10) continue; rt_kprintf("rt_usbh_storage_test_unit_ready error\n"); - return -RT_ERROR; + return -RT_ERROR; } i = 0; rt_memset(stor->capicity, 0, sizeof(stor->capicity)); /* get storage capacity */ - while((ret = rt_usbh_storage_get_capacity(intf, + while((ret = rt_usbh_storage_get_capacity(intf, (rt_uint8_t*)stor->capicity)) != RT_EOK) - { - if(ret == -RT_EIO) return ret; - + { + if(ret == -RT_EIO) return ret; + rt_thread_delay(50); if(i++ < 10) continue; @@ -262,16 +274,16 @@ rt_err_t rt_udisk_run(struct uhintf* intf) stor->capicity[1] = 0x200; rt_kprintf("rt_usbh_storage_get_capacity error\n"); - break; + break; } stor->capicity[0] = uswap_32(stor->capicity[0]); stor->capicity[1] = uswap_32(stor->capicity[1]); stor->capicity[0] += 1; - - RT_DEBUG_LOG(RT_DEBUG_USB, ("capicity %d, block size %d\n", + + RT_DEBUG_LOG(RT_DEBUG_USB, ("capicity %d, block size %d\n", stor->capicity[0], stor->capicity[1])); - + /* get the first sector to read partition table */ sector = (rt_uint8_t*) rt_malloc (SECTOR_SIZE); if (sector == RT_NULL) @@ -283,42 +295,46 @@ rt_err_t rt_udisk_run(struct uhintf* intf) rt_memset(sector, 0, SECTOR_SIZE); RT_DEBUG_LOG(RT_DEBUG_USB, ("read partition table\n")); - + /* get the partition table */ ret = rt_usbh_storage_read10(intf, sector, 0, 1, 500); if(ret != RT_EOK) { rt_kprintf("read parition table error\n"); - rt_free(sector); - return -RT_ERROR; + rt_free(sector); + return -RT_ERROR; } RT_DEBUG_LOG(RT_DEBUG_USB, ("finished reading partition\n")); - + for(i=0; iintf = intf; + data->intf = intf; data->udisk_id = udisk_get_id(); rt_snprintf(dname, 6, "ud%d-%d", data->udisk_id, i); rt_snprintf(sname, 8, "sem_ud%d", i); data->part.lock = rt_sem_create(sname, 1, RT_IPC_FLAG_FIFO); /* register sdcard device */ - stor->dev[i].type = RT_Device_Class_Block; - stor->dev[i].init = rt_udisk_init; - stor->dev[i].read = rt_udisk_read; - stor->dev[i].write = rt_udisk_write; + stor->dev[i].type = RT_Device_Class_Block; +#ifdef RT_USING_DEVICE_OPS + stor->dev[i].ops = &udisk_device_ops; +#else + stor->dev[i].init = rt_udisk_init; + stor->dev[i].read = rt_udisk_read; + stor->dev[i].write = rt_udisk_write; stor->dev[i].control = rt_udisk_control; +#endif stor->dev[i].user_data = (void*)data; - rt_device_register(&stor->dev[i], dname, RT_DEVICE_FLAG_RDWR | + rt_device_register(&stor->dev[i], dname, RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_REMOVABLE | RT_DEVICE_FLAG_STANDALONE); stor->dev_cnt++; @@ -330,16 +346,16 @@ rt_err_t rt_udisk_run(struct uhintf* intf) else { RT_DEBUG_LOG(RT_DEBUG_USB, ("udisk part %d mount failed\n", i)); - } + } } else { if(i == 0) - { - struct ustor_data* data = rt_malloc(sizeof(struct ustor_data)); - rt_memset(data, 0, sizeof(struct ustor_data)); + { + struct ustor_data* data = rt_malloc(sizeof(struct ustor_data)); + rt_memset(data, 0, sizeof(struct ustor_data)); data->udisk_id = udisk_get_id(); - + /* there is no partition table */ data->part.offset = 0; data->part.size = 0; @@ -349,23 +365,27 @@ rt_err_t rt_udisk_run(struct uhintf* intf) rt_snprintf(dname, 7, "udisk%d", data->udisk_id); /* register sdcard device */ - stor->dev[0].type = RT_Device_Class_Block; - stor->dev[0].init = rt_udisk_init; - stor->dev[0].read = rt_udisk_read; - stor->dev[0].write = rt_udisk_write; + stor->dev[0].type = RT_Device_Class_Block; +#ifdef RT_USING_DEVICE_OPS + stor->dev[i].ops = &udisk_device_ops; +#else + stor->dev[0].init = rt_udisk_init; + stor->dev[0].read = rt_udisk_read; + stor->dev[0].write = rt_udisk_write; stor->dev[0].control = rt_udisk_control; +#endif stor->dev[0].user_data = (void*)data; rt_device_register(&stor->dev[0], dname, - RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_REMOVABLE + RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_REMOVABLE | RT_DEVICE_FLAG_STANDALONE); stor->dev_cnt++; - if (dfs_mount(stor->dev[0].parent.name, UDISK_MOUNTPOINT, + if (dfs_mount(stor->dev[0].parent.name, UDISK_MOUNTPOINT, "elm", 0, 0) == 0) - { + { rt_kprintf("Mount FAT on Udisk successful.\n"); - } + } else { rt_kprintf("Mount FAT on Udisk failed.\n"); @@ -382,31 +402,31 @@ rt_err_t rt_udisk_run(struct uhintf* intf) } /** - * This function will be invoked when usb disk plug out is detected and it would clean + * This function will be invoked when usb disk plug out is detected and it would clean * and release all udisk related resources. * * @param intf the usb interface instance. - * + * * @return the error code, RT_EOK on successfully. */ rt_err_t rt_udisk_stop(struct uhintf* intf) { int i; - ustor_t stor; + ustor_t stor; struct ustor_data* data; /* check parameter */ RT_ASSERT(intf != RT_NULL); RT_ASSERT(intf->device != RT_NULL); - stor = (ustor_t)intf->user_data; + stor = (ustor_t)intf->user_data; RT_ASSERT(stor != RT_NULL); for(i=0; idev_cnt; i++) { rt_device_t dev = &stor->dev[i]; data = (struct ustor_data*)dev->user_data; - + /* unmount filesystem */ dfs_unmount(UDISK_MOUNTPOINT); diff --git a/components/drivers/watchdog/watchdog.c b/components/drivers/watchdog/watchdog.c index af2dcace78a2020a3aa7d4e767fb1abec6d2ad64..e5453f8e435938f058c48453402334edd9a2e262 100644 --- a/components/drivers/watchdog/watchdog.c +++ b/components/drivers/watchdog/watchdog.c @@ -78,6 +78,18 @@ static rt_err_t rt_watchdog_control(struct rt_device *dev, return (wtd->ops->control(wtd, cmd, args)); } +#ifdef RT_USING_DEVICE_OPS +const static struct rt_device_ops wdt_ops = +{ + rt_watchdog_init, + rt_watchdog_open, + rt_watchdog_close, + RT_NULL, + RT_NULL, + rt_watchdog_control, +}; +#endif + /** * This function register a watchdog device */ @@ -95,12 +107,16 @@ rt_err_t rt_hw_watchdog_register(struct rt_watchdog_device *wtd, device->rx_indicate = RT_NULL; device->tx_complete = RT_NULL; +#ifdef RT_USING_DEVICE_OPS + device->ops = &wdt_ops; +#else device->init = rt_watchdog_init; device->open = rt_watchdog_open; device->close = rt_watchdog_close; device->read = RT_NULL; device->write = RT_NULL; device->control = rt_watchdog_control; +#endif device->user_data = data; /* register a character device */ diff --git a/components/finsh/cmd.c b/components/finsh/cmd.c index 139cd8d66946a69d7c057b0a5b1f0d91f6b1f010..1d9156ce4bd9c38fc1c598d6e0d982a8fac143d2 100644 --- a/components/finsh/cmd.c +++ b/components/finsh/cmd.c @@ -614,113 +614,6 @@ int list_module(void) } FINSH_FUNCTION_EXPORT(list_module, list module in system); MSH_CMD_EXPORT(list_module, list module in system); - -int list_mod_detail(const char *name) -{ - int i; - struct rt_module *module; - - /* find module */ - if ((module = rt_module_find(name)) != RT_NULL) - { - /* module has entry point */ - if (!(module->parent.flag & RT_MODULE_FLAG_WITHOUTENTRY)) - { - struct rt_thread *thread; - struct rt_list_node *tlist; - rt_uint8_t *ptr; - - /* list main thread in module */ - if (module->module_thread != RT_NULL) - { - rt_uint8_t stat; - - rt_kprintf("main thread pri status sp stack size max used left tick error\n"); - rt_kprintf("------------- ---- ------- ---------- ---------- ---------- ---------- ---\n"); - thread = module->module_thread; - rt_kprintf("%-8.*s 0x%02x", RT_NAME_MAX, thread->name, thread->current_priority); - - stat = (thread->stat & RT_THREAD_STAT_MASK); - if (stat == RT_THREAD_READY) rt_kprintf(" ready "); - else if (stat == RT_THREAD_SUSPEND) rt_kprintf(" suspend"); - else if (stat == RT_THREAD_INIT) rt_kprintf(" init "); - - ptr = (rt_uint8_t *)thread->stack_addr; - while (*ptr == '#')ptr ++; - - rt_kprintf(" 0x%08x 0x%08x 0x%08x 0x%08x %03d\n", - thread->stack_size + ((rt_uint32_t)thread->stack_addr - (rt_uint32_t)thread->sp), - thread->stack_size, - thread->stack_size - ((rt_uint32_t) ptr - (rt_uint32_t)thread->stack_addr), - thread->remaining_tick, - thread->error); - } - - /* list sub thread in module */ - tlist = &module->module_object[RT_Object_Class_Thread].object_list; - if (!rt_list_isempty(tlist)) _list_thread(tlist); -#ifdef RT_USING_SEMAPHORE - /* list semaphored in module */ - tlist = &module->module_object[RT_Object_Class_Semaphore].object_list; - if (!rt_list_isempty(tlist)) _list_sem(tlist); -#endif -#ifdef RT_USING_MUTEX - /* list mutex in module */ - tlist = &module->module_object[RT_Object_Class_Mutex].object_list; - if (!rt_list_isempty(tlist)) _list_mutex(tlist); -#endif -#ifdef RT_USING_EVENT - /* list event in module */ - tlist = &module->module_object[RT_Object_Class_Event].object_list; - if (!rt_list_isempty(tlist)) _list_event(tlist); -#endif -#ifdef RT_USING_MAILBOX - /* list mailbox in module */ - tlist = &module->module_object[RT_Object_Class_MailBox].object_list; - if (!rt_list_isempty(tlist)) _list_mailbox(tlist); -#endif -#ifdef RT_USING_MESSAGEQUEUE - /* list message queue in module */ - tlist = &module->module_object[RT_Object_Class_MessageQueue].object_list; - if (!rt_list_isempty(tlist)) _list_msgqueue(tlist); -#endif -#ifdef RT_USING_MEMHEAP - /* list memory heap in module */ - tlist = &module->module_object[RT_Object_Class_MemHeap].object_list; - if (!rt_list_isempty(tlist)) _list_memheap(tlist); -#endif -#ifdef RT_USING_MEMPOOL - /* list memory pool in module */ - tlist = &module->module_object[RT_Object_Class_MemPool].object_list; - if (!rt_list_isempty(tlist)) _list_mempool(tlist); -#endif -#ifdef RT_USING_DEVICE - /* list device in module */ - tlist = &module->module_object[RT_Object_Class_Device].object_list; - if (!rt_list_isempty(tlist)) _list_device(tlist); -#endif - /* list timer in module */ - tlist = &module->module_object[RT_Object_Class_Timer].object_list; - if (!rt_list_isempty(tlist)) _list_timer(tlist); - } - - if (module->nsym > 0) - { - rt_kprintf("symbol address \n"); - rt_kprintf("-------- ----------\n"); - - /* list module export symbols */ - for (i = 0; i < module->nsym; i++) - { - rt_kprintf("%s 0x%x\n", - module->symtab[i].name, module->symtab[i].addr); - } - } - } - - return 0; -} -FINSH_FUNCTION_EXPORT(list_mod_detail, list module objects in system) #endif long list(void) diff --git a/components/finsh/msh.c b/components/finsh/msh.c index 005cbc7df32855dd8725429bcfaecea381a39ae8..e13f8598fdfe74b3df3120af0f77457002378902 100644 --- a/components/finsh/msh.c +++ b/components/finsh/msh.c @@ -336,7 +336,7 @@ int msh_exec(char *cmd, rt_size_t length) { return cmd_ret; } -#ifdef RT_USING_MODULE +#if defined(RT_USING_MODULE) && defined(RT_USING_DFS) if (msh_exec_module(cmd, length) == 0) { return 0; diff --git a/components/libc/compilers/newlib/libc.c b/components/libc/compilers/newlib/libc.c index 6d6a7d734ec3e293646dd822d24e073197e4108d..0b7350c30edc67f9063312f0497bb930ed3bb888 100644 --- a/components/libc/compilers/newlib/libc.c +++ b/components/libc/compilers/newlib/libc.c @@ -35,6 +35,8 @@ #include #endif +int _EXFUN(putenv,(char *__string)); + int libc_system_init(void) { #if defined(RT_USING_DFS) & defined(RT_USING_DFS_DEVFS) diff --git a/components/libc/compilers/newlib/stdio.c b/components/libc/compilers/newlib/stdio.c index 394705bf15fb4ad26c107cd7e6accdeb9c206019..9f30106b729c5f59a95a3a602d1a77c8ef67da62 100644 --- a/components/libc/compilers/newlib/stdio.c +++ b/components/libc/compilers/newlib/stdio.c @@ -31,6 +31,8 @@ #define STDIO_DEVICE_NAME_MAX 32 +int _EXFUN(fileno, (FILE *)); + static FILE* std_console = NULL; int libc_stdio_set_console(const char* device_name, int mode) diff --git a/components/libc/compilers/newlib/syscalls.c b/components/libc/compilers/newlib/syscalls.c index 514dda147fc621cc285155ace3bd4d829d8d0902..822182ba9346a29e5e17f949d924151fae24eca8 100644 --- a/components/libc/compilers/newlib/syscalls.c +++ b/components/libc/compilers/newlib/syscalls.c @@ -7,7 +7,7 @@ #include #endif -#ifdef RT_USING_PTHREADS +#ifdef RT_USING_PTHREADS #include #endif @@ -126,7 +126,7 @@ _open_r(struct _reent *ptr, const char *file, int flags, int mode) #endif } -_ssize_t +_ssize_t _read_r(struct _reent *ptr, int fd, void *buf, size_t nbytes) { #ifndef RT_USING_DFS @@ -372,7 +372,7 @@ void *_calloc_r (struct _reent *ptr, size_t size, size_t len) return result; } -void +void _free_r (struct _reent *ptr, void *addr) { rt_free (addr); @@ -387,43 +387,20 @@ _exit (int status) module = rt_module_self(); if (module != RT_NULL) { - struct rt_list_node *list; - struct rt_object *object; - - rt_enter_critical(); - - /* delete all threads in the module */ - list = &module->module_object[RT_Object_Class_Thread].object_list; - while (list->next != list) - { - object = rt_list_entry(list->next, struct rt_object, list); - if (rt_object_is_systemobject(object) == RT_TRUE) - { - /* detach static object */ - rt_thread_detach((rt_thread_t)object); - } - else - { - /* delete dynamic object */ - rt_thread_delete((rt_thread_t)object); - } - } - /* delete main thread */ - rt_thread_delete(module->module_thread); - rt_exit_critical(); + rt_thread_suspend(rt_thread_self()); /* re-schedule */ rt_schedule(); } #endif - + rt_kprintf("thread:%s exit with %d\n", rt_thread_self()->name, status); RT_ASSERT(0); while (1); } -void +void _system(const char *s) { /* not support this call */ diff --git a/components/lwp/Kconfig b/components/lwp/Kconfig new file mode 100644 index 0000000000000000000000000000000000000000..e3f13a3b6d559ba43943bed8b42577e5a921de7b --- /dev/null +++ b/components/lwp/Kconfig @@ -0,0 +1,7 @@ +config RT_USING_LWP + bool "Using light-weight process" + select RT_USING_DFS + depends on ARCH_ARM_CORTEX_M + default n + help + The lwP is a light weight process running in user mode. diff --git a/components/lwp/SConscript b/components/lwp/SConscript new file mode 100644 index 0000000000000000000000000000000000000000..f54d9422e19822518733d9b304d592a1ee04a135 --- /dev/null +++ b/components/lwp/SConscript @@ -0,0 +1,20 @@ +Import('rtconfig') +from building import * + +cwd = GetCurrentDir() +src = [] +CPPPATH = [] + +support_arch = {"arm": ["cortex-m3", "cortex-m4", "cortex-m7"]} +platform_file = {'armcc': 'rvds.S', 'gcc': 'gcc.S', 'iar': 'iar.S'} + +if rtconfig.PLATFORM in platform_file.keys(): # support platforms + if rtconfig.ARCH in support_arch.keys() and rtconfig.CPU in support_arch[rtconfig.ARCH]: + # arch/arm/cortex-m7/lwp_gcc.S + asm_path = 'arch/' + rtconfig.ARCH + '/' + rtconfig.CPU + '/*_' + platform_file[rtconfig.PLATFORM] + src = Glob('*.c') + Glob(asm_path) + CPPPATH = [cwd] + +group = DefineGroup('lwP', src, depend = ['RT_USING_LWP'], CPPPATH = CPPPATH) + +Return('group') diff --git a/components/lwp/arch/arm/cortex-m3/lwp_gcc.S b/components/lwp/arch/arm/cortex-m3/lwp_gcc.S new file mode 100644 index 0000000000000000000000000000000000000000..8c866f999012459f7a0ff0083ef3af91e1e2a86a --- /dev/null +++ b/components/lwp/arch/arm/cortex-m3/lwp_gcc.S @@ -0,0 +1,176 @@ +/* + * File : lwp_gcc.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2018, RT-Thread Development Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes + */ + +.cpu cortex-m3 +.syntax unified +.thumb +.text + +/* + * void* lwp_get_sys_api(rt_uint32_t number); + */ +.global lwp_get_sys_api +.global lwp_get_kernel_sp +.global lwp_set_kernel_sp + + +/* + * void lwp_user_entry(u32 R0_text_addr, u32 R1_data_addr); + */ +.global lwp_user_entry +.type lwp_user_entry, % function +lwp_user_entry: + PUSH {R0 - R1} /* push text&data addr. */ + + MOV R0, SP /* v1 = SP */ + BL lwp_set_kernel_sp /* lwp_set_kernel_sp(v1) */ + + POP {R0 - R1} /* pop app address to R1. */ + + /* set CPU to user-thread mode. */ + MRS R2, CONTROL + ORR R2, R2, #0x03 /* use PSP, user-thread mode. */ + MSR CONTROL, R2 + + /* set data address. */ + MOV R9, R1 + + /* run app, only Thumb-mode. */ + ORR R0, R0, #0x01 + BX R0 + +/* + * void SVC_Handler(void); + */ +.global SVC_Handler +.type SVC_Handler, % function +SVC_Handler: + + PUSH {LR} + + /* get user SP. */ + TST LR, #0x4 + ITE EQ + MRSEQ R1, MSP + MRSNE R1, PSP + + PUSH {R1} /* push app SP. */ + MOV R2, R1 + + STMFD R2!, {R4 - R11} /* push app R4-R11 to app stack , and R1 not change. */ + + /* get SVC number. */ + LDR R0, [R1, #24] /* get the app LR. */ + LDRB R0, [R0, #-2] /* get the SVC No. from instruction. */ + + /* get kernel system API */ + BL lwp_get_sys_api + + /* if(api == NULL) return; */ + CMP R0, #0 + POPEQ {R1} + POPEQ {LR} + BXEQ LR + + /* push api */ + PUSH {R0} + + /* get kernel SP to R0. */ + BL lwp_get_kernel_sp + + POP {R2} /* pop api to R2. */ + POP {R1} /* pop app SP to R1. */ + + /* copy R1(app SP) to R0(server SP). */ + LDMFD R1, {R4 - R11} /* pop exception_stack_frame to r4 - r11 register */ + STMFD R0!, {R4 - R11} /* push exception_stack_frame to server SP. */ + + POP {LR} + PUSH {LR} + + /* save app SP. */ + PUSH {R0 - R3} + SUB R0, R1, #0x20 /* keep {R4 - R11} */ + BL lwp_set_kernel_sp + POP {R0 - R3} + + /* set to thread-privilege mode. */ + MRS R3, CONTROL + BIC R3, R3, #0x01 + ORR R3, R3, #0x02 + MSR CONTROL, R3 + + /* call api. */ + LDR R3, = svc_exit + STR R3, [R0, #20] /* update LR */ + STR R2, [R0, #24] /* update api to PC */ + MSR PSP, R0 /* update stack pointer */ + POP {LR} /* 0xFFFFFFED */ + + ORR LR, LR, #0x10 + + BX LR + +/* +* void svc_exit(void); +*/ +.global svc_exit +.type svc_exit, % function +svc_exit: + + /* get user SP. */ + PUSH {R0} /* push result to SP. */ + BL lwp_get_kernel_sp + + LDMFD R0!, {R4 - R11} /* pop app {R4 - R11} */ + + ADD R0, R0, #16 /* skip R0-R3 */ + LDMFD R0!, {R12, LR} + LDMFD R0!, {R1} /* pop PC to R1 */ + LDMFD R0!, {R2} /* pop PSR to R2 */ + + /* align to 2 words */ + ADD R0, R0, #0x07 + BIC R0, R0, #0x07 + PUSH {R0} /* push user-SP to SP */ + + /* save server SP. */ + ADD R0, SP, #0x08 /* [user-SP, result] */ + PUSH {R1 - R2, LR} + BL lwp_set_kernel_sp + POP {R1 - R2, LR} + + POP {R3} /* pop user-SP to R3 */ + POP {R0} /* restore API result. */ + + MSR APSR, R2 /* restore PSR */ + MSR PSP, R3 /* restore app stack pointer */ + + /* restore to PSP & thread-unprivilege mode. */ + MRS R2, CONTROL + ORR R2, R2, #0x03 + MSR CONTROL, R2 + + /* return to lwp. */ + ORR R1, R1, #0x01 /* only Thumb-mode. */ + BX R1 /* return to user app. */ diff --git a/components/lwp/arch/arm/cortex-m3/lwp_iar.S b/components/lwp/arch/arm/cortex-m3/lwp_iar.S new file mode 100644 index 0000000000000000000000000000000000000000..e00424cbec442d4cb216b3b73cdf0542723b9b89 --- /dev/null +++ b/components/lwp/arch/arm/cortex-m3/lwp_iar.S @@ -0,0 +1,176 @@ +;/* +; * File : lwp_iar.S +; * This file is part of RT-Thread RTOS +; * COPYRIGHT (C) 2006 - 2018, RT-Thread Development Team +; * +; * This program is free software; you can redistribute it and/or modify +; * it under the terms of the GNU General Public License as published by +; * the Free Software Foundation; either version 2 of the License, or +; * (at your option) any later version. +; * +; * This program is distributed in the hope that it will be useful, +; * but WITHOUT ANY WARRANTY; without even the implied warranty of +; * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; * GNU General Public License for more details. +; * +; * You should have received a copy of the GNU General Public License along +; * with this program; if not, write to the Free Software Foundation, Inc., +; * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +; * +; * Change Logs: +; * Date Author Notes +; */ + + SECTION .text:CODE(2) + THUMB + REQUIRE8 + PRESERVE8 + +;/* +; * void* lwp_get_sys_api(rt_uint32_t number); +; */ + IMPORT lwp_get_sys_api + IMPORT lwp_get_kernel_sp + IMPORT lwp_set_kernel_sp + +;/* +; * void lwp_user_entry(u32 R0_text_addr, u32 R1_data_addr); +; */ + EXPORT lwp_user_entry +lwp_user_entry: + + PUSH {R0-R1} ; push text&data addr. + + MOV R0, SP ; v1 = SP + BL lwp_set_kernel_sp ; lwp_set_kernel_sp(v1) + + POP {R0-R1} ; pop app address to R1. + + ; set CPU to user-thread mode. + MRS R2, CONTROL + ORR R2, R2, #0x03 ; use PSP, user-thread mode. + MSR CONTROL, R2 + + ; set data address. + MOV R9, R1 + + ; run app, only Thumb-mode. + ORR R0, R0, #0x01 + BX R0 + +;/* +; * void SVC_Handler(void); +; */ + EXPORT SVC_Handler +SVC_Handler: + + PUSH {LR} + + ; get user SP. + TST LR, #0x4 + ITE EQ + MRSEQ R1, MSP + MRSNE R1, PSP + + PUSH {R1} ; push app SP. + MOV R2, R1 + + STMFD R2!, {R4 - R11} ; push app R4-R11 to app stack , and R1 not change. + + ; get SVC number. + LDR R0, [R1, #24] ; get the app LR. + LDRB R0, [R0, #-2] ; get the SVC No. from instruction. + + ; get kernel system API + BL lwp_get_sys_api + + ; if(api == NULL) return; + CMP R0, #0 + ITTT EQ + POPEQ {R1} + POPEQ {LR} + BXEQ LR + + ; push api + PUSH {R0} + + ; get kernel SP to R0. + BL lwp_get_kernel_sp + + POP {R2} ; pop api to R2. + POP {R1} ; pop app SP to R1. + + ; copy R1(app SP) to R0(server SP). + LDMFD R1, {R4 - R11} ; pop exception_stack_frame to r4 - r11 register + STMFD R0!, {R4 - R11} ; push exception_stack_frame to server SP. + + POP {LR} + PUSH {LR} + + ; save app SP. + PUSH {R0 - R3} + SUB R0, R1, #0x20 ; keep {R4 - R11} + BL lwp_set_kernel_sp + POP {R0 - R3} + + ; set to thread-privilege mode. + MRS R3, CONTROL + BIC R3, R3, #0x01 + ORR R3, R3, #0x02 + MSR CONTROL, R3 + + ; call api. + LDR R3, =svc_exit + STR R3, [R0, #20] ; update LR + STR R2, [R0, #24] ; update api to PC + MSR PSP, R0 ; update stack pointer + POP {LR} ; 0xFFFFFFED + + ORR LR, LR, #0x10 + + BX LR + +;/* +; * void svc_exit(void); +; */ + EXPORT svc_exit +svc_exit: + + ; get user SP. + PUSH {R0} ; push result to SP. + BL lwp_get_kernel_sp + + LDMFD R0!, {R4 - R11} ; pop app {R4 - R11} + + ADD R0, R0, #16 ; skip R0-R3 + LDMFD R0!, {R12, LR} ; + LDMFD R0!, {R1} ; pop PC to R1 + LDMFD R0!, {R2} ; pop PSR to R2 + + ; align to 2 words + ADD R0, R0, #0x07 + BIC R0, R0, #0x07 + PUSH {R0} ; push user-SP to SP + + ; save server SP. + ADD R0, SP, #0x08 ; [user-SP, result] + PUSH {R1 - R2, LR} + BL lwp_set_kernel_sp + POP {R1 - R2, LR} + + POP {R3} ; pop user-SP to R3 + POP {R0} ; restore API result. + + MSR APSR, R2 ; restore PSR + MSR PSP, R3 ; restore app stack pointer + + ; restore to PSP & thread-unprivilege mode. + MRS R2, CONTROL + ORR R2, R2, #0x03 + MSR CONTROL, R2 + + ; return to lwp. + ORR R1, R1, #0x01 ; only Thumb-mode. + BX R1 ; return to user app. + + END diff --git a/components/lwp/arch/arm/cortex-m3/lwp_rvds.S b/components/lwp/arch/arm/cortex-m3/lwp_rvds.S new file mode 100644 index 0000000000000000000000000000000000000000..ff79cfda4bece59cff3fcf30853b74c7372d4db0 --- /dev/null +++ b/components/lwp/arch/arm/cortex-m3/lwp_rvds.S @@ -0,0 +1,184 @@ +;/* +; * File : lwp_rvds.S +; * This file is part of RT-Thread RTOS +; * COPYRIGHT (C) 2006 - 2018, RT-Thread Development Team +; * +; * This program is free software; you can redistribute it and/or modify +; * it under the terms of the GNU General Public License as published by +; * the Free Software Foundation; either version 2 of the License, or +; * (at your option) any later version. +; * +; * This program is distributed in the hope that it will be useful, +; * but WITHOUT ANY WARRANTY; without even the implied warranty of +; * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; * GNU General Public License for more details. +; * +; * You should have received a copy of the GNU General Public License along +; * with this program; if not, write to the Free Software Foundation, Inc., +; * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +; * +; * Change Logs: +; * Date Author Notes +; */ + + AREA |.text|, CODE, READONLY, ALIGN=2 + THUMB + REQUIRE8 + PRESERVE8 + +;/* +; * void* lwp_get_sys_api(rt_uint32_t number); +; */ + IMPORT lwp_get_sys_api + IMPORT lwp_get_kernel_sp + IMPORT lwp_set_kernel_sp + +;/* +; * void lwp_user_entry(u32 R0_text_addr, u32 R1_data_addr); +; */ +lwp_user_entry PROC + EXPORT lwp_user_entry + + PUSH {R0-R1} ; push text&data addr. + + MOV R0, SP ; v1 = SP + BL lwp_set_kernel_sp ; lwp_set_kernel_sp(v1) + + POP {R0-R1} ; pop app address to R1. + + ; set CPU to user-thread mode. + MRS R2, CONTROL + ORR R2, R2, #0x03 ; use PSP, user-thread mode. + MSR CONTROL, R2 + + ; set data address. + MOV R9, R1 + + ; run app, only Thumb-mode. + ORR R0, R0, #0x01 + BX R0 + + ; never reach here! + ENDP + +;/* +; * void SVC_Handler(void); +; */ +SVC_Handler PROC + EXPORT SVC_Handler + + PUSH {LR} + + ; get user SP. + TST LR, #0x4 + ITE EQ + MRSEQ R1, MSP + MRSNE R1, PSP + + PUSH {R1} ; push app SP. + MOV R2, R1 + + STMFD R2!, {R4 - R11} ; push app R4-R11 to app stack , and R1 not change. + + ; get SVC number. + LDR R0, [R1, #24] ; get the app LR. + LDRB R0, [R0, #-2] ; get the SVC No. from instruction. + + ; get kernel system API + BL lwp_get_sys_api + + ; if(api == NULL) return; + CMP R0, #0 + POPEQ {R1} + POPEQ {LR} + BXEQ LR + + ; push api + PUSH {R0} + + ; get kernel SP to R0. + BL lwp_get_kernel_sp + + POP {R2} ; pop api to R2. + POP {R1} ; pop app SP to R1. + + ; copy R1(app SP) to R0(server SP). + LDMFD R1, {R4 - R11} ; pop exception_stack_frame to r4 - r11 register + STMFD R0!, {R4 - R11} ; push exception_stack_frame to server SP. + + POP {LR} + PUSH {LR} + + ; save app SP. + PUSH {R0 - R3} + SUB R0, R1, #0x20 ; keep {R4 - R11} + BL lwp_set_kernel_sp + POP {R0 - R3} + + ; set to thread-privilege mode. + MRS R3, CONTROL + BIC R3, R3, #0x01 + ORR R3, R3, #0x02 + MSR CONTROL, R3 + + ; call api. + LDR R3, =svc_exit + STR R3, [R0, #20] ; update LR + STR R2, [R0, #24] ; update api to PC + MSR PSP, R0 ; update stack pointer + POP {LR} ; 0xFFFFFFED + + ORR LR, LR, #0x10 + + BX LR + + ENDP + +;/* +; * void svc_exit(void); +; */ +svc_exit PROC + EXPORT svc_exit + + ; get user SP. + PUSH {R0} ; push result to SP. + BL lwp_get_kernel_sp + + LDMFD R0!, {R4 - R11} ; pop app {R4 - R11} + + ADD R0, R0, #16 ; skip R0-R3 + LDMFD R0!, {R12, LR} ; + LDMFD R0!, {R1} ; pop PC to R1 + LDMFD R0!, {R2} ; pop PSR to R2 + + ; align to 2 words + ADD R0, R0, #0x07 + BIC R0, R0, #0x07 + PUSH {R0} ; push user-SP to SP + + ; save server SP. + ADD R0, SP, #0x08 ; [user-SP, result] + PUSH {R1 - R2, LR} + BL lwp_set_kernel_sp + POP {R1 - R2, LR} + + POP {R3} ; pop user-SP to R3 + POP {R0} ; restore API result. + + MSR APSR, R2 ; restore PSR + MSR PSP, R3 ; restore app stack pointer + + ; restore to PSP & thread-unprivilege mode. + MRS R2, CONTROL + ORR R2, R2, #0x03 + MSR CONTROL, R2 + + ; return to lwp. + ORR R1, R1, #0x01 ; only Thumb-mode. + BX R1 ; return to user app. + + ENDP + + ALIGN + + END diff --git a/components/lwp/arch/arm/cortex-m4/lwp_gcc.S b/components/lwp/arch/arm/cortex-m4/lwp_gcc.S new file mode 100644 index 0000000000000000000000000000000000000000..fd46d6142df6c43f17f3a2418c98bcc696d1fd50 --- /dev/null +++ b/components/lwp/arch/arm/cortex-m4/lwp_gcc.S @@ -0,0 +1,210 @@ +/* + * File : lwp_gcc.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2018, RT-Thread Development Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes + */ + +.cpu cortex-m4 +.syntax unified +.thumb +.text + +/* + * void* lwp_get_sys_api(rt_uint32_t number); + */ +.global lwp_get_sys_api +.global lwp_get_kernel_sp +.global lwp_set_kernel_sp + + +/* + * void lwp_user_entry(u32 R0_text_addr, u32 R1_data_addr); + */ +.global lwp_user_entry +.type lwp_user_entry, % function +lwp_user_entry: + PUSH {R0 - R1} /* push text&data addr. */ + + MOV R0, SP /* v1 = SP */ + BL lwp_set_kernel_sp /* lwp_set_kernel_sp(v1) */ + + POP {R0 - R1} /* pop app address to R1. */ + + /* set CPU to user-thread mode. */ + MRS R2, CONTROL + ORR R2, R2, #0x03 /* use PSP, user-thread mode. */ + MSR CONTROL, R2 + + /* set data address. */ + MOV R9, R1 + + /* run app, only Thumb-mode. */ + ORR R0, R0, #0x01 + BX R0 + +/* + * void SVC_Handler(void); + */ +.global SVC_Handler +.type SVC_Handler, % function +SVC_Handler: + + PUSH {LR} + + /* get user SP. */ + TST LR, #0x4 + ITE EQ + MRSEQ R1, MSP + MRSNE R1, PSP + + PUSH {R1} /* push app SP. */ + MOV R2, R1 + +#if defined (__VFP_FP__) && !defined(__SOFTFP__) + TST LR, #0x10 + VSTMDBEQ R2!, {D8 - D15} +#endif + + STMFD R2!, {R4 - R11} /* push app R4-R11 to app stack , and R1 not change. */ + +#if defined (__VFP_FP__) && !defined(__SOFTFP__) + MOV R4, #0x00 /* flag = 0 */ + TST LR, #0x10 /* if(!EXC_RETURN[4]) */ + MOVEQ R4, #0x01 /* flag = 1 */ + STMFD R2!, {R4} /* push flag */ +#endif + + /* get SVC number. */ + LDR R0, [R1, #24] /* get the app LR. */ + LDRB R0, [R0, #-2] /* get the SVC No. from instruction. */ + + /* get kernel system API */ + BL lwp_get_sys_api + + /* if(api == NULL) return; */ + CMP R0, #0 + POPEQ {R1} + POPEQ {LR} + BXEQ LR + + /* push api */ + PUSH {R0} + + /* get kernel SP to R0. */ + BL lwp_get_kernel_sp + + POP {R2} /* pop api to R2. */ + POP {R1} /* pop app SP to R1. */ + + /* copy R1(app SP) to R0(server SP). */ + LDMFD R1, {R4 - R11} /* pop exception_stack_frame to r4 - r11 register */ + STMFD R0!, {R4 - R11} /* push exception_stack_frame to server SP. */ + + POP {LR} + PUSH {LR} + + /* save app SP. */ + PUSH {R0 - R3} +#if defined (__VFP_FP__) && !defined(__SOFTFP__) + TST LR, #0x10 + SUBEQ R0, R1, #0x64 /* keep {R4 - R11}, {D8-D15}, FLAG */ + SUBNE R0, R1, #0x24 /* keep {R4 - R11}, FLAG */ +#else + SUB R0, R1, #0x20 /* keep {R4 - R11} */ +#endif + BL lwp_set_kernel_sp + POP {R0 - R3} + + /* set to thread-privilege mode. */ + MRS R3, CONTROL + BIC R3, R3, #0x01 + ORR R3, R3, #0x02 + MSR CONTROL, R3 + + /* call api. */ + LDR R3, = svc_exit + STR R3, [R0, #20] /* update LR */ + STR R2, [R0, #24] /* update api to PC */ + MSR PSP, R0 /* update stack pointer */ + POP {LR} /* 0xFFFFFFED */ + + ORR LR, LR, #0x10 + + BX LR + +/* +* void svc_exit(void); +*/ +.global svc_exit +.type svc_exit, % function +svc_exit: + + /* get user SP. */ + PUSH {R0} /* push result to SP. */ + BL lwp_get_kernel_sp + +#if defined (__VFP_FP__) && !defined(__SOFTFP__) + LDMFD R0!, {R3} /* pop flag */ +#endif + + LDMFD R0!, {R4 - R11} /* pop app {R4 - R11} */ + +#if defined (__VFP_FP__) && !defined(__SOFTFP__) + CMP R3, #0 /* if(flag_r3 != 0) */ + VLDMIANE R0!, {D8 - D15} /* pop FPU register s16~s31 */ +#endif + + ADD R0, R0, #16 /* skip R0-R3 */ + LDMFD R0!, {R12, LR} + LDMFD R0!, {R1} /* pop PC to R1 */ + LDMFD R0!, {R2} /* pop PSR to R2 */ + +#if defined (__VFP_FP__) && !defined(__SOFTFP__) + CMP R3, #0 /* if(flag_r3 != 0) */ + VLDMIANE R0!, {D0 - D7} /* pop FPU register s16~s31 */ + LDMIANE R0!, {R3} + VMSRNE FPSCR, R3 +#endif + + /* align to 2 words */ + ADD R0, R0, #0x07 + BIC R0, R0, #0x07 + PUSH {R0} /* push user-SP to SP */ + + /* save server SP. */ + ADD R0, SP, #0x08 /* [user-SP, result] */ + PUSH {R1 - R2, LR} + BL lwp_set_kernel_sp + POP {R1 - R2, LR} + + POP {R3} /* pop user-SP to R3 */ + POP {R0} /* restore API result. */ + + MSR APSR, R2 /* restore PSR */ + MSR PSP, R3 /* restore app stack pointer */ + + /* restore to PSP & thread-unprivilege mode. */ + MRS R2, CONTROL + ORR R2, R2, #0x03 + MSR CONTROL, R2 + + /* return to lwp. */ + ORR R1, R1, #0x01 /* only Thumb-mode. */ + BX R1 /* return to user app. */ diff --git a/components/lwp/arch/arm/cortex-m4/lwp_iar.S b/components/lwp/arch/arm/cortex-m4/lwp_iar.S new file mode 100644 index 0000000000000000000000000000000000000000..27ca8778e0839426ed2de939201754e4e93104ba --- /dev/null +++ b/components/lwp/arch/arm/cortex-m4/lwp_iar.S @@ -0,0 +1,215 @@ +;/* +; * File : lwp_iar.S +; * This file is part of RT-Thread RTOS +; * COPYRIGHT (C) 2006 - 2018, RT-Thread Development Team +; * +; * This program is free software; you can redistribute it and/or modify +; * it under the terms of the GNU General Public License as published by +; * the Free Software Foundation; either version 2 of the License, or +; * (at your option) any later version. +; * +; * This program is distributed in the hope that it will be useful, +; * but WITHOUT ANY WARRANTY; without even the implied warranty of +; * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; * GNU General Public License for more details. +; * +; * You should have received a copy of the GNU General Public License along +; * with this program; if not, write to the Free Software Foundation, Inc., +; * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +; * +; * Change Logs: +; * Date Author Notes +; */ + + SECTION .text:CODE(2) + THUMB + REQUIRE8 + PRESERVE8 + +;/* +; * void* lwp_get_sys_api(rt_uint32_t number); +; */ + IMPORT lwp_get_sys_api + IMPORT lwp_get_kernel_sp + IMPORT lwp_set_kernel_sp + +;/* +; * void lwp_user_entry(u32 R0_text_addr, u32 R1_data_addr); +; */ + EXPORT lwp_user_entry +lwp_user_entry: + + PUSH {R0-R1} ; push text&data addr. + + MOV R0, SP ; v1 = SP + BL lwp_set_kernel_sp ; lwp_set_kernel_sp(v1) + + POP {R0-R1} ; pop app address to R1. + + ; set CPU to user-thread mode. + MRS R2, CONTROL + ORR R2, R2, #0x03 ; use PSP, user-thread mode. + MSR CONTROL, R2 + + ; set data address. + MOV R9, R1 + + ; run app, only Thumb-mode. + ORR R0, R0, #0x01 + BX R0 + +;/* +; * void SVC_Handler(void); +; */ + EXPORT SVC_Handler +SVC_Handler: + + PUSH {LR} + + ; get user SP. + TST LR, #0x4 + ITE EQ + MRSEQ R1, MSP + MRSNE R1, PSP + + PUSH {R1} ; push app SP. + MOV R2, R1 + +#if defined ( __ARMVFP__ ) + TST LR, #0x10 + IT EQ + VSTMDBEQ R2!, {D8 - D15} +#endif + + STMFD R2!, {R4 - R11} ; push app R4-R11 to app stack , and R1 not change. + +#if defined ( __ARMVFP__ ) + MOV R4, #0x00 ; flag = 0 + TST LR, #0x10 ; if(!EXC_RETURN[4]) + IT EQ + MOVEQ R4, #0x01 ; flag = 1 + STMFD R2!, {R4} ; push flag +#endif + + ; get SVC number. + LDR R0, [R1, #24] ; get the app LR. + LDRB R0, [R0, #-2] ; get the SVC No. from instruction. + + ; get kernel system API + BL lwp_get_sys_api + + ; if(api == NULL) return; + CMP R0, #0 + ITTT EQ + POPEQ {R1} + POPEQ {LR} + BXEQ LR + + ; push api + PUSH {R0} + + ; get kernel SP to R0. + BL lwp_get_kernel_sp + + POP {R2} ; pop api to R2. + POP {R1} ; pop app SP to R1. + + ; copy R1(app SP) to R0(server SP). + LDMFD R1, {R4 - R11} ; pop exception_stack_frame to r4 - r11 register + STMFD R0!, {R4 - R11} ; push exception_stack_frame to server SP. + + POP {LR} + PUSH {LR} + + ; save app SP. + PUSH {R0 - R3} +#if defined ( __ARMVFP__ ) + TST LR, #0x10 + ITE EQ + SUBEQ R0, R1, #0x64 ; keep {R4 - R11}, {D8-D15}, FLAG + SUBNE R0, R1, #0x24 ; keep {R4 - R11}, FLAG +#else + SUB R0, R1, #0x20 ; keep {R4 - R11} +#endif + BL lwp_set_kernel_sp + POP {R0 - R3} + + ; set to thread-privilege mode. + MRS R3, CONTROL + BIC R3, R3, #0x01 + ORR R3, R3, #0x02 + MSR CONTROL, R3 + + ; call api. + LDR R3, =svc_exit + STR R3, [R0, #20] ; update LR + STR R2, [R0, #24] ; update api to PC + MSR PSP, R0 ; update stack pointer + POP {LR} ; 0xFFFFFFED + + ORR LR, LR, #0x10 + + BX LR + +;/* +; * void svc_exit(void); +; */ + EXPORT svc_exit +svc_exit: + + ; get user SP. + PUSH {R0} ; push result to SP. + BL lwp_get_kernel_sp + +#if defined ( __ARMVFP__ ) + LDMFD R0!, {R3} ; pop flag +#endif + + LDMFD R0!, {R4 - R11} ; pop app {R4 - R11} + +#if defined ( __ARMVFP__ ) + CMP R3, #0 ; if(flag_r3 != 0) + IT NE + VLDMIANE R0!, {D8 - D15} ; pop FPU register s16~s31 +#endif + + ADD R0, R0, #16 ; skip R0-R3 + LDMFD R0!, {R12, LR} ; + LDMFD R0!, {R1} ; pop PC to R1 + LDMFD R0!, {R2} ; pop PSR to R2 + +#if defined ( __ARMVFP__ ) + CMP R3, #0 ; if(flag_r3 != 0) + ITTT NE + VLDMIANE R0!, {D0 - D7} ; pop FPU register s16~s31 + LDMIANE R0!, {R3} + VMSRNE FPSCR, R3 +#endif + + ; align to 2 words + ADD R0, R0, #0x07 + BIC R0, R0, #0x07 + PUSH {R0} ; push user-SP to SP + + ; save server SP. + ADD R0, SP, #0x08 ; [user-SP, result] + PUSH {R1 - R2, LR} + BL lwp_set_kernel_sp + POP {R1 - R2, LR} + + POP {R3} ; pop user-SP to R3 + POP {R0} ; restore API result. + + MSR APSR, R2 ; restore PSR + MSR PSP, R3 ; restore app stack pointer + + ; restore to PSP & thread-unprivilege mode. + MRS R2, CONTROL + ORR R2, R2, #0x03 + MSR CONTROL, R2 + + ; return to lwp. + ORR R1, R1, #0x01 ; only Thumb-mode. + BX R1 ; return to user app. + + END diff --git a/components/lwp/arch/arm/cortex-m4/lwp_rvds.S b/components/lwp/arch/arm/cortex-m4/lwp_rvds.S new file mode 100644 index 0000000000000000000000000000000000000000..16e81710c11b246d2fd0b95d9e52e65d22ef9d50 --- /dev/null +++ b/components/lwp/arch/arm/cortex-m4/lwp_rvds.S @@ -0,0 +1,219 @@ +;/* +; * File : lwp_rvds.S +; * This file is part of RT-Thread RTOS +; * COPYRIGHT (C) 2006 - 2018, RT-Thread Development Team +; * +; * This program is free software; you can redistribute it and/or modify +; * it under the terms of the GNU General Public License as published by +; * the Free Software Foundation; either version 2 of the License, or +; * (at your option) any later version. +; * +; * This program is distributed in the hope that it will be useful, +; * but WITHOUT ANY WARRANTY; without even the implied warranty of +; * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; * GNU General Public License for more details. +; * +; * You should have received a copy of the GNU General Public License along +; * with this program; if not, write to the Free Software Foundation, Inc., +; * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +; * +; * Change Logs: +; * Date Author Notes +; */ + + AREA |.text|, CODE, READONLY, ALIGN=2 + THUMB + REQUIRE8 + PRESERVE8 + +;/* +; * void* lwp_get_sys_api(rt_uint32_t number); +; */ + IMPORT lwp_get_sys_api + IMPORT lwp_get_kernel_sp + IMPORT lwp_set_kernel_sp + +;/* +; * void lwp_user_entry(u32 R0_text_addr, u32 R1_data_addr); +; */ +lwp_user_entry PROC + EXPORT lwp_user_entry + + PUSH {R0-R1} ; push text&data addr. + + MOV R0, SP ; v1 = SP + BL lwp_set_kernel_sp ; lwp_set_kernel_sp(v1) + + POP {R0-R1} ; pop app address to R1. + + ; set CPU to user-thread mode. + MRS R2, CONTROL + ORR R2, R2, #0x03 ; use PSP, user-thread mode. + MSR CONTROL, R2 + + ; set data address. + MOV R9, R1 + + ; run app, only Thumb-mode. + ORR R0, R0, #0x01 + BX R0 + + ; never reach here! + ENDP + +;/* +; * void SVC_Handler(void); +; */ +SVC_Handler PROC + EXPORT SVC_Handler + + PUSH {LR} + + ; get user SP. + TST LR, #0x4 + ITE EQ + MRSEQ R1, MSP + MRSNE R1, PSP + + PUSH {R1} ; push app SP. + MOV R2, R1 + + IF {FPU} != "SoftVFP" + TST LR, #0x10 + VSTMFDEQ R2!, {D8 - D15} + ENDIF + + STMFD R2!, {R4 - R11} ; push app R4-R11 to app stack , and R1 not change. + + IF {FPU} != "SoftVFP" + MOV R4, #0x00 ; flag = 0 + TST LR, #0x10 ; if(!EXC_RETURN[4]) + MOVEQ R4, #0x01 ; flag = 1 + STMFD R2!, {R4} ; push flag + ENDIF + + ; get SVC number. + LDR R0, [R1, #24] ; get the app LR. + LDRB R0, [R0, #-2] ; get the SVC No. from instruction. + + ; get kernel system API + BL lwp_get_sys_api + + ; if(api == NULL) return; + CMP R0, #0 + POPEQ {R1} + POPEQ {LR} + BXEQ LR + + ; push api + PUSH {R0} + + ; get kernel SP to R0. + BL lwp_get_kernel_sp + + POP {R2} ; pop api to R2. + POP {R1} ; pop app SP to R1. + + ; copy R1(app SP) to R0(server SP). + LDMFD R1, {R4 - R11} ; pop exception_stack_frame to r4 - r11 register + STMFD R0!, {R4 - R11} ; push exception_stack_frame to server SP. + + POP {LR} + PUSH {LR} + + ; save app SP. + PUSH {R0 - R3} + IF {FPU} != "SoftVFP" + TST LR, #0x10 + SUBEQ R0, R1, #0x64 ; keep {R4 - R11}, {D8-D15}, FLAG + SUBNE R0, R1, #0x24 ; keep {R4 - R11}, FLAG + ELSE + SUB R0, R1, #0x20 ; keep {R4 - R11} + ENDIF + BL lwp_set_kernel_sp + POP {R0 - R3} + + ; set to thread-privilege mode. + MRS R3, CONTROL + BIC R3, R3, #0x01 + ORR R3, R3, #0x02 + MSR CONTROL, R3 + + ; call api. + LDR R3, =svc_exit + STR R3, [R0, #20] ; update LR + STR R2, [R0, #24] ; update api to PC + MSR PSP, R0 ; update stack pointer + POP {LR} ; 0xFFFFFFED + + ORR LR, LR, #0x10 + + BX LR + + ENDP + +;/* +; * void svc_exit(void); +; */ +svc_exit PROC + EXPORT svc_exit + + ; get user SP. + PUSH {R0} ; push result to SP. + BL lwp_get_kernel_sp + + IF {FPU} != "SoftVFP" + LDMFD R0!, {R3} ; pop flag + ENDIF + + LDMFD R0!, {R4 - R11} ; pop app {R4 - R11} + + IF {FPU} != "SoftVFP" + CMP R3, #0 ; if(flag_r3 != 0) + VLDMFDNE R0!, {D8 - D15} ; pop FPU register s16~s31 + ENDIF + + ADD R0, R0, #16 ; skip R0-R3 + LDMFD R0!, {R12, LR} ; + LDMFD R0!, {R1} ; pop PC to R1 + LDMFD R0!, {R2} ; pop PSR to R2 + + IF {FPU} != "SoftVFP" + CMP R3, #0 ; if(flag_r3 != 0) + VLDMFDNE R0!, {D0 - D7} ; pop FPU register s16~s31 + LDMFDNE R0!, {R3} + VMSRNE FPSCR, R3 + + ENDIF + + ; align to 2 words + ADD R0, R0, #0x07 + BIC R0, R0, #0x07 + PUSH {R0} ; push user-SP to SP + + ; save server SP. + ADD R0, SP, #0x08 ; [user-SP, result] + PUSH {R1 - R2, LR} + BL lwp_set_kernel_sp + POP {R1 - R2, LR} + + POP {R3} ; pop user-SP to R3 + POP {R0} ; restore API result. + + MSR APSR, R2 ; restore PSR + MSR PSP, R3 ; restore app stack pointer + + ; restore to PSP & thread-unprivilege mode. + MRS R2, CONTROL + ORR R2, R2, #0x03 + MSR CONTROL, R2 + + ; return to lwp. + ORR R1, R1, #0x01 ; only Thumb-mode. + BX R1 ; return to user app. + + ENDP + + ALIGN + + END diff --git a/components/lwp/arch/arm/cortex-m7/lwp_gcc.S b/components/lwp/arch/arm/cortex-m7/lwp_gcc.S new file mode 100644 index 0000000000000000000000000000000000000000..fd46d6142df6c43f17f3a2418c98bcc696d1fd50 --- /dev/null +++ b/components/lwp/arch/arm/cortex-m7/lwp_gcc.S @@ -0,0 +1,210 @@ +/* + * File : lwp_gcc.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2018, RT-Thread Development Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes + */ + +.cpu cortex-m4 +.syntax unified +.thumb +.text + +/* + * void* lwp_get_sys_api(rt_uint32_t number); + */ +.global lwp_get_sys_api +.global lwp_get_kernel_sp +.global lwp_set_kernel_sp + + +/* + * void lwp_user_entry(u32 R0_text_addr, u32 R1_data_addr); + */ +.global lwp_user_entry +.type lwp_user_entry, % function +lwp_user_entry: + PUSH {R0 - R1} /* push text&data addr. */ + + MOV R0, SP /* v1 = SP */ + BL lwp_set_kernel_sp /* lwp_set_kernel_sp(v1) */ + + POP {R0 - R1} /* pop app address to R1. */ + + /* set CPU to user-thread mode. */ + MRS R2, CONTROL + ORR R2, R2, #0x03 /* use PSP, user-thread mode. */ + MSR CONTROL, R2 + + /* set data address. */ + MOV R9, R1 + + /* run app, only Thumb-mode. */ + ORR R0, R0, #0x01 + BX R0 + +/* + * void SVC_Handler(void); + */ +.global SVC_Handler +.type SVC_Handler, % function +SVC_Handler: + + PUSH {LR} + + /* get user SP. */ + TST LR, #0x4 + ITE EQ + MRSEQ R1, MSP + MRSNE R1, PSP + + PUSH {R1} /* push app SP. */ + MOV R2, R1 + +#if defined (__VFP_FP__) && !defined(__SOFTFP__) + TST LR, #0x10 + VSTMDBEQ R2!, {D8 - D15} +#endif + + STMFD R2!, {R4 - R11} /* push app R4-R11 to app stack , and R1 not change. */ + +#if defined (__VFP_FP__) && !defined(__SOFTFP__) + MOV R4, #0x00 /* flag = 0 */ + TST LR, #0x10 /* if(!EXC_RETURN[4]) */ + MOVEQ R4, #0x01 /* flag = 1 */ + STMFD R2!, {R4} /* push flag */ +#endif + + /* get SVC number. */ + LDR R0, [R1, #24] /* get the app LR. */ + LDRB R0, [R0, #-2] /* get the SVC No. from instruction. */ + + /* get kernel system API */ + BL lwp_get_sys_api + + /* if(api == NULL) return; */ + CMP R0, #0 + POPEQ {R1} + POPEQ {LR} + BXEQ LR + + /* push api */ + PUSH {R0} + + /* get kernel SP to R0. */ + BL lwp_get_kernel_sp + + POP {R2} /* pop api to R2. */ + POP {R1} /* pop app SP to R1. */ + + /* copy R1(app SP) to R0(server SP). */ + LDMFD R1, {R4 - R11} /* pop exception_stack_frame to r4 - r11 register */ + STMFD R0!, {R4 - R11} /* push exception_stack_frame to server SP. */ + + POP {LR} + PUSH {LR} + + /* save app SP. */ + PUSH {R0 - R3} +#if defined (__VFP_FP__) && !defined(__SOFTFP__) + TST LR, #0x10 + SUBEQ R0, R1, #0x64 /* keep {R4 - R11}, {D8-D15}, FLAG */ + SUBNE R0, R1, #0x24 /* keep {R4 - R11}, FLAG */ +#else + SUB R0, R1, #0x20 /* keep {R4 - R11} */ +#endif + BL lwp_set_kernel_sp + POP {R0 - R3} + + /* set to thread-privilege mode. */ + MRS R3, CONTROL + BIC R3, R3, #0x01 + ORR R3, R3, #0x02 + MSR CONTROL, R3 + + /* call api. */ + LDR R3, = svc_exit + STR R3, [R0, #20] /* update LR */ + STR R2, [R0, #24] /* update api to PC */ + MSR PSP, R0 /* update stack pointer */ + POP {LR} /* 0xFFFFFFED */ + + ORR LR, LR, #0x10 + + BX LR + +/* +* void svc_exit(void); +*/ +.global svc_exit +.type svc_exit, % function +svc_exit: + + /* get user SP. */ + PUSH {R0} /* push result to SP. */ + BL lwp_get_kernel_sp + +#if defined (__VFP_FP__) && !defined(__SOFTFP__) + LDMFD R0!, {R3} /* pop flag */ +#endif + + LDMFD R0!, {R4 - R11} /* pop app {R4 - R11} */ + +#if defined (__VFP_FP__) && !defined(__SOFTFP__) + CMP R3, #0 /* if(flag_r3 != 0) */ + VLDMIANE R0!, {D8 - D15} /* pop FPU register s16~s31 */ +#endif + + ADD R0, R0, #16 /* skip R0-R3 */ + LDMFD R0!, {R12, LR} + LDMFD R0!, {R1} /* pop PC to R1 */ + LDMFD R0!, {R2} /* pop PSR to R2 */ + +#if defined (__VFP_FP__) && !defined(__SOFTFP__) + CMP R3, #0 /* if(flag_r3 != 0) */ + VLDMIANE R0!, {D0 - D7} /* pop FPU register s16~s31 */ + LDMIANE R0!, {R3} + VMSRNE FPSCR, R3 +#endif + + /* align to 2 words */ + ADD R0, R0, #0x07 + BIC R0, R0, #0x07 + PUSH {R0} /* push user-SP to SP */ + + /* save server SP. */ + ADD R0, SP, #0x08 /* [user-SP, result] */ + PUSH {R1 - R2, LR} + BL lwp_set_kernel_sp + POP {R1 - R2, LR} + + POP {R3} /* pop user-SP to R3 */ + POP {R0} /* restore API result. */ + + MSR APSR, R2 /* restore PSR */ + MSR PSP, R3 /* restore app stack pointer */ + + /* restore to PSP & thread-unprivilege mode. */ + MRS R2, CONTROL + ORR R2, R2, #0x03 + MSR CONTROL, R2 + + /* return to lwp. */ + ORR R1, R1, #0x01 /* only Thumb-mode. */ + BX R1 /* return to user app. */ diff --git a/components/lwp/arch/arm/cortex-m7/lwp_iar.S b/components/lwp/arch/arm/cortex-m7/lwp_iar.S new file mode 100644 index 0000000000000000000000000000000000000000..27ca8778e0839426ed2de939201754e4e93104ba --- /dev/null +++ b/components/lwp/arch/arm/cortex-m7/lwp_iar.S @@ -0,0 +1,215 @@ +;/* +; * File : lwp_iar.S +; * This file is part of RT-Thread RTOS +; * COPYRIGHT (C) 2006 - 2018, RT-Thread Development Team +; * +; * This program is free software; you can redistribute it and/or modify +; * it under the terms of the GNU General Public License as published by +; * the Free Software Foundation; either version 2 of the License, or +; * (at your option) any later version. +; * +; * This program is distributed in the hope that it will be useful, +; * but WITHOUT ANY WARRANTY; without even the implied warranty of +; * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; * GNU General Public License for more details. +; * +; * You should have received a copy of the GNU General Public License along +; * with this program; if not, write to the Free Software Foundation, Inc., +; * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +; * +; * Change Logs: +; * Date Author Notes +; */ + + SECTION .text:CODE(2) + THUMB + REQUIRE8 + PRESERVE8 + +;/* +; * void* lwp_get_sys_api(rt_uint32_t number); +; */ + IMPORT lwp_get_sys_api + IMPORT lwp_get_kernel_sp + IMPORT lwp_set_kernel_sp + +;/* +; * void lwp_user_entry(u32 R0_text_addr, u32 R1_data_addr); +; */ + EXPORT lwp_user_entry +lwp_user_entry: + + PUSH {R0-R1} ; push text&data addr. + + MOV R0, SP ; v1 = SP + BL lwp_set_kernel_sp ; lwp_set_kernel_sp(v1) + + POP {R0-R1} ; pop app address to R1. + + ; set CPU to user-thread mode. + MRS R2, CONTROL + ORR R2, R2, #0x03 ; use PSP, user-thread mode. + MSR CONTROL, R2 + + ; set data address. + MOV R9, R1 + + ; run app, only Thumb-mode. + ORR R0, R0, #0x01 + BX R0 + +;/* +; * void SVC_Handler(void); +; */ + EXPORT SVC_Handler +SVC_Handler: + + PUSH {LR} + + ; get user SP. + TST LR, #0x4 + ITE EQ + MRSEQ R1, MSP + MRSNE R1, PSP + + PUSH {R1} ; push app SP. + MOV R2, R1 + +#if defined ( __ARMVFP__ ) + TST LR, #0x10 + IT EQ + VSTMDBEQ R2!, {D8 - D15} +#endif + + STMFD R2!, {R4 - R11} ; push app R4-R11 to app stack , and R1 not change. + +#if defined ( __ARMVFP__ ) + MOV R4, #0x00 ; flag = 0 + TST LR, #0x10 ; if(!EXC_RETURN[4]) + IT EQ + MOVEQ R4, #0x01 ; flag = 1 + STMFD R2!, {R4} ; push flag +#endif + + ; get SVC number. + LDR R0, [R1, #24] ; get the app LR. + LDRB R0, [R0, #-2] ; get the SVC No. from instruction. + + ; get kernel system API + BL lwp_get_sys_api + + ; if(api == NULL) return; + CMP R0, #0 + ITTT EQ + POPEQ {R1} + POPEQ {LR} + BXEQ LR + + ; push api + PUSH {R0} + + ; get kernel SP to R0. + BL lwp_get_kernel_sp + + POP {R2} ; pop api to R2. + POP {R1} ; pop app SP to R1. + + ; copy R1(app SP) to R0(server SP). + LDMFD R1, {R4 - R11} ; pop exception_stack_frame to r4 - r11 register + STMFD R0!, {R4 - R11} ; push exception_stack_frame to server SP. + + POP {LR} + PUSH {LR} + + ; save app SP. + PUSH {R0 - R3} +#if defined ( __ARMVFP__ ) + TST LR, #0x10 + ITE EQ + SUBEQ R0, R1, #0x64 ; keep {R4 - R11}, {D8-D15}, FLAG + SUBNE R0, R1, #0x24 ; keep {R4 - R11}, FLAG +#else + SUB R0, R1, #0x20 ; keep {R4 - R11} +#endif + BL lwp_set_kernel_sp + POP {R0 - R3} + + ; set to thread-privilege mode. + MRS R3, CONTROL + BIC R3, R3, #0x01 + ORR R3, R3, #0x02 + MSR CONTROL, R3 + + ; call api. + LDR R3, =svc_exit + STR R3, [R0, #20] ; update LR + STR R2, [R0, #24] ; update api to PC + MSR PSP, R0 ; update stack pointer + POP {LR} ; 0xFFFFFFED + + ORR LR, LR, #0x10 + + BX LR + +;/* +; * void svc_exit(void); +; */ + EXPORT svc_exit +svc_exit: + + ; get user SP. + PUSH {R0} ; push result to SP. + BL lwp_get_kernel_sp + +#if defined ( __ARMVFP__ ) + LDMFD R0!, {R3} ; pop flag +#endif + + LDMFD R0!, {R4 - R11} ; pop app {R4 - R11} + +#if defined ( __ARMVFP__ ) + CMP R3, #0 ; if(flag_r3 != 0) + IT NE + VLDMIANE R0!, {D8 - D15} ; pop FPU register s16~s31 +#endif + + ADD R0, R0, #16 ; skip R0-R3 + LDMFD R0!, {R12, LR} ; + LDMFD R0!, {R1} ; pop PC to R1 + LDMFD R0!, {R2} ; pop PSR to R2 + +#if defined ( __ARMVFP__ ) + CMP R3, #0 ; if(flag_r3 != 0) + ITTT NE + VLDMIANE R0!, {D0 - D7} ; pop FPU register s16~s31 + LDMIANE R0!, {R3} + VMSRNE FPSCR, R3 +#endif + + ; align to 2 words + ADD R0, R0, #0x07 + BIC R0, R0, #0x07 + PUSH {R0} ; push user-SP to SP + + ; save server SP. + ADD R0, SP, #0x08 ; [user-SP, result] + PUSH {R1 - R2, LR} + BL lwp_set_kernel_sp + POP {R1 - R2, LR} + + POP {R3} ; pop user-SP to R3 + POP {R0} ; restore API result. + + MSR APSR, R2 ; restore PSR + MSR PSP, R3 ; restore app stack pointer + + ; restore to PSP & thread-unprivilege mode. + MRS R2, CONTROL + ORR R2, R2, #0x03 + MSR CONTROL, R2 + + ; return to lwp. + ORR R1, R1, #0x01 ; only Thumb-mode. + BX R1 ; return to user app. + + END diff --git a/components/lwp/arch/arm/cortex-m7/lwp_rvds.S b/components/lwp/arch/arm/cortex-m7/lwp_rvds.S new file mode 100644 index 0000000000000000000000000000000000000000..16e81710c11b246d2fd0b95d9e52e65d22ef9d50 --- /dev/null +++ b/components/lwp/arch/arm/cortex-m7/lwp_rvds.S @@ -0,0 +1,219 @@ +;/* +; * File : lwp_rvds.S +; * This file is part of RT-Thread RTOS +; * COPYRIGHT (C) 2006 - 2018, RT-Thread Development Team +; * +; * This program is free software; you can redistribute it and/or modify +; * it under the terms of the GNU General Public License as published by +; * the Free Software Foundation; either version 2 of the License, or +; * (at your option) any later version. +; * +; * This program is distributed in the hope that it will be useful, +; * but WITHOUT ANY WARRANTY; without even the implied warranty of +; * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; * GNU General Public License for more details. +; * +; * You should have received a copy of the GNU General Public License along +; * with this program; if not, write to the Free Software Foundation, Inc., +; * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +; * +; * Change Logs: +; * Date Author Notes +; */ + + AREA |.text|, CODE, READONLY, ALIGN=2 + THUMB + REQUIRE8 + PRESERVE8 + +;/* +; * void* lwp_get_sys_api(rt_uint32_t number); +; */ + IMPORT lwp_get_sys_api + IMPORT lwp_get_kernel_sp + IMPORT lwp_set_kernel_sp + +;/* +; * void lwp_user_entry(u32 R0_text_addr, u32 R1_data_addr); +; */ +lwp_user_entry PROC + EXPORT lwp_user_entry + + PUSH {R0-R1} ; push text&data addr. + + MOV R0, SP ; v1 = SP + BL lwp_set_kernel_sp ; lwp_set_kernel_sp(v1) + + POP {R0-R1} ; pop app address to R1. + + ; set CPU to user-thread mode. + MRS R2, CONTROL + ORR R2, R2, #0x03 ; use PSP, user-thread mode. + MSR CONTROL, R2 + + ; set data address. + MOV R9, R1 + + ; run app, only Thumb-mode. + ORR R0, R0, #0x01 + BX R0 + + ; never reach here! + ENDP + +;/* +; * void SVC_Handler(void); +; */ +SVC_Handler PROC + EXPORT SVC_Handler + + PUSH {LR} + + ; get user SP. + TST LR, #0x4 + ITE EQ + MRSEQ R1, MSP + MRSNE R1, PSP + + PUSH {R1} ; push app SP. + MOV R2, R1 + + IF {FPU} != "SoftVFP" + TST LR, #0x10 + VSTMFDEQ R2!, {D8 - D15} + ENDIF + + STMFD R2!, {R4 - R11} ; push app R4-R11 to app stack , and R1 not change. + + IF {FPU} != "SoftVFP" + MOV R4, #0x00 ; flag = 0 + TST LR, #0x10 ; if(!EXC_RETURN[4]) + MOVEQ R4, #0x01 ; flag = 1 + STMFD R2!, {R4} ; push flag + ENDIF + + ; get SVC number. + LDR R0, [R1, #24] ; get the app LR. + LDRB R0, [R0, #-2] ; get the SVC No. from instruction. + + ; get kernel system API + BL lwp_get_sys_api + + ; if(api == NULL) return; + CMP R0, #0 + POPEQ {R1} + POPEQ {LR} + BXEQ LR + + ; push api + PUSH {R0} + + ; get kernel SP to R0. + BL lwp_get_kernel_sp + + POP {R2} ; pop api to R2. + POP {R1} ; pop app SP to R1. + + ; copy R1(app SP) to R0(server SP). + LDMFD R1, {R4 - R11} ; pop exception_stack_frame to r4 - r11 register + STMFD R0!, {R4 - R11} ; push exception_stack_frame to server SP. + + POP {LR} + PUSH {LR} + + ; save app SP. + PUSH {R0 - R3} + IF {FPU} != "SoftVFP" + TST LR, #0x10 + SUBEQ R0, R1, #0x64 ; keep {R4 - R11}, {D8-D15}, FLAG + SUBNE R0, R1, #0x24 ; keep {R4 - R11}, FLAG + ELSE + SUB R0, R1, #0x20 ; keep {R4 - R11} + ENDIF + BL lwp_set_kernel_sp + POP {R0 - R3} + + ; set to thread-privilege mode. + MRS R3, CONTROL + BIC R3, R3, #0x01 + ORR R3, R3, #0x02 + MSR CONTROL, R3 + + ; call api. + LDR R3, =svc_exit + STR R3, [R0, #20] ; update LR + STR R2, [R0, #24] ; update api to PC + MSR PSP, R0 ; update stack pointer + POP {LR} ; 0xFFFFFFED + + ORR LR, LR, #0x10 + + BX LR + + ENDP + +;/* +; * void svc_exit(void); +; */ +svc_exit PROC + EXPORT svc_exit + + ; get user SP. + PUSH {R0} ; push result to SP. + BL lwp_get_kernel_sp + + IF {FPU} != "SoftVFP" + LDMFD R0!, {R3} ; pop flag + ENDIF + + LDMFD R0!, {R4 - R11} ; pop app {R4 - R11} + + IF {FPU} != "SoftVFP" + CMP R3, #0 ; if(flag_r3 != 0) + VLDMFDNE R0!, {D8 - D15} ; pop FPU register s16~s31 + ENDIF + + ADD R0, R0, #16 ; skip R0-R3 + LDMFD R0!, {R12, LR} ; + LDMFD R0!, {R1} ; pop PC to R1 + LDMFD R0!, {R2} ; pop PSR to R2 + + IF {FPU} != "SoftVFP" + CMP R3, #0 ; if(flag_r3 != 0) + VLDMFDNE R0!, {D0 - D7} ; pop FPU register s16~s31 + LDMFDNE R0!, {R3} + VMSRNE FPSCR, R3 + + ENDIF + + ; align to 2 words + ADD R0, R0, #0x07 + BIC R0, R0, #0x07 + PUSH {R0} ; push user-SP to SP + + ; save server SP. + ADD R0, SP, #0x08 ; [user-SP, result] + PUSH {R1 - R2, LR} + BL lwp_set_kernel_sp + POP {R1 - R2, LR} + + POP {R3} ; pop user-SP to R3 + POP {R0} ; restore API result. + + MSR APSR, R2 ; restore PSR + MSR PSP, R3 ; restore app stack pointer + + ; restore to PSP & thread-unprivilege mode. + MRS R2, CONTROL + ORR R2, R2, #0x03 + MSR CONTROL, R2 + + ; return to lwp. + ORR R1, R1, #0x01 ; only Thumb-mode. + BX R1 ; return to user app. + + ENDP + + ALIGN + + END diff --git a/components/lwp/lwp.c b/components/lwp/lwp.c new file mode 100644 index 0000000000000000000000000000000000000000..6837e30b53ec104c74574042a4c72d66e6eacc6b --- /dev/null +++ b/components/lwp/lwp.c @@ -0,0 +1,364 @@ +/* + * File : clock.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2018, RT-Thread Development Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes + */ + +#include +#include +#include + +#ifdef RT_USING_FINSH + #include +#endif + +#ifndef RT_USING_DFS + #error "lwp need file system(RT_USING_DFS)" +#endif + +#include "lwp.h" + +#define DBG_ENABLE +#define DBG_SECTION_NAME "[LWP]" +#define DBG_COLOR +#define DBG_LEVEL DBG_LOG +#include + +extern rt_thread_t rt_current_thread; +extern void lwp_user_entry(const void *text, void *data); + +/** + * RT-Thread light-weight process + */ +void lwp_set_kernel_sp(uint32_t *sp) +{ + struct rt_lwp *user_data; + user_data = (struct rt_lwp *)rt_current_thread->user_data; + user_data->kernel_sp = sp; +} + +uint32_t *lwp_get_kernel_sp(void) +{ + struct rt_lwp *user_data; + user_data = (struct rt_lwp *)rt_current_thread->user_data; + + return user_data->kernel_sp; +} + +static int lwp_load(const char *filename, struct rt_lwp *lwp, uint8_t *load_addr, size_t addr_size) +{ + int fd; + uint8_t *ptr; + int result = RT_EOK; + int nbytes; + struct lwp_header header; + struct lwp_chunk chunk; + + /* check file name */ + RT_ASSERT(filename != RT_NULL); + /* check lwp control block */ + RT_ASSERT(lwp != RT_NULL); + + memset(lwp, 0x00, sizeof(struct rt_lwp)); + + if (load_addr != RT_NULL) + { + lwp->lwp_type = LWP_TYPE_FIX_ADDR; + ptr = load_addr; + } + else + { + lwp->lwp_type = LWP_TYPE_DYN_ADDR; + ptr = RT_NULL; + } + + /* open lwp */ + fd = open(filename, 0, O_RDONLY); + if (fd < 0) + { + dbg_log(DBG_ERROR, "open file:%s failed!\n", filename); + result = -RT_ENOSYS; + goto _exit; + } + + /* read lwp header */ + nbytes = read(fd, &header, sizeof(struct lwp_header)); + if (nbytes != sizeof(struct lwp_header)) + { + dbg_log(DBG_ERROR, "read lwp header return error size: %d!\n", nbytes); + result = -RT_EIO; + goto _exit; + } + + /* check file header */ + if (header.magic != LWP_MAGIC) + { + dbg_log(DBG_ERROR, "erro header magic number: 0x%02X\n", header.magic); + result = -RT_EINVAL; + goto _exit; + } + + /* read text chunk info */ + nbytes = read(fd, &chunk, sizeof(struct lwp_chunk)); + if (nbytes != sizeof(struct lwp_chunk)) + { + dbg_log(DBG_ERROR, "read text chunk info failed!\n"); + result = -RT_EIO; + goto _exit; + } + + dbg_log(DBG_LOG, "chunk name: %s, total len %d, data %d, need space %d!\n", + "text", /*chunk.name*/ chunk.total_len, chunk.data_len, chunk.data_len_space); + + /* load text */ + { + lwp->text_size = RT_ALIGN(chunk.data_len_space, 4); + if (load_addr) + lwp->text_entry = ptr; + else + { +#ifdef RT_USING_CACHE + lwp->text_entry = (rt_uint8_t *)rt_malloc_align(lwp->text_size, RT_CPU_CACHE_LINE_SZ); +#else + lwp->text_entry = (rt_uint8_t *)rt_malloc(lwp->text_size); +#endif + + if (lwp->text_entry == RT_NULL) + { + dbg_log(DBG_ERROR, "alloc text memory faild!\n"); + result = -RT_ENOMEM; + goto _exit; + } + else + { + dbg_log(DBG_LOG, "lwp text malloc : %p, size: %d!\n", lwp->text_entry, lwp->text_size); + } + } + dbg_log(DBG_INFO, "load text %d => (0x%08x, 0x%08x)\n", lwp->text_size, (uint32_t)lwp->text_entry, (uint32_t)lwp->text_entry + lwp->text_size); + + nbytes = read(fd, lwp->text_entry, chunk.data_len); + if (nbytes != chunk.data_len) + { + dbg_log(DBG_ERROR, "read text region from file failed!\n"); + result = -RT_EIO; + goto _exit; + } +#ifdef RT_USING_CACHE + else + { + rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, lwp->text_entry, lwp->text_size); + rt_hw_cpu_icache_ops(RT_HW_CACHE_INVALIDATE, lwp->text_entry, lwp->text_size); + } +#endif + + if (ptr != RT_NULL) ptr += nbytes; + + /* skip text hole */ + if ((chunk.total_len - sizeof(struct lwp_chunk) - chunk.data_len)) + { + dbg_log(DBG_LOG, "skip text hole %d!\n", (chunk.total_len - sizeof(struct lwp_chunk) - chunk.data_len)); + lseek(fd, (chunk.total_len - sizeof(struct lwp_chunk) - chunk.data_len), SEEK_CUR); + } + } + + /* load data */ + nbytes = read(fd, &chunk, sizeof(struct lwp_chunk)); + if (nbytes != sizeof(struct lwp_chunk)) + { + dbg_log(DBG_ERROR, "read data chunk info failed!\n"); + result = -RT_EIO; + goto _exit; + } + + dbg_log(DBG_LOG, "chunk name: %s, total len %d, data %d, need space %d!\n", + chunk.name, chunk.total_len, chunk.data_len, chunk.data_len_space); + + { + lwp->data_size = RT_ALIGN(chunk.data_len_space, 4); + if (load_addr) + lwp->data = ptr; + else + { + lwp->data = rt_malloc(lwp->data_size); + if (lwp->data == RT_NULL) + { + dbg_log(DBG_ERROR, "alloc data memory faild!\n"); + result = -RT_ENOMEM; + goto _exit; + } + else + { + dbg_log(DBG_LOG, "lwp data malloc : %p, size: %d!\n", lwp->data, lwp->data_size); + rt_memset(lwp->data, 0, lwp->data_size); + } + } + + dbg_log(DBG_INFO, "load data %d => (0x%08x, 0x%08x)\n", lwp->data_size, (uint32_t)lwp->data, (uint32_t)lwp->data + lwp->data_size); + nbytes = read(fd, lwp->data, chunk.data_len); + if (nbytes != chunk.data_len) + { + dbg_log(DBG_ERROR, "read data region from file failed!\n"); + result = -RT_ERROR; + goto _exit; + } + } + +_exit: + if (fd >= 0) + close(fd); + + if (result != RT_EOK) + { + if (lwp->lwp_type == LWP_TYPE_DYN_ADDR) + { + dbg_log(DBG_ERROR, "lwp dynamic load faild, %d\n", result); + if (lwp->text_entry) + { + dbg_log(DBG_LOG, "lwp text free: %p\n", lwp->text_entry); +#ifdef RT_USING_CACHE + rt_free_align(lwp->text_entry); +#else + rt_free(lwp->text_entry); +#endif + } + if (lwp->data) + { + dbg_log(DBG_LOG, "lwp data free: %p\n", lwp->data); + rt_free(lwp->data); + } + } + } + + return result; +} + +static void lwp_cleanup(struct rt_thread *tid) +{ + struct rt_lwp *lwp; + + dbg_log(DBG_INFO, "thread: %s, stack_addr: %08X\n", tid->name, tid->stack_addr); + + lwp = (struct rt_lwp *)tid->user_data; + + if (lwp->lwp_type == LWP_TYPE_DYN_ADDR) + { + dbg_log(DBG_INFO, "dynamic lwp\n"); + if (lwp->text_entry) + { + dbg_log(DBG_LOG, "lwp text free: %p\n", lwp->text_entry); +#ifdef RT_USING_CACHE + rt_free_align(lwp->text_entry); +#else + rt_free(lwp->text_entry); +#endif + } + if (lwp->data) + { + dbg_log(DBG_LOG, "lwp data free: %p\n", lwp->data); + rt_free(lwp->data); + } + } + + dbg_log(DBG_LOG, "lwp free memory pages\n"); + rt_lwp_mem_deinit(lwp); + + dbg_log(DBG_LOG, "lwp free: %p\n", lwp); + rt_free(lwp); + + /* TODO: cleanup fd table */ +} + +static void lwp_thread(void *parameter) +{ + volatile uint32_t tmp; + rt_thread_t tid; + struct rt_lwp *lwp; + + rt_kprintf("%08x %08x\n", &tmp, tmp); + + lwp = (struct rt_lwp *)parameter; + rt_lwp_mem_init(lwp); + tid = rt_thread_self(); + tid->user_data = (rt_uint32_t)lwp; + tid->cleanup = lwp_cleanup; + + lwp_user_entry(lwp->text_entry, lwp->data); +} + +struct rt_lwp *rt_lwp_self(void) +{ + return (struct rt_lwp *)rt_thread_self()->user_data; +} + +int exec(char *filename) +{ + struct rt_lwp *lwp; + int result; + + if (filename == RT_NULL) + return -RT_ERROR; + + lwp = (struct rt_lwp *)rt_malloc(sizeof(struct rt_lwp)); + if (lwp == RT_NULL) + { + dbg_log(DBG_ERROR, "lwp struct out of memory!\n"); + return -RT_ENOMEM; + } + dbg_log(DBG_INFO, "lwp malloc : %p, size: %d!\n", lwp, sizeof(struct rt_lwp)); + + rt_memset(lwp, 0, sizeof(*lwp)); + result = lwp_load(filename, lwp, RT_NULL, 0); + if (result == RT_EOK) + { + rt_thread_t tid; + + tid = rt_thread_create("user", lwp_thread, (void *)lwp, + 1024 * 4, 2, 200); + if (tid != RT_NULL) + { + dbg_log(DBG_LOG, "lwp kernel => (0x%08x, 0x%08x)\n", (rt_uint32_t)tid->stack_addr, (rt_uint32_t)tid->stack_addr + tid->stack_size); + rt_thread_startup(tid); + return RT_EOK; + } + else + { +#ifdef RT_USING_CACHE + rt_free_align(lwp->text_entry); +#else + rt_free(lwp->text_entry); +#endif + rt_free(lwp->data); + } + } + + rt_free(lwp); + + return -RT_ERROR; +} +FINSH_FUNCTION_EXPORT(exec, loader a user app &run); + +int _exec(int argc, char **argv) +{ + if (argc != 2) + return -RT_ERROR; + + return exec(argv[1]); +} +MSH_CMD_EXPORT_ALIAS(_exec, exec, loader a user app &run); diff --git a/components/lwp/lwp.h b/components/lwp/lwp.h new file mode 100644 index 0000000000000000000000000000000000000000..b1ce96455eb29269165b951b11f9a7a417d964cf --- /dev/null +++ b/components/lwp/lwp.h @@ -0,0 +1,83 @@ +/* + * File : lwp.h + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2018, RT-Thread Development Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes + */ + +#ifndef __LWP_H__ +#define __LWP_H__ + +#define LWP_MAGIC 0x5A + +#define LWP_TYPE_FIX_ADDR 0x01 +#define LWP_TYPE_DYN_ADDR 0x02 + +#define LWP_ARG_MAX 8 + +#include +#include +#include +#include + +struct rt_lwp +{ + uint8_t lwp_type; + uint8_t heap_cnt; + uint8_t reserv[2]; + + rt_list_t hlist; /**< headp list */ + + uint8_t *text_entry; + uint32_t text_size; + + uint8_t *data; + uint32_t data_size; + + uint32_t *kernel_sp; /**< kernel stack point */ + struct dfs_fdtable fdt; +}; + +struct lwp_header +{ + uint8_t magic; + uint8_t compress_encrypt_algo; + uint16_t reserved; + + uint32_t crc32; +}; + +struct lwp_chunk +{ + uint32_t total_len; + + char name[4]; + uint32_t data_len; + uint32_t data_len_space; +}; + +extern struct rt_lwp *rt_lwp_self(void); + +extern void rt_lwp_mem_init(struct rt_lwp *lwp); +extern void rt_lwp_mem_deinit(struct rt_lwp *lwp); +extern void *rt_lwp_mem_malloc(rt_uint32_t size); +extern void rt_lwp_mem_free(void *addr); +extern void *rt_lwp_mem_realloc(void *rmem, rt_size_t newsize); + +#endif diff --git a/components/lwp/lwp_mem.c b/components/lwp/lwp_mem.c new file mode 100644 index 0000000000000000000000000000000000000000..95c95441b83ba1fff6315eab214b37c2f8421fb2 --- /dev/null +++ b/components/lwp/lwp_mem.c @@ -0,0 +1,232 @@ +/* + * File : lwp_mem.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2012, RT-Thread Development Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes + * 2018-03-24 Tanek the first version + */ + +#include +#include +#include + +#define DBG_ENABLE +#define DBG_SECTION_NAME "[LWPMEM]" +#define DBG_COLOR +#define DBG_LEVEL DBG_LOG +#include + +// todo: remove repleat code +#define RT_MEMHEAP_SIZE RT_ALIGN(sizeof(struct rt_lwp_memheap_item), RT_ALIGN_SIZE) +#define MEMITEM_SIZE(item) ((rt_uint32_t)item->next - (rt_uint32_t)item - RT_MEMHEAP_SIZE) + +#ifndef LWP_MEM_PAGE_SIZE + #define LWP_MEM_PAGE_SIZE (4 * 1024) +#endif + +#ifndef LWP_MEM_MAX_PAGE_COUNT + #define LWP_MEM_MAX_PAGE_COUNT (256 * 4) +#endif + +static void *rt_lwp_malloc_page(struct rt_lwp *lwp, rt_size_t npages) +{ + void *chunk; + char name[6]; + struct rt_lwp_memheap *lwp_heap; + rt_size_t page_cnt; + + RT_ASSERT(lwp != RT_NULL); + + page_cnt = lwp->heap_cnt + npages; + if (page_cnt > LWP_MEM_MAX_PAGE_COUNT) + { + dbg_log(DBG_ERROR, "alloc new page failed, lwp memory size out of limited: %d\n", page_cnt); + return RT_NULL; + } + + lwp_heap = rt_malloc(sizeof(struct rt_lwp_memheap)); + if (lwp_heap == RT_NULL) + { + dbg_log(DBG_ERROR, "alloc new page head failed, out of memory : %d\n", page_cnt); + return RT_NULL; + } + + chunk = rt_malloc(npages * LWP_MEM_PAGE_SIZE); + if (chunk == RT_NULL) + { + dbg_log(DBG_ERROR, "alloc new page buffer failed, out of memory : %d\n", page_cnt); + rt_free(lwp_heap); + return RT_NULL; + } + + dbg_log(DBG_LOG, "lwp alloc page: %d\n", npages); + + sprintf(name, "lwp%02x", lwp->heap_cnt); + rt_lwp_memheap_init(lwp_heap, name, chunk, npages * LWP_MEM_PAGE_SIZE); + + rt_list_insert_before(&lwp->hlist, &lwp_heap->mlist); + + lwp->heap_cnt += npages; + + return chunk; +} + +static void rt_lwp_free_page(struct rt_lwp *lwp, struct rt_lwp_memheap *lwp_heap) +{ + rt_size_t npages; + + RT_ASSERT(lwp != RT_NULL); + RT_ASSERT(lwp_heap != RT_NULL); + RT_ASSERT(lwp_heap->start_addr != RT_NULL); + + npages = lwp_heap->pool_size / LWP_MEM_PAGE_SIZE; + lwp->heap_cnt -= npages; + + dbg_log(DBG_LOG, "lwp free page: %d\n", npages); + + rt_list_remove(&lwp_heap->mlist); + + rt_free(lwp_heap->start_addr); + rt_free(lwp_heap); +} + +void rt_lwp_mem_init(struct rt_lwp *lwp) +{ + RT_ASSERT(lwp != RT_NULL); + rt_list_init(&lwp->hlist); +} + +void rt_lwp_mem_deinit(struct rt_lwp *lwp) +{ + struct rt_list_node *node; + + RT_ASSERT(lwp != RT_NULL); + + for (node = lwp->hlist.next; node != &(lwp->hlist); node = node->next) + { + struct rt_lwp_memheap *lwp_heap; + lwp_heap = rt_list_entry(node, struct rt_lwp_memheap, mlist); + + RT_ASSERT(lwp_heap != RT_NULL); + + rt_lwp_free_page(lwp, lwp_heap); + } +} + +void *rt_lwp_mem_malloc(rt_uint32_t size) +{ + struct rt_lwp *lwp; + struct rt_list_node *node; + void *addr = RT_NULL; + rt_uint32_t npages; + + if (size == 0) + return RT_NULL; + + lwp = rt_lwp_self(); + RT_ASSERT(lwp != RT_NULL); + + for (node = lwp->hlist.next; node != &(lwp->hlist); node = node->next) + { + struct rt_lwp_memheap *lwp_heap; + lwp_heap = rt_list_entry(node, struct rt_lwp_memheap, mlist); + + addr = rt_lwp_memheap_alloc(lwp_heap, size); + if (addr != RT_NULL) + { + dbg_log(DBG_LOG, "lwp alloc 0x%x/%d\n", addr, size); + return addr; + } + } + + npages = (size + rt_lwp_memheap_unavailable_size_get() + LWP_MEM_PAGE_SIZE) / LWP_MEM_PAGE_SIZE; + if (RT_NULL != rt_lwp_malloc_page(lwp, npages)) + return rt_lwp_mem_malloc(size); + else + return RT_NULL; +} + +void rt_lwp_mem_free(void *addr) +{ + struct rt_lwp_memheap_item *header_ptr; + struct rt_lwp_memheap *lwp_heap; + + if (addr == RT_NULL) + return ; + + /* get memory item */ + header_ptr = (struct rt_lwp_memheap_item *)((rt_uint8_t *)addr - RT_MEMHEAP_SIZE); + RT_ASSERT(header_ptr); + + lwp_heap = header_ptr->pool_ptr; + RT_ASSERT(lwp_heap); + + dbg_log(DBG_LOG, "lwp free 0x%x\n", addr); + rt_lwp_memheap_free((void *)addr); + + if (rt_lwp_memheap_is_empty(lwp_heap)) + { + rt_lwp_free_page(rt_lwp_self(), lwp_heap); + } +} + +void *rt_lwp_mem_realloc(void *rmem, rt_size_t newsize) +{ + void *new_ptr; + struct rt_lwp_memheap_item *header_ptr; + + if (rmem == RT_NULL) + return rt_lwp_mem_malloc(newsize); + + if (newsize == 0) + { + rt_lwp_mem_free(rmem); + return RT_NULL; + } + + /* get old memory item */ + header_ptr = (struct rt_lwp_memheap_item *) + ((rt_uint8_t *)rmem - RT_MEMHEAP_SIZE); + + new_ptr = rt_lwp_memheap_realloc(header_ptr->pool_ptr, rmem, newsize); + if (new_ptr == RT_NULL) + { + /* allocate memory block from other memheap */ + new_ptr = rt_lwp_mem_malloc(newsize); + if (new_ptr != RT_NULL && rmem != RT_NULL) + { + rt_size_t oldsize; + + /* get the size of old memory block */ + oldsize = MEMITEM_SIZE(header_ptr); + if (newsize > oldsize) + rt_memcpy(new_ptr, rmem, oldsize); + else + rt_memcpy(new_ptr, rmem, newsize); + + dbg_log(DBG_LOG, "lwp realloc with memcpy 0x%x -> 0x%x/%d\n", rmem, new_ptr, newsize); + rt_lwp_mem_free(rmem); + + } + } + + dbg_log(DBG_LOG, "lwp realloc in same address 0x%x/%d\n", rmem, newsize); + + return new_ptr; +} diff --git a/components/lwp/lwp_mem.h b/components/lwp/lwp_mem.h new file mode 100644 index 0000000000000000000000000000000000000000..117a18f677f0c925eb747cb12dc2307ad69203c2 --- /dev/null +++ b/components/lwp/lwp_mem.h @@ -0,0 +1,34 @@ +/* + * File : lwp_mem.h + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2018, RT-Thread Development Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes + */ + +#ifndef __LWP_MEM_H__ +#define __LWP_MEM_H__ + +extern void rt_lwp_mem_init(struct rt_lwp *lwp); +extern void rt_lwp_mem_deinit(struct rt_lwp *lwp); + +extern void *rt_lwp_mem_malloc(rt_uint32_t size); +extern void rt_lwp_mem_free(void *addr); +extern void *rt_lwp_mem_realloc(void *rmem, rt_size_t newsize); + +#endif diff --git a/components/lwp/lwp_memheap.c b/components/lwp/lwp_memheap.c new file mode 100644 index 0000000000000000000000000000000000000000..46ba667695da8309121c1cb575454ffba2f86f1e --- /dev/null +++ b/components/lwp/lwp_memheap.c @@ -0,0 +1,590 @@ +/* + * File : lwp_memheap.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2012, RT-Thread Development Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes + * 2012-04-10 Bernard first implementation + * 2012-10-16 Bernard add the mutex lock for heap object. + * 2012-12-29 Bernard memheap can be used as system heap. + * change mutex lock to semaphore lock. + * 2013-04-10 Bernard add rt_lwp_memheap_realloc function. + * 2013-05-24 Bernard fix the rt_lwp_memheap_realloc issue. + * 2013-07-11 Grissiom fix the memory block splitting issue. + * 2013-07-15 Grissiom optimize rt_lwp_memheap_realloc + */ + +#include +#include +#include + +/* dynamic pool magic and mask */ +#define RT_MEMHEAP_MAGIC 0x1ea01ea0 +#define RT_MEMHEAP_MASK 0xfffffffe +#define RT_MEMHEAP_USED 0x01 +#define RT_MEMHEAP_FREED 0x00 + +#define RT_MEMHEAP_IS_USED(i) ((i)->magic & RT_MEMHEAP_USED) +#define RT_MEMHEAP_MINIALLOC 12 + +#define RT_MEMHEAP_SIZE RT_ALIGN(sizeof(struct rt_lwp_memheap_item), RT_ALIGN_SIZE) +#define MEMITEM_SIZE(item) ((rt_uint32_t)item->next - (rt_uint32_t)item - RT_MEMHEAP_SIZE) + +/* + * The initialized memory pool will be: + * +-----------------------------------+--------------------------+ + * | whole freed memory block | Used Memory Block Tailer | + * +-----------------------------------+--------------------------+ + * + * block_list --> whole freed memory block + * + * The length of Used Memory Block Tailer is 0, + * which is prevents block merging across list + */ +rt_err_t rt_lwp_memheap_init(struct rt_lwp_memheap *memheap, + const char *name, + void *start_addr, + rt_uint32_t size) +{ + struct rt_lwp_memheap_item *item; + + RT_ASSERT(memheap != RT_NULL); + + /* initialize pool object */ + memheap->start_addr = start_addr; + memheap->pool_size = RT_ALIGN_DOWN(size, RT_ALIGN_SIZE); + memheap->available_size = memheap->pool_size - (2 * RT_MEMHEAP_SIZE); + memheap->max_used_size = memheap->pool_size - memheap->available_size; + + /* initialize the free list header */ + item = &(memheap->free_header); + item->magic = RT_MEMHEAP_MAGIC; + item->pool_ptr = memheap; + item->next = RT_NULL; + item->prev = RT_NULL; + item->next_free = item; + item->prev_free = item; + + /* set the free list to free list header */ + memheap->free_list = item; + + /* initialize the first big memory block */ + item = (struct rt_lwp_memheap_item *)start_addr; + item->magic = RT_MEMHEAP_MAGIC; + item->pool_ptr = memheap; + item->next = RT_NULL; + item->prev = RT_NULL; + item->next_free = item; + item->prev_free = item; + + item->next = (struct rt_lwp_memheap_item *) + ((rt_uint8_t *)item + memheap->available_size + RT_MEMHEAP_SIZE); + item->prev = item->next; + + /* block list header */ + memheap->block_list = item; + + /* place the big memory block to free list */ + item->next_free = memheap->free_list->next_free; + item->prev_free = memheap->free_list; + memheap->free_list->next_free->prev_free = item; + memheap->free_list->next_free = item; + + /* move to the end of memory pool to build a small tailer block, + * which prevents block merging + */ + item = item->next; + /* it's a used memory block */ + item->magic = RT_MEMHEAP_MAGIC | RT_MEMHEAP_USED; + item->pool_ptr = memheap; + item->next = (struct rt_lwp_memheap_item *)start_addr; + item->prev = (struct rt_lwp_memheap_item *)start_addr; + /* not in free list */ + item->next_free = item->prev_free = RT_NULL; + + /* initialize semaphore lock */ + rt_sem_init(&(memheap->lock), name, 1, RT_IPC_FLAG_FIFO); + + RT_DEBUG_LOG(RT_DEBUG_MEMHEAP, + ("memory heap: start addr 0x%08x, size %d, free list header 0x%08x\n", + start_addr, size, &(memheap->free_header))); + + return RT_EOK; +} + +void *rt_lwp_memheap_alloc(struct rt_lwp_memheap *heap, rt_uint32_t size) +{ + rt_err_t result; + rt_uint32_t free_size; + struct rt_lwp_memheap_item *header_ptr; + + RT_ASSERT(heap != RT_NULL); + + /* align allocated size */ + size = RT_ALIGN(size, RT_ALIGN_SIZE); + if (size < RT_MEMHEAP_MINIALLOC) + size = RT_MEMHEAP_MINIALLOC; + + RT_DEBUG_LOG(RT_DEBUG_MEMHEAP, ("allocate %d on heap:%8.*s", + size, RT_NAME_MAX, heap->parent.name)); + + if (size < heap->available_size) + { + /* search on free list */ + free_size = 0; + + /* lock memheap */ + result = rt_sem_take(&(heap->lock), RT_WAITING_FOREVER); + if (result != RT_EOK) + { + rt_set_errno(result); + + return RT_NULL; + } + + /* get the first free memory block */ + header_ptr = heap->free_list->next_free; + while (header_ptr != heap->free_list && free_size < size) + { + /* get current freed memory block size */ + free_size = MEMITEM_SIZE(header_ptr); + if (free_size < size) + { + /* move to next free memory block */ + header_ptr = header_ptr->next_free; + } + } + + /* determine if the memory is available. */ + if (free_size >= size) + { + /* a block that satisfies the request has been found. */ + + /* determine if the block needs to be split. */ + if (free_size >= (size + RT_MEMHEAP_SIZE + RT_MEMHEAP_MINIALLOC)) + { + struct rt_lwp_memheap_item *new_ptr; + + /* split the block. */ + new_ptr = (struct rt_lwp_memheap_item *) + (((rt_uint8_t *)header_ptr) + size + RT_MEMHEAP_SIZE); + + RT_DEBUG_LOG(RT_DEBUG_MEMHEAP, + ("split: block[0x%08x] nextm[0x%08x] prevm[0x%08x] to new[0x%08x]\n", + header_ptr, + header_ptr->next, + header_ptr->prev, + new_ptr)); + + /* mark the new block as a memory block and freed. */ + new_ptr->magic = RT_MEMHEAP_MAGIC; + + /* put the pool pointer into the new block. */ + new_ptr->pool_ptr = heap; + + /* break down the block list */ + new_ptr->prev = header_ptr; + new_ptr->next = header_ptr->next; + header_ptr->next->prev = new_ptr; + header_ptr->next = new_ptr; + + /* remove header ptr from free list */ + header_ptr->next_free->prev_free = header_ptr->prev_free; + header_ptr->prev_free->next_free = header_ptr->next_free; + header_ptr->next_free = RT_NULL; + header_ptr->prev_free = RT_NULL; + + /* insert new_ptr to free list */ + new_ptr->next_free = heap->free_list->next_free; + new_ptr->prev_free = heap->free_list; + heap->free_list->next_free->prev_free = new_ptr; + heap->free_list->next_free = new_ptr; + RT_DEBUG_LOG(RT_DEBUG_MEMHEAP, ("new ptr: next_free 0x%08x, prev_free 0x%08x\n", + new_ptr->next_free, + new_ptr->prev_free)); + + /* decrement the available byte count. */ + heap->available_size = heap->available_size - + size - + RT_MEMHEAP_SIZE; + if (heap->pool_size - heap->available_size > heap->max_used_size) + heap->max_used_size = heap->pool_size - heap->available_size; + } + else + { + /* decrement the entire free size from the available bytes count. */ + heap->available_size = heap->available_size - free_size; + if (heap->pool_size - heap->available_size > heap->max_used_size) + heap->max_used_size = heap->pool_size - heap->available_size; + + /* remove header_ptr from free list */ + RT_DEBUG_LOG(RT_DEBUG_MEMHEAP, + ("one block: block[0x%08x], next_free 0x%08x, prev_free 0x%08x\n", + header_ptr, + header_ptr->next_free, + header_ptr->prev_free)); + + header_ptr->next_free->prev_free = header_ptr->prev_free; + header_ptr->prev_free->next_free = header_ptr->next_free; + header_ptr->next_free = RT_NULL; + header_ptr->prev_free = RT_NULL; + } + + /* Mark the allocated block as not available. */ + header_ptr->magic |= RT_MEMHEAP_USED; + + /* release lock */ + rt_sem_release(&(heap->lock)); + + /* Return a memory address to the caller. */ + RT_DEBUG_LOG(RT_DEBUG_MEMHEAP, + ("alloc mem: memory[0x%08x], heap[0x%08x], size: %d\n", + (void *)((rt_uint8_t *)header_ptr + RT_MEMHEAP_SIZE), + header_ptr, + size)); + + return (void *)((rt_uint8_t *)header_ptr + RT_MEMHEAP_SIZE); + } + + /* release lock */ + rt_sem_release(&(heap->lock)); + } + + RT_DEBUG_LOG(RT_DEBUG_MEMHEAP, ("allocate memory: failed\n")); + + /* Return the completion status. */ + return RT_NULL; +} + +void *rt_lwp_memheap_realloc(struct rt_lwp_memheap *heap, void *ptr, rt_size_t newsize) +{ + rt_err_t result; + rt_size_t oldsize; + struct rt_lwp_memheap_item *header_ptr; + struct rt_lwp_memheap_item *new_ptr; + + if (newsize == 0) + { + rt_lwp_memheap_free(ptr); + + return RT_NULL; + } + /* align allocated size */ + newsize = RT_ALIGN(newsize, RT_ALIGN_SIZE); + if (newsize < RT_MEMHEAP_MINIALLOC) + newsize = RT_MEMHEAP_MINIALLOC; + + if (ptr == RT_NULL) + { + return rt_lwp_memheap_alloc(heap, newsize); + } + + /* get memory block header and get the size of memory block */ + header_ptr = (struct rt_lwp_memheap_item *) + ((rt_uint8_t *)ptr - RT_MEMHEAP_SIZE); + oldsize = MEMITEM_SIZE(header_ptr); + /* re-allocate memory */ + if (newsize > oldsize) + { + void *new_ptr; + struct rt_lwp_memheap_item *next_ptr; + + /* lock memheap */ + result = rt_sem_take(&(heap->lock), RT_WAITING_FOREVER); + if (result != RT_EOK) + { + rt_set_errno(result); + return RT_NULL; + } + + next_ptr = header_ptr->next; + + /* header_ptr should not be the tail */ + RT_ASSERT(next_ptr > header_ptr); + + /* check whether the following free space is enough to expand */ + if (!RT_MEMHEAP_IS_USED(next_ptr)) + { + rt_int32_t nextsize; + + nextsize = MEMITEM_SIZE(next_ptr); + RT_ASSERT(next_ptr > 0); + + /* Here is the ASCII art of the situation that we can make use of + * the next free node without alloc/memcpy, |*| is the control + * block: + * + * oldsize free node + * |*|-----------|*|----------------------|*| + * newsize >= minialloc + * |*|----------------|*|-----------------|*| + */ + if (nextsize + oldsize > newsize + RT_MEMHEAP_MINIALLOC) + { + /* decrement the entire free size from the available bytes count. */ + heap->available_size = heap->available_size - (newsize - oldsize); + if (heap->pool_size - heap->available_size > heap->max_used_size) + heap->max_used_size = heap->pool_size - heap->available_size; + + /* remove next_ptr from free list */ + RT_DEBUG_LOG(RT_DEBUG_MEMHEAP, + ("remove block: block[0x%08x], next_free 0x%08x, prev_free 0x%08x", + next_ptr, + next_ptr->next_free, + next_ptr->prev_free)); + + next_ptr->next_free->prev_free = next_ptr->prev_free; + next_ptr->prev_free->next_free = next_ptr->next_free; + next_ptr->next->prev = next_ptr->prev; + next_ptr->prev->next = next_ptr->next; + + /* build a new one on the right place */ + next_ptr = (struct rt_lwp_memheap_item *)((char *)ptr + newsize); + + RT_DEBUG_LOG(RT_DEBUG_MEMHEAP, + ("new free block: block[0x%08x] nextm[0x%08x] prevm[0x%08x]", + next_ptr, + next_ptr->next, + next_ptr->prev)); + + /* mark the new block as a memory block and freed. */ + next_ptr->magic = RT_MEMHEAP_MAGIC; + + /* put the pool pointer into the new block. */ + next_ptr->pool_ptr = heap; + + next_ptr->prev = header_ptr; + next_ptr->next = header_ptr->next; + header_ptr->next->prev = next_ptr; + header_ptr->next = next_ptr; + + /* insert next_ptr to free list */ + next_ptr->next_free = heap->free_list->next_free; + next_ptr->prev_free = heap->free_list; + heap->free_list->next_free->prev_free = next_ptr; + heap->free_list->next_free = next_ptr; + RT_DEBUG_LOG(RT_DEBUG_MEMHEAP, ("new ptr: next_free 0x%08x, prev_free 0x%08x", + next_ptr->next_free, + next_ptr->prev_free)); + + /* release lock */ + rt_sem_release(&(heap->lock)); + + return ptr; + } + } + + /* release lock */ + rt_sem_release(&(heap->lock)); + + /* re-allocate a memory block */ + new_ptr = (void *)rt_lwp_memheap_alloc(heap, newsize); + if (new_ptr != RT_NULL) + { + rt_memcpy(new_ptr, ptr, oldsize < newsize ? oldsize : newsize); + rt_lwp_memheap_free(ptr); + } + + return new_ptr; + } + + /* don't split when there is less than one node space left */ + if (newsize + RT_MEMHEAP_SIZE + RT_MEMHEAP_MINIALLOC >= oldsize) + return ptr; + + /* lock memheap */ + result = rt_sem_take(&(heap->lock), RT_WAITING_FOREVER); + if (result != RT_EOK) + { + rt_set_errno(result); + + return RT_NULL; + } + + /* split the block. */ + new_ptr = (struct rt_lwp_memheap_item *) + (((rt_uint8_t *)header_ptr) + newsize + RT_MEMHEAP_SIZE); + + RT_DEBUG_LOG(RT_DEBUG_MEMHEAP, + ("split: block[0x%08x] nextm[0x%08x] prevm[0x%08x] to new[0x%08x]\n", + header_ptr, + header_ptr->next, + header_ptr->prev, + new_ptr)); + + /* mark the new block as a memory block and freed. */ + new_ptr->magic = RT_MEMHEAP_MAGIC; + /* put the pool pointer into the new block. */ + new_ptr->pool_ptr = heap; + + /* break down the block list */ + new_ptr->prev = header_ptr; + new_ptr->next = header_ptr->next; + header_ptr->next->prev = new_ptr; + header_ptr->next = new_ptr; + + /* determine if the block can be merged with the next neighbor. */ + if (!RT_MEMHEAP_IS_USED(new_ptr->next)) + { + struct rt_lwp_memheap_item *free_ptr; + + /* merge block with next neighbor. */ + free_ptr = new_ptr->next; + heap->available_size = heap->available_size - MEMITEM_SIZE(free_ptr); + + RT_DEBUG_LOG(RT_DEBUG_MEMHEAP, + ("merge: right node 0x%08x, next_free 0x%08x, prev_free 0x%08x\n", + header_ptr, header_ptr->next_free, header_ptr->prev_free)); + + free_ptr->next->prev = new_ptr; + new_ptr->next = free_ptr->next; + + /* remove free ptr from free list */ + free_ptr->next_free->prev_free = free_ptr->prev_free; + free_ptr->prev_free->next_free = free_ptr->next_free; + } + + /* insert the split block to free list */ + new_ptr->next_free = heap->free_list->next_free; + new_ptr->prev_free = heap->free_list; + heap->free_list->next_free->prev_free = new_ptr; + heap->free_list->next_free = new_ptr; + RT_DEBUG_LOG(RT_DEBUG_MEMHEAP, ("new free ptr: next_free 0x%08x, prev_free 0x%08x\n", + new_ptr->next_free, + new_ptr->prev_free)); + + /* increment the available byte count. */ + heap->available_size = heap->available_size + MEMITEM_SIZE(new_ptr); + + /* release lock */ + rt_sem_release(&(heap->lock)); + + /* return the old memory block */ + return ptr; +} + +void rt_lwp_memheap_free(void *ptr) +{ + rt_err_t result; + struct rt_lwp_memheap *heap; + struct rt_lwp_memheap_item *header_ptr, *new_ptr; + rt_uint32_t insert_header; + + /* NULL check */ + if (ptr == RT_NULL) return; + + /* set initial status as OK */ + insert_header = 1; + new_ptr = RT_NULL; + header_ptr = (struct rt_lwp_memheap_item *) + ((rt_uint8_t *)ptr - RT_MEMHEAP_SIZE); + + RT_DEBUG_LOG(RT_DEBUG_MEMHEAP, ("free memory: memory[0x%08x], block[0x%08x]\n", + ptr, header_ptr)); + + /* check magic */ + RT_ASSERT((header_ptr->magic & RT_MEMHEAP_MASK) == RT_MEMHEAP_MAGIC); + RT_ASSERT(header_ptr->magic & RT_MEMHEAP_USED); + /* check whether this block of memory has been over-written. */ + RT_ASSERT((header_ptr->next->magic & RT_MEMHEAP_MASK) == RT_MEMHEAP_MAGIC); + + /* get pool ptr */ + heap = header_ptr->pool_ptr; + + /* lock memheap */ + result = rt_sem_take(&(heap->lock), RT_WAITING_FOREVER); + if (result != RT_EOK) + { + rt_set_errno(result); + + return ; + } + + /* Mark the memory as available. */ + header_ptr->magic &= ~RT_MEMHEAP_USED; + /* Adjust the available number of bytes. */ + heap->available_size = heap->available_size + MEMITEM_SIZE(header_ptr); + + /* Determine if the block can be merged with the previous neighbor. */ + if (!RT_MEMHEAP_IS_USED(header_ptr->prev)) + { + RT_DEBUG_LOG(RT_DEBUG_MEMHEAP, ("merge: left node 0x%08x\n", + header_ptr->prev)); + + /* adjust the available number of bytes. */ + heap->available_size = heap->available_size + RT_MEMHEAP_SIZE; + + /* yes, merge block with previous neighbor. */ + (header_ptr->prev)->next = header_ptr->next; + (header_ptr->next)->prev = header_ptr->prev; + + /* move header pointer to previous. */ + header_ptr = header_ptr->prev; + /* don't insert header to free list */ + insert_header = 0; + } + + /* determine if the block can be merged with the next neighbor. */ + if (!RT_MEMHEAP_IS_USED(header_ptr->next)) + { + /* adjust the available number of bytes. */ + heap->available_size = heap->available_size + RT_MEMHEAP_SIZE; + + /* merge block with next neighbor. */ + new_ptr = header_ptr->next; + + RT_DEBUG_LOG(RT_DEBUG_MEMHEAP, + ("merge: right node 0x%08x, next_free 0x%08x, prev_free 0x%08x\n", + new_ptr, new_ptr->next_free, new_ptr->prev_free)); + + new_ptr->next->prev = header_ptr; + header_ptr->next = new_ptr->next; + + /* remove new ptr from free list */ + new_ptr->next_free->prev_free = new_ptr->prev_free; + new_ptr->prev_free->next_free = new_ptr->next_free; + } + + if (insert_header) + { + /* no left merge, insert to free list */ + header_ptr->next_free = heap->free_list->next_free; + header_ptr->prev_free = heap->free_list; + heap->free_list->next_free->prev_free = header_ptr; + heap->free_list->next_free = header_ptr; + + RT_DEBUG_LOG(RT_DEBUG_MEMHEAP, + ("insert to free list: next_free 0x%08x, prev_free 0x%08x\n", + header_ptr->next_free, header_ptr->prev_free)); + } + + /* release lock */ + rt_sem_release(&(heap->lock)); +} + +rt_bool_t rt_lwp_memheap_is_empty(struct rt_lwp_memheap *memheap) +{ + RT_ASSERT(memheap != RT_NULL); + + return (memheap->available_size + 2 * sizeof(struct rt_lwp_memheap_item)) == memheap->pool_size; +} + +rt_bool_t rt_lwp_memheap_unavailable_size_get(void) +{ + return 2 * RT_MEMHEAP_SIZE + 3; +} diff --git a/components/lwp/lwp_memheap.h b/components/lwp/lwp_memheap.h new file mode 100644 index 0000000000000000000000000000000000000000..064238585c5c0495b30c56b4c89d43e40ad4aa47 --- /dev/null +++ b/components/lwp/lwp_memheap.h @@ -0,0 +1,74 @@ +/* + * File : lwp_memheap.h + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2018, RT-Thread Development Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes + */ + +#ifndef __LWP_MEMHEAP_H__ +#define __LWP_MEMHEAP_H__ + +#include +#include + +/** + * memory item on the heap + */ +struct rt_lwp_memheap_item +{ + rt_uint32_t magic; /**< magic number for memheap */ + struct rt_lwp_memheap *pool_ptr; /**< point of pool */ + + struct rt_lwp_memheap_item *next; /**< next memheap item */ + struct rt_lwp_memheap_item *prev; /**< prev memheap item */ + + struct rt_lwp_memheap_item *next_free; /**< next free memheap item */ + struct rt_lwp_memheap_item *prev_free; /**< prev free memheap item */ +}; + +/** + * Base structure of memory heap object + */ +struct rt_lwp_memheap +{ + struct rt_object parent; /**< inherit from rt_object */ + + void *start_addr; /**< pool start address and size */ + + rt_uint32_t pool_size; /**< pool size */ + rt_uint32_t available_size; /**< available size */ + rt_uint32_t max_used_size; /**< maximum allocated size */ + + struct rt_lwp_memheap_item *block_list; /**< used block list */ + struct rt_lwp_memheap_item *free_list; /**< free block list */ + struct rt_lwp_memheap_item free_header; /**< free block list header */ + + struct rt_semaphore lock; /**< semaphore lock */ + + rt_list_t mlist; +}; + +extern rt_err_t rt_lwp_memheap_init(struct rt_lwp_memheap *memheap, const char *name, void *start_addr, rt_uint32_t size); +extern void *rt_lwp_memheap_alloc(struct rt_lwp_memheap *heap, rt_uint32_t size); +extern void rt_lwp_memheap_free(void *ptr); +extern void *rt_lwp_memheap_realloc(struct rt_lwp_memheap *heap, void *ptr, rt_size_t newsize); +extern rt_bool_t rt_lwp_memheap_is_empty(struct rt_lwp_memheap *memheap); +extern rt_bool_t rt_lwp_memheap_unavailable_size_get(void); + +#endif diff --git a/components/lwp/lwp_syscall.c b/components/lwp/lwp_syscall.c new file mode 100644 index 0000000000000000000000000000000000000000..be5e15dcb39fea4f0069141b41d2d5f48b7c0ddb --- /dev/null +++ b/components/lwp/lwp_syscall.c @@ -0,0 +1,242 @@ +/* + * File : lwp_syscall.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2018, RT-Thread Development Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes + */ + +/* RT-Thread System call */ +#include +#include +#include + +#define DBG_ENABLE +#define DBG_SECTION_NAME "[LWP_CALL]" +#define DBG_COLOR +#define DBG_LEVEL DBG_WARNING +#include + +/* thread/process */ +void sys_exit(int value) +{ + /* TODO: handle the return_value */ + + dbg_log(DBG_LOG, "enter sys_exit\n"); + + rt_thread_delete(rt_thread_self()); + + rt_schedule(); + + return; +} + +/* syscall: "read" ret: "ssize_t" args: "int" "void *" "size_t" */ +ssize_t sys_read(int fd, void *buf, size_t nbyte) +{ + return read(fd, buf, nbyte); +} + +/* syscall: "write" ret: "ssize_t" args: "int" "const void *" "size_t" */ +ssize_t sys_write(int fd, const void *buf, size_t nbyte) +{ + return write(fd, buf, nbyte); +} + +/* syscall: "lseek" ret: "off_t" args: "int" "off_t" "int" */ +off_t sys_lseek(int fd, off_t offset, int whence) +{ + return lseek(fd, offset, whence); +} + +/* syscall: "open" ret: "int" args: "const char *" "int" "..." */ +int sys_open(const char *name, int mode, ...) +{ + return open(name, mode, 0); +} + +/* syscall: "close" ret: "int" args: "int" */ +int sys_close(int fd) +{ + return close(fd); +} + +/* syscall: "ioctl" ret: "int" args: "int" "u_long" "..." */ +int sys_ioctl(int fd, unsigned long cmd, void* data) +{ + return ioctl(fd, cmd, data); +} + +/* syscall: "nanosleep" ret: "int" args: "const struct timespec *" "struct timespec *" */ +int sys_nanosleep(const struct timespec *rqtp, struct timespec *rmtp) +{ + rt_tick_t tick; + + dbg_log(DBG_LOG, "sys_nanosleep\n"); + + tick = rqtp->tv_sec * RT_TICK_PER_SECOND + (rqtp->tv_nsec * RT_TICK_PER_SECOND)/ 1000000000; + rt_thread_delay(tick); + + if (rmtp) + { + tick = rt_tick_get() - tick; + /* get the passed time */ + rmtp->tv_sec = tick/RT_TICK_PER_SECOND; + rmtp->tv_nsec = (tick%RT_TICK_PER_SECOND) * (1000000000/RT_TICK_PER_SECOND); + } + + return 0; +} + +/* syscall: "getpriority" ret: "int" args: "int" "id_t" */ +int sys_getpriority(int which, id_t who) +{ + if (which == PRIO_PROCESS) + { + rt_thread_t tid; + + tid = rt_thread_self(); + if (who == (id_t)tid || who == 0xff) + { + return tid->current_priority; + } + } + + return 0xff; +} + +/* syscall: "setpriority" ret: "int" args: "int" "id_t" "int" */ +int sys_setpriority(int which, id_t who, int prio) +{ + if (which == PRIO_PROCESS) + { + rt_thread_t tid; + + tid = rt_thread_self(); + if ((who == (id_t)tid || who == 0xff) && (prio >= 0 && prio < RT_THREAD_PRIORITY_MAX)) + { + rt_thread_control(tid, RT_THREAD_CTRL_CHANGE_PRIORITY, &prio); + return 0; + } + } + + return -1; +} + +/* syscall: "gettimeofday" ret: "int" args: "struct timeval *" "struct timezone *" */ +int sys_gettimeofday(struct timeval *tp, struct timezone *tzp) +{ + if (tp) + { + tp->tv_sec = rt_tick_get() / RT_TICK_PER_SECOND; + tp->tv_usec = (rt_tick_get() % RT_TICK_PER_SECOND) * (1000000 / RT_TICK_PER_SECOND); + } + + return 0; +} + +/* syscall: "settimeofday" ret: "int" args: "const struct timeval *" "const struct timezone *" */ +int sys_settimeofday(const struct timeval *tv, const struct timezone *tzp) +{ + return 0; +} + +/* syscall: "msgget" ret: "int" args: "key_t" "int" */ +int sys_msgget(key_t key, int msgflg) +{ + return -1; +} + +/* syscall: "msgsnd" ret: "int" args: "int" "const void *" "size_t" "int" */ +int sys_msgsend(int msqid, const void *msgp, size_t msgsz, int msgflg) +{ + return -1; +} + +/* syscall: "msgrcv" ret: "int" args: "int" "void *" "size_t" "long" "int" */ +int sys_msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg) +{ + return -1; +} + +/* syscall: "sys_log" ret: "int" args: "const char*" "size" */ +int sys_log(const char* log, int size) +{ + rt_device_t console = rt_console_get_device(); + + if (console) rt_device_write(console, -1, log, size); + + return 0; +} + +void *sys_malloc(size_t size) +{ + return rt_lwp_mem_malloc(size); +} + +void sys_free(void *addr) +{ + rt_lwp_mem_free(addr); +} + +void *sys_realloc(void *rmem, size_t newsize) +{ + return rt_lwp_mem_realloc(rmem, newsize); +} + +const static void* func_table[] = +{ + (void *)sys_exit, // 0x01 + (void *)sys_read, // 0x02 + (void *)sys_write, // 0x03 + (void *)sys_lseek, // 0x04 + (void *)sys_open, // 0x05 + (void *)sys_close, // 0x06 + (void *)sys_ioctl, // 0x07 + + (void *)sys_nanosleep, // 0x08 + + (void *)sys_getpriority, // 0x09 + (void *)sys_setpriority, // 0x0a + + (void *)sys_gettimeofday, // 0x0b + (void *)sys_settimeofday, // 0x0c + + (void *)sys_malloc, // 0x0d + (void *)sys_free, // 0x0e +}; + +const void *lwp_get_sys_api(rt_uint32_t number) +{ + const void *func = RT_NULL; + + if (number == 0xff) + { + func = (void *)sys_log; + } + else + { + number -= 1; + if (number < sizeof(func_table)/sizeof(func_table[0])) + { + func = func_table[number]; + } + } + + return func; +} diff --git a/components/lwp/lwp_syscall.h b/components/lwp/lwp_syscall.h new file mode 100644 index 0000000000000000000000000000000000000000..eba25c40e35ad94d1be6c80e7c5042be10f24353 --- /dev/null +++ b/components/lwp/lwp_syscall.h @@ -0,0 +1,78 @@ +/* + * File : lwp_syscall.h + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2018, RT-Thread Development Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes + * 2006-03-18 Bernard the first version + * 2006-04-25 Bernard add rt_hw_context_switch_interrupt declaration + * 2006-09-24 Bernard add rt_hw_context_switch_to declaration + * 2012-12-29 Bernard add rt_hw_exception_install declaration + * 2017-10-17 Hichard add some micros + */ + +#ifndef __LWP_SYSCALL_H__ +#define __LWP_SYSCALL_H__ + +#include +#include +#include +#include +#include + +typedef long suseconds_t; /* microseconds (signed) */ +typedef long key_t; /* IPC key (for Sys V IPC) */ +typedef uint32_t id_t; /* may contain pid, uid or gid */ + +/* + * Process priority specifications to get/setpriority. + */ +#define PRIO_MIN (-20) +#define PRIO_MAX 20 + +#define PRIO_PROCESS 0 /* only support lwp process */ +#define PRIO_PGRP 1 +#define PRIO_USER 2 + +#define TIMEVAL_TO_TIMESPEC(tv, ts) { \ + (ts)->tv_sec = (tv)->tv_sec; \ + (ts)->tv_nsec = (tv)->tv_usec * 1000; \ +} +#define TIMESPEC_TO_TIMEVAL(tv, ts) { \ + (tv)->tv_sec = (ts)->tv_sec; \ + (tv)->tv_usec = (ts)->tv_nsec / 1000; \ +} + +void sys_exit(int value); +ssize_t sys_read(int fd, void *buf, size_t nbyte); +ssize_t sys_write(int fd, const void *buf, size_t nbyte); +off_t sys_lseek(int fd, off_t offset, int whence); +int sys_open(const char *name, int mode, ...); +int sys_close(int fd); +int sys_nanosleep(const struct timespec *rqtp, struct timespec *rmtp); +int sys_getpriority(int which, id_t who); +int sys_setpriority(int which, id_t who, int prio); +int sys_gettimeofday(struct timeval *tp, struct timezone *tzp); +int sys_settimeofday(const struct timeval *tv, const struct timezone *tzp); +int sys_msgget(key_t key, int msgflg); +int sys_msgsend(int msqid, const void *msgp, size_t msgsz, int msgflg); +int sys_msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg); + +int sys_log(const char* log, int size); + +#endif diff --git a/components/utilities/logtrace/log_file.c b/components/utilities/logtrace/log_file.c index 4e4e15896989b26205c81d7646387af67bcb68f7..42d1f6e7a98580d051754ed8e8858af486e7c10d 100644 --- a/components/utilities/logtrace/log_file.c +++ b/components/utilities/logtrace/log_file.c @@ -112,6 +112,18 @@ static rt_err_t fdevice_control(rt_device_t dev, int cmd, void *arg) return RT_EOK; } +#ifdef RT_USING_DEVICE_OPS +const static struct rt_device_ops log_trace_ops = +{ + RT_NULL, + fdevice_open, + fdevice_close, + RT_NULL, + fdevice_write, + fdevice_control +}; +#endif + void log_trace_file_init(const char *filename) { rt_device_t device; @@ -123,11 +135,15 @@ void log_trace_file_init(const char *filename) _file_device.parent.type = RT_Device_Class_Char; +#ifdef RT_USING_DEVICE_OPS + _file_device.parent.ops = &log_trace_ops; +#else _file_device.parent.init = RT_NULL; _file_device.parent.open = fdevice_open; _file_device.parent.close = fdevice_close; _file_device.parent.write = fdevice_write; _file_device.parent.control = fdevice_control; +#endif rt_device_register(&_file_device.parent, "logfile", O_RDWR); } diff --git a/components/utilities/logtrace/log_trace.c b/components/utilities/logtrace/log_trace.c index 79bcde207593e2c413c0b35b6312ed7143cf3da4..4ea0ff13fd6cfeb8fa8d40e087fca392d3284131 100644 --- a/components/utilities/logtrace/log_trace.c +++ b/components/utilities/logtrace/log_trace.c @@ -383,17 +383,33 @@ static rt_err_t _log_control(rt_device_t dev, int cmd, void *arg) return rt_device_control(_traceout_device, cmd, arg); } +#ifdef RT_USING_DEVICE_OPS +const static struct rt_device_ops log_device_ops = +{ + RT_NULL, + RT_NULL, + RT_NULL, + RT_NULL, + _log_write, + _log_control +}; +#endif + int log_trace_init(void) { rt_memset(&_log_device, 0x00, sizeof(_log_device)); _log_device.type = RT_Device_Class_Char; +#ifdef RT_USING_DEVICE_OPS + _log_device.ops = &log_device_ops; +#else _log_device.init = RT_NULL; _log_device.open = RT_NULL; _log_device.close = RT_NULL; _log_device.read = RT_NULL; _log_device.write = _log_write; _log_device.control = _log_control; +#endif /* no indication and complete callback */ _log_device.rx_indicate = RT_NULL; diff --git a/include/rtdef.h b/include/rtdef.h index de243b7d5cf87c7b686efe242c7b10657d72b754..5f6f7289675545e4f21cd82f759bcf7c4c6fdb39 100644 --- a/include/rtdef.h +++ b/include/rtdef.h @@ -848,6 +848,17 @@ enum rt_device_class_type #define RT_DEVICE_CTRL_RTC_SET_ALARM 0x13 /**< set alarm */ typedef struct rt_device *rt_device_t; +struct rt_device_ops +{ + /* common device interface */ + rt_err_t (*init) (rt_device_t dev); + rt_err_t (*open) (rt_device_t dev, rt_uint16_t oflag); + rt_err_t (*close) (rt_device_t dev); + rt_size_t (*read) (rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size); + rt_size_t (*write) (rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size); + rt_err_t (*control)(rt_device_t dev, int cmd, void *args); +}; + /** * Device structure */ @@ -866,6 +877,9 @@ struct rt_device rt_err_t (*rx_indicate)(rt_device_t dev, rt_size_t size); rt_err_t (*tx_complete)(rt_device_t dev, void *buffer); +#ifdef RT_USING_DEVICE_OPS + const struct rt_device_ops *ops; +#else /* common device interface */ rt_err_t (*init) (rt_device_t dev); rt_err_t (*open) (rt_device_t dev, rt_uint16_t oflag); @@ -873,6 +887,7 @@ struct rt_device rt_size_t (*read) (rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size); rt_size_t (*write) (rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size); rt_err_t (*control)(rt_device_t dev, int cmd, void *args); +#endif #if defined(RT_USING_POSIX) const struct dfs_file_ops *fops; @@ -1030,8 +1045,8 @@ struct rt_module rt_uint32_t user_data; /**< arch data in the module */ - /* object in this module, module object is the last basic object type */ - struct rt_object_information module_object[RT_Object_Class_Unknown]; + void (*module_init)(void); + void (*module_cleanup)(void); }; typedef struct rt_module *rt_module_t; diff --git a/src/Kconfig b/src/Kconfig index d8ddbfc838d4bb5abc3c02e510a9399e23486496..89f709478b981713e57b20f9e3a0c44483ae40b9 100644 --- a/src/Kconfig +++ b/src/Kconfig @@ -192,6 +192,10 @@ menu "Kernel Device Object" bool "Using device object" default y + config RT_USING_DEVICE_OPS + bool "Using ops for each device object" + default n + config RT_USING_INTERRUPT_INFO bool "Enable additional interrupt trace information" default n diff --git a/src/device.c b/src/device.c index 231a052b86803071ebf97216face134b0702995c..2a919cace6543434a6bce7e284136783b38be4e3 100644 --- a/src/device.c +++ b/src/device.c @@ -32,12 +32,28 @@ #ifdef RT_USING_DEVICE +#ifdef RT_USING_DEVICE_OPS +#define device_init (dev->ops->init) +#define device_open (dev->ops->open) +#define device_close (dev->ops->close) +#define device_read (dev->ops->read) +#define device_write (dev->ops->write) +#define device_control (dev->ops->control) +#else +#define device_init (dev->init) +#define device_open (dev->open) +#define device_close (dev->close) +#define device_read (dev->read) +#define device_write (dev->write) +#define device_control (dev->control) +#endif + /** * This function registers a device driver with specified name. * * @param dev the pointer of device driver structure * @param name the device driver's name - * @param flags the flag of device + * @param flags the capabilities flag of device * * @return the error code, RT_EOK on initialization successfully. */ @@ -154,6 +170,8 @@ rt_device_t rt_device_create(int type, int attach_size) rt_device_t device; size = RT_ALIGN(sizeof(struct rt_device), RT_ALIGN_SIZE); + attach_size = RT_ALIGN(attach_size, RT_ALIGN_SIZE); + /* use the totoal size */ size += attach_size; device = (rt_device_t)rt_malloc(size); @@ -197,11 +215,11 @@ rt_err_t rt_device_init(rt_device_t dev) RT_ASSERT(dev != RT_NULL); /* get device init handler */ - if (dev->init != RT_NULL) + if (device_init != RT_NULL) { if (!(dev->flag & RT_DEVICE_FLAG_ACTIVATED)) { - result = dev->init(dev); + result = device_init(dev); if (result != RT_EOK) { rt_kprintf("To initialize device:%s failed. The error code is %d\n", @@ -234,9 +252,9 @@ rt_err_t rt_device_open(rt_device_t dev, rt_uint16_t oflag) /* if device is not initialized, initialize it. */ if (!(dev->flag & RT_DEVICE_FLAG_ACTIVATED)) { - if (dev->init != RT_NULL) + if (device_init != RT_NULL) { - result = dev->init(dev); + result = device_init(dev); if (result != RT_EOK) { rt_kprintf("To initialize device:%s failed. The error code is %d\n", @@ -257,9 +275,9 @@ rt_err_t rt_device_open(rt_device_t dev, rt_uint16_t oflag) } /* call device open interface */ - if (dev->open != RT_NULL) + if (device_open != RT_NULL) { - result = dev->open(dev, oflag); + result = device_open(dev, oflag); } else { @@ -304,9 +322,9 @@ rt_err_t rt_device_close(rt_device_t dev) return RT_EOK; /* call device close interface */ - if (dev->close != RT_NULL) + if (device_close != RT_NULL) { - result = dev->close(dev); + result = device_close(dev); } /* set open flag */ @@ -343,9 +361,9 @@ rt_size_t rt_device_read(rt_device_t dev, } /* call device read interface */ - if (dev->read != RT_NULL) + if (device_read != RT_NULL) { - return dev->read(dev, pos, buffer, size); + return device_read(dev, pos, buffer, size); } /* set error code */ @@ -381,9 +399,9 @@ rt_size_t rt_device_write(rt_device_t dev, } /* call device write interface */ - if (dev->write != RT_NULL) + if (device_write != RT_NULL) { - return dev->write(dev, pos, buffer, size); + return device_write(dev, pos, buffer, size); } /* set error code */ @@ -407,9 +425,9 @@ rt_err_t rt_device_control(rt_device_t dev, int cmd, void *arg) RT_ASSERT(dev != RT_NULL); /* call device write interface */ - if (dev->control != RT_NULL) + if (device_control != RT_NULL) { - return dev->control(dev, cmd, arg); + return device_control(dev, cmd, arg); } return -RT_ENOSYS; diff --git a/src/idle.c b/src/idle.c index ecd894b8e2bb0de8ff746292bcc0864fca524436..f636d0fd4c3bd2e21211c258fecb09cd35805c21 100644 --- a/src/idle.c +++ b/src/idle.c @@ -164,35 +164,11 @@ void rt_thread_idle_excute(void) rt_hw_interrupt_enable(lock); #ifdef RT_USING_HEAP -#if defined(RT_USING_MODULE) && defined(RT_USING_SLAB) - /* the thread belongs to an application module */ - if (thread->flags & RT_OBJECT_FLAG_MODULE) - rt_module_free((rt_module_t)thread->module_id, thread->stack_addr); - else -#endif - /* release thread's stack */ - RT_KERNEL_FREE(thread->stack_addr); + /* release thread's stack */ + RT_KERNEL_FREE(thread->stack_addr); /* delete thread object */ rt_object_delete((rt_object_t)thread); #endif - -#ifdef RT_USING_MODULE - if (module != RT_NULL) - { - extern rt_err_t rt_module_destroy(rt_module_t module); - - /* if sub thread list and main thread are all empty */ - if ((module->module_thread == RT_NULL) && - rt_list_isempty(&module->module_object[RT_Object_Class_Thread].object_list)) - { - module->nref --; - } - - /* destroy module */ - if (module->nref == 0) - rt_module_destroy(module); - } -#endif } } diff --git a/src/ipc.c b/src/ipc.c index 5aed193996ad6c216c6c83849eaa6180f75e0a7e..055c8cb2e420110771d683bc4fa2d23f2126537f 100644 --- a/src/ipc.c +++ b/src/ipc.c @@ -1380,15 +1380,8 @@ rt_err_t rt_mb_delete(rt_mailbox_t mb) /* also resume all mailbox private suspended thread */ rt_ipc_list_resume_all(&(mb->suspend_sender_thread)); -#if defined(RT_USING_MODULE) && defined(RT_USING_SLAB) - /* the mb object belongs to an application module */ - if (mb->parent.parent.flag & RT_OBJECT_FLAG_MODULE) - rt_module_free(mb->parent.parent.module_id, mb->msg_pool); - else -#endif - - /* free mailbox pool */ - RT_KERNEL_FREE(mb->msg_pool); + /* free mailbox pool */ + RT_KERNEL_FREE(mb->msg_pool); /* delete mailbox object */ rt_object_delete(&(mb->parent.parent)); @@ -1900,15 +1893,8 @@ rt_err_t rt_mq_delete(rt_mq_t mq) /* resume all suspended thread */ rt_ipc_list_resume_all(&(mq->parent.suspend_thread)); -#if defined(RT_USING_MODULE) && defined(RT_USING_SLAB) - /* the mq object belongs to an application module */ - if (mq->parent.parent.flag & RT_OBJECT_FLAG_MODULE) - rt_module_free(mq->parent.parent.module_id, mq->msg_pool); - else -#endif - - /* free message queue pool */ - RT_KERNEL_FREE(mq->msg_pool); + /* free message queue pool */ + RT_KERNEL_FREE(mq->msg_pool); /* delete message queue object */ rt_object_delete(&(mq->parent.parent)); diff --git a/src/mempool.c b/src/mempool.c index 5d80d665332254c9008bd48a6a2b630fda7c467a..3f95279ed1dff4b2b2a37638c1563d92c7c6af4e 100644 --- a/src/mempool.c +++ b/src/mempool.c @@ -292,15 +292,8 @@ rt_err_t rt_mp_delete(rt_mp_t mp) rt_hw_interrupt_enable(temp); } -#if defined(RT_USING_MODULE) && defined(RT_USING_SLAB) - /* the mp object belongs to an application module */ - if (mp->parent.flag & RT_OBJECT_FLAG_MODULE) - rt_module_free(mp->parent.module_id, mp->start_address); - else -#endif - - /* release allocated room */ - rt_free(mp->start_address); + /* release allocated room */ + rt_free(mp->start_address); /* detach object */ rt_object_delete(&(mp->parent)); diff --git a/src/module.c b/src/module.c index b48fae9418f1e9d36a71a54fdc2bcd7ed4973b55..843b3364a93b67dd3c7b1cfa673027a013830fcb 100644 --- a/src/module.c +++ b/src/module.c @@ -65,30 +65,6 @@ #define RT_USING_MODULE_PRIO (RT_THREAD_PRIORITY_MAX - 2) #endif -#ifdef RT_USING_SLAB -#define PAGE_COUNT_MAX 256 - -/* module memory allocator */ -struct rt_mem_head -{ - rt_size_t size; /* size of memory block */ - struct rt_mem_head *next; /* next valid memory block */ -}; - -struct rt_page_info -{ - rt_uint32_t *page_ptr; - rt_uint32_t npage; -}; - -static void *rt_module_malloc_page(rt_size_t npages); -static void rt_module_free_page(rt_module_t module, - void *page_ptr, - rt_size_t npages); - -static struct rt_semaphore mod_sem; -#endif - static struct rt_module_symtab *_rt_module_symtab_begin = RT_NULL; static struct rt_module_symtab *_rt_module_symtab_end = RT_NULL; @@ -120,10 +96,6 @@ int rt_system_module_init(void) _rt_module_symtab_end = __section_end("RTMSymTab"); #endif -#ifdef RT_USING_SLAB - /* initialize heap semaphore */ - rt_sem_init(&mod_sem, "module", 1, RT_IPC_FLAG_FIFO); -#endif return 0; } INIT_COMPONENT_EXPORT(rt_system_module_init); @@ -138,7 +110,7 @@ void list_symbol(void) index != _rt_module_symtab_end; index ++) { - rt_kprintf("%s\n", index->name); + rt_kprintf("%s => 0x%08x\n", index->name, index->addr); } return ; @@ -295,80 +267,6 @@ static int rt_module_arm_relocate(struct rt_module *module, return 0; } -void rt_module_init_object_container(struct rt_module *module) -{ - RT_ASSERT(module != RT_NULL); - - /* clear all of object information */ - rt_memset(&module->module_object[0], 0x0, sizeof(module->module_object)); - - /* initialize object container - thread */ - rt_list_init(&(module->module_object[RT_Object_Class_Thread].object_list)); - module->module_object[RT_Object_Class_Thread].object_size = sizeof(struct rt_thread); - module->module_object[RT_Object_Class_Thread].type = RT_Object_Class_Thread; - -#ifdef RT_USING_SEMAPHORE - /* initialize object container - semaphore */ - rt_list_init(&(module->module_object[RT_Object_Class_Semaphore].object_list)); - module->module_object[RT_Object_Class_Semaphore].object_size = sizeof(struct rt_semaphore); - module->module_object[RT_Object_Class_Semaphore].type = RT_Object_Class_Semaphore; -#endif - -#ifdef RT_USING_MUTEX - /* initialize object container - mutex */ - rt_list_init(&(module->module_object[RT_Object_Class_Mutex].object_list)); - module->module_object[RT_Object_Class_Mutex].object_size = sizeof(struct rt_mutex); - module->module_object[RT_Object_Class_Mutex].type = RT_Object_Class_Mutex; -#endif - -#ifdef RT_USING_EVENT - /* initialize object container - event */ - rt_list_init(&(module->module_object[RT_Object_Class_Event].object_list)); - module->module_object[RT_Object_Class_Event].object_size = sizeof(struct rt_event); - module->module_object[RT_Object_Class_Event].type = RT_Object_Class_Event; -#endif - -#ifdef RT_USING_MAILBOX - /* initialize object container - mailbox */ - rt_list_init(&(module->module_object[RT_Object_Class_MailBox].object_list)); - module->module_object[RT_Object_Class_MailBox].object_size = sizeof(struct rt_mailbox); - module->module_object[RT_Object_Class_MailBox].type = RT_Object_Class_MailBox; -#endif - -#ifdef RT_USING_MESSAGEQUEUE - /* initialize object container - message queue */ - rt_list_init(&(module->module_object[RT_Object_Class_MessageQueue].object_list)); - module->module_object[RT_Object_Class_MessageQueue].object_size = sizeof(struct rt_messagequeue); - module->module_object[RT_Object_Class_MessageQueue].type = RT_Object_Class_MessageQueue; -#endif - -#ifdef RT_USING_MEMHEAP - /* initialize object container - memory heap */ - rt_list_init(&(module->module_object[RT_Object_Class_MemHeap].object_list)); - module->module_object[RT_Object_Class_MemHeap].object_size = sizeof(struct rt_memheap); - module->module_object[RT_Object_Class_MemHeap].type = RT_Object_Class_MemHeap; -#endif - -#ifdef RT_USING_MEMPOOL - /* initialize object container - memory pool */ - rt_list_init(&(module->module_object[RT_Object_Class_MemPool].object_list)); - module->module_object[RT_Object_Class_MemPool].object_size = sizeof(struct rt_mempool); - module->module_object[RT_Object_Class_MemPool].type = RT_Object_Class_MemPool; -#endif - -#ifdef RT_USING_DEVICE - /* initialize object container - device */ - rt_list_init(&(module->module_object[RT_Object_Class_Device].object_list)); - module->module_object[RT_Object_Class_Device].object_size = sizeof(struct rt_device); - module->module_object[RT_Object_Class_Device].type = RT_Object_Class_Device; -#endif - - /* initialize object container - timer */ - rt_list_init(&(module->module_object[RT_Object_Class_Timer].object_list)); - module->module_object[RT_Object_Class_Timer].object_size = sizeof(struct rt_timer); - module->module_object[RT_Object_Class_Timer].type = RT_Object_Class_Timer; -} - #ifdef RT_USING_HOOK static void (*rt_module_load_hook)(rt_module_t module); static void (*rt_module_unload_hook)(rt_module_t module); @@ -1016,9 +914,6 @@ rt_module_t rt_module_do_main(const char *name, if (module == RT_NULL) return RT_NULL; - /* init module object container */ - rt_module_init_object_container(module); - if (line_size && cmd_line) { /* set module argument */ @@ -1042,16 +937,6 @@ rt_module_t rt_module_do_main(const char *name, if (elf_module->e_entry != 0) { -#ifdef RT_USING_SLAB - /* init module memory allocator */ - module->mem_list = RT_NULL; - - /* create page array */ - module->page_array = - (void *)rt_malloc(PAGE_COUNT_MAX * sizeof(struct rt_page_info)); - module->page_cnt = 0; -#endif - /* create module thread */ module->module_thread = rt_thread_create(name, module_main_entry, module, @@ -1291,8 +1176,6 @@ FINSH_FUNCTION_EXPORT_ALIAS(rt_module_open, exec, exec module from a file); rt_err_t rt_module_destroy(rt_module_t module) { int i; - struct rt_object *object; - struct rt_list_node *list; RT_DEBUG_NOT_IN_INTERRUPT; @@ -1306,147 +1189,6 @@ rt_err_t rt_module_destroy(rt_module_t module) /* module has entry point */ if (!(module->parent.flag & RT_MODULE_FLAG_WITHOUTENTRY)) { -#ifdef RT_USING_SEMAPHORE - /* delete semaphores */ - list = &module->module_object[RT_Object_Class_Semaphore].object_list; - while (list->next != list) - { - object = rt_list_entry(list->next, struct rt_object, list); - if (rt_object_is_systemobject(object) == RT_TRUE) - { - /* detach static object */ - rt_sem_detach((rt_sem_t)object); - } - else - { - /* delete dynamic object */ - rt_sem_delete((rt_sem_t)object); - } - } -#endif - -#ifdef RT_USING_MUTEX - /* delete mutexs*/ - list = &module->module_object[RT_Object_Class_Mutex].object_list; - while (list->next != list) - { - object = rt_list_entry(list->next, struct rt_object, list); - if (rt_object_is_systemobject(object) == RT_TRUE) - { - /* detach static object */ - rt_mutex_detach((rt_mutex_t)object); - } - else - { - /* delete dynamic object */ - rt_mutex_delete((rt_mutex_t)object); - } - } -#endif - -#ifdef RT_USING_EVENT - /* delete mailboxs */ - list = &module->module_object[RT_Object_Class_Event].object_list; - while (list->next != list) - { - object = rt_list_entry(list->next, struct rt_object, list); - if (rt_object_is_systemobject(object) == RT_TRUE) - { - /* detach static object */ - rt_event_detach((rt_event_t)object); - } - else - { - /* delete dynamic object */ - rt_event_delete((rt_event_t)object); - } - } -#endif - -#ifdef RT_USING_MAILBOX - /* delete mailboxs */ - list = &module->module_object[RT_Object_Class_MailBox].object_list; - while (list->next != list) - { - object = rt_list_entry(list->next, struct rt_object, list); - if (rt_object_is_systemobject(object) == RT_TRUE) - { - /* detach static object */ - rt_mb_detach((rt_mailbox_t)object); - } - else - { - /* delete dynamic object */ - rt_mb_delete((rt_mailbox_t)object); - } - } -#endif - -#ifdef RT_USING_MESSAGEQUEUE - /* delete msgqueues */ - list = &module->module_object[RT_Object_Class_MessageQueue].object_list; - while (list->next != list) - { - object = rt_list_entry(list->next, struct rt_object, list); - if (rt_object_is_systemobject(object) == RT_TRUE) - { - /* detach static object */ - rt_mq_detach((rt_mq_t)object); - } - else - { - /* delete dynamic object */ - rt_mq_delete((rt_mq_t)object); - } - } -#endif - -#ifdef RT_USING_MEMPOOL - /* delete mempools */ - list = &module->module_object[RT_Object_Class_MemPool].object_list; - while (list->next != list) - { - object = rt_list_entry(list->next, struct rt_object, list); - if (rt_object_is_systemobject(object) == RT_TRUE) - { - /* detach static object */ - rt_mp_detach((rt_mp_t)object); - } - else - { - /* delete dynamic object */ - rt_mp_delete((rt_mp_t)object); - } - } -#endif - -#ifdef RT_USING_DEVICE - /* delete devices */ - list = &module->module_object[RT_Object_Class_Device].object_list; - while (list->next != list) - { - object = rt_list_entry(list->next, struct rt_object, list); - rt_device_unregister((rt_device_t)object); - } -#endif - - /* delete timers */ - list = &module->module_object[RT_Object_Class_Timer].object_list; - while (list->next != list) - { - object = rt_list_entry(list->next, struct rt_object, list); - if (rt_object_is_systemobject(object) == RT_TRUE) - { - /* detach static object */ - rt_timer_detach((rt_timer_t)object); - } - else - { - /* delete dynamic object */ - rt_timer_delete((rt_timer_t)object); - } - } - /* delete command line */ if (module->module_cmd_line != RT_NULL) { @@ -1454,20 +1196,6 @@ rt_err_t rt_module_destroy(rt_module_t module) } } -#ifdef RT_USING_SLAB - if (module->page_cnt > 0) - { - struct rt_page_info *page = (struct rt_page_info *)module->page_array; - - rt_kprintf("Module: warning - memory still hasn't been free finished\n"); - - while (module->page_cnt != 0) - { - rt_module_free_page(module, page[0].page_ptr, page[0].npage); - } - } -#endif - /* release module space memory */ rt_free(module->module_space); @@ -1479,11 +1207,6 @@ rt_err_t rt_module_destroy(rt_module_t module) if (module->symtab != RT_NULL) rt_free(module->symtab); -#ifdef RT_USING_SLAB - if (module->page_array != RT_NULL) - rt_free(module->page_array); -#endif - /* delete module object */ rt_object_delete((rt_object_t)module); @@ -1499,10 +1222,6 @@ rt_err_t rt_module_destroy(rt_module_t module) */ rt_err_t rt_module_unload(rt_module_t module) { - struct rt_object *object; - struct rt_list_node *list; - rt_bool_t mdelete = RT_TRUE; - RT_DEBUG_NOT_IN_INTERRUPT; /* check parameter */ @@ -1510,34 +1229,7 @@ rt_err_t rt_module_unload(rt_module_t module) return -RT_ERROR; rt_enter_critical(); - if (!(module->parent.flag & RT_MODULE_FLAG_WITHOUTENTRY)) - { - /* delete module in main thread destroy */ - mdelete = RT_FALSE; - - /* delete all sub-threads */ - list = &module->module_object[RT_Object_Class_Thread].object_list; - while (list->next != list) - { - object = rt_list_entry(list->next, struct rt_object, list); - if (rt_object_is_systemobject(object) == RT_TRUE) - { - /* detach static object */ - rt_thread_detach((rt_thread_t)object); - } - else - { - /* delete dynamic object */ - rt_thread_delete((rt_thread_t)object); - } - } - - /* delete the main thread of module */ - if (module->module_thread != RT_NULL) - { - rt_thread_delete(module->module_thread); - } - } + /* invoke module cleanup */ rt_exit_critical(); #ifdef RT_USING_HOOK @@ -1547,11 +1239,6 @@ rt_err_t rt_module_unload(rt_module_t module) } #endif - if (mdelete == RT_TRUE) - { - rt_module_destroy(module); - } - return RT_EOK; } @@ -1598,462 +1285,4 @@ rt_module_t rt_module_find(const char *name) } RTM_EXPORT(rt_module_find); -#ifdef RT_USING_SLAB -/* - * This function will allocate the numbers page with specified size - * in page memory. - * - * @param size the size of memory to be allocated. - * @note this function is used for RT-Thread Application Module - */ -static void *rt_module_malloc_page(rt_size_t npages) -{ - void *chunk; - struct rt_page_info *page; - rt_module_t self_module; - - self_module = rt_module_self(); - RT_ASSERT(self_module != RT_NULL); - - chunk = rt_page_alloc(npages); - if (chunk == RT_NULL) - return RT_NULL; - - page = (struct rt_page_info *)self_module->page_array; - page[self_module->page_cnt].page_ptr = chunk; - page[self_module->page_cnt].npage = npages; - self_module->page_cnt ++; - - RT_ASSERT(self_module->page_cnt <= PAGE_COUNT_MAX); - RT_DEBUG_LOG(RT_DEBUG_MODULE, ("rt_module_malloc_page 0x%x %d\n", - chunk, npages)); - - return chunk; -} - -/* - * This function will release the previously allocated memory page - * by rt_malloc_page. - * - * @param page_ptr the page address to be released. - * @param npages the number of page shall be released. - * - * @note this function is used for RT-Thread Application Module - */ -static void rt_module_free_page(rt_module_t module, - void *page_ptr, - rt_size_t npages) -{ - int i, index; - struct rt_page_info *page; - rt_module_t self_module; - - self_module = rt_module_self(); - RT_ASSERT(self_module != RT_NULL); - - RT_DEBUG_LOG(RT_DEBUG_MODULE, ("rt_module_free_page 0x%x %d\n", - page_ptr, npages)); - rt_page_free(page_ptr, npages); - - page = (struct rt_page_info *)module->page_array; - - for (i = 0; i < module->page_cnt; i ++) - { - if (page[i].page_ptr == page_ptr) - { - if (page[i].npage == npages + 1) - { - page[i].page_ptr += - npages * RT_MM_PAGE_SIZE / sizeof(rt_uint32_t); - page[i].npage -= npages; - } - else if (page[i].npage == npages) - { - for (index = i; index < module->page_cnt - 1; index ++) - { - page[index].page_ptr = page[index + 1].page_ptr; - page[index].npage = page[index + 1].npage; - } - page[module->page_cnt - 1].page_ptr = RT_NULL; - page[module->page_cnt - 1].npage = 0; - - module->page_cnt --; - } - else - RT_ASSERT(RT_FALSE); - self_module->page_cnt --; - - return; - } - } - - /* should not get here */ - RT_ASSERT(RT_FALSE); -} - -/** - * rt_module_malloc - allocate memory block in free list - */ -void *rt_module_malloc(rt_size_t size) -{ - struct rt_mem_head *b, *n, *up; - struct rt_mem_head **prev; - rt_uint32_t npage; - rt_size_t nunits; - rt_module_t self_module; - - self_module = rt_module_self(); - RT_ASSERT(self_module != RT_NULL); - - RT_DEBUG_NOT_IN_INTERRUPT; - - nunits = (size + sizeof(struct rt_mem_head) - 1) / - sizeof(struct rt_mem_head) - + 1; - - RT_ASSERT(size != 0); - RT_ASSERT(nunits != 0); - - rt_sem_take(&mod_sem, RT_WAITING_FOREVER); - - for (prev = (struct rt_mem_head **)&self_module->mem_list; - (b = *prev) != RT_NULL; - prev = &(b->next)) - { - if (b->size > nunits) - { - /* split memory */ - n = b + nunits; - n->next = b->next; - n->size = b->size - nunits; - b->size = nunits; - *prev = n; - - RT_DEBUG_LOG(RT_DEBUG_MODULE, ("rt_module_malloc 0x%x, %d\n", - b + 1, size)); - rt_sem_release(&mod_sem); - - return (void *)(b + 1); - } - - if (b->size == nunits) - { - /* this node fit, remove this node */ - *prev = b->next; - - RT_DEBUG_LOG(RT_DEBUG_MODULE, ("rt_module_malloc 0x%x, %d\n", - b + 1, size)); - - rt_sem_release(&mod_sem); - - return (void *)(b + 1); - } - } - - /* allocate pages from system heap */ - npage = (size + sizeof(struct rt_mem_head) + RT_MM_PAGE_SIZE - 1) / - RT_MM_PAGE_SIZE; - if ((up = (struct rt_mem_head *)rt_module_malloc_page(npage)) == RT_NULL) - return RT_NULL; - - up->size = npage * RT_MM_PAGE_SIZE / sizeof(struct rt_mem_head); - - for (prev = (struct rt_mem_head **)&self_module->mem_list; - (b = *prev) != RT_NULL; - prev = &(b->next)) - { - if (b > up + up->size) - break; - } - - up->next = b; - *prev = up; - - rt_sem_release(&mod_sem); - - return rt_module_malloc(size); -} - -/** - * rt_module_free - free memory block in free list - */ -void rt_module_free(rt_module_t module, void *addr) -{ - struct rt_mem_head *b, *n, *r; - struct rt_mem_head **prev; - - RT_DEBUG_NOT_IN_INTERRUPT; - - RT_ASSERT(addr); - RT_ASSERT((((rt_uint32_t)addr) & (sizeof(struct rt_mem_head) - 1)) == 0); - - RT_DEBUG_LOG(RT_DEBUG_MODULE, ("rt_module_free 0x%x\n", addr)); - - rt_sem_take(&mod_sem, RT_WAITING_FOREVER); - - n = (struct rt_mem_head *)addr - 1; - prev = (struct rt_mem_head **)&module->mem_list; - - while ((b = *prev) != RT_NULL) - { - RT_ASSERT(b->size > 0); - RT_ASSERT(b > n || b + b->size <= n); - - if (b + b->size == n && ((rt_uint32_t)n % RT_MM_PAGE_SIZE != 0)) - { - if (b + (b->size + n->size) == b->next) - { - b->size += b->next->size + n->size; - b->next = b->next->next; - } - else - b->size += n->size; - - if ((rt_uint32_t)b % RT_MM_PAGE_SIZE == 0) - { - int npage = - b->size * sizeof(struct rt_page_info) / RT_MM_PAGE_SIZE; - if (npage > 0) - { - if ((b->size * sizeof(struct rt_page_info) % RT_MM_PAGE_SIZE) != 0) - { - rt_size_t nunits = npage * - RT_MM_PAGE_SIZE / - sizeof(struct rt_mem_head); - /* split memory */ - r = b + nunits; - r->next = b->next; - r->size = b->size - nunits; - *prev = r; - } - else - { - *prev = b->next; - } - - rt_module_free_page(module, b, npage); - } - } - - /* unlock */ - rt_sem_release(&mod_sem); - - return; - } - - if (b == n + n->size) - { - n->size = b->size + n->size; - n->next = b->next; - - if ((rt_uint32_t)n % RT_MM_PAGE_SIZE == 0) - { - int npage = - n->size * sizeof(struct rt_page_info) / RT_MM_PAGE_SIZE; - if (npage > 0) - { - if ((n->size * sizeof(struct rt_page_info) % RT_MM_PAGE_SIZE) != 0) - { - rt_size_t nunits = npage * - RT_MM_PAGE_SIZE / - sizeof(struct rt_mem_head); - /* split memory */ - r = n + nunits; - r->next = n->next; - r->size = n->size - nunits; - *prev = r; - } - else - *prev = n->next; - - rt_module_free_page(module, n, npage); - } - } - else - { - *prev = n; - } - - /* unlock */ - rt_sem_release(&mod_sem); - - return; - } - if (b > n + n->size) - break; - - prev = &(b->next); - } - - if ((rt_uint32_t)n % RT_MM_PAGE_SIZE == 0) - { - int npage = n->size * sizeof(struct rt_page_info) / RT_MM_PAGE_SIZE; - if (npage > 0) - { - rt_module_free_page(module, n, npage); - if (n->size % RT_MM_PAGE_SIZE != 0) - { - rt_size_t nunits = - npage * RT_MM_PAGE_SIZE / sizeof(struct rt_mem_head); - /* split memory */ - r = n + nunits; - r->next = b; - r->size = n->size - nunits; - *prev = r; - } - else - { - *prev = b; - } - } - } - else - { - n->next = b; - *prev = n; - } - - /* unlock */ - rt_sem_release(&mod_sem); -} - -/** - * rt_module_realloc - realloc memory block in free list - */ -void *rt_module_realloc(void *ptr, rt_size_t size) -{ - struct rt_mem_head *b, *p, *prev, *tmpp; - rt_size_t nunits; - rt_module_t self_module; - - self_module = rt_module_self(); - RT_ASSERT(self_module != RT_NULL); - - RT_DEBUG_NOT_IN_INTERRUPT; - - if (!ptr) - return rt_module_malloc(size); - if (size == 0) - { - rt_module_free(self_module, ptr); - - return RT_NULL; - } - - nunits = (size + sizeof(struct rt_mem_head) - 1) / - sizeof(struct rt_mem_head) - + 1; - b = (struct rt_mem_head *)ptr - 1; - - if (nunits <= b->size) - { - /* new size is smaller or equal then before */ - if (nunits == b->size) - return ptr; - else - { - p = b + nunits; - p->size = b->size - nunits; - b->size = nunits; - rt_module_free(self_module, (void *)(p + 1)); - - return (void *)(b + 1); - } - } - else - { - /* more space then required */ - prev = (struct rt_mem_head *)self_module->mem_list; - for (p = prev->next; - p != (b->size + b) && p != RT_NULL; - prev = p, p = p->next) - { - break; - } - - /* available block after ap in freelist */ - if (p != RT_NULL && - (p->size >= (nunits - (b->size))) && - p == (b + b->size)) - { - /* perfect match */ - if (p->size == (nunits - (b->size))) - { - b->size = nunits; - prev->next = p->next; - } - else /* more space then required, split block */ - { - /* pointer to old header */ - tmpp = p; - p = b + nunits; - - /* restoring old pointer */ - p->next = tmpp->next; - - /* new size for p */ - p->size = tmpp->size + b->size - nunits; - b->size = nunits; - prev->next = p; - } - self_module->mem_list = (void *)prev; - - return (void *)(b + 1); - } - else /* allocate new memory and copy old data */ - { - if ((p = rt_module_malloc(size)) == RT_NULL) - return RT_NULL; - rt_memmove(p, (b + 1), ((b->size) * sizeof(struct rt_mem_head))); - rt_module_free(self_module, (void *)(b + 1)); - - return (void *)(p); - } - } -} - -#ifdef RT_USING_FINSH -#include - -void list_memlist(const char *name) -{ - rt_module_t module; - struct rt_mem_head **prev; - struct rt_mem_head *b; - - module = rt_module_find(name); - if (module == RT_NULL) - return; - - for (prev = (struct rt_mem_head **)&module->mem_list; - (b = *prev) != RT_NULL; - prev = &(b->next)) - { - rt_kprintf("0x%x--%d\n", b, b->size * sizeof(struct rt_mem_head)); - } -} -FINSH_FUNCTION_EXPORT(list_memlist, list module free memory information) - -void list_mempage(const char *name) -{ - rt_module_t module; - struct rt_page_info *page; - int i; - - module = rt_module_find(name); - if (module == RT_NULL) - return; - - page = (struct rt_page_info *)module->page_array; - - for (i = 0; i < module->page_cnt; i ++) - { - rt_kprintf("0x%x--%d\n", page[i].page_ptr, page[i].npage); - } -} -FINSH_FUNCTION_EXPORT(list_mempage, list module using memory page information) -#endif /* RT_USING_FINSH */ - -#endif /* RT_USING_SLAB */ - #endif diff --git a/src/object.c b/src/object.c index 14d5f1cf3b41286264a5ab3ce78ed747de0c2668..958161e3203aa97fc6ba07d1f49e902b563417da 100644 --- a/src/object.c +++ b/src/object.c @@ -252,15 +252,9 @@ void rt_object_init(struct rt_object *object, register rt_base_t temp; struct rt_object_information *information; -#ifdef RT_USING_MODULE - /* get module object information */ - information = (rt_module_self() != RT_NULL) ? - &rt_module_self()->module_object[type] : rt_object_get_information(type); -#else /* get object information */ information = rt_object_get_information(type); RT_ASSERT(information != RT_NULL); -#endif /* initialize object's parameters */ @@ -324,18 +318,9 @@ rt_object_t rt_object_allocate(enum rt_object_class_type type, const char *name) RT_DEBUG_NOT_IN_INTERRUPT; -#ifdef RT_USING_MODULE - /* - * get module object information, - * module object should be managed by kernel object container - */ - information = (rt_module_self() != RT_NULL && (type != RT_Object_Class_Module)) ? - &rt_module_self()->module_object[type] : rt_object_get_information(type); -#else /* get object information */ information = rt_object_get_information(type); RT_ASSERT(information != RT_NULL); -#endif object = (struct rt_object *)RT_KERNEL_MALLOC(information->object_size); if (object == RT_NULL) @@ -402,14 +387,8 @@ void rt_object_delete(rt_object_t object) /* unlock interrupt */ rt_hw_interrupt_enable(temp); -#if defined(RT_USING_MODULE) && defined(RT_USING_SLAB) - if (object->flag & RT_OBJECT_FLAG_MODULE) - rt_module_free((rt_module_t)object->module_id, object); - else -#endif - - /* free the memory of object */ - RT_KERNEL_FREE(object); + /* free the memory of object */ + RT_KERNEL_FREE(object); } #endif @@ -458,65 +437,6 @@ rt_object_t rt_object_find(const char *name, rt_uint8_t type) /* which is invoke in interrupt status */ RT_DEBUG_NOT_IN_INTERRUPT; -#ifdef RT_USING_MODULE - /* check whether to find a object inside a module. */ - { - const char *name_ptr; - int module_name_length; - - name_ptr = name; - while ((*name_ptr != '\0') && (*name_ptr != '/')) - name_ptr ++; - - if (*name_ptr == '/') - { - struct rt_module *module = RT_NULL; - - /* get the name length of module */ - module_name_length = name_ptr - name; - - /* enter critical */ - rt_enter_critical(); - - /* find module */ - information = rt_object_get_information(RT_Object_Class_Module); - RT_ASSERT(information != RT_NULL); - - for (node = information->object_list.next; - node != &(information->object_list); - node = node->next) - { - object = rt_list_entry(node, struct rt_object, list); - if ((rt_strncmp(object->name, name, module_name_length) == 0) && - (module_name_length == RT_NAME_MAX || object->name[module_name_length] == '\0')) - { - /* get module */ - module = (struct rt_module *)object; - break; - } - } - rt_exit_critical(); - - /* there is no this module inside the system */ - if (module == RT_NULL) return RT_NULL; - - /* get the object pool of module */ - information = &(module->module_object[type]); - - /* get object name */ - while ((*name_ptr == '/') && (*name_ptr != '\0')) name_ptr ++; - if (*name_ptr == '\0') - { - if (type == RT_Object_Class_Module) return object; - return RT_NULL; - } - - /* point to the object name */ - name = name_ptr; - } - } -#endif - /* enter critical */ rt_enter_critical(); diff --git a/src/slab.c b/src/slab.c index 5e6a204896015516bc7613e7151c7937b5da486b..16c68a24085a1bd757cc351345500008a3e800ed 100644 --- a/src/slab.c +++ b/src/slab.c @@ -496,11 +496,6 @@ void *rt_malloc(rt_size_t size) if (size == 0) return RT_NULL; -#ifdef RT_USING_MODULE - if (rt_module_self() != RT_NULL) - return rt_module_malloc(size); -#endif - /* * Handle large allocations directly. There should not be very many of * these so performance is not a big issue. @@ -705,11 +700,6 @@ void *rt_realloc(void *ptr, rt_size_t size) return RT_NULL; } -#ifdef RT_USING_MODULE - if (rt_module_self() != RT_NULL) - return rt_module_realloc(ptr, size); -#endif - /* * Get the original allocation's zone. If the new request winds up * using the same chunk size we do not have to do anything. @@ -800,15 +790,6 @@ void rt_free(void *ptr) RT_OBJECT_HOOK_CALL(rt_free_hook, (ptr)); -#ifdef RT_USING_MODULE - if (rt_module_self() != RT_NULL) - { - rt_module_free(rt_module_self(), ptr); - - return; - } -#endif - /* get memory usage */ #if RT_DEBUG_SLAB {