commit
b110d77d8f
@ -5,8 +5,8 @@
|
|||||||
#include <rtthread.h>
|
#include <rtthread.h>
|
||||||
#include "drv_clcd.h"
|
#include "drv_clcd.h"
|
||||||
|
|
||||||
#define CLCD_WIDTH 480
|
#define CLCD_WIDTH 640
|
||||||
#define CLCD_HEIGHT 320
|
#define CLCD_HEIGHT 480
|
||||||
|
|
||||||
#define CLCD_DEVICE(dev) (struct drv_clcd_device*)(dev)
|
#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;
|
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)
|
int drv_clcd_hw_init(void)
|
||||||
{
|
{
|
||||||
PL111MMIO *plio;
|
PL111MMIO *plio;
|
||||||
@ -107,8 +119,13 @@ int drv_clcd_hw_init(void)
|
|||||||
plio->control = 0x1921 | (0x6 << 1);
|
plio->control = 0x1921 | (0x6 << 1);
|
||||||
|
|
||||||
device->type = RT_Device_Class_Graphic;
|
device->type = RT_Device_Class_Graphic;
|
||||||
|
#ifdef RT_USING_DEVICE_OPS
|
||||||
|
device->ops = &clcd_ops;
|
||||||
|
#else
|
||||||
device->init = drv_clcd_init;
|
device->init = drv_clcd_init;
|
||||||
device->control = drv_clcd_control;
|
device->control = drv_clcd_control;
|
||||||
|
#endif
|
||||||
|
|
||||||
rt_device_register(device, "lcd", RT_DEVICE_FLAG_RDWR);
|
rt_device_register(device, "lcd", RT_DEVICE_FLAG_RDWR);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -485,6 +485,18 @@ struct pbuf *smc911x_emac_rx(rt_device_t dev)
|
|||||||
return p;
|
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)
|
int smc911x_emac_hw_init(void)
|
||||||
{
|
{
|
||||||
_emac.iobase = VEXPRESS_ETH_BASE;
|
_emac.iobase = VEXPRESS_ETH_BASE;
|
||||||
@ -507,12 +519,16 @@ int smc911x_emac_hw_init(void)
|
|||||||
_emac.enetaddr[4] = 0x22;
|
_emac.enetaddr[4] = 0x22;
|
||||||
_emac.enetaddr[5] = 0x33;
|
_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.init = smc911x_emac_init;
|
||||||
_emac.parent.parent.open = RT_NULL;
|
_emac.parent.parent.open = RT_NULL;
|
||||||
_emac.parent.parent.close = RT_NULL;
|
_emac.parent.parent.close = RT_NULL;
|
||||||
_emac.parent.parent.read = RT_NULL;
|
_emac.parent.parent.read = RT_NULL;
|
||||||
_emac.parent.parent.write = RT_NULL;
|
_emac.parent.parent.write = RT_NULL;
|
||||||
_emac.parent.parent.control = smc911x_emac_control;
|
_emac.parent.parent.control = smc911x_emac_control;
|
||||||
|
#endif
|
||||||
_emac.parent.parent.user_data = RT_NULL;
|
_emac.parent.parent.user_data = RT_NULL;
|
||||||
_emac.parent.eth_rx = smc911x_emac_rx;
|
_emac.parent.eth_rx = smc911x_emac_rx;
|
||||||
_emac.parent.eth_tx = smc911x_emac_tx;
|
_emac.parent.eth_tx = smc911x_emac_tx;
|
||||||
@ -540,12 +556,3 @@ int smc911x_emac_hw_init(void)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
INIT_APP_EXPORT(smc911x_emac_hw_init);
|
INIT_APP_EXPORT(smc911x_emac_hw_init);
|
||||||
|
|
||||||
#include <finsh.h>
|
|
||||||
int emac(int argc, char** argv)
|
|
||||||
{
|
|
||||||
rt_hw_interrupt_umask(_emac.irqno);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
MSH_CMD_EXPORT(emac, emac dump);
|
|
||||||
|
@ -15,6 +15,11 @@ config $PKGS_DIR
|
|||||||
option env="PKGS_ROOT"
|
option env="PKGS_ROOT"
|
||||||
default "packages"
|
default "packages"
|
||||||
|
|
||||||
|
config BOARD_STM32F411_NUCLEO
|
||||||
|
bool
|
||||||
|
select ARCH_ARM_CORTEX_M4
|
||||||
|
default y
|
||||||
|
|
||||||
source "$RTT_DIR/Kconfig"
|
source "$RTT_DIR/Kconfig"
|
||||||
source "$PKGS_DIR/Kconfig"
|
source "$PKGS_DIR/Kconfig"
|
||||||
|
|
||||||
|
@ -93,15 +93,6 @@ void UsageFault_Handler(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief This function handles SVCall exception.
|
|
||||||
* @param None
|
|
||||||
* @retval None
|
|
||||||
*/
|
|
||||||
void SVC_Handler(void)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @}
|
* @}
|
||||||
*/
|
*/
|
||||||
|
@ -39,6 +39,12 @@ SECTIONS
|
|||||||
__vsymtab_end = .;
|
__vsymtab_end = .;
|
||||||
. = ALIGN(4);
|
. = ALIGN(4);
|
||||||
|
|
||||||
|
/* section information for modules */
|
||||||
|
. = ALIGN(4);
|
||||||
|
__rtmsymtab_start = .;
|
||||||
|
KEEP(*(RTMSymTab))
|
||||||
|
__rtmsymtab_end = .;
|
||||||
|
|
||||||
/* section information for initial. */
|
/* section information for initial. */
|
||||||
. = ALIGN(4);
|
. = ALIGN(4);
|
||||||
__rt_init_start = .;
|
__rt_init_start = .;
|
||||||
|
@ -26,6 +26,8 @@ source "$RTT_DIR/components/drivers/Kconfig"
|
|||||||
|
|
||||||
source "$RTT_DIR/components/libc/Kconfig"
|
source "$RTT_DIR/components/libc/Kconfig"
|
||||||
|
|
||||||
|
source "$RTT_DIR/components/lwp/Kconfig"
|
||||||
|
|
||||||
source "$RTT_DIR/components/net/Kconfig"
|
source "$RTT_DIR/components/net/Kconfig"
|
||||||
|
|
||||||
source "$RTT_DIR/components/vbus/Kconfig"
|
source "$RTT_DIR/components/vbus/Kconfig"
|
||||||
|
@ -95,6 +95,12 @@ struct dirent
|
|||||||
char d_name[DFS_PATH_MAX]; /* The null-terminated file name */
|
char d_name[DFS_PATH_MAX]; /* The null-terminated file name */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct dfs_fdtable
|
||||||
|
{
|
||||||
|
uint32_t maxfd;
|
||||||
|
struct dfs_fd **fds;
|
||||||
|
};
|
||||||
|
|
||||||
/* Initialization of dfs */
|
/* Initialization of dfs */
|
||||||
int dfs_init(void);
|
int dfs_init(void);
|
||||||
|
|
||||||
@ -110,6 +116,8 @@ struct dfs_fd *fd_get(int fd);
|
|||||||
void fd_put(struct dfs_fd *fd);
|
void fd_put(struct dfs_fd *fd);
|
||||||
int fd_is_open(const char *pathname);
|
int fd_is_open(const char *pathname);
|
||||||
|
|
||||||
|
struct dfs_fdtable* dfs_fdtable_get(void);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -21,12 +21,16 @@
|
|||||||
* Date Author Notes
|
* Date Author Notes
|
||||||
* 2005-02-22 Bernard The first version.
|
* 2005-02-22 Bernard The first version.
|
||||||
* 2017-12-11 Bernard Use rt_free to instead of free in fd_is_open().
|
* 2017-12-11 Bernard Use rt_free to instead of free in fd_is_open().
|
||||||
|
* 2018-03-20 Heyuanjie dynamic allocation FD
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <dfs.h>
|
#include <dfs.h>
|
||||||
#include <dfs_fs.h>
|
#include <dfs_fs.h>
|
||||||
#include <dfs_file.h>
|
#include <dfs_file.h>
|
||||||
#include "dfs_private.h"
|
#include "dfs_private.h"
|
||||||
|
#ifdef RT_USING_LWP
|
||||||
|
#include <lwp.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Global variables */
|
/* Global variables */
|
||||||
const struct dfs_filesystem_ops *filesystem_operation_table[DFS_FILESYSTEM_TYPES_MAX];
|
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] = {"/"};
|
char working_directory[DFS_PATH_MAX] = {"/"};
|
||||||
#endif
|
#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
|
* @addtogroup DFS
|
||||||
@ -57,7 +62,7 @@ int dfs_init(void)
|
|||||||
/* clear filesystem table */
|
/* clear filesystem table */
|
||||||
memset(filesystem_table, 0, sizeof(filesystem_table));
|
memset(filesystem_table, 0, sizeof(filesystem_table));
|
||||||
/* clean fd table */
|
/* clean fd table */
|
||||||
memset(fd_table, 0, sizeof(fd_table));
|
memset(&_fdtab, 0, sizeof(_fdtab));
|
||||||
|
|
||||||
/* create device filesystem lock */
|
/* create device filesystem lock */
|
||||||
rt_mutex_init(&fslock, "fslock", RT_IPC_FLAG_FIFO);
|
rt_mutex_init(&fslock, "fslock", RT_IPC_FLAG_FIFO);
|
||||||
@ -90,9 +95,13 @@ INIT_PREV_EXPORT(dfs_init);
|
|||||||
*/
|
*/
|
||||||
void dfs_lock(void)
|
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)
|
if (result != RT_EOK)
|
||||||
{
|
{
|
||||||
RT_ASSERT(0);
|
RT_ASSERT(0);
|
||||||
@ -109,6 +118,54 @@ void dfs_unlock(void)
|
|||||||
rt_mutex_release(&fslock);
|
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
|
* @ingroup Fd
|
||||||
* This function will allocate a file descriptor.
|
* This function will allocate a file descriptor.
|
||||||
@ -119,21 +176,23 @@ int fd_new(void)
|
|||||||
{
|
{
|
||||||
struct dfs_fd *d;
|
struct dfs_fd *d;
|
||||||
int idx;
|
int idx;
|
||||||
|
struct dfs_fdtable *fdt;
|
||||||
|
|
||||||
|
fdt = dfs_fdtable_get();
|
||||||
/* lock filesystem */
|
/* lock filesystem */
|
||||||
dfs_lock();
|
dfs_lock();
|
||||||
|
|
||||||
/* find an empty fd entry */
|
/* 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 */
|
/* can't find an empty fd entry */
|
||||||
if (idx == DFS_FD_MAX)
|
if (idx == fdt->maxfd)
|
||||||
{
|
{
|
||||||
idx = -(1 + DFS_FD_OFFSET);
|
idx = -(1 + DFS_FD_OFFSET);
|
||||||
goto __result;
|
goto __result;
|
||||||
}
|
}
|
||||||
|
|
||||||
d = &(fd_table[idx]);
|
d = fdt->fds[idx];
|
||||||
d->ref_count = 1;
|
d->ref_count = 1;
|
||||||
d->magic = DFS_FD_MAGIC;
|
d->magic = DFS_FD_MAGIC;
|
||||||
|
|
||||||
@ -154,13 +213,15 @@ __result:
|
|||||||
struct dfs_fd *fd_get(int fd)
|
struct dfs_fd *fd_get(int fd)
|
||||||
{
|
{
|
||||||
struct dfs_fd *d;
|
struct dfs_fd *d;
|
||||||
|
struct dfs_fdtable *fdt;
|
||||||
|
|
||||||
|
fdt = dfs_fdtable_get();
|
||||||
fd = fd - DFS_FD_OFFSET;
|
fd = fd - DFS_FD_OFFSET;
|
||||||
if (fd < 0 || fd >= DFS_FD_MAX)
|
if (fd < 0 || fd >= fdt->maxfd)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
dfs_lock();
|
dfs_lock();
|
||||||
d = &fd_table[fd];
|
d = fdt->fds[fd];
|
||||||
|
|
||||||
/* check dfs_fd valid or not */
|
/* check dfs_fd valid or not */
|
||||||
if (d->magic != DFS_FD_MAGIC)
|
if (d->magic != DFS_FD_MAGIC)
|
||||||
@ -186,12 +247,25 @@ void fd_put(struct dfs_fd *fd)
|
|||||||
RT_ASSERT(fd != NULL);
|
RT_ASSERT(fd != NULL);
|
||||||
|
|
||||||
dfs_lock();
|
dfs_lock();
|
||||||
|
|
||||||
fd->ref_count --;
|
fd->ref_count --;
|
||||||
|
|
||||||
/* clear this fd entry */
|
/* clear this fd entry */
|
||||||
if (fd->ref_count == 0)
|
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();
|
dfs_unlock();
|
||||||
}
|
}
|
||||||
@ -211,7 +285,9 @@ int fd_is_open(const char *pathname)
|
|||||||
unsigned int index;
|
unsigned int index;
|
||||||
struct dfs_filesystem *fs;
|
struct dfs_filesystem *fs;
|
||||||
struct dfs_fd *fd;
|
struct dfs_fd *fd;
|
||||||
|
struct dfs_fdtable *fdt;
|
||||||
|
|
||||||
|
fdt = dfs_fdtable_get();
|
||||||
fullpath = dfs_normalize_path(NULL, pathname);
|
fullpath = dfs_normalize_path(NULL, pathname);
|
||||||
if (fullpath != NULL)
|
if (fullpath != NULL)
|
||||||
{
|
{
|
||||||
@ -233,11 +309,10 @@ int fd_is_open(const char *pathname)
|
|||||||
|
|
||||||
dfs_lock();
|
dfs_lock();
|
||||||
|
|
||||||
for (index = 0; index < DFS_FD_MAX; index++)
|
for (index = 0; index < fdt->maxfd; index++)
|
||||||
{
|
{
|
||||||
fd = &(fd_table[index]);
|
fd = fdt->fds[index];
|
||||||
if (fd->fops == NULL)
|
if (fd == NULL) continue;
|
||||||
continue;
|
|
||||||
|
|
||||||
if (fd->fops == fs->ops->fops && strcmp(fd->path, mountpath) == 0)
|
if (fd->fops == fs->ops->fops && strcmp(fd->path, mountpath) == 0)
|
||||||
{
|
{
|
||||||
@ -414,17 +489,43 @@ up_one:
|
|||||||
return fullpath;
|
return fullpath;
|
||||||
}
|
}
|
||||||
RTM_EXPORT(dfs_normalize_path);
|
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
|
#ifdef RT_USING_FINSH
|
||||||
#include <finsh.h>
|
#include <finsh.h>
|
||||||
int list_fd(void)
|
int list_fd(void)
|
||||||
{
|
{
|
||||||
int index;
|
int index;
|
||||||
|
struct dfs_fdtable *fd_table;
|
||||||
|
|
||||||
|
fd_table = dfs_fdtable_get();
|
||||||
|
if (!fd_table) return -1;
|
||||||
|
|
||||||
rt_enter_critical();
|
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)
|
if (fd->fops)
|
||||||
{
|
{
|
||||||
|
@ -421,6 +421,18 @@ static rt_err_t _audio_dev_control(struct rt_device *dev, int cmd, void *args)
|
|||||||
return result;
|
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)
|
rt_err_t rt_audio_register(struct rt_audio_device *audio, const char *name, rt_uint32_t flag, void *data)
|
||||||
{
|
{
|
||||||
struct rt_device *device;
|
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->rx_indicate = RT_NULL;
|
||||||
device->tx_complete = RT_NULL;
|
device->tx_complete = RT_NULL;
|
||||||
|
|
||||||
device->init = _audio_dev_init;
|
#ifdef RT_USING_DEVICE_OPS
|
||||||
device->open = _audio_dev_open;
|
device->ops = &audio_ops;
|
||||||
device->close = _audio_dev_close;
|
#else
|
||||||
device->read = _audio_dev_read;
|
device->init = _audio_dev_init;
|
||||||
device->write = _audio_dev_write;
|
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;
|
device->control = _audio_dev_control;
|
||||||
|
#endif
|
||||||
device->user_data = data;
|
device->user_data = data;
|
||||||
|
|
||||||
//init memory pool for replay
|
//init memory pool for replay
|
||||||
|
@ -201,6 +201,18 @@ static rt_err_t rt_pipe_control(rt_device_t dev, int cmd, void *args)
|
|||||||
return RT_EOK;
|
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
|
* This function will initialize a pipe device and put it under control of
|
||||||
* resource management.
|
* resource management.
|
||||||
@ -233,12 +245,16 @@ rt_err_t rt_audio_pipe_init(struct rt_audio_pipe *pipe,
|
|||||||
|
|
||||||
/* create pipe */
|
/* create pipe */
|
||||||
pipe->parent.type = RT_Device_Class_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.init = RT_NULL;
|
||||||
pipe->parent.open = RT_NULL;
|
pipe->parent.open = RT_NULL;
|
||||||
pipe->parent.close = RT_NULL;
|
pipe->parent.close = RT_NULL;
|
||||||
pipe->parent.read = rt_pipe_read;
|
pipe->parent.read = rt_pipe_read;
|
||||||
pipe->parent.write = rt_pipe_write;
|
pipe->parent.write = rt_pipe_write;
|
||||||
pipe->parent.control = rt_pipe_control;
|
pipe->parent.control = rt_pipe_control;
|
||||||
|
#endif
|
||||||
|
|
||||||
return rt_device_register(&(pipe->parent), name, RT_DEVICE_FLAG_RDWR);
|
return rt_device_register(&(pipe->parent), name, RT_DEVICE_FLAG_RDWR);
|
||||||
}
|
}
|
||||||
|
@ -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
|
* can register
|
||||||
*/
|
*/
|
||||||
@ -712,12 +724,17 @@ rt_err_t rt_hw_can_register(struct rt_can_device *can,
|
|||||||
#ifdef RT_CAN_USING_BUS_HOOK
|
#ifdef RT_CAN_USING_BUS_HOOK
|
||||||
can->bus_hook = RT_NULL;
|
can->bus_hook = RT_NULL;
|
||||||
#endif /*RT_CAN_USING_BUS_HOOK*/
|
#endif /*RT_CAN_USING_BUS_HOOK*/
|
||||||
|
|
||||||
|
#ifdef RT_USING_DEVICE_OPS
|
||||||
|
device->ops = &can_device_ops;
|
||||||
|
#else
|
||||||
device->init = rt_can_init;
|
device->init = rt_can_init;
|
||||||
device->open = rt_can_open;
|
device->open = rt_can_open;
|
||||||
device->close = rt_can_close;
|
device->close = rt_can_close;
|
||||||
device->read = rt_can_read;
|
device->read = rt_can_read;
|
||||||
device->write = rt_can_write;
|
device->write = rt_can_write;
|
||||||
device->control = rt_can_control;
|
device->control = rt_can_control;
|
||||||
|
#endif
|
||||||
can->ops = ops;
|
can->ops = ops;
|
||||||
|
|
||||||
can->status_indicate.ind = RT_NULL;
|
can->status_indicate.ind = RT_NULL;
|
||||||
|
@ -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_min = 1;
|
||||||
float devi;
|
float devi;
|
||||||
|
|
||||||
/* 把定时器溢出时间和定时时间换算成秒 */
|
/* changed to second */
|
||||||
overflow = timer->info->maxcnt/(float)timer->freq;
|
overflow = timer->info->maxcnt/(float)timer->freq;
|
||||||
tv_sec = tv->sec + tv->usec/(float)1000000;
|
tv_sec = tv->sec + tv->usec/(float)1000000;
|
||||||
|
|
||||||
if (tv_sec < (1/(float)timer->freq))
|
if (tv_sec < (1/(float)timer->freq))
|
||||||
{
|
{
|
||||||
/* 定时时间小于计数周期 */
|
/* little timeout */
|
||||||
i = 0;
|
i = 0;
|
||||||
timeout = 1/(float)timer->freq;
|
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;
|
counter = timeout*timer->freq;
|
||||||
devi = tv_sec - (counter/(float)timer->freq)*i;
|
devi = tv_sec - (counter/(float)timer->freq)*i;
|
||||||
/* 计算最小误差 */
|
/* Minimum calculation error */
|
||||||
if (devi > devi_min)
|
if (devi > devi_min)
|
||||||
{
|
{
|
||||||
i = index;
|
i = index;
|
||||||
@ -89,7 +89,7 @@ static rt_err_t rt_hwtimer_init(struct rt_device *dev)
|
|||||||
rt_hwtimer_t *timer;
|
rt_hwtimer_t *timer;
|
||||||
|
|
||||||
timer = (rt_hwtimer_t *)dev;
|
timer = (rt_hwtimer_t *)dev;
|
||||||
/* 尝试将默认计数频率设为1Mhz */
|
/* try to change to 1MHz */
|
||||||
if ((1000000 <= timer->info->maxfreq) && (1000000 >= timer->info->minfreq))
|
if ((1000000 <= timer->info->maxfreq) && (1000000 >= timer->info->minfreq))
|
||||||
{
|
{
|
||||||
timer->freq = 1000000;
|
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)
|
rt_err_t rt_device_hwtimer_register(rt_hwtimer_t *timer, const char *name, void *user_data)
|
||||||
{
|
{
|
||||||
struct rt_device *device;
|
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->rx_indicate = RT_NULL;
|
||||||
device->tx_complete = RT_NULL;
|
device->tx_complete = RT_NULL;
|
||||||
|
|
||||||
|
#ifdef RT_USING_DEVICE_OPS
|
||||||
|
device->ops = &hwtimer_ops;
|
||||||
|
#else
|
||||||
device->init = rt_hwtimer_init;
|
device->init = rt_hwtimer_init;
|
||||||
device->open = rt_hwtimer_open;
|
device->open = rt_hwtimer_open;
|
||||||
device->close = rt_hwtimer_close;
|
device->close = rt_hwtimer_close;
|
||||||
device->read = rt_hwtimer_read;
|
device->read = rt_hwtimer_read;
|
||||||
device->write = rt_hwtimer_write;
|
device->write = rt_hwtimer_write;
|
||||||
device->control = rt_hwtimer_control;
|
device->control = rt_hwtimer_control;
|
||||||
|
#endif
|
||||||
device->user_data = user_data;
|
device->user_data = user_data;
|
||||||
|
|
||||||
return rt_device_register(device, name, RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_STANDALONE);
|
return rt_device_register(device, name, RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_STANDALONE);
|
||||||
|
@ -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;
|
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)
|
rt_err_t fm24clxx_register(const char *fm_device_name, const char *i2c_bus, void *user_data)
|
||||||
{
|
{
|
||||||
static struct fm24clxx_device fm24clxx_drv;
|
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.bus = bus;
|
||||||
fm24clxx_drv.parent.type = RT_Device_Class_Block;
|
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.init = fm24clxx_init;
|
||||||
fm24clxx_drv.parent.open = fm24clxx_open;
|
fm24clxx_drv.parent.open = fm24clxx_open;
|
||||||
fm24clxx_drv.parent.close = fm24clxx_close;
|
fm24clxx_drv.parent.close = fm24clxx_close;
|
||||||
fm24clxx_drv.parent.read = fm24clxx_read;
|
fm24clxx_drv.parent.read = fm24clxx_read;
|
||||||
fm24clxx_drv.parent.write = fm24clxx_write;
|
fm24clxx_drv.parent.write = fm24clxx_write;
|
||||||
fm24clxx_drv.parent.control = fm24clxx_control;
|
fm24clxx_drv.parent.control = fm24clxx_control;
|
||||||
|
#endif
|
||||||
|
|
||||||
fm24clxx_drv.parent.user_data = user_data;
|
fm24clxx_drv.parent.user_data = user_data;
|
||||||
|
|
||||||
return rt_device_register(&fm24clxx_drv.parent, fm_device_name, RT_DEVICE_FLAG_RDWR);
|
return rt_device_register(&fm24clxx_drv.parent, fm_device_name, RT_DEVICE_FLAG_RDWR);
|
||||||
|
@ -102,6 +102,18 @@ static rt_err_t i2c_bus_device_control(rt_device_t dev,
|
|||||||
return RT_EOK;
|
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,
|
rt_err_t rt_i2c_bus_device_device_init(struct rt_i2c_bus_device *bus,
|
||||||
const char *name)
|
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 */
|
/* set device type */
|
||||||
device->type = RT_Device_Class_I2CBUS;
|
device->type = RT_Device_Class_I2CBUS;
|
||||||
/* initialize device interface */
|
/* initialize device interface */
|
||||||
|
#ifdef RT_USING_DEVICE_OPS
|
||||||
|
device->ops = &i2c_ops;
|
||||||
|
#else
|
||||||
device->init = RT_NULL;
|
device->init = RT_NULL;
|
||||||
device->open = RT_NULL;
|
device->open = RT_NULL;
|
||||||
device->close = RT_NULL;
|
device->close = RT_NULL;
|
||||||
device->read = i2c_bus_device_read;
|
device->read = i2c_bus_device_read;
|
||||||
device->write = i2c_bus_device_write;
|
device->write = i2c_bus_device_write;
|
||||||
device->control = i2c_bus_device_control;
|
device->control = i2c_bus_device_control;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* register to device manager */
|
/* register to device manager */
|
||||||
rt_device_register(device, name, RT_DEVICE_FLAG_RDWR);
|
rt_device_register(device, name, RT_DEVICE_FLAG_RDWR);
|
||||||
|
@ -76,18 +76,34 @@ static rt_err_t _pin_control(rt_device_t dev, int cmd, void *args)
|
|||||||
return 0;
|
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)
|
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.type = RT_Device_Class_Miscellaneous;
|
||||||
_hw_pin.parent.rx_indicate = RT_NULL;
|
_hw_pin.parent.rx_indicate = RT_NULL;
|
||||||
_hw_pin.parent.tx_complete = 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.init = RT_NULL;
|
||||||
_hw_pin.parent.open = RT_NULL;
|
_hw_pin.parent.open = RT_NULL;
|
||||||
_hw_pin.parent.close = RT_NULL;
|
_hw_pin.parent.close = RT_NULL;
|
||||||
_hw_pin.parent.read = _pin_read;
|
_hw_pin.parent.read = _pin_read;
|
||||||
_hw_pin.parent.write = _pin_write;
|
_hw_pin.parent.write = _pin_write;
|
||||||
_hw_pin.parent.control = _pin_control;
|
_hw_pin.parent.control = _pin_control;
|
||||||
|
#endif
|
||||||
|
|
||||||
_hw_pin.ops = ops;
|
_hw_pin.ops = ops;
|
||||||
_hw_pin.parent.user_data = user_data;
|
_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;
|
return RT_ENOSYS;
|
||||||
}
|
}
|
||||||
|
|
||||||
rt_err_t rt_pin_irq_enable(rt_base_t pin, rt_uint32_t enabled)
|
rt_err_t rt_pin_irq_enable(rt_base_t pin, rt_uint32_t enabled)
|
||||||
{
|
{
|
||||||
RT_ASSERT(_hw_pin.ops != RT_NULL);
|
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;
|
return RT_ENOSYS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* RT-Thread Hardware PIN APIs */
|
/* RT-Thread Hardware PIN APIs */
|
||||||
void rt_pin_mode(rt_base_t pin, rt_base_t mode)
|
void rt_pin_mode(rt_base_t pin, rt_base_t mode)
|
||||||
{
|
{
|
||||||
|
@ -69,6 +69,18 @@ static rt_err_t _mtd_control(rt_device_t dev, int cmd, void *args)
|
|||||||
return RT_EOK;
|
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,
|
rt_err_t rt_mtd_nand_register_device(const char *name,
|
||||||
struct rt_mtd_nand_device *device)
|
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 */
|
/* set device class and generic device interface */
|
||||||
dev->type = RT_Device_Class_MTD;
|
dev->type = RT_Device_Class_MTD;
|
||||||
|
#ifdef RT_USING_DEVICE_OPS
|
||||||
|
dev->ops = &mtd_nand_ops;
|
||||||
|
#else
|
||||||
dev->init = _mtd_init;
|
dev->init = _mtd_init;
|
||||||
dev->open = _mtd_open;
|
dev->open = _mtd_open;
|
||||||
dev->read = _mtd_read;
|
dev->read = _mtd_read;
|
||||||
dev->write = _mtd_write;
|
dev->write = _mtd_write;
|
||||||
dev->close = _mtd_close;
|
dev->close = _mtd_close;
|
||||||
dev->control = _mtd_control;
|
dev->control = _mtd_control;
|
||||||
|
#endif
|
||||||
|
|
||||||
dev->rx_indicate = RT_NULL;
|
dev->rx_indicate = RT_NULL;
|
||||||
dev->tx_complete = RT_NULL;
|
dev->tx_complete = RT_NULL;
|
||||||
|
@ -65,6 +65,18 @@ static rt_err_t _mtd_control(rt_device_t dev, int cmd, void *args)
|
|||||||
return RT_EOK;
|
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,
|
rt_err_t rt_mtd_nor_register_device(const char *name,
|
||||||
struct rt_mtd_nor_device *device)
|
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 */
|
/* set device class and generic device interface */
|
||||||
dev->type = RT_Device_Class_MTD;
|
dev->type = RT_Device_Class_MTD;
|
||||||
|
#ifdef RT_USING_DEVICE_OPS
|
||||||
|
dev->ops = &mtd_nor_ops;
|
||||||
|
#else
|
||||||
dev->init = _mtd_init;
|
dev->init = _mtd_init;
|
||||||
dev->open = _mtd_open;
|
dev->open = _mtd_open;
|
||||||
dev->read = _mtd_read;
|
dev->read = _mtd_read;
|
||||||
dev->write = _mtd_write;
|
dev->write = _mtd_write;
|
||||||
dev->close = _mtd_close;
|
dev->close = _mtd_close;
|
||||||
dev->control = _mtd_control;
|
dev->control = _mtd_control;
|
||||||
|
#endif
|
||||||
|
|
||||||
dev->rx_indicate = RT_NULL;
|
dev->rx_indicate = RT_NULL;
|
||||||
dev->tx_complete = RT_NULL;
|
dev->tx_complete = RT_NULL;
|
||||||
|
@ -68,6 +68,18 @@ static rt_err_t soft_rtc_control(rt_device_t dev, int cmd, void *args)
|
|||||||
return RT_EOK;
|
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)
|
int rt_soft_rtc_init(void)
|
||||||
{
|
{
|
||||||
static rt_bool_t init_ok = RT_FALSE;
|
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;
|
soft_rtc_dev.type = RT_Device_Class_RTC;
|
||||||
|
|
||||||
/* register rtc device */
|
/* 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.init = RT_NULL;
|
||||||
soft_rtc_dev.open = RT_NULL;
|
soft_rtc_dev.open = RT_NULL;
|
||||||
soft_rtc_dev.close = RT_NULL;
|
soft_rtc_dev.close = RT_NULL;
|
||||||
soft_rtc_dev.read = RT_NULL;
|
soft_rtc_dev.read = RT_NULL;
|
||||||
soft_rtc_dev.write = RT_NULL;
|
soft_rtc_dev.write = RT_NULL;
|
||||||
soft_rtc_dev.control = soft_rtc_control;
|
soft_rtc_dev.control = soft_rtc_control;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* no private */
|
/* no private */
|
||||||
soft_rtc_dev.user_data = RT_NULL;
|
soft_rtc_dev.user_data = RT_NULL;
|
||||||
|
@ -319,6 +319,18 @@ static rt_int32_t mmcsd_set_blksize(struct rt_mmcsd_card *card)
|
|||||||
return 0;
|
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 rt_mmcsd_blk_probe(struct rt_mmcsd_card *card)
|
||||||
{
|
{
|
||||||
rt_int32_t err = 0;
|
rt_int32_t err = 0;
|
||||||
@ -367,12 +379,16 @@ rt_int32_t rt_mmcsd_blk_probe(struct rt_mmcsd_card *card)
|
|||||||
|
|
||||||
/* register mmcsd device */
|
/* 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.init = rt_mmcsd_init;
|
||||||
blk_dev->dev.open = rt_mmcsd_open;
|
blk_dev->dev.open = rt_mmcsd_open;
|
||||||
blk_dev->dev.close = rt_mmcsd_close;
|
blk_dev->dev.close = rt_mmcsd_close;
|
||||||
blk_dev->dev.read = rt_mmcsd_read;
|
blk_dev->dev.read = rt_mmcsd_read;
|
||||||
blk_dev->dev.write = rt_mmcsd_write;
|
blk_dev->dev.write = rt_mmcsd_write;
|
||||||
blk_dev->dev.control = rt_mmcsd_control;
|
blk_dev->dev.control = rt_mmcsd_control;
|
||||||
|
#endif
|
||||||
blk_dev->dev.user_data = blk_dev;
|
blk_dev->dev.user_data = blk_dev;
|
||||||
|
|
||||||
blk_dev->card = card;
|
blk_dev->card = card;
|
||||||
@ -396,12 +412,16 @@ rt_int32_t rt_mmcsd_blk_probe(struct rt_mmcsd_card *card)
|
|||||||
|
|
||||||
/* register mmcsd device */
|
/* 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.init = rt_mmcsd_init;
|
||||||
blk_dev->dev.open = rt_mmcsd_open;
|
blk_dev->dev.open = rt_mmcsd_open;
|
||||||
blk_dev->dev.close = rt_mmcsd_close;
|
blk_dev->dev.close = rt_mmcsd_close;
|
||||||
blk_dev->dev.read = rt_mmcsd_read;
|
blk_dev->dev.read = rt_mmcsd_read;
|
||||||
blk_dev->dev.write = rt_mmcsd_write;
|
blk_dev->dev.write = rt_mmcsd_write;
|
||||||
blk_dev->dev.control = rt_mmcsd_control;
|
blk_dev->dev.control = rt_mmcsd_control;
|
||||||
|
#endif
|
||||||
blk_dev->dev.user_data = blk_dev;
|
blk_dev->dev.user_data = blk_dev;
|
||||||
|
|
||||||
blk_dev->card = card;
|
blk_dev->card = card;
|
||||||
@ -482,6 +502,3 @@ int rt_mmcsd_blk_init(void)
|
|||||||
/* nothing */
|
/* nothing */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
INIT_PREV_EXPORT(rt_mmcsd_blk_init);
|
|
||||||
|
|
||||||
|
@ -1072,6 +1072,18 @@ static rt_err_t rt_serial_control(struct rt_device *dev,
|
|||||||
return ret;
|
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
|
* serial register
|
||||||
*/
|
*/
|
||||||
@ -1090,12 +1102,16 @@ rt_err_t rt_hw_serial_register(struct rt_serial_device *serial,
|
|||||||
device->rx_indicate = RT_NULL;
|
device->rx_indicate = RT_NULL;
|
||||||
device->tx_complete = RT_NULL;
|
device->tx_complete = RT_NULL;
|
||||||
|
|
||||||
|
#ifdef RT_USING_DEVICE_OPS
|
||||||
|
device->ops = &serial_ops;
|
||||||
|
#else
|
||||||
device->init = rt_serial_init;
|
device->init = rt_serial_init;
|
||||||
device->open = rt_serial_open;
|
device->open = rt_serial_open;
|
||||||
device->close = rt_serial_close;
|
device->close = rt_serial_close;
|
||||||
device->read = rt_serial_read;
|
device->read = rt_serial_read;
|
||||||
device->write = rt_serial_write;
|
device->write = rt_serial_write;
|
||||||
device->control = rt_serial_control;
|
device->control = rt_serial_control;
|
||||||
|
#endif
|
||||||
device->user_data = data;
|
device->user_data = data;
|
||||||
|
|
||||||
/* register a character device */
|
/* register a character device */
|
||||||
|
@ -741,6 +741,18 @@ static struct pbuf *enc28j60_rx(rt_device_t dev)
|
|||||||
return p;
|
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)
|
rt_err_t enc28j60_attach(const char *spi_device_name)
|
||||||
{
|
{
|
||||||
struct rt_spi_device *spi_device;
|
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 */
|
/* init rt-thread device struct */
|
||||||
enc28j60_dev.parent.parent.type = RT_Device_Class_NetIf;
|
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.init = enc28j60_init;
|
||||||
enc28j60_dev.parent.parent.open = enc28j60_open;
|
enc28j60_dev.parent.parent.open = enc28j60_open;
|
||||||
enc28j60_dev.parent.parent.close = enc28j60_close;
|
enc28j60_dev.parent.parent.close = enc28j60_close;
|
||||||
enc28j60_dev.parent.parent.read = enc28j60_read;
|
enc28j60_dev.parent.parent.read = enc28j60_read;
|
||||||
enc28j60_dev.parent.parent.write = enc28j60_write;
|
enc28j60_dev.parent.parent.write = enc28j60_write;
|
||||||
enc28j60_dev.parent.parent.control = enc28j60_control;
|
enc28j60_dev.parent.parent.control = enc28j60_control;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* init rt-thread ethernet device struct */
|
/* init rt-thread ethernet device struct */
|
||||||
enc28j60_dev.parent.eth_rx = enc28j60_rx;
|
enc28j60_dev.parent.eth_rx = enc28j60_rx;
|
||||||
|
@ -69,6 +69,18 @@ static rt_err_t _spi_bus_device_control(rt_device_t dev,
|
|||||||
return RT_EOK;
|
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)
|
rt_err_t rt_spi_bus_device_init(struct rt_spi_bus *bus, const char *name)
|
||||||
{
|
{
|
||||||
struct rt_device *device;
|
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 */
|
/* set device type */
|
||||||
device->type = RT_Device_Class_SPIBUS;
|
device->type = RT_Device_Class_SPIBUS;
|
||||||
/* initialize device interface */
|
/* initialize device interface */
|
||||||
|
#ifdef RT_USING_DEVICE_OPS
|
||||||
|
device->ops = &spi_bus_ops;
|
||||||
|
#else
|
||||||
device->init = RT_NULL;
|
device->init = RT_NULL;
|
||||||
device->open = RT_NULL;
|
device->open = RT_NULL;
|
||||||
device->close = RT_NULL;
|
device->close = RT_NULL;
|
||||||
device->read = _spi_bus_device_read;
|
device->read = _spi_bus_device_read;
|
||||||
device->write = _spi_bus_device_write;
|
device->write = _spi_bus_device_write;
|
||||||
device->control = _spi_bus_device_control;
|
device->control = _spi_bus_device_control;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* register to device manager */
|
/* register to device manager */
|
||||||
return rt_device_register(device, name, RT_DEVICE_FLAG_RDWR);
|
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;
|
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)
|
rt_err_t rt_spidev_device_init(struct rt_spi_device *dev, const char *name)
|
||||||
{
|
{
|
||||||
struct rt_device *device;
|
struct rt_device *device;
|
||||||
@ -143,12 +171,16 @@ rt_err_t rt_spidev_device_init(struct rt_spi_device *dev, const char *name)
|
|||||||
|
|
||||||
/* set device type */
|
/* set device type */
|
||||||
device->type = RT_Device_Class_SPIDevice;
|
device->type = RT_Device_Class_SPIDevice;
|
||||||
|
#ifdef RT_USING_DEVICE_OPS
|
||||||
|
device->ops = &spi_device_ops;
|
||||||
|
#else
|
||||||
device->init = RT_NULL;
|
device->init = RT_NULL;
|
||||||
device->open = RT_NULL;
|
device->open = RT_NULL;
|
||||||
device->close = RT_NULL;
|
device->close = RT_NULL;
|
||||||
device->read = _spidev_device_read;
|
device->read = _spidev_device_read;
|
||||||
device->write = _spidev_device_write;
|
device->write = _spidev_device_write;
|
||||||
device->control = _spidev_device_control;
|
device->control = _spidev_device_control;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* register to device manager */
|
/* register to device manager */
|
||||||
return rt_device_register(device, name, RT_DEVICE_FLAG_RDWR);
|
return rt_device_register(device, name, RT_DEVICE_FLAG_RDWR);
|
||||||
|
@ -254,6 +254,18 @@ static rt_size_t w25qxx_flash_write(rt_device_t dev,
|
|||||||
return size;
|
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)
|
rt_err_t gd_init(const char * flash_device_name, const char * spi_device_name)
|
||||||
{
|
{
|
||||||
struct rt_spi_device * rt_spi_device;
|
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 */
|
/* register device */
|
||||||
spi_flash_device.flash_device.type = RT_Device_Class_Block;
|
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.init = w25qxx_flash_init;
|
||||||
spi_flash_device.flash_device.open = w25qxx_flash_open;
|
spi_flash_device.flash_device.open = w25qxx_flash_open;
|
||||||
spi_flash_device.flash_device.close = w25qxx_flash_close;
|
spi_flash_device.flash_device.close = w25qxx_flash_close;
|
||||||
spi_flash_device.flash_device.read = w25qxx_flash_read;
|
spi_flash_device.flash_device.read = w25qxx_flash_read;
|
||||||
spi_flash_device.flash_device.write = w25qxx_flash_write;
|
spi_flash_device.flash_device.write = w25qxx_flash_write;
|
||||||
spi_flash_device.flash_device.control = w25qxx_flash_control;
|
spi_flash_device.flash_device.control = w25qxx_flash_control;
|
||||||
|
#endif
|
||||||
/* no private */
|
/* no private */
|
||||||
spi_flash_device.flash_device.user_data = RT_NULL;
|
spi_flash_device.flash_device.user_data = RT_NULL;
|
||||||
|
|
||||||
|
@ -228,6 +228,18 @@ sfud_err sfud_spi_port_init(sfud_flash *flash) {
|
|||||||
return result;
|
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.
|
* Probe SPI flash by SFUD(Serial Flash Universal Driver) driver library and though SPI device.
|
||||||
*
|
*
|
||||||
@ -297,12 +309,16 @@ rt_spi_flash_device_t rt_sfud_flash_probe(const char *spi_flash_dev_name, const
|
|||||||
|
|
||||||
/* register device */
|
/* register device */
|
||||||
rtt_dev->flash_device.type = RT_Device_Class_Block;
|
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.init = RT_NULL;
|
||||||
rtt_dev->flash_device.open = RT_NULL;
|
rtt_dev->flash_device.open = RT_NULL;
|
||||||
rtt_dev->flash_device.close = RT_NULL;
|
rtt_dev->flash_device.close = RT_NULL;
|
||||||
rtt_dev->flash_device.read = rt_sfud_read;
|
rtt_dev->flash_device.read = rt_sfud_read;
|
||||||
rtt_dev->flash_device.write = rt_sfud_write;
|
rtt_dev->flash_device.write = rt_sfud_write;
|
||||||
rtt_dev->flash_device.control = rt_sfud_control;
|
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);
|
rt_device_register(&(rtt_dev->flash_device), spi_flash_dev_name, RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_STANDALONE);
|
||||||
|
|
||||||
|
@ -254,6 +254,18 @@ static rt_size_t sst25vfxx_flash_write(rt_device_t dev, rt_off_t pos, const void
|
|||||||
return size;
|
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)
|
rt_err_t sst25vfxx_init(const char * flash_device_name, const char * spi_device_name)
|
||||||
{
|
{
|
||||||
struct rt_spi_device * rt_spi_device;
|
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 */
|
/* register device */
|
||||||
spi_flash->flash_device.type = RT_Device_Class_Block;
|
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.init = sst25vfxx_flash_init;
|
||||||
spi_flash->flash_device.open = sst25vfxx_flash_open;
|
spi_flash->flash_device.open = sst25vfxx_flash_open;
|
||||||
spi_flash->flash_device.close = sst25vfxx_flash_close;
|
spi_flash->flash_device.close = sst25vfxx_flash_close;
|
||||||
spi_flash->flash_device.read = sst25vfxx_flash_read;
|
spi_flash->flash_device.read = sst25vfxx_flash_read;
|
||||||
spi_flash->flash_device.write = sst25vfxx_flash_write;
|
spi_flash->flash_device.write = sst25vfxx_flash_write;
|
||||||
spi_flash->flash_device.control = sst25vfxx_flash_control;
|
spi_flash->flash_device.control = sst25vfxx_flash_control;
|
||||||
|
#endif
|
||||||
/* no private */
|
/* no private */
|
||||||
spi_flash->flash_device.user_data = RT_NULL;
|
spi_flash->flash_device.user_data = RT_NULL;
|
||||||
|
|
||||||
|
@ -264,6 +264,18 @@ static rt_size_t w25qxx_flash_write(rt_device_t dev,
|
|||||||
return size;
|
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)
|
rt_err_t w25qxx_init(const char * flash_device_name, const char * spi_device_name)
|
||||||
{
|
{
|
||||||
struct rt_spi_device * rt_spi_device;
|
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 */
|
/* register device */
|
||||||
spi_flash_device.flash_device.type = RT_Device_Class_Block;
|
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.init = w25qxx_flash_init;
|
||||||
spi_flash_device.flash_device.open = w25qxx_flash_open;
|
spi_flash_device.flash_device.open = w25qxx_flash_open;
|
||||||
spi_flash_device.flash_device.close = w25qxx_flash_close;
|
spi_flash_device.flash_device.close = w25qxx_flash_close;
|
||||||
spi_flash_device.flash_device.read = w25qxx_flash_read;
|
spi_flash_device.flash_device.read = w25qxx_flash_read;
|
||||||
spi_flash_device.flash_device.write = w25qxx_flash_write;
|
spi_flash_device.flash_device.write = w25qxx_flash_write;
|
||||||
spi_flash_device.flash_device.control = w25qxx_flash_control;
|
spi_flash_device.flash_device.control = w25qxx_flash_control;
|
||||||
|
#endif
|
||||||
/* no private */
|
/* no private */
|
||||||
spi_flash_device.flash_device.user_data = RT_NULL;
|
spi_flash_device.flash_device.user_data = RT_NULL;
|
||||||
|
|
||||||
|
@ -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_token(struct rt_spi_device *device, uint8_t token);
|
||||||
static rt_err_t _wait_ready(struct rt_spi_device *device);
|
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_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_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_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_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)
|
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);
|
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 */
|
/* RT-Thread Device Driver Interface */
|
||||||
static rt_err_t rt_msd_init(rt_device_t dev)
|
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)
|
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->read = rt_msd_sdhc_read;
|
||||||
dev->write = rt_msd_sdhc_write;
|
dev->write = rt_msd_sdhc_write;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
#ifdef RT_USING_DEVICE_OPS
|
||||||
|
dev->ops = &msd_ops;
|
||||||
|
#else
|
||||||
dev->read = rt_msd_read;
|
dev->read = rt_msd_read;
|
||||||
dev->write = rt_msd_write;
|
dev->write = rt_msd_write;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* set CRC */
|
/* 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.sector_count = 0;
|
||||||
_msd_device.geometry.block_size = 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.init = rt_msd_init;
|
||||||
_msd_device.parent.open = rt_msd_open;
|
_msd_device.parent.open = rt_msd_open;
|
||||||
_msd_device.parent.close = rt_msd_close;
|
_msd_device.parent.close = rt_msd_close;
|
||||||
_msd_device.parent.read = RT_NULL;
|
_msd_device.parent.read = RT_NULL;
|
||||||
_msd_device.parent.write = RT_NULL;
|
_msd_device.parent.write = RT_NULL;
|
||||||
_msd_device.parent.control = rt_msd_control;
|
_msd_device.parent.control = rt_msd_control;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* no private, no callback */
|
/* no private, no callback */
|
||||||
_msd_device.parent.user_data = RT_NULL;
|
_msd_device.parent.user_data = RT_NULL;
|
||||||
|
@ -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)
|
rt_err_t rt_hw_wifi_init(const char *spi_device_name, wifi_mode_t mode)
|
||||||
{
|
{
|
||||||
/* align and struct size check. */
|
/* 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);
|
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.init = rw009_wifi_init;
|
||||||
rw009_wifi_device.parent.parent.open = rw009_wifi_open;
|
rw009_wifi_device.parent.parent.open = rw009_wifi_open;
|
||||||
rw009_wifi_device.parent.parent.close = rw009_wifi_close;
|
rw009_wifi_device.parent.parent.close = rw009_wifi_close;
|
||||||
rw009_wifi_device.parent.parent.read = rw009_wifi_read;
|
rw009_wifi_device.parent.parent.read = rw009_wifi_read;
|
||||||
rw009_wifi_device.parent.parent.write = rw009_wifi_write;
|
rw009_wifi_device.parent.parent.write = rw009_wifi_write;
|
||||||
rw009_wifi_device.parent.parent.control = rw009_wifi_control;
|
rw009_wifi_device.parent.parent.control = rw009_wifi_control;
|
||||||
|
#endif
|
||||||
rw009_wifi_device.parent.parent.user_data = RT_NULL;
|
rw009_wifi_device.parent.parent.user_data = RT_NULL;
|
||||||
|
|
||||||
rw009_wifi_device.parent.eth_rx = rw009_wifi_rx;
|
rw009_wifi_device.parent.eth_rx = rw009_wifi_rx;
|
||||||
|
@ -416,6 +416,18 @@ rt_err_t rt_pipe_control(rt_device_t dev, int cmd, void *args)
|
|||||||
return RT_EOK;
|
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 *rt_pipe_create(const char *name, int bufsz)
|
||||||
{
|
{
|
||||||
rt_pipe_t *pipe;
|
rt_pipe_t *pipe;
|
||||||
@ -434,12 +446,16 @@ rt_pipe_t *rt_pipe_create(const char *name, int bufsz)
|
|||||||
|
|
||||||
dev = &(pipe->parent);
|
dev = &(pipe->parent);
|
||||||
dev->type = RT_Device_Class_Pipe;
|
dev->type = RT_Device_Class_Pipe;
|
||||||
|
#ifdef RT_USING_DEVICE_OPS
|
||||||
|
dev->ops = &pipe_ops;
|
||||||
|
#else
|
||||||
dev->init = RT_NULL;
|
dev->init = RT_NULL;
|
||||||
dev->open = rt_pipe_open;
|
dev->open = rt_pipe_open;
|
||||||
dev->read = rt_pipe_read;
|
dev->read = rt_pipe_read;
|
||||||
dev->write = rt_pipe_write;
|
dev->write = rt_pipe_write;
|
||||||
dev->close = rt_pipe_close;
|
dev->close = rt_pipe_close;
|
||||||
dev->control = rt_pipe_control;
|
dev->control = rt_pipe_control;
|
||||||
|
#endif
|
||||||
|
|
||||||
dev->rx_indicate = RT_NULL;
|
dev->rx_indicate = RT_NULL;
|
||||||
dev->tx_complete = RT_NULL;
|
dev->tx_complete = RT_NULL;
|
||||||
|
@ -327,6 +327,19 @@ static rt_err_t rt_ecm_eth_control(rt_device_t dev, int cmd, void *args)
|
|||||||
|
|
||||||
return RT_EOK;
|
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 *rt_ecm_eth_rx(rt_device_t dev)
|
||||||
{
|
{
|
||||||
struct pbuf* p = RT_NULL;
|
struct pbuf* p = RT_NULL;
|
||||||
|
@ -592,14 +592,33 @@ static void hid_thread_entry(void* parameter)
|
|||||||
HID_Report_Received(&report);
|
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 rt_uint8_t hid_mq_pool[(sizeof(struct hid_report)+sizeof(void*))*8];
|
||||||
static void rt_usb_hid_init(struct ufunction *func)
|
static void rt_usb_hid_init(struct ufunction *func)
|
||||||
{
|
{
|
||||||
struct hid_s *hiddev;
|
struct hid_s *hiddev;
|
||||||
hiddev = (struct hid_s *)func->user_data;
|
hiddev = (struct hid_s *)func->user_data;
|
||||||
rt_memset(&hiddev->parent, 0, sizeof(hiddev->parent));
|
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->parent.write = _hid_write;
|
||||||
hiddev->func = func;
|
#endif
|
||||||
|
hiddev->func = func;
|
||||||
|
|
||||||
rt_device_register(&hiddev->parent, "hidd", RT_DEVICE_FLAG_RDWR);
|
rt_device_register(&hiddev->parent, "hidd", RT_DEVICE_FLAG_RDWR);
|
||||||
rt_mq_init(&hiddev->hid_mq, "hiddmq", hid_mq_pool, sizeof(struct hid_report),
|
rt_mq_init(&hiddev->hid_mq, "hiddmq", hid_mq_pool, sizeof(struct hid_report),
|
||||||
sizeof(hid_mq_pool), RT_IPC_FLAG_FIFO);
|
sizeof(hid_mq_pool), RT_IPC_FLAG_FIFO);
|
||||||
|
@ -1180,6 +1180,19 @@ rt_err_t rt_rndis_eth_tx(rt_device_t dev, struct pbuf* p)
|
|||||||
|
|
||||||
return result;
|
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 */
|
#endif /* RT_USING_LWIP */
|
||||||
|
|
||||||
#ifdef RNDIS_DELAY_LINK_UP
|
#ifdef RNDIS_DELAY_LINK_UP
|
||||||
@ -1307,18 +1320,22 @@ ufunction_t rt_usbd_function_rndis_create(udevice_t device)
|
|||||||
_rndis->host_addr[4] = 0xEA;//*(const rt_uint8_t *)(0x0FE081F1);
|
_rndis->host_addr[4] = 0xEA;//*(const rt_uint8_t *)(0x0FE081F1);
|
||||||
_rndis->host_addr[5] = 0x13;//*(const rt_uint8_t *)(0x0FE081F2);
|
_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.init = rt_rndis_eth_init;
|
||||||
_rndis->parent.parent.open = rt_rndis_eth_open;
|
_rndis->parent.parent.open = rt_rndis_eth_open;
|
||||||
_rndis->parent.parent.close = rt_rndis_eth_close;
|
_rndis->parent.parent.close = rt_rndis_eth_close;
|
||||||
_rndis->parent.parent.read = rt_rndis_eth_read;
|
_rndis->parent.parent.read = rt_rndis_eth_read;
|
||||||
_rndis->parent.parent.write = rt_rndis_eth_write;
|
_rndis->parent.parent.write = rt_rndis_eth_write;
|
||||||
_rndis->parent.parent.control = rt_rndis_eth_control;
|
_rndis->parent.parent.control = rt_rndis_eth_control;
|
||||||
|
#endif
|
||||||
_rndis->parent.parent.user_data = device;
|
_rndis->parent.parent.user_data = device;
|
||||||
|
|
||||||
_rndis->parent.eth_rx = rt_rndis_eth_rx;
|
_rndis->parent.eth_rx = rt_rndis_eth_rx;
|
||||||
_rndis->parent.eth_tx = rt_rndis_eth_tx;
|
_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");
|
eth_device_init(&((rt_rndis_eth_t)cdc->user_data)->parent, "u0");
|
||||||
|
|
||||||
#endif /* RT_USING_LWIP */
|
#endif /* RT_USING_LWIP */
|
||||||
|
@ -246,16 +246,34 @@ static rt_err_t win_usb_control(rt_device_t dev, int cmd, void *args)
|
|||||||
}
|
}
|
||||||
return RT_EOK;
|
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)
|
static rt_err_t rt_usb_winusb_init(ufunction_t func)
|
||||||
{
|
{
|
||||||
winusb_device_t winusb_device = (winusb_device_t)func->user_data;
|
winusb_device_t winusb_device = (winusb_device_t)func->user_data;
|
||||||
winusb_device->parent.type = RT_Device_Class_Miscellaneous;
|
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.init = RT_NULL;
|
||||||
winusb_device->parent.open = RT_NULL;
|
winusb_device->parent.open = RT_NULL;
|
||||||
winusb_device->parent.close = RT_NULL;
|
winusb_device->parent.close = RT_NULL;
|
||||||
winusb_device->parent.read = win_usb_read;
|
winusb_device->parent.read = win_usb_read;
|
||||||
winusb_device->parent.write = win_usb_write;
|
winusb_device->parent.write = win_usb_write;
|
||||||
winusb_device->parent.control = win_usb_control;
|
winusb_device->parent.control = win_usb_control;
|
||||||
|
#endif
|
||||||
|
|
||||||
winusb_device->parent.user_data = func;
|
winusb_device->parent.user_data = func;
|
||||||
|
|
||||||
|
@ -209,6 +209,18 @@ static rt_size_t rt_usbh_adk_write (rt_device_t device, rt_off_t pos, const void
|
|||||||
return length;
|
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
|
* 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.
|
* as a adk class device, it will continue the enumulate process.
|
||||||
@ -341,13 +353,17 @@ static rt_err_t rt_usbh_adk_enable(void* arg)
|
|||||||
if(ret != RT_EOK) return ret;
|
if(ret != RT_EOK) return ret;
|
||||||
|
|
||||||
/* register adk device */
|
/* register adk device */
|
||||||
adk->device.type = RT_Device_Class_Char;
|
adk->device.type = RT_Device_Class_Char;
|
||||||
adk->device.init = RT_NULL;
|
#ifdef RT_USING_DEVICE_OPS
|
||||||
adk->device.open = RT_NULL;
|
adk->device.ops = &adk_device_ops;
|
||||||
adk->device.close = RT_NULL;
|
#else
|
||||||
adk->device.read = rt_usbh_adk_read;
|
adk->device.init = RT_NULL;
|
||||||
adk->device.write = rt_usbh_adk_write;
|
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;
|
adk->device.control = RT_NULL;
|
||||||
|
#endif
|
||||||
adk->device.user_data = (void*)intf;
|
adk->device.user_data = (void*)intf;
|
||||||
|
|
||||||
rt_device_register(&adk->device, "adkdev", RT_DEVICE_FLAG_RDWR);
|
rt_device_register(&adk->device, "adkdev", RT_DEVICE_FLAG_RDWR);
|
||||||
|
@ -167,6 +167,18 @@ static rt_err_t rt_udisk_control(rt_device_t dev, int cmd, void *args)
|
|||||||
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.
|
* This function will run udisk driver when usb disk is detected.
|
||||||
*
|
*
|
||||||
@ -311,11 +323,15 @@ rt_err_t rt_udisk_run(struct uhintf* intf)
|
|||||||
data->part.lock = rt_sem_create(sname, 1, RT_IPC_FLAG_FIFO);
|
data->part.lock = rt_sem_create(sname, 1, RT_IPC_FLAG_FIFO);
|
||||||
|
|
||||||
/* register sdcard device */
|
/* register sdcard device */
|
||||||
stor->dev[i].type = RT_Device_Class_Block;
|
stor->dev[i].type = RT_Device_Class_Block;
|
||||||
stor->dev[i].init = rt_udisk_init;
|
#ifdef RT_USING_DEVICE_OPS
|
||||||
stor->dev[i].read = rt_udisk_read;
|
stor->dev[i].ops = &udisk_device_ops;
|
||||||
stor->dev[i].write = rt_udisk_write;
|
#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;
|
stor->dev[i].control = rt_udisk_control;
|
||||||
|
#endif
|
||||||
stor->dev[i].user_data = (void*)data;
|
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 |
|
||||||
@ -349,11 +365,15 @@ rt_err_t rt_udisk_run(struct uhintf* intf)
|
|||||||
rt_snprintf(dname, 7, "udisk%d", data->udisk_id);
|
rt_snprintf(dname, 7, "udisk%d", data->udisk_id);
|
||||||
|
|
||||||
/* register sdcard device */
|
/* register sdcard device */
|
||||||
stor->dev[0].type = RT_Device_Class_Block;
|
stor->dev[0].type = RT_Device_Class_Block;
|
||||||
stor->dev[0].init = rt_udisk_init;
|
#ifdef RT_USING_DEVICE_OPS
|
||||||
stor->dev[0].read = rt_udisk_read;
|
stor->dev[i].ops = &udisk_device_ops;
|
||||||
stor->dev[0].write = rt_udisk_write;
|
#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;
|
stor->dev[0].control = rt_udisk_control;
|
||||||
|
#endif
|
||||||
stor->dev[0].user_data = (void*)data;
|
stor->dev[0].user_data = (void*)data;
|
||||||
|
|
||||||
rt_device_register(&stor->dev[0], dname,
|
rt_device_register(&stor->dev[0], dname,
|
||||||
|
@ -78,6 +78,18 @@ static rt_err_t rt_watchdog_control(struct rt_device *dev,
|
|||||||
return (wtd->ops->control(wtd, cmd, args));
|
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
|
* 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->rx_indicate = RT_NULL;
|
||||||
device->tx_complete = RT_NULL;
|
device->tx_complete = RT_NULL;
|
||||||
|
|
||||||
|
#ifdef RT_USING_DEVICE_OPS
|
||||||
|
device->ops = &wdt_ops;
|
||||||
|
#else
|
||||||
device->init = rt_watchdog_init;
|
device->init = rt_watchdog_init;
|
||||||
device->open = rt_watchdog_open;
|
device->open = rt_watchdog_open;
|
||||||
device->close = rt_watchdog_close;
|
device->close = rt_watchdog_close;
|
||||||
device->read = RT_NULL;
|
device->read = RT_NULL;
|
||||||
device->write = RT_NULL;
|
device->write = RT_NULL;
|
||||||
device->control = rt_watchdog_control;
|
device->control = rt_watchdog_control;
|
||||||
|
#endif
|
||||||
device->user_data = data;
|
device->user_data = data;
|
||||||
|
|
||||||
/* register a character device */
|
/* register a character device */
|
||||||
|
@ -614,113 +614,6 @@ int list_module(void)
|
|||||||
}
|
}
|
||||||
FINSH_FUNCTION_EXPORT(list_module, list module in system);
|
FINSH_FUNCTION_EXPORT(list_module, list module in system);
|
||||||
MSH_CMD_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
|
#endif
|
||||||
|
|
||||||
long list(void)
|
long list(void)
|
||||||
|
@ -336,7 +336,7 @@ int msh_exec(char *cmd, rt_size_t length)
|
|||||||
{
|
{
|
||||||
return cmd_ret;
|
return cmd_ret;
|
||||||
}
|
}
|
||||||
#ifdef RT_USING_MODULE
|
#if defined(RT_USING_MODULE) && defined(RT_USING_DFS)
|
||||||
if (msh_exec_module(cmd, length) == 0)
|
if (msh_exec_module(cmd, length) == 0)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -35,6 +35,8 @@
|
|||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
int _EXFUN(putenv,(char *__string));
|
||||||
|
|
||||||
int libc_system_init(void)
|
int libc_system_init(void)
|
||||||
{
|
{
|
||||||
#if defined(RT_USING_DFS) & defined(RT_USING_DFS_DEVFS)
|
#if defined(RT_USING_DFS) & defined(RT_USING_DFS_DEVFS)
|
||||||
|
@ -31,6 +31,8 @@
|
|||||||
|
|
||||||
#define STDIO_DEVICE_NAME_MAX 32
|
#define STDIO_DEVICE_NAME_MAX 32
|
||||||
|
|
||||||
|
int _EXFUN(fileno, (FILE *));
|
||||||
|
|
||||||
static FILE* std_console = NULL;
|
static FILE* std_console = NULL;
|
||||||
|
|
||||||
int libc_stdio_set_console(const char* device_name, int mode)
|
int libc_stdio_set_console(const char* device_name, int mode)
|
||||||
|
@ -387,30 +387,7 @@ _exit (int status)
|
|||||||
module = rt_module_self();
|
module = rt_module_self();
|
||||||
if (module != RT_NULL)
|
if (module != RT_NULL)
|
||||||
{
|
{
|
||||||
struct rt_list_node *list;
|
rt_thread_suspend(rt_thread_self());
|
||||||
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();
|
|
||||||
|
|
||||||
/* re-schedule */
|
/* re-schedule */
|
||||||
rt_schedule();
|
rt_schedule();
|
||||||
|
7
components/lwp/Kconfig
Normal file
7
components/lwp/Kconfig
Normal file
@ -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.
|
20
components/lwp/SConscript
Normal file
20
components/lwp/SConscript
Normal file
@ -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')
|
176
components/lwp/arch/arm/cortex-m3/lwp_gcc.S
Normal file
176
components/lwp/arch/arm/cortex-m3/lwp_gcc.S
Normal file
@ -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. */
|
176
components/lwp/arch/arm/cortex-m3/lwp_iar.S
Normal file
176
components/lwp/arch/arm/cortex-m3/lwp_iar.S
Normal file
@ -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
|
184
components/lwp/arch/arm/cortex-m3/lwp_rvds.S
Normal file
184
components/lwp/arch/arm/cortex-m3/lwp_rvds.S
Normal file
@ -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
|
210
components/lwp/arch/arm/cortex-m4/lwp_gcc.S
Normal file
210
components/lwp/arch/arm/cortex-m4/lwp_gcc.S
Normal file
@ -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. */
|
215
components/lwp/arch/arm/cortex-m4/lwp_iar.S
Normal file
215
components/lwp/arch/arm/cortex-m4/lwp_iar.S
Normal file
@ -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
|
219
components/lwp/arch/arm/cortex-m4/lwp_rvds.S
Normal file
219
components/lwp/arch/arm/cortex-m4/lwp_rvds.S
Normal file
@ -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
|
210
components/lwp/arch/arm/cortex-m7/lwp_gcc.S
Normal file
210
components/lwp/arch/arm/cortex-m7/lwp_gcc.S
Normal file
@ -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. */
|
215
components/lwp/arch/arm/cortex-m7/lwp_iar.S
Normal file
215
components/lwp/arch/arm/cortex-m7/lwp_iar.S
Normal file
@ -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
|
219
components/lwp/arch/arm/cortex-m7/lwp_rvds.S
Normal file
219
components/lwp/arch/arm/cortex-m7/lwp_rvds.S
Normal file
@ -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
|
364
components/lwp/lwp.c
Normal file
364
components/lwp/lwp.c
Normal file
@ -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 <rtthread.h>
|
||||||
|
#include <rthw.h>
|
||||||
|
#include <dfs_posix.h>
|
||||||
|
|
||||||
|
#ifdef RT_USING_FINSH
|
||||||
|
#include <finsh.h>
|
||||||
|
#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 <rtdbg.h>
|
||||||
|
|
||||||
|
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);
|
83
components/lwp/lwp.h
Normal file
83
components/lwp/lwp.h
Normal file
@ -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 <stdint.h>
|
||||||
|
#include <rtthread.h>
|
||||||
|
#include <dfs.h>
|
||||||
|
#include <lwp_memheap.h>
|
||||||
|
|
||||||
|
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
|
232
components/lwp/lwp_mem.c
Normal file
232
components/lwp/lwp_mem.c
Normal file
@ -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 <stdio.h>
|
||||||
|
#include <rtthread.h>
|
||||||
|
#include <lwp.h>
|
||||||
|
|
||||||
|
#define DBG_ENABLE
|
||||||
|
#define DBG_SECTION_NAME "[LWPMEM]"
|
||||||
|
#define DBG_COLOR
|
||||||
|
#define DBG_LEVEL DBG_LOG
|
||||||
|
#include <rtdbg.h>
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
}
|
34
components/lwp/lwp_mem.h
Normal file
34
components/lwp/lwp_mem.h
Normal file
@ -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
|
590
components/lwp/lwp_memheap.c
Normal file
590
components/lwp/lwp_memheap.c
Normal file
@ -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 <rthw.h>
|
||||||
|
#include <rtthread.h>
|
||||||
|
#include <lwp.h>
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
}
|
74
components/lwp/lwp_memheap.h
Normal file
74
components/lwp/lwp_memheap.h
Normal file
@ -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 <stdint.h>
|
||||||
|
#include <rtthread.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
242
components/lwp/lwp_syscall.c
Normal file
242
components/lwp/lwp_syscall.c
Normal file
@ -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 <lwp.h>
|
||||||
|
#include <lwp_mem.h>
|
||||||
|
#include <lwp_syscall.h>
|
||||||
|
|
||||||
|
#define DBG_ENABLE
|
||||||
|
#define DBG_SECTION_NAME "[LWP_CALL]"
|
||||||
|
#define DBG_COLOR
|
||||||
|
#define DBG_LEVEL DBG_WARNING
|
||||||
|
#include <rtdbg.h>
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
}
|
78
components/lwp/lwp_syscall.h
Normal file
78
components/lwp/lwp_syscall.h
Normal file
@ -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 <stdint.h>
|
||||||
|
#include <rtthread.h>
|
||||||
|
#include <dfs_posix.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
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
|
@ -112,6 +112,18 @@ static rt_err_t fdevice_control(rt_device_t dev, int cmd, void *arg)
|
|||||||
return RT_EOK;
|
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)
|
void log_trace_file_init(const char *filename)
|
||||||
{
|
{
|
||||||
rt_device_t device;
|
rt_device_t device;
|
||||||
@ -123,11 +135,15 @@ void log_trace_file_init(const char *filename)
|
|||||||
|
|
||||||
_file_device.parent.type = RT_Device_Class_Char;
|
_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.init = RT_NULL;
|
||||||
_file_device.parent.open = fdevice_open;
|
_file_device.parent.open = fdevice_open;
|
||||||
_file_device.parent.close = fdevice_close;
|
_file_device.parent.close = fdevice_close;
|
||||||
_file_device.parent.write = fdevice_write;
|
_file_device.parent.write = fdevice_write;
|
||||||
_file_device.parent.control = fdevice_control;
|
_file_device.parent.control = fdevice_control;
|
||||||
|
#endif
|
||||||
|
|
||||||
rt_device_register(&_file_device.parent, "logfile", O_RDWR);
|
rt_device_register(&_file_device.parent, "logfile", O_RDWR);
|
||||||
}
|
}
|
||||||
|
@ -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);
|
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)
|
int log_trace_init(void)
|
||||||
{
|
{
|
||||||
rt_memset(&_log_device, 0x00, sizeof(_log_device));
|
rt_memset(&_log_device, 0x00, sizeof(_log_device));
|
||||||
|
|
||||||
_log_device.type = RT_Device_Class_Char;
|
_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.init = RT_NULL;
|
||||||
_log_device.open = RT_NULL;
|
_log_device.open = RT_NULL;
|
||||||
_log_device.close = RT_NULL;
|
_log_device.close = RT_NULL;
|
||||||
_log_device.read = RT_NULL;
|
_log_device.read = RT_NULL;
|
||||||
_log_device.write = _log_write;
|
_log_device.write = _log_write;
|
||||||
_log_device.control = _log_control;
|
_log_device.control = _log_control;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* no indication and complete callback */
|
/* no indication and complete callback */
|
||||||
_log_device.rx_indicate = RT_NULL;
|
_log_device.rx_indicate = RT_NULL;
|
||||||
|
@ -848,6 +848,17 @@ enum rt_device_class_type
|
|||||||
#define RT_DEVICE_CTRL_RTC_SET_ALARM 0x13 /**< set alarm */
|
#define RT_DEVICE_CTRL_RTC_SET_ALARM 0x13 /**< set alarm */
|
||||||
|
|
||||||
typedef struct rt_device *rt_device_t;
|
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
|
* 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 (*rx_indicate)(rt_device_t dev, rt_size_t size);
|
||||||
rt_err_t (*tx_complete)(rt_device_t dev, void *buffer);
|
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 */
|
/* common device interface */
|
||||||
rt_err_t (*init) (rt_device_t dev);
|
rt_err_t (*init) (rt_device_t dev);
|
||||||
rt_err_t (*open) (rt_device_t dev, rt_uint16_t oflag);
|
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 (*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_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);
|
rt_err_t (*control)(rt_device_t dev, int cmd, void *args);
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(RT_USING_POSIX)
|
#if defined(RT_USING_POSIX)
|
||||||
const struct dfs_file_ops *fops;
|
const struct dfs_file_ops *fops;
|
||||||
@ -1030,8 +1045,8 @@ struct rt_module
|
|||||||
|
|
||||||
rt_uint32_t user_data; /**< arch data in the module */
|
rt_uint32_t user_data; /**< arch data in the module */
|
||||||
|
|
||||||
/* object in this module, module object is the last basic object type */
|
void (*module_init)(void);
|
||||||
struct rt_object_information module_object[RT_Object_Class_Unknown];
|
void (*module_cleanup)(void);
|
||||||
};
|
};
|
||||||
typedef struct rt_module *rt_module_t;
|
typedef struct rt_module *rt_module_t;
|
||||||
|
|
||||||
|
@ -192,6 +192,10 @@ menu "Kernel Device Object"
|
|||||||
bool "Using device object"
|
bool "Using device object"
|
||||||
default y
|
default y
|
||||||
|
|
||||||
|
config RT_USING_DEVICE_OPS
|
||||||
|
bool "Using ops for each device object"
|
||||||
|
default n
|
||||||
|
|
||||||
config RT_USING_INTERRUPT_INFO
|
config RT_USING_INTERRUPT_INFO
|
||||||
bool "Enable additional interrupt trace information"
|
bool "Enable additional interrupt trace information"
|
||||||
default n
|
default n
|
||||||
|
48
src/device.c
48
src/device.c
@ -32,12 +32,28 @@
|
|||||||
|
|
||||||
#ifdef RT_USING_DEVICE
|
#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.
|
* This function registers a device driver with specified name.
|
||||||
*
|
*
|
||||||
* @param dev the pointer of device driver structure
|
* @param dev the pointer of device driver structure
|
||||||
* @param name the device driver's name
|
* @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.
|
* @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;
|
rt_device_t device;
|
||||||
|
|
||||||
size = RT_ALIGN(sizeof(struct rt_device), RT_ALIGN_SIZE);
|
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;
|
size += attach_size;
|
||||||
|
|
||||||
device = (rt_device_t)rt_malloc(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);
|
RT_ASSERT(dev != RT_NULL);
|
||||||
|
|
||||||
/* get device init handler */
|
/* get device init handler */
|
||||||
if (dev->init != RT_NULL)
|
if (device_init != RT_NULL)
|
||||||
{
|
{
|
||||||
if (!(dev->flag & RT_DEVICE_FLAG_ACTIVATED))
|
if (!(dev->flag & RT_DEVICE_FLAG_ACTIVATED))
|
||||||
{
|
{
|
||||||
result = dev->init(dev);
|
result = device_init(dev);
|
||||||
if (result != RT_EOK)
|
if (result != RT_EOK)
|
||||||
{
|
{
|
||||||
rt_kprintf("To initialize device:%s failed. The error code is %d\n",
|
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 device is not initialized, initialize it. */
|
||||||
if (!(dev->flag & RT_DEVICE_FLAG_ACTIVATED))
|
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)
|
if (result != RT_EOK)
|
||||||
{
|
{
|
||||||
rt_kprintf("To initialize device:%s failed. The error code is %d\n",
|
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 */
|
/* 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
|
else
|
||||||
{
|
{
|
||||||
@ -304,9 +322,9 @@ rt_err_t rt_device_close(rt_device_t dev)
|
|||||||
return RT_EOK;
|
return RT_EOK;
|
||||||
|
|
||||||
/* call device close interface */
|
/* 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 */
|
/* set open flag */
|
||||||
@ -343,9 +361,9 @@ rt_size_t rt_device_read(rt_device_t dev,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* call device read interface */
|
/* 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 */
|
/* set error code */
|
||||||
@ -381,9 +399,9 @@ rt_size_t rt_device_write(rt_device_t dev,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* call device write interface */
|
/* 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 */
|
/* 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);
|
RT_ASSERT(dev != RT_NULL);
|
||||||
|
|
||||||
/* call device write interface */
|
/* 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;
|
return -RT_ENOSYS;
|
||||||
|
28
src/idle.c
28
src/idle.c
@ -164,35 +164,11 @@ void rt_thread_idle_excute(void)
|
|||||||
rt_hw_interrupt_enable(lock);
|
rt_hw_interrupt_enable(lock);
|
||||||
|
|
||||||
#ifdef RT_USING_HEAP
|
#ifdef RT_USING_HEAP
|
||||||
#if defined(RT_USING_MODULE) && defined(RT_USING_SLAB)
|
/* release thread's stack */
|
||||||
/* the thread belongs to an application module */
|
RT_KERNEL_FREE(thread->stack_addr);
|
||||||
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);
|
|
||||||
/* delete thread object */
|
/* delete thread object */
|
||||||
rt_object_delete((rt_object_t)thread);
|
rt_object_delete((rt_object_t)thread);
|
||||||
#endif
|
#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
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
22
src/ipc.c
22
src/ipc.c
@ -1380,15 +1380,8 @@ rt_err_t rt_mb_delete(rt_mailbox_t mb)
|
|||||||
/* also resume all mailbox private suspended thread */
|
/* also resume all mailbox private suspended thread */
|
||||||
rt_ipc_list_resume_all(&(mb->suspend_sender_thread));
|
rt_ipc_list_resume_all(&(mb->suspend_sender_thread));
|
||||||
|
|
||||||
#if defined(RT_USING_MODULE) && defined(RT_USING_SLAB)
|
/* free mailbox pool */
|
||||||
/* the mb object belongs to an application module */
|
RT_KERNEL_FREE(mb->msg_pool);
|
||||||
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);
|
|
||||||
|
|
||||||
/* delete mailbox object */
|
/* delete mailbox object */
|
||||||
rt_object_delete(&(mb->parent.parent));
|
rt_object_delete(&(mb->parent.parent));
|
||||||
@ -1900,15 +1893,8 @@ rt_err_t rt_mq_delete(rt_mq_t mq)
|
|||||||
/* resume all suspended thread */
|
/* resume all suspended thread */
|
||||||
rt_ipc_list_resume_all(&(mq->parent.suspend_thread));
|
rt_ipc_list_resume_all(&(mq->parent.suspend_thread));
|
||||||
|
|
||||||
#if defined(RT_USING_MODULE) && defined(RT_USING_SLAB)
|
/* free message queue pool */
|
||||||
/* the mq object belongs to an application module */
|
RT_KERNEL_FREE(mq->msg_pool);
|
||||||
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);
|
|
||||||
|
|
||||||
/* delete message queue object */
|
/* delete message queue object */
|
||||||
rt_object_delete(&(mq->parent.parent));
|
rt_object_delete(&(mq->parent.parent));
|
||||||
|
@ -292,15 +292,8 @@ rt_err_t rt_mp_delete(rt_mp_t mp)
|
|||||||
rt_hw_interrupt_enable(temp);
|
rt_hw_interrupt_enable(temp);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(RT_USING_MODULE) && defined(RT_USING_SLAB)
|
/* release allocated room */
|
||||||
/* the mp object belongs to an application module */
|
rt_free(mp->start_address);
|
||||||
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);
|
|
||||||
|
|
||||||
/* detach object */
|
/* detach object */
|
||||||
rt_object_delete(&(mp->parent));
|
rt_object_delete(&(mp->parent));
|
||||||
|
775
src/module.c
775
src/module.c
@ -65,30 +65,6 @@
|
|||||||
#define RT_USING_MODULE_PRIO (RT_THREAD_PRIORITY_MAX - 2)
|
#define RT_USING_MODULE_PRIO (RT_THREAD_PRIORITY_MAX - 2)
|
||||||
#endif
|
#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_begin = RT_NULL;
|
||||||
static struct rt_module_symtab *_rt_module_symtab_end = 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");
|
_rt_module_symtab_end = __section_end("RTMSymTab");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef RT_USING_SLAB
|
|
||||||
/* initialize heap semaphore */
|
|
||||||
rt_sem_init(&mod_sem, "module", 1, RT_IPC_FLAG_FIFO);
|
|
||||||
#endif
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
INIT_COMPONENT_EXPORT(rt_system_module_init);
|
INIT_COMPONENT_EXPORT(rt_system_module_init);
|
||||||
@ -138,7 +110,7 @@ void list_symbol(void)
|
|||||||
index != _rt_module_symtab_end;
|
index != _rt_module_symtab_end;
|
||||||
index ++)
|
index ++)
|
||||||
{
|
{
|
||||||
rt_kprintf("%s\n", index->name);
|
rt_kprintf("%s => 0x%08x\n", index->name, index->addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ;
|
return ;
|
||||||
@ -295,80 +267,6 @@ static int rt_module_arm_relocate(struct rt_module *module,
|
|||||||
return 0;
|
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
|
#ifdef RT_USING_HOOK
|
||||||
static void (*rt_module_load_hook)(rt_module_t module);
|
static void (*rt_module_load_hook)(rt_module_t module);
|
||||||
static void (*rt_module_unload_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)
|
if (module == RT_NULL)
|
||||||
return RT_NULL;
|
return RT_NULL;
|
||||||
|
|
||||||
/* init module object container */
|
|
||||||
rt_module_init_object_container(module);
|
|
||||||
|
|
||||||
if (line_size && cmd_line)
|
if (line_size && cmd_line)
|
||||||
{
|
{
|
||||||
/* set module argument */
|
/* set module argument */
|
||||||
@ -1042,16 +937,6 @@ rt_module_t rt_module_do_main(const char *name,
|
|||||||
|
|
||||||
if (elf_module->e_entry != 0)
|
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 */
|
/* create module thread */
|
||||||
module->module_thread = rt_thread_create(name,
|
module->module_thread = rt_thread_create(name,
|
||||||
module_main_entry, module,
|
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)
|
rt_err_t rt_module_destroy(rt_module_t module)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
struct rt_object *object;
|
|
||||||
struct rt_list_node *list;
|
|
||||||
|
|
||||||
RT_DEBUG_NOT_IN_INTERRUPT;
|
RT_DEBUG_NOT_IN_INTERRUPT;
|
||||||
|
|
||||||
@ -1306,147 +1189,6 @@ rt_err_t rt_module_destroy(rt_module_t module)
|
|||||||
/* module has entry point */
|
/* module has entry point */
|
||||||
if (!(module->parent.flag & RT_MODULE_FLAG_WITHOUTENTRY))
|
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 */
|
/* delete command line */
|
||||||
if (module->module_cmd_line != RT_NULL)
|
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 */
|
/* release module space memory */
|
||||||
rt_free(module->module_space);
|
rt_free(module->module_space);
|
||||||
|
|
||||||
@ -1479,11 +1207,6 @@ rt_err_t rt_module_destroy(rt_module_t module)
|
|||||||
if (module->symtab != RT_NULL)
|
if (module->symtab != RT_NULL)
|
||||||
rt_free(module->symtab);
|
rt_free(module->symtab);
|
||||||
|
|
||||||
#ifdef RT_USING_SLAB
|
|
||||||
if (module->page_array != RT_NULL)
|
|
||||||
rt_free(module->page_array);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* delete module object */
|
/* delete module object */
|
||||||
rt_object_delete((rt_object_t)module);
|
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)
|
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;
|
RT_DEBUG_NOT_IN_INTERRUPT;
|
||||||
|
|
||||||
/* check parameter */
|
/* check parameter */
|
||||||
@ -1510,34 +1229,7 @@ rt_err_t rt_module_unload(rt_module_t module)
|
|||||||
return -RT_ERROR;
|
return -RT_ERROR;
|
||||||
|
|
||||||
rt_enter_critical();
|
rt_enter_critical();
|
||||||
if (!(module->parent.flag & RT_MODULE_FLAG_WITHOUTENTRY))
|
/* invoke module cleanup */
|
||||||
{
|
|
||||||
/* 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
rt_exit_critical();
|
rt_exit_critical();
|
||||||
|
|
||||||
#ifdef RT_USING_HOOK
|
#ifdef RT_USING_HOOK
|
||||||
@ -1547,11 +1239,6 @@ rt_err_t rt_module_unload(rt_module_t module)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (mdelete == RT_TRUE)
|
|
||||||
{
|
|
||||||
rt_module_destroy(module);
|
|
||||||
}
|
|
||||||
|
|
||||||
return RT_EOK;
|
return RT_EOK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1598,462 +1285,4 @@ rt_module_t rt_module_find(const char *name)
|
|||||||
}
|
}
|
||||||
RTM_EXPORT(rt_module_find);
|
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 <finsh.h>
|
|
||||||
|
|
||||||
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
|
#endif
|
||||||
|
84
src/object.c
84
src/object.c
@ -252,15 +252,9 @@ void rt_object_init(struct rt_object *object,
|
|||||||
register rt_base_t temp;
|
register rt_base_t temp;
|
||||||
struct rt_object_information *information;
|
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 */
|
/* get object information */
|
||||||
information = rt_object_get_information(type);
|
information = rt_object_get_information(type);
|
||||||
RT_ASSERT(information != RT_NULL);
|
RT_ASSERT(information != RT_NULL);
|
||||||
#endif
|
|
||||||
|
|
||||||
/* initialize object's parameters */
|
/* 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;
|
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 */
|
/* get object information */
|
||||||
information = rt_object_get_information(type);
|
information = rt_object_get_information(type);
|
||||||
RT_ASSERT(information != RT_NULL);
|
RT_ASSERT(information != RT_NULL);
|
||||||
#endif
|
|
||||||
|
|
||||||
object = (struct rt_object *)RT_KERNEL_MALLOC(information->object_size);
|
object = (struct rt_object *)RT_KERNEL_MALLOC(information->object_size);
|
||||||
if (object == RT_NULL)
|
if (object == RT_NULL)
|
||||||
@ -402,14 +387,8 @@ void rt_object_delete(rt_object_t object)
|
|||||||
/* unlock interrupt */
|
/* unlock interrupt */
|
||||||
rt_hw_interrupt_enable(temp);
|
rt_hw_interrupt_enable(temp);
|
||||||
|
|
||||||
#if defined(RT_USING_MODULE) && defined(RT_USING_SLAB)
|
/* free the memory of object */
|
||||||
if (object->flag & RT_OBJECT_FLAG_MODULE)
|
RT_KERNEL_FREE(object);
|
||||||
rt_module_free((rt_module_t)object->module_id, object);
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* free the memory of object */
|
|
||||||
RT_KERNEL_FREE(object);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -458,65 +437,6 @@ rt_object_t rt_object_find(const char *name, rt_uint8_t type)
|
|||||||
/* which is invoke in interrupt status */
|
/* which is invoke in interrupt status */
|
||||||
RT_DEBUG_NOT_IN_INTERRUPT;
|
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 */
|
/* enter critical */
|
||||||
rt_enter_critical();
|
rt_enter_critical();
|
||||||
|
|
||||||
|
19
src/slab.c
19
src/slab.c
@ -496,11 +496,6 @@ void *rt_malloc(rt_size_t size)
|
|||||||
if (size == 0)
|
if (size == 0)
|
||||||
return RT_NULL;
|
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
|
* Handle large allocations directly. There should not be very many of
|
||||||
* these so performance is not a big issue.
|
* these so performance is not a big issue.
|
||||||
@ -705,11 +700,6 @@ void *rt_realloc(void *ptr, rt_size_t size)
|
|||||||
return RT_NULL;
|
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
|
* Get the original allocation's zone. If the new request winds up
|
||||||
* using the same chunk size we do not have to do anything.
|
* 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));
|
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 */
|
/* get memory usage */
|
||||||
#if RT_DEBUG_SLAB
|
#if RT_DEBUG_SLAB
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user