mirror of
https://github.com/RT-Thread/rt-thread.git
synced 2026-05-25 05:05:35 +08:00
@@ -5,8 +5,8 @@
|
||||
#include <rtthread.h>
|
||||
#include "drv_clcd.h"
|
||||
|
||||
#define CLCD_WIDTH 480
|
||||
#define CLCD_HEIGHT 320
|
||||
#define CLCD_WIDTH 640
|
||||
#define CLCD_HEIGHT 480
|
||||
|
||||
#define CLCD_DEVICE(dev) (struct drv_clcd_device*)(dev)
|
||||
|
||||
@@ -78,6 +78,18 @@ static rt_err_t drv_clcd_control(struct rt_device *device, int cmd, void *args)
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
#ifdef RT_USING_DEVICE_OPS
|
||||
const static struct rt_device_ops clcd_ops =
|
||||
{
|
||||
drv_clcd_init,
|
||||
RT_NULL,
|
||||
RT_NULL,
|
||||
RT_NULL,
|
||||
RT_NULL,
|
||||
drv_clcd_control
|
||||
};
|
||||
#endif
|
||||
|
||||
int drv_clcd_hw_init(void)
|
||||
{
|
||||
PL111MMIO *plio;
|
||||
@@ -107,8 +119,13 @@ int drv_clcd_hw_init(void)
|
||||
plio->control = 0x1921 | (0x6 << 1);
|
||||
|
||||
device->type = RT_Device_Class_Graphic;
|
||||
#ifdef RT_USING_DEVICE_OPS
|
||||
device->ops = &clcd_ops;
|
||||
#else
|
||||
device->init = drv_clcd_init;
|
||||
device->control = drv_clcd_control;
|
||||
#endif
|
||||
|
||||
rt_device_register(device, "lcd", RT_DEVICE_FLAG_RDWR);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -485,6 +485,18 @@ struct pbuf *smc911x_emac_rx(rt_device_t dev)
|
||||
return p;
|
||||
}
|
||||
|
||||
#ifdef RT_USING_DEVICE_OPS
|
||||
const static struct rt_device_ops smc911x_emac_ops =
|
||||
{
|
||||
smc911x_emac_init,
|
||||
RT_NULL,
|
||||
RT_NULL,
|
||||
RT_NULL,
|
||||
RT_NULL,
|
||||
smc911x_emac_control
|
||||
};
|
||||
#endif
|
||||
|
||||
int smc911x_emac_hw_init(void)
|
||||
{
|
||||
_emac.iobase = VEXPRESS_ETH_BASE;
|
||||
@@ -507,12 +519,16 @@ int smc911x_emac_hw_init(void)
|
||||
_emac.enetaddr[4] = 0x22;
|
||||
_emac.enetaddr[5] = 0x33;
|
||||
|
||||
#ifdef RT_USING_DEVICE_OPS
|
||||
_emac.parent.parent.ops = &smc911x_emac_ops;
|
||||
#else
|
||||
_emac.parent.parent.init = smc911x_emac_init;
|
||||
_emac.parent.parent.open = RT_NULL;
|
||||
_emac.parent.parent.close = RT_NULL;
|
||||
_emac.parent.parent.read = RT_NULL;
|
||||
_emac.parent.parent.write = RT_NULL;
|
||||
_emac.parent.parent.control = smc911x_emac_control;
|
||||
#endif
|
||||
_emac.parent.parent.user_data = RT_NULL;
|
||||
_emac.parent.eth_rx = smc911x_emac_rx;
|
||||
_emac.parent.eth_tx = smc911x_emac_tx;
|
||||
@@ -540,12 +556,3 @@ int smc911x_emac_hw_init(void)
|
||||
return 0;
|
||||
}
|
||||
INIT_APP_EXPORT(smc911x_emac_hw_init);
|
||||
|
||||
#include <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"
|
||||
default "packages"
|
||||
|
||||
config BOARD_STM32F411_NUCLEO
|
||||
bool
|
||||
select ARCH_ARM_CORTEX_M4
|
||||
default y
|
||||
|
||||
source "$RTT_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 = .;
|
||||
. = ALIGN(4);
|
||||
|
||||
/* section information for modules */
|
||||
. = ALIGN(4);
|
||||
__rtmsymtab_start = .;
|
||||
KEEP(*(RTMSymTab))
|
||||
__rtmsymtab_end = .;
|
||||
|
||||
/* section information for initial. */
|
||||
. = ALIGN(4);
|
||||
__rt_init_start = .;
|
||||
|
||||
@@ -26,6 +26,8 @@ source "$RTT_DIR/components/drivers/Kconfig"
|
||||
|
||||
source "$RTT_DIR/components/libc/Kconfig"
|
||||
|
||||
source "$RTT_DIR/components/lwp/Kconfig"
|
||||
|
||||
source "$RTT_DIR/components/net/Kconfig"
|
||||
|
||||
source "$RTT_DIR/components/vbus/Kconfig"
|
||||
|
||||
@@ -95,6 +95,12 @@ struct dirent
|
||||
char d_name[DFS_PATH_MAX]; /* The null-terminated file name */
|
||||
};
|
||||
|
||||
struct dfs_fdtable
|
||||
{
|
||||
uint32_t maxfd;
|
||||
struct dfs_fd **fds;
|
||||
};
|
||||
|
||||
/* Initialization of dfs */
|
||||
int dfs_init(void);
|
||||
|
||||
@@ -110,6 +116,8 @@ struct dfs_fd *fd_get(int fd);
|
||||
void fd_put(struct dfs_fd *fd);
|
||||
int fd_is_open(const char *pathname);
|
||||
|
||||
struct dfs_fdtable* dfs_fdtable_get(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
+117
-16
@@ -21,12 +21,16 @@
|
||||
* Date Author Notes
|
||||
* 2005-02-22 Bernard The first version.
|
||||
* 2017-12-11 Bernard Use rt_free to instead of free in fd_is_open().
|
||||
* 2018-03-20 Heyuanjie dynamic allocation FD
|
||||
*/
|
||||
|
||||
#include <dfs.h>
|
||||
#include <dfs_fs.h>
|
||||
#include <dfs_file.h>
|
||||
#include "dfs_private.h"
|
||||
#ifdef RT_USING_LWP
|
||||
#include <lwp.h>
|
||||
#endif
|
||||
|
||||
/* Global variables */
|
||||
const struct dfs_filesystem_ops *filesystem_operation_table[DFS_FILESYSTEM_TYPES_MAX];
|
||||
@@ -39,7 +43,8 @@ static struct rt_mutex fslock;
|
||||
char working_directory[DFS_PATH_MAX] = {"/"};
|
||||
#endif
|
||||
|
||||
struct dfs_fd fd_table[DFS_FD_MAX];
|
||||
static struct dfs_fdtable _fdtab;
|
||||
static int fd_alloc(struct dfs_fdtable *fdt, int startfd);
|
||||
|
||||
/**
|
||||
* @addtogroup DFS
|
||||
@@ -57,7 +62,7 @@ int dfs_init(void)
|
||||
/* clear filesystem table */
|
||||
memset(filesystem_table, 0, sizeof(filesystem_table));
|
||||
/* clean fd table */
|
||||
memset(fd_table, 0, sizeof(fd_table));
|
||||
memset(&_fdtab, 0, sizeof(_fdtab));
|
||||
|
||||
/* create device filesystem lock */
|
||||
rt_mutex_init(&fslock, "fslock", RT_IPC_FLAG_FIFO);
|
||||
@@ -90,9 +95,13 @@ INIT_PREV_EXPORT(dfs_init);
|
||||
*/
|
||||
void dfs_lock(void)
|
||||
{
|
||||
rt_err_t result;
|
||||
rt_err_t result = -RT_EBUSY;
|
||||
|
||||
while (result == -RT_EBUSY)
|
||||
{
|
||||
result = rt_mutex_take(&fslock, RT_WAITING_FOREVER);
|
||||
}
|
||||
|
||||
result = rt_mutex_take(&fslock, RT_WAITING_FOREVER);
|
||||
if (result != RT_EOK)
|
||||
{
|
||||
RT_ASSERT(0);
|
||||
@@ -109,6 +118,54 @@ void dfs_unlock(void)
|
||||
rt_mutex_release(&fslock);
|
||||
}
|
||||
|
||||
static int fd_alloc(struct dfs_fdtable *fdt, int startfd)
|
||||
{
|
||||
int idx;
|
||||
|
||||
/* find an empty fd entry */
|
||||
for (idx = startfd; idx < fdt->maxfd; idx++)
|
||||
{
|
||||
if (fdt->fds[idx] == RT_NULL)
|
||||
break;
|
||||
if (fdt->fds[idx]->ref_count == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
/* allocate a larger FD container */
|
||||
if (idx == fdt->maxfd && fdt->maxfd < DFS_FD_MAX)
|
||||
{
|
||||
int cnt, index;
|
||||
struct dfs_fd **fds;
|
||||
|
||||
/* increase the number of FD with 4 step length */
|
||||
cnt = fdt->maxfd + 4;
|
||||
cnt = cnt > DFS_FD_MAX? DFS_FD_MAX : cnt;
|
||||
|
||||
fds = rt_realloc(fdt->fds, cnt * sizeof(struct dfs_fd *));
|
||||
if (fds == NULL) goto __out; /* return fdt->maxfd */
|
||||
|
||||
/* clean the new allocated fds */
|
||||
for (index = fdt->maxfd; index < cnt; index ++)
|
||||
{
|
||||
fds[index] = NULL;
|
||||
}
|
||||
|
||||
fdt->fds = fds;
|
||||
fdt->maxfd = cnt;
|
||||
}
|
||||
|
||||
/* allocate 'struct dfs_fd' */
|
||||
if (idx < fdt->maxfd &&fdt->fds[idx] == RT_NULL)
|
||||
{
|
||||
fdt->fds[idx] = rt_malloc(sizeof(struct dfs_fd));
|
||||
if (fdt->fds[idx] == RT_NULL)
|
||||
idx = fdt->maxfd;
|
||||
}
|
||||
|
||||
__out:
|
||||
return idx;
|
||||
}
|
||||
|
||||
/**
|
||||
* @ingroup Fd
|
||||
* This function will allocate a file descriptor.
|
||||
@@ -119,21 +176,23 @@ int fd_new(void)
|
||||
{
|
||||
struct dfs_fd *d;
|
||||
int idx;
|
||||
struct dfs_fdtable *fdt;
|
||||
|
||||
fdt = dfs_fdtable_get();
|
||||
/* lock filesystem */
|
||||
dfs_lock();
|
||||
|
||||
/* find an empty fd entry */
|
||||
for (idx = 0; idx < DFS_FD_MAX && fd_table[idx].ref_count > 0; idx++);
|
||||
idx = fd_alloc(fdt, 0);
|
||||
|
||||
/* can't find an empty fd entry */
|
||||
if (idx == DFS_FD_MAX)
|
||||
if (idx == fdt->maxfd)
|
||||
{
|
||||
idx = -(1 + DFS_FD_OFFSET);
|
||||
goto __result;
|
||||
}
|
||||
|
||||
d = &(fd_table[idx]);
|
||||
d = fdt->fds[idx];
|
||||
d->ref_count = 1;
|
||||
d->magic = DFS_FD_MAGIC;
|
||||
|
||||
@@ -154,13 +213,15 @@ __result:
|
||||
struct dfs_fd *fd_get(int fd)
|
||||
{
|
||||
struct dfs_fd *d;
|
||||
struct dfs_fdtable *fdt;
|
||||
|
||||
fdt = dfs_fdtable_get();
|
||||
fd = fd - DFS_FD_OFFSET;
|
||||
if (fd < 0 || fd >= DFS_FD_MAX)
|
||||
if (fd < 0 || fd >= fdt->maxfd)
|
||||
return NULL;
|
||||
|
||||
dfs_lock();
|
||||
d = &fd_table[fd];
|
||||
d = fdt->fds[fd];
|
||||
|
||||
/* check dfs_fd valid or not */
|
||||
if (d->magic != DFS_FD_MAGIC)
|
||||
@@ -186,12 +247,25 @@ void fd_put(struct dfs_fd *fd)
|
||||
RT_ASSERT(fd != NULL);
|
||||
|
||||
dfs_lock();
|
||||
|
||||
fd->ref_count --;
|
||||
|
||||
/* clear this fd entry */
|
||||
if (fd->ref_count == 0)
|
||||
{
|
||||
memset(fd, 0, sizeof(struct dfs_fd));
|
||||
int index;
|
||||
struct dfs_fdtable *fdt;
|
||||
|
||||
fdt = dfs_fdtable_get();
|
||||
for (index = 0; index < fdt->maxfd; index ++)
|
||||
{
|
||||
if (fdt->fds[index] == fd)
|
||||
{
|
||||
rt_free(fd);
|
||||
fdt->fds[index] = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
dfs_unlock();
|
||||
}
|
||||
@@ -211,7 +285,9 @@ int fd_is_open(const char *pathname)
|
||||
unsigned int index;
|
||||
struct dfs_filesystem *fs;
|
||||
struct dfs_fd *fd;
|
||||
struct dfs_fdtable *fdt;
|
||||
|
||||
fdt = dfs_fdtable_get();
|
||||
fullpath = dfs_normalize_path(NULL, pathname);
|
||||
if (fullpath != NULL)
|
||||
{
|
||||
@@ -233,11 +309,10 @@ int fd_is_open(const char *pathname)
|
||||
|
||||
dfs_lock();
|
||||
|
||||
for (index = 0; index < DFS_FD_MAX; index++)
|
||||
for (index = 0; index < fdt->maxfd; index++)
|
||||
{
|
||||
fd = &(fd_table[index]);
|
||||
if (fd->fops == NULL)
|
||||
continue;
|
||||
fd = fdt->fds[index];
|
||||
if (fd == NULL) continue;
|
||||
|
||||
if (fd->fops == fs->ops->fops && strcmp(fd->path, mountpath) == 0)
|
||||
{
|
||||
@@ -414,17 +489,43 @@ up_one:
|
||||
return fullpath;
|
||||
}
|
||||
RTM_EXPORT(dfs_normalize_path);
|
||||
|
||||
/**
|
||||
* This function will get the file descriptor table of current process.
|
||||
*/
|
||||
struct dfs_fdtable* dfs_fdtable_get(void)
|
||||
{
|
||||
struct dfs_fdtable *fdt;
|
||||
#ifdef RT_USING_LWP
|
||||
struct rt_lwp *lwp;
|
||||
|
||||
lwp = (struct rt_lwp *)rt_thread_self()->user_data;
|
||||
if (lwp)
|
||||
fdt = &lwp->fdt;
|
||||
else
|
||||
fdt = &_fdtab;
|
||||
#else
|
||||
fdt = &_fdtab;
|
||||
#endif
|
||||
|
||||
return fdt;
|
||||
}
|
||||
|
||||
#ifdef RT_USING_FINSH
|
||||
#include <finsh.h>
|
||||
int list_fd(void)
|
||||
{
|
||||
int index;
|
||||
struct dfs_fdtable *fd_table;
|
||||
|
||||
fd_table = dfs_fdtable_get();
|
||||
if (!fd_table) return -1;
|
||||
|
||||
rt_enter_critical();
|
||||
|
||||
for (index = 0; index < DFS_FD_MAX; index ++)
|
||||
for (index = 0; index < fd_table->maxfd; index ++)
|
||||
{
|
||||
struct dfs_fd *fd = &(fd_table[index]);
|
||||
struct dfs_fd *fd = fd_table->fds[index];
|
||||
|
||||
if (fd->fops)
|
||||
{
|
||||
|
||||
@@ -421,6 +421,18 @@ static rt_err_t _audio_dev_control(struct rt_device *dev, int cmd, void *args)
|
||||
return result;
|
||||
}
|
||||
|
||||
#ifdef RT_USING_DEVICE_OPS
|
||||
const static struct rt_device_ops audio_ops =
|
||||
{
|
||||
_audio_dev_init,
|
||||
_audio_dev_open,
|
||||
_audio_dev_close,
|
||||
_audio_dev_read,
|
||||
_audio_dev_write,
|
||||
_audio_dev_control
|
||||
};
|
||||
#endif
|
||||
|
||||
rt_err_t rt_audio_register(struct rt_audio_device *audio, const char *name, rt_uint32_t flag, void *data)
|
||||
{
|
||||
struct rt_device *device;
|
||||
@@ -431,12 +443,16 @@ rt_err_t rt_audio_register(struct rt_audio_device *audio, const char *name, rt_u
|
||||
device->rx_indicate = RT_NULL;
|
||||
device->tx_complete = RT_NULL;
|
||||
|
||||
device->init = _audio_dev_init;
|
||||
device->open = _audio_dev_open;
|
||||
device->close = _audio_dev_close;
|
||||
device->read = _audio_dev_read;
|
||||
device->write = _audio_dev_write;
|
||||
#ifdef RT_USING_DEVICE_OPS
|
||||
device->ops = &audio_ops;
|
||||
#else
|
||||
device->init = _audio_dev_init;
|
||||
device->open = _audio_dev_open;
|
||||
device->close = _audio_dev_close;
|
||||
device->read = _audio_dev_read;
|
||||
device->write = _audio_dev_write;
|
||||
device->control = _audio_dev_control;
|
||||
#endif
|
||||
device->user_data = data;
|
||||
|
||||
//init memory pool for replay
|
||||
|
||||
@@ -193,14 +193,26 @@ static rt_size_t rt_pipe_write(rt_device_t dev,
|
||||
static rt_err_t rt_pipe_control(rt_device_t dev, int cmd, void *args)
|
||||
{
|
||||
struct rt_audio_pipe *pipe;
|
||||
|
||||
|
||||
pipe = (struct rt_audio_pipe *)dev;
|
||||
|
||||
|
||||
if (cmd == PIPE_CTRL_GET_SPACE && args)
|
||||
*(rt_size_t*)args = rt_ringbuffer_space_len(&pipe->ringbuffer);
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
#ifdef RT_USING_DEVICE_OPS
|
||||
const static struct rt_device_ops audio_pipe_ops
|
||||
{
|
||||
RT_NULL,
|
||||
RT_NULL,
|
||||
RT_NULL,
|
||||
rt_pipe_read,
|
||||
rt_pipe_write,
|
||||
rt_pipe_control
|
||||
};
|
||||
#endif
|
||||
|
||||
/**
|
||||
* This function will initialize a pipe device and put it under control of
|
||||
* resource management.
|
||||
@@ -233,12 +245,16 @@ rt_err_t rt_audio_pipe_init(struct rt_audio_pipe *pipe,
|
||||
|
||||
/* create pipe */
|
||||
pipe->parent.type = RT_Device_Class_Pipe;
|
||||
#ifdef RT_USING_DEVICE_OPS
|
||||
pipe->parent.ops = &audio_pipe_ops;
|
||||
#else
|
||||
pipe->parent.init = RT_NULL;
|
||||
pipe->parent.open = RT_NULL;
|
||||
pipe->parent.close = RT_NULL;
|
||||
pipe->parent.read = rt_pipe_read;
|
||||
pipe->parent.write = rt_pipe_write;
|
||||
pipe->parent.control = rt_pipe_control;
|
||||
#endif
|
||||
|
||||
return rt_device_register(&(pipe->parent), name, RT_DEVICE_FLAG_RDWR);
|
||||
}
|
||||
|
||||
@@ -687,6 +687,18 @@ static void cantimeout(void *arg)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef RT_USING_DEVICE_OPS
|
||||
const static struct rt_device_ops can_device_ops =
|
||||
{
|
||||
rt_can_init,
|
||||
rt_can_open,
|
||||
rt_can_close,
|
||||
rt_can_read,
|
||||
rt_can_write,
|
||||
rt_can_control
|
||||
};
|
||||
#endif
|
||||
|
||||
/*
|
||||
* can register
|
||||
*/
|
||||
@@ -712,12 +724,17 @@ rt_err_t rt_hw_can_register(struct rt_can_device *can,
|
||||
#ifdef RT_CAN_USING_BUS_HOOK
|
||||
can->bus_hook = RT_NULL;
|
||||
#endif /*RT_CAN_USING_BUS_HOOK*/
|
||||
|
||||
#ifdef RT_USING_DEVICE_OPS
|
||||
device->ops = &can_device_ops;
|
||||
#else
|
||||
device->init = rt_can_init;
|
||||
device->open = rt_can_open;
|
||||
device->close = rt_can_close;
|
||||
device->read = rt_can_read;
|
||||
device->write = rt_can_write;
|
||||
device->control = rt_can_control;
|
||||
#endif
|
||||
can->ops = ops;
|
||||
|
||||
can->status_indicate.ind = RT_NULL;
|
||||
|
||||
@@ -35,13 +35,13 @@ rt_inline rt_uint32_t timeout_calc(rt_hwtimer_t *timer, rt_hwtimerval_t *tv)
|
||||
float devi_min = 1;
|
||||
float devi;
|
||||
|
||||
/* 把定时器溢出时间和定时时间换算成秒 */
|
||||
/* changed to second */
|
||||
overflow = timer->info->maxcnt/(float)timer->freq;
|
||||
tv_sec = tv->sec + tv->usec/(float)1000000;
|
||||
|
||||
if (tv_sec < (1/(float)timer->freq))
|
||||
{
|
||||
/* 定时时间小于计数周期 */
|
||||
/* little timeout */
|
||||
i = 0;
|
||||
timeout = 1/(float)timer->freq;
|
||||
}
|
||||
@@ -55,7 +55,7 @@ rt_inline rt_uint32_t timeout_calc(rt_hwtimer_t *timer, rt_hwtimerval_t *tv)
|
||||
{
|
||||
counter = timeout*timer->freq;
|
||||
devi = tv_sec - (counter/(float)timer->freq)*i;
|
||||
/* 计算最小误差 */
|
||||
/* Minimum calculation error */
|
||||
if (devi > devi_min)
|
||||
{
|
||||
i = index;
|
||||
@@ -89,7 +89,7 @@ static rt_err_t rt_hwtimer_init(struct rt_device *dev)
|
||||
rt_hwtimer_t *timer;
|
||||
|
||||
timer = (rt_hwtimer_t *)dev;
|
||||
/* 尝试将默认计数频率设为1Mhz */
|
||||
/* try to change to 1MHz */
|
||||
if ((1000000 <= timer->info->maxfreq) && (1000000 >= timer->info->minfreq))
|
||||
{
|
||||
timer->freq = 1000000;
|
||||
@@ -330,6 +330,18 @@ void rt_device_hwtimer_isr(rt_hwtimer_t *timer)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef RT_USING_DEVICE_OPS
|
||||
const static struct rt_device_ops hwtimer_ops =
|
||||
{
|
||||
rt_hwtimer_init,
|
||||
rt_hwtimer_open,
|
||||
rt_hwtimer_close,
|
||||
rt_hwtimer_read,
|
||||
rt_hwtimer_write,
|
||||
rt_hwtimer_control
|
||||
};
|
||||
#endif
|
||||
|
||||
rt_err_t rt_device_hwtimer_register(rt_hwtimer_t *timer, const char *name, void *user_data)
|
||||
{
|
||||
struct rt_device *device;
|
||||
@@ -344,12 +356,16 @@ rt_err_t rt_device_hwtimer_register(rt_hwtimer_t *timer, const char *name, void
|
||||
device->rx_indicate = RT_NULL;
|
||||
device->tx_complete = RT_NULL;
|
||||
|
||||
#ifdef RT_USING_DEVICE_OPS
|
||||
device->ops = &hwtimer_ops;
|
||||
#else
|
||||
device->init = rt_hwtimer_init;
|
||||
device->open = rt_hwtimer_open;
|
||||
device->close = rt_hwtimer_close;
|
||||
device->read = rt_hwtimer_read;
|
||||
device->write = rt_hwtimer_write;
|
||||
device->control = rt_hwtimer_control;
|
||||
#endif
|
||||
device->user_data = user_data;
|
||||
|
||||
return rt_device_register(device, name, RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_STANDALONE);
|
||||
|
||||
@@ -132,6 +132,18 @@ static rt_size_t fm24clxx_write(rt_device_t dev, rt_off_t pos, const void *buffe
|
||||
return (ret == 2) ? size : 0;
|
||||
}
|
||||
|
||||
#ifdef RT_USING_DEVICE_OPS
|
||||
const static struct rt_device fm24clxx_ops =
|
||||
{
|
||||
fm24clxx_init,
|
||||
fm24clxx_open,
|
||||
fm24clxx_close,
|
||||
fm24clxx_read,
|
||||
fm24clxx_write,
|
||||
fm24clxx_control
|
||||
};
|
||||
#endif
|
||||
|
||||
rt_err_t fm24clxx_register(const char *fm_device_name, const char *i2c_bus, void *user_data)
|
||||
{
|
||||
static struct fm24clxx_device fm24clxx_drv;
|
||||
@@ -145,12 +157,17 @@ rt_err_t fm24clxx_register(const char *fm_device_name, const char *i2c_bus, void
|
||||
|
||||
fm24clxx_drv.bus = bus;
|
||||
fm24clxx_drv.parent.type = RT_Device_Class_Block;
|
||||
#ifdef RT_USING_DEVICE_OPS
|
||||
fm24clxx_drv.parent.ops = &fm24clxx_ops;
|
||||
#else
|
||||
fm24clxx_drv.parent.init = fm24clxx_init;
|
||||
fm24clxx_drv.parent.open = fm24clxx_open;
|
||||
fm24clxx_drv.parent.close = fm24clxx_close;
|
||||
fm24clxx_drv.parent.read = fm24clxx_read;
|
||||
fm24clxx_drv.parent.write = fm24clxx_write;
|
||||
fm24clxx_drv.parent.control = fm24clxx_control;
|
||||
#endif
|
||||
|
||||
fm24clxx_drv.parent.user_data = user_data;
|
||||
|
||||
return rt_device_register(&fm24clxx_drv.parent, fm_device_name, RT_DEVICE_FLAG_RDWR);
|
||||
|
||||
@@ -102,6 +102,18 @@ static rt_err_t i2c_bus_device_control(rt_device_t dev,
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
#ifdef RT_USING_DEVICE_OPS
|
||||
const static struct rt_device_ops i2c_ops =
|
||||
{
|
||||
RT_NULL,
|
||||
RT_NULL,
|
||||
RT_NULL,
|
||||
i2c_bus_device_read,
|
||||
i2c_bus_device_write,
|
||||
i2c_bus_device_control
|
||||
};
|
||||
#endif
|
||||
|
||||
rt_err_t rt_i2c_bus_device_device_init(struct rt_i2c_bus_device *bus,
|
||||
const char *name)
|
||||
{
|
||||
@@ -115,12 +127,16 @@ rt_err_t rt_i2c_bus_device_device_init(struct rt_i2c_bus_device *bus,
|
||||
/* set device type */
|
||||
device->type = RT_Device_Class_I2CBUS;
|
||||
/* initialize device interface */
|
||||
#ifdef RT_USING_DEVICE_OPS
|
||||
device->ops = &i2c_ops;
|
||||
#else
|
||||
device->init = RT_NULL;
|
||||
device->open = RT_NULL;
|
||||
device->close = RT_NULL;
|
||||
device->read = i2c_bus_device_read;
|
||||
device->write = i2c_bus_device_write;
|
||||
device->control = i2c_bus_device_control;
|
||||
#endif
|
||||
|
||||
/* register to device manager */
|
||||
rt_device_register(device, name, RT_DEVICE_FLAG_RDWR);
|
||||
|
||||
@@ -76,18 +76,34 @@ static rt_err_t _pin_control(rt_device_t dev, int cmd, void *args)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef RT_USING_DEVICE_OPS
|
||||
const static struct rt_device_ops pin_ops =
|
||||
{
|
||||
RT_NULL,
|
||||
RT_NULL,
|
||||
RT_NULL,
|
||||
_pin_read,
|
||||
_pin_write,
|
||||
_pin_control
|
||||
};
|
||||
#endif
|
||||
|
||||
int rt_device_pin_register(const char *name, const struct rt_pin_ops *ops, void *user_data)
|
||||
{
|
||||
_hw_pin.parent.type = RT_Device_Class_Miscellaneous;
|
||||
_hw_pin.parent.rx_indicate = RT_NULL;
|
||||
_hw_pin.parent.tx_complete = RT_NULL;
|
||||
|
||||
#ifdef RT_USING_DEVICE_OPS
|
||||
_hw_pin.parent.ops = &pin_ops;
|
||||
#else
|
||||
_hw_pin.parent.init = RT_NULL;
|
||||
_hw_pin.parent.open = RT_NULL;
|
||||
_hw_pin.parent.close = RT_NULL;
|
||||
_hw_pin.parent.read = _pin_read;
|
||||
_hw_pin.parent.write = _pin_write;
|
||||
_hw_pin.parent.control = _pin_control;
|
||||
#endif
|
||||
|
||||
_hw_pin.ops = ops;
|
||||
_hw_pin.parent.user_data = user_data;
|
||||
@@ -117,6 +133,7 @@ rt_err_t rt_pin_dettach_irq(rt_int32_t pin)
|
||||
}
|
||||
return RT_ENOSYS;
|
||||
}
|
||||
|
||||
rt_err_t rt_pin_irq_enable(rt_base_t pin, rt_uint32_t enabled)
|
||||
{
|
||||
RT_ASSERT(_hw_pin.ops != RT_NULL);
|
||||
@@ -126,6 +143,7 @@ rt_err_t rt_pin_irq_enable(rt_base_t pin, rt_uint32_t enabled)
|
||||
}
|
||||
return RT_ENOSYS;
|
||||
}
|
||||
|
||||
/* RT-Thread Hardware PIN APIs */
|
||||
void rt_pin_mode(rt_base_t pin, rt_base_t mode)
|
||||
{
|
||||
|
||||
@@ -69,6 +69,18 @@ static rt_err_t _mtd_control(rt_device_t dev, int cmd, void *args)
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
#ifdef RT_USING_DEVICE_OPS
|
||||
const static struct rt_device_ops mtd_nand_ops =
|
||||
{
|
||||
_mtd_init,
|
||||
_mtd_open,
|
||||
_mtd_close,
|
||||
_mtd_read,
|
||||
_mtd_write,
|
||||
_mtd_control
|
||||
};
|
||||
#endif
|
||||
|
||||
rt_err_t rt_mtd_nand_register_device(const char *name,
|
||||
struct rt_mtd_nand_device *device)
|
||||
{
|
||||
@@ -79,12 +91,16 @@ rt_err_t rt_mtd_nand_register_device(const char *name,
|
||||
|
||||
/* set device class and generic device interface */
|
||||
dev->type = RT_Device_Class_MTD;
|
||||
#ifdef RT_USING_DEVICE_OPS
|
||||
dev->ops = &mtd_nand_ops;
|
||||
#else
|
||||
dev->init = _mtd_init;
|
||||
dev->open = _mtd_open;
|
||||
dev->read = _mtd_read;
|
||||
dev->write = _mtd_write;
|
||||
dev->close = _mtd_close;
|
||||
dev->control = _mtd_control;
|
||||
#endif
|
||||
|
||||
dev->rx_indicate = RT_NULL;
|
||||
dev->tx_complete = RT_NULL;
|
||||
|
||||
@@ -65,6 +65,18 @@ static rt_err_t _mtd_control(rt_device_t dev, int cmd, void *args)
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
#ifdef RT_USING_DEVICE_OPS
|
||||
const static struct rt_device_ops mtd_nor_ops =
|
||||
{
|
||||
_mtd_init,
|
||||
_mtd_open,
|
||||
_mtd_close,
|
||||
_mtd_read,
|
||||
_mtd_write,
|
||||
_mtd_control
|
||||
};
|
||||
#endif
|
||||
|
||||
rt_err_t rt_mtd_nor_register_device(const char *name,
|
||||
struct rt_mtd_nor_device *device)
|
||||
{
|
||||
@@ -75,12 +87,16 @@ rt_err_t rt_mtd_nor_register_device(const char *name,
|
||||
|
||||
/* set device class and generic device interface */
|
||||
dev->type = RT_Device_Class_MTD;
|
||||
#ifdef RT_USING_DEVICE_OPS
|
||||
dev->ops = &mtd_nor_ops;
|
||||
#else
|
||||
dev->init = _mtd_init;
|
||||
dev->open = _mtd_open;
|
||||
dev->read = _mtd_read;
|
||||
dev->write = _mtd_write;
|
||||
dev->close = _mtd_close;
|
||||
dev->control = _mtd_control;
|
||||
#endif
|
||||
|
||||
dev->rx_indicate = RT_NULL;
|
||||
dev->tx_complete = RT_NULL;
|
||||
|
||||
@@ -68,6 +68,18 @@ static rt_err_t soft_rtc_control(rt_device_t dev, int cmd, void *args)
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
#ifdef RT_USING_DEVICE_OPS
|
||||
const static struct rt_device_ops soft_rtc_ops =
|
||||
{
|
||||
RT_NULL,
|
||||
RT_NULL,
|
||||
RT_NULL,
|
||||
RT_NULL,
|
||||
RT_NULL,
|
||||
soft_rtc_control
|
||||
};
|
||||
#endif
|
||||
|
||||
int rt_soft_rtc_init(void)
|
||||
{
|
||||
static rt_bool_t init_ok = RT_FALSE;
|
||||
@@ -86,12 +98,16 @@ int rt_soft_rtc_init(void)
|
||||
soft_rtc_dev.type = RT_Device_Class_RTC;
|
||||
|
||||
/* register rtc device */
|
||||
#ifdef RT_USING_DEVICE_OPS
|
||||
soft_rtc_dev.ops = &soft_rtc_ops;
|
||||
#else
|
||||
soft_rtc_dev.init = RT_NULL;
|
||||
soft_rtc_dev.open = RT_NULL;
|
||||
soft_rtc_dev.close = RT_NULL;
|
||||
soft_rtc_dev.read = RT_NULL;
|
||||
soft_rtc_dev.write = RT_NULL;
|
||||
soft_rtc_dev.control = soft_rtc_control;
|
||||
#endif
|
||||
|
||||
/* no private */
|
||||
soft_rtc_dev.user_data = RT_NULL;
|
||||
|
||||
@@ -319,6 +319,18 @@ static rt_int32_t mmcsd_set_blksize(struct rt_mmcsd_card *card)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef RT_USING_DEVICE_OPS
|
||||
const static struct rt_device_ops mmcsd_blk_ops =
|
||||
{
|
||||
rt_mmcsd_init,
|
||||
rt_mmcsd_open,
|
||||
rt_mmcsd_close,
|
||||
rt_mmcsd_read,
|
||||
rt_mmcsd_write,
|
||||
rt_mmcsd_control
|
||||
};
|
||||
#endif
|
||||
|
||||
rt_int32_t rt_mmcsd_blk_probe(struct rt_mmcsd_card *card)
|
||||
{
|
||||
rt_int32_t err = 0;
|
||||
@@ -366,13 +378,17 @@ rt_int32_t rt_mmcsd_blk_probe(struct rt_mmcsd_card *card)
|
||||
blk_dev->part.lock = rt_sem_create(sname, 1, RT_IPC_FLAG_FIFO);
|
||||
|
||||
/* register mmcsd device */
|
||||
blk_dev->dev.type = RT_Device_Class_Block;
|
||||
blk_dev->dev.type = RT_Device_Class_Block;
|
||||
#ifdef RT_USING_DEVICE_OPS
|
||||
blk_dev->dev.ops = &mmcsd_blk_ops;
|
||||
#else
|
||||
blk_dev->dev.init = rt_mmcsd_init;
|
||||
blk_dev->dev.open = rt_mmcsd_open;
|
||||
blk_dev->dev.close = rt_mmcsd_close;
|
||||
blk_dev->dev.read = rt_mmcsd_read;
|
||||
blk_dev->dev.write = rt_mmcsd_write;
|
||||
blk_dev->dev.control = rt_mmcsd_control;
|
||||
#endif
|
||||
blk_dev->dev.user_data = blk_dev;
|
||||
|
||||
blk_dev->card = card;
|
||||
@@ -396,12 +412,16 @@ rt_int32_t rt_mmcsd_blk_probe(struct rt_mmcsd_card *card)
|
||||
|
||||
/* register mmcsd device */
|
||||
blk_dev->dev.type = RT_Device_Class_Block;
|
||||
#ifdef RT_USING_DEVICE_OPS
|
||||
blk_dev->dev.ops = &mmcsd_blk_ops;
|
||||
#else
|
||||
blk_dev->dev.init = rt_mmcsd_init;
|
||||
blk_dev->dev.open = rt_mmcsd_open;
|
||||
blk_dev->dev.close = rt_mmcsd_close;
|
||||
blk_dev->dev.read = rt_mmcsd_read;
|
||||
blk_dev->dev.write = rt_mmcsd_write;
|
||||
blk_dev->dev.control = rt_mmcsd_control;
|
||||
#endif
|
||||
blk_dev->dev.user_data = blk_dev;
|
||||
|
||||
blk_dev->card = card;
|
||||
@@ -482,6 +502,3 @@ int rt_mmcsd_blk_init(void)
|
||||
/* nothing */
|
||||
return 0;
|
||||
}
|
||||
|
||||
INIT_PREV_EXPORT(rt_mmcsd_blk_init);
|
||||
|
||||
|
||||
@@ -1072,6 +1072,18 @@ static rt_err_t rt_serial_control(struct rt_device *dev,
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef RT_USING_DEVICE_OPS
|
||||
const static struct rt_device_ops serial_ops =
|
||||
{
|
||||
rt_serial_init,
|
||||
rt_serial_open,
|
||||
rt_serial_close,
|
||||
rt_serial_read,
|
||||
rt_serial_write,
|
||||
rt_serial_control
|
||||
};
|
||||
#endif
|
||||
|
||||
/*
|
||||
* serial register
|
||||
*/
|
||||
@@ -1090,12 +1102,16 @@ rt_err_t rt_hw_serial_register(struct rt_serial_device *serial,
|
||||
device->rx_indicate = RT_NULL;
|
||||
device->tx_complete = RT_NULL;
|
||||
|
||||
#ifdef RT_USING_DEVICE_OPS
|
||||
device->ops = &serial_ops;
|
||||
#else
|
||||
device->init = rt_serial_init;
|
||||
device->open = rt_serial_open;
|
||||
device->close = rt_serial_close;
|
||||
device->read = rt_serial_read;
|
||||
device->write = rt_serial_write;
|
||||
device->control = rt_serial_control;
|
||||
#endif
|
||||
device->user_data = data;
|
||||
|
||||
/* register a character device */
|
||||
|
||||
@@ -741,6 +741,18 @@ static struct pbuf *enc28j60_rx(rt_device_t dev)
|
||||
return p;
|
||||
}
|
||||
|
||||
#ifdef RT_USING_DEVICE_OPS
|
||||
const static struct rt_device_ops enc28j60_ops =
|
||||
{
|
||||
enc28j60_init,
|
||||
enc28j60_open,
|
||||
enc28j60_close,
|
||||
enc28j60_read,
|
||||
enc28j60_write,
|
||||
enc28j60_control
|
||||
};
|
||||
#endif
|
||||
|
||||
rt_err_t enc28j60_attach(const char *spi_device_name)
|
||||
{
|
||||
struct rt_spi_device *spi_device;
|
||||
@@ -802,12 +814,16 @@ rt_err_t enc28j60_attach(const char *spi_device_name)
|
||||
|
||||
/* init rt-thread device struct */
|
||||
enc28j60_dev.parent.parent.type = RT_Device_Class_NetIf;
|
||||
#ifdef RT_USING_DEVICE_OPS
|
||||
enc28j60_dev.parent.parent.ops = &enc28j60_ops;
|
||||
#else
|
||||
enc28j60_dev.parent.parent.init = enc28j60_init;
|
||||
enc28j60_dev.parent.parent.open = enc28j60_open;
|
||||
enc28j60_dev.parent.parent.close = enc28j60_close;
|
||||
enc28j60_dev.parent.parent.read = enc28j60_read;
|
||||
enc28j60_dev.parent.parent.write = enc28j60_write;
|
||||
enc28j60_dev.parent.parent.control = enc28j60_control;
|
||||
#endif
|
||||
|
||||
/* init rt-thread ethernet device struct */
|
||||
enc28j60_dev.parent.eth_rx = enc28j60_rx;
|
||||
|
||||
@@ -69,6 +69,18 @@ static rt_err_t _spi_bus_device_control(rt_device_t dev,
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
#ifdef RT_USING_DEVICE_OPS
|
||||
const static struct rt_device_ops spi_bus_ops =
|
||||
{
|
||||
RT_NULL,
|
||||
RT_NULL,
|
||||
RT_NULL,
|
||||
_spi_bus_device_read,
|
||||
_spi_bus_device_write,
|
||||
_spi_bus_device_control
|
||||
};
|
||||
#endif
|
||||
|
||||
rt_err_t rt_spi_bus_device_init(struct rt_spi_bus *bus, const char *name)
|
||||
{
|
||||
struct rt_device *device;
|
||||
@@ -79,12 +91,16 @@ rt_err_t rt_spi_bus_device_init(struct rt_spi_bus *bus, const char *name)
|
||||
/* set device type */
|
||||
device->type = RT_Device_Class_SPIBUS;
|
||||
/* initialize device interface */
|
||||
#ifdef RT_USING_DEVICE_OPS
|
||||
device->ops = &spi_bus_ops;
|
||||
#else
|
||||
device->init = RT_NULL;
|
||||
device->open = RT_NULL;
|
||||
device->close = RT_NULL;
|
||||
device->read = _spi_bus_device_read;
|
||||
device->write = _spi_bus_device_write;
|
||||
device->control = _spi_bus_device_control;
|
||||
#endif
|
||||
|
||||
/* register to device manager */
|
||||
return rt_device_register(device, name, RT_DEVICE_FLAG_RDWR);
|
||||
@@ -134,6 +150,18 @@ static rt_err_t _spidev_device_control(rt_device_t dev,
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
#ifdef RT_USING_DEVICE_OPS
|
||||
const static struct rt_device_ops spi_device_ops =
|
||||
{
|
||||
RT_NULL,
|
||||
RT_NULL,
|
||||
RT_NULL,
|
||||
_spidev_device_read,
|
||||
_spidev_device_write,
|
||||
_spidev_device_control
|
||||
};
|
||||
#endif
|
||||
|
||||
rt_err_t rt_spidev_device_init(struct rt_spi_device *dev, const char *name)
|
||||
{
|
||||
struct rt_device *device;
|
||||
@@ -143,13 +171,17 @@ rt_err_t rt_spidev_device_init(struct rt_spi_device *dev, const char *name)
|
||||
|
||||
/* set device type */
|
||||
device->type = RT_Device_Class_SPIDevice;
|
||||
#ifdef RT_USING_DEVICE_OPS
|
||||
device->ops = &spi_device_ops;
|
||||
#else
|
||||
device->init = RT_NULL;
|
||||
device->open = RT_NULL;
|
||||
device->close = RT_NULL;
|
||||
device->read = _spidev_device_read;
|
||||
device->write = _spidev_device_write;
|
||||
device->control = _spidev_device_control;
|
||||
|
||||
#endif
|
||||
|
||||
/* register to device manager */
|
||||
return rt_device_register(device, name, RT_DEVICE_FLAG_RDWR);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* File : spi_flash_gd.c
|
||||
* This file is part of RT-Thread RTOS
|
||||
* Copyright (c) 2016 Shanghai Fullhan Microelectronics Co., Ltd.
|
||||
* Copyright (c) 2016 Shanghai Fullhan Microelectronics Co., Ltd.
|
||||
* All rights reserved
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -254,6 +254,18 @@ static rt_size_t w25qxx_flash_write(rt_device_t dev,
|
||||
return size;
|
||||
}
|
||||
|
||||
#ifdef RT_USING_DEVICE_OPS
|
||||
const static struct rt_device_ops gd_device_ops =
|
||||
{
|
||||
w25qxx_flash_init,
|
||||
w25qxx_flash_open,
|
||||
w25qxx_flash_close,
|
||||
w25qxx_flash_read,
|
||||
w25qxx_flash_write,
|
||||
w25qxx_flash_control
|
||||
};
|
||||
#endif
|
||||
|
||||
rt_err_t gd_init(const char * flash_device_name, const char * spi_device_name)
|
||||
{
|
||||
struct rt_spi_device * rt_spi_device;
|
||||
@@ -330,12 +342,16 @@ rt_err_t gd_init(const char * flash_device_name, const char * spi_device_name)
|
||||
|
||||
/* register device */
|
||||
spi_flash_device.flash_device.type = RT_Device_Class_Block;
|
||||
#ifdef RT_USING_DEVICE_OPS
|
||||
spi_flash_device.flash_device.ops = &gd_device_ops;
|
||||
#else
|
||||
spi_flash_device.flash_device.init = w25qxx_flash_init;
|
||||
spi_flash_device.flash_device.open = w25qxx_flash_open;
|
||||
spi_flash_device.flash_device.close = w25qxx_flash_close;
|
||||
spi_flash_device.flash_device.read = w25qxx_flash_read;
|
||||
spi_flash_device.flash_device.write = w25qxx_flash_write;
|
||||
spi_flash_device.flash_device.control = w25qxx_flash_control;
|
||||
#endif
|
||||
/* no private */
|
||||
spi_flash_device.flash_device.user_data = RT_NULL;
|
||||
|
||||
|
||||
@@ -228,6 +228,18 @@ sfud_err sfud_spi_port_init(sfud_flash *flash) {
|
||||
return result;
|
||||
}
|
||||
|
||||
#ifdef RT_USING_DEVICE_OPS
|
||||
const static struct rt_device_ops flash_device_ops =
|
||||
{
|
||||
RT_NULL,
|
||||
RT_NULL,
|
||||
RT_NULL,
|
||||
rt_sfud_read,
|
||||
rt_sfud_write,
|
||||
rt_sfud_control
|
||||
};
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Probe SPI flash by SFUD(Serial Flash Universal Driver) driver library and though SPI device.
|
||||
*
|
||||
@@ -258,7 +270,7 @@ rt_spi_flash_device_t rt_sfud_flash_probe(const char *spi_flash_dev_name, const
|
||||
/* initialize lock */
|
||||
rt_mutex_init(&(rtt_dev->lock), spi_flash_dev_name, RT_IPC_FLAG_FIFO);
|
||||
}
|
||||
|
||||
|
||||
if (rtt_dev && sfud_dev && spi_flash_dev_name_bak && spi_dev_name_bak) {
|
||||
rt_memset(sfud_dev, 0, sizeof(sfud_flash));
|
||||
rt_strncpy(spi_flash_dev_name_bak, spi_flash_dev_name, rt_strlen(spi_flash_dev_name));
|
||||
@@ -297,12 +309,16 @@ rt_spi_flash_device_t rt_sfud_flash_probe(const char *spi_flash_dev_name, const
|
||||
|
||||
/* register device */
|
||||
rtt_dev->flash_device.type = RT_Device_Class_Block;
|
||||
#ifdef RT_USING_DEVICE_OPS
|
||||
rtt_dev->flash_device.ops = &flash_device_ops;
|
||||
#else
|
||||
rtt_dev->flash_device.init = RT_NULL;
|
||||
rtt_dev->flash_device.open = RT_NULL;
|
||||
rtt_dev->flash_device.close = RT_NULL;
|
||||
rtt_dev->flash_device.read = rt_sfud_read;
|
||||
rtt_dev->flash_device.write = rt_sfud_write;
|
||||
rtt_dev->flash_device.control = rt_sfud_control;
|
||||
#endif
|
||||
|
||||
rt_device_register(&(rtt_dev->flash_device), spi_flash_dev_name, RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_STANDALONE);
|
||||
|
||||
|
||||
@@ -254,6 +254,18 @@ static rt_size_t sst25vfxx_flash_write(rt_device_t dev, rt_off_t pos, const void
|
||||
return size;
|
||||
}
|
||||
|
||||
#ifdef RT_USING_DEVICE_OPS
|
||||
const static struct rt_device_ops sst25vfxx_device_ops =
|
||||
{
|
||||
sst25vfxx_flash_init,
|
||||
sst25vfxx_flash_open,
|
||||
sst25vfxx_flash_close,
|
||||
sst25vfxx_flash_read,
|
||||
sst25vfxx_flash_write,
|
||||
sst25vfxx_flash_control
|
||||
};
|
||||
#endif
|
||||
|
||||
rt_err_t sst25vfxx_init(const char * flash_device_name, const char * spi_device_name)
|
||||
{
|
||||
struct rt_spi_device * rt_spi_device;
|
||||
@@ -340,12 +352,16 @@ rt_err_t sst25vfxx_init(const char * flash_device_name, const char * spi_device_
|
||||
|
||||
/* register device */
|
||||
spi_flash->flash_device.type = RT_Device_Class_Block;
|
||||
#ifdef RT_USING_DEVICE_OPS
|
||||
spi_flash->flash_device.ops = &sst25vfxx_device_ops;
|
||||
#else
|
||||
spi_flash->flash_device.init = sst25vfxx_flash_init;
|
||||
spi_flash->flash_device.open = sst25vfxx_flash_open;
|
||||
spi_flash->flash_device.close = sst25vfxx_flash_close;
|
||||
spi_flash->flash_device.read = sst25vfxx_flash_read;
|
||||
spi_flash->flash_device.write = sst25vfxx_flash_write;
|
||||
spi_flash->flash_device.control = sst25vfxx_flash_control;
|
||||
#endif
|
||||
/* no private */
|
||||
spi_flash->flash_device.user_data = RT_NULL;
|
||||
|
||||
|
||||
@@ -264,6 +264,18 @@ static rt_size_t w25qxx_flash_write(rt_device_t dev,
|
||||
return size;
|
||||
}
|
||||
|
||||
#ifdef RT_USING_DEVICE_OPS
|
||||
const static struct rt_device_ops w25qxx_device_ops =
|
||||
{
|
||||
w25qxx_flash_init,
|
||||
w25qxx_flash_open,
|
||||
w25qxx_flash_close,
|
||||
w25qxx_flash_read,
|
||||
w25qxx_flash_write,
|
||||
w25qxx_flash_control
|
||||
};
|
||||
#endif
|
||||
|
||||
rt_err_t w25qxx_init(const char * flash_device_name, const char * spi_device_name)
|
||||
{
|
||||
struct rt_spi_device * rt_spi_device;
|
||||
@@ -375,12 +387,16 @@ rt_err_t w25qxx_init(const char * flash_device_name, const char * spi_device_nam
|
||||
|
||||
/* register device */
|
||||
spi_flash_device.flash_device.type = RT_Device_Class_Block;
|
||||
#ifdef RT_USING_DEVICE_OPS
|
||||
spi_flash_device.flash_device.ops = &w25qxx_device_ops;
|
||||
#else
|
||||
spi_flash_device.flash_device.init = w25qxx_flash_init;
|
||||
spi_flash_device.flash_device.open = w25qxx_flash_open;
|
||||
spi_flash_device.flash_device.close = w25qxx_flash_close;
|
||||
spi_flash_device.flash_device.read = w25qxx_flash_read;
|
||||
spi_flash_device.flash_device.write = w25qxx_flash_write;
|
||||
spi_flash_device.flash_device.control = w25qxx_flash_control;
|
||||
#endif
|
||||
/* no private */
|
||||
spi_flash_device.flash_device.user_data = RT_NULL;
|
||||
|
||||
|
||||
@@ -47,10 +47,14 @@ static void MSD_release_cs(struct rt_spi_device *device);
|
||||
|
||||
static rt_err_t _wait_token(struct rt_spi_device *device, uint8_t token);
|
||||
static rt_err_t _wait_ready(struct rt_spi_device *device);
|
||||
static rt_err_t rt_msd_init(rt_device_t dev);
|
||||
static rt_err_t rt_msd_open(rt_device_t dev, rt_uint16_t oflag);
|
||||
static rt_err_t rt_msd_close(rt_device_t dev);
|
||||
static rt_size_t rt_msd_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size);
|
||||
static rt_size_t rt_msd_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size);
|
||||
static rt_size_t rt_msd_sdhc_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size);
|
||||
static rt_size_t rt_msd_sdhc_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size);
|
||||
static rt_err_t rt_msd_control(rt_device_t dev, int cmd, void *args);
|
||||
|
||||
static rt_err_t MSD_take_owner(struct rt_spi_device *spi_device)
|
||||
{
|
||||
@@ -461,6 +465,28 @@ static rt_err_t _write_block(struct rt_spi_device *device, const void *buffer, u
|
||||
return _wait_ready(device);
|
||||
}
|
||||
|
||||
#ifdef RT_USING_DEVICE_OPS
|
||||
const static struct rt_device_ops msd_ops =
|
||||
{
|
||||
rt_msd_init,
|
||||
rt_msd_open,
|
||||
rt_msd_close,
|
||||
rt_msd_read,
|
||||
rt_msd_write,
|
||||
rt_msd_control
|
||||
};
|
||||
|
||||
const static struct rt_device_ops msd_sdhc_ops =
|
||||
{
|
||||
rt_msd_init,
|
||||
rt_msd_open,
|
||||
rt_msd_close,
|
||||
rt_msd_sdhc_read,
|
||||
rt_msd_sdhc_write,
|
||||
rt_msd_control
|
||||
};
|
||||
#endif
|
||||
|
||||
/* RT-Thread Device Driver Interface */
|
||||
static rt_err_t rt_msd_init(rt_device_t dev)
|
||||
{
|
||||
@@ -893,13 +919,21 @@ static rt_err_t rt_msd_init(rt_device_t dev)
|
||||
|
||||
if (msd->card_type == MSD_CARD_TYPE_SD_SDHC)
|
||||
{
|
||||
#ifdef RT_USING_DEVICE_OPS
|
||||
dev->ops = &msd_sdhc_ops;
|
||||
#else
|
||||
dev->read = rt_msd_sdhc_read;
|
||||
dev->write = rt_msd_sdhc_write;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef RT_USING_DEVICE_OPS
|
||||
dev->ops = &msd_ops;
|
||||
#else
|
||||
dev->read = rt_msd_read;
|
||||
dev->write = rt_msd_write;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* set CRC */
|
||||
@@ -1674,12 +1708,16 @@ rt_err_t msd_init(const char *sd_device_name, const char *spi_device_name)
|
||||
_msd_device.geometry.sector_count = 0;
|
||||
_msd_device.geometry.block_size = 0;
|
||||
|
||||
#ifdef RT_USING_DEVICE_OPS
|
||||
_msd_device.parent.ops = &msd_ops;
|
||||
#else
|
||||
_msd_device.parent.init = rt_msd_init;
|
||||
_msd_device.parent.open = rt_msd_open;
|
||||
_msd_device.parent.close = rt_msd_close;
|
||||
_msd_device.parent.read = RT_NULL;
|
||||
_msd_device.parent.write = RT_NULL;
|
||||
_msd_device.parent.control = rt_msd_control;
|
||||
#endif
|
||||
|
||||
/* no private, no callback */
|
||||
_msd_device.parent.user_data = RT_NULL;
|
||||
|
||||
@@ -629,6 +629,18 @@ static void spi_wifi_data_thread_entry(void *parameter)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef RT_USING_DEVICE_OPS
|
||||
const static struct rt_device_ops rw009_ops =
|
||||
{
|
||||
rw009_wifi_init,
|
||||
rw009_wifi_open,
|
||||
rw009_wifi_close,
|
||||
rw009_wifi_read,
|
||||
rw009_wifi_write,
|
||||
rw009_wifi_control
|
||||
};
|
||||
#endif
|
||||
|
||||
rt_err_t rt_hw_wifi_init(const char *spi_device_name, wifi_mode_t mode)
|
||||
{
|
||||
/* align and struct size check. */
|
||||
@@ -654,12 +666,16 @@ rt_err_t rt_hw_wifi_init(const char *spi_device_name, wifi_mode_t mode)
|
||||
rt_spi_configure(rw009_wifi_device.rt_spi_device, &cfg);
|
||||
}
|
||||
|
||||
#ifdef RT_USING_DEVICE_OPS
|
||||
rw009_wifi_device.parent.parent.ops = &rw009_ops;
|
||||
#else
|
||||
rw009_wifi_device.parent.parent.init = rw009_wifi_init;
|
||||
rw009_wifi_device.parent.parent.open = rw009_wifi_open;
|
||||
rw009_wifi_device.parent.parent.close = rw009_wifi_close;
|
||||
rw009_wifi_device.parent.parent.read = rw009_wifi_read;
|
||||
rw009_wifi_device.parent.parent.write = rw009_wifi_write;
|
||||
rw009_wifi_device.parent.parent.control = rw009_wifi_control;
|
||||
#endif
|
||||
rw009_wifi_device.parent.parent.user_data = RT_NULL;
|
||||
|
||||
rw009_wifi_device.parent.eth_rx = rw009_wifi_rx;
|
||||
|
||||
@@ -416,6 +416,18 @@ rt_err_t rt_pipe_control(rt_device_t dev, int cmd, void *args)
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
#ifdef RT_USING_DEVICE_OPS
|
||||
const static struct rt_device_ops pipe_ops =
|
||||
{
|
||||
RT_NULL,
|
||||
rt_pipe_open,
|
||||
rt_pipe_close,
|
||||
rt_pipe_read,
|
||||
rt_pipe_write,
|
||||
rt_pipe_control,
|
||||
};
|
||||
#endif
|
||||
|
||||
rt_pipe_t *rt_pipe_create(const char *name, int bufsz)
|
||||
{
|
||||
rt_pipe_t *pipe;
|
||||
@@ -434,12 +446,16 @@ rt_pipe_t *rt_pipe_create(const char *name, int bufsz)
|
||||
|
||||
dev = &(pipe->parent);
|
||||
dev->type = RT_Device_Class_Pipe;
|
||||
#ifdef RT_USING_DEVICE_OPS
|
||||
dev->ops = &pipe_ops;
|
||||
#else
|
||||
dev->init = RT_NULL;
|
||||
dev->open = rt_pipe_open;
|
||||
dev->read = rt_pipe_read;
|
||||
dev->write = rt_pipe_write;
|
||||
dev->close = rt_pipe_close;
|
||||
dev->control = rt_pipe_control;
|
||||
#endif
|
||||
|
||||
dev->rx_indicate = RT_NULL;
|
||||
dev->tx_complete = RT_NULL;
|
||||
|
||||
@@ -327,6 +327,19 @@ static rt_err_t rt_ecm_eth_control(rt_device_t dev, int cmd, void *args)
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
#ifdef RT_USING_DEVICE_OPS
|
||||
const static struct rt_device_ops ecm_device_ops =
|
||||
{
|
||||
rt_ecm_eth_init,
|
||||
rt_ecm_eth_open,
|
||||
rt_ecm_eth_close,
|
||||
rt_ecm_eth_read,
|
||||
rt_ecm_eth_write,
|
||||
rt_ecm_eth_control
|
||||
};
|
||||
#endif
|
||||
|
||||
struct pbuf *rt_ecm_eth_rx(rt_device_t dev)
|
||||
{
|
||||
struct pbuf* p = RT_NULL;
|
||||
|
||||
@@ -592,14 +592,33 @@ static void hid_thread_entry(void* parameter)
|
||||
HID_Report_Received(&report);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef RT_USING_DEVICE_OPS
|
||||
const static struct rt_device_ops hid_device_ops =
|
||||
{
|
||||
RT_NULL,
|
||||
RT_NULL,
|
||||
RT_NULL,
|
||||
RT_NULL,
|
||||
_hid_write,
|
||||
RT_NULL,
|
||||
};
|
||||
#endif
|
||||
|
||||
static rt_uint8_t hid_mq_pool[(sizeof(struct hid_report)+sizeof(void*))*8];
|
||||
static void rt_usb_hid_init(struct ufunction *func)
|
||||
{
|
||||
struct hid_s *hiddev;
|
||||
hiddev = (struct hid_s *)func->user_data;
|
||||
rt_memset(&hiddev->parent, 0, sizeof(hiddev->parent));
|
||||
|
||||
#ifdef RT_USING_DEVICE_OPS
|
||||
hiddev->parent.ops = &hid_device_ops;
|
||||
#else
|
||||
hiddev->parent.write = _hid_write;
|
||||
hiddev->func = func;
|
||||
#endif
|
||||
hiddev->func = func;
|
||||
|
||||
rt_device_register(&hiddev->parent, "hidd", RT_DEVICE_FLAG_RDWR);
|
||||
rt_mq_init(&hiddev->hid_mq, "hiddmq", hid_mq_pool, sizeof(struct hid_report),
|
||||
sizeof(hid_mq_pool), RT_IPC_FLAG_FIFO);
|
||||
|
||||
@@ -1180,6 +1180,19 @@ rt_err_t rt_rndis_eth_tx(rt_device_t dev, struct pbuf* p)
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#ifdef RT_USING_DEVICE_OPS
|
||||
const static struct rt_device_ops rndis_device_ops =
|
||||
{
|
||||
rt_rndis_eth_init,
|
||||
rt_rndis_eth_open,
|
||||
rt_rndis_eth_close,
|
||||
rt_rndis_eth_read,
|
||||
rt_rndis_eth_write,
|
||||
rt_rndis_eth_control
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif /* RT_USING_LWIP */
|
||||
|
||||
#ifdef RNDIS_DELAY_LINK_UP
|
||||
@@ -1307,20 +1320,24 @@ ufunction_t rt_usbd_function_rndis_create(udevice_t device)
|
||||
_rndis->host_addr[4] = 0xEA;//*(const rt_uint8_t *)(0x0FE081F1);
|
||||
_rndis->host_addr[5] = 0x13;//*(const rt_uint8_t *)(0x0FE081F2);
|
||||
|
||||
#ifdef RT_USING_DEVICE_OPS
|
||||
_rndis->parent.parent.ops = &rndis_device_ops;
|
||||
#else
|
||||
_rndis->parent.parent.init = rt_rndis_eth_init;
|
||||
_rndis->parent.parent.open = rt_rndis_eth_open;
|
||||
_rndis->parent.parent.close = rt_rndis_eth_close;
|
||||
_rndis->parent.parent.read = rt_rndis_eth_read;
|
||||
_rndis->parent.parent.write = rt_rndis_eth_write;
|
||||
_rndis->parent.parent.control = rt_rndis_eth_control;
|
||||
#endif
|
||||
_rndis->parent.parent.user_data = device;
|
||||
|
||||
_rndis->parent.eth_rx = rt_rndis_eth_rx;
|
||||
_rndis->parent.eth_tx = rt_rndis_eth_tx;
|
||||
|
||||
/* register eth device */
|
||||
/* register eth device */
|
||||
eth_device_init(&((rt_rndis_eth_t)cdc->user_data)->parent, "u0");
|
||||
|
||||
|
||||
#endif /* RT_USING_LWIP */
|
||||
|
||||
return cdc;
|
||||
|
||||
@@ -246,16 +246,34 @@ static rt_err_t win_usb_control(rt_device_t dev, int cmd, void *args)
|
||||
}
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
#ifdef RT_USING_DEVICE_OPS
|
||||
const static struct rt_device_ops winusb_device_ops =
|
||||
{
|
||||
RT_NULL,
|
||||
RT_NULL,
|
||||
RT_NULL,
|
||||
win_usb_read,
|
||||
win_usb_write,
|
||||
win_usb_control,
|
||||
};
|
||||
#endif
|
||||
|
||||
static rt_err_t rt_usb_winusb_init(ufunction_t func)
|
||||
{
|
||||
winusb_device_t winusb_device = (winusb_device_t)func->user_data;
|
||||
winusb_device->parent.type = RT_Device_Class_Miscellaneous;
|
||||
|
||||
#ifdef RT_USING_DEVICE_OPS
|
||||
winusb_device->parent.ops = &winusb_device_ops;
|
||||
#else
|
||||
winusb_device->parent.init = RT_NULL;
|
||||
winusb_device->parent.open = RT_NULL;
|
||||
winusb_device->parent.close = RT_NULL;
|
||||
winusb_device->parent.read = win_usb_read;
|
||||
winusb_device->parent.write = win_usb_write;
|
||||
winusb_device->parent.control = win_usb_control;
|
||||
#endif
|
||||
|
||||
winusb_device->parent.user_data = func;
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ static const char* _adk_uri = RT_NULL;
|
||||
static const char* _adk_serial = RT_NULL;
|
||||
|
||||
rt_err_t rt_usbh_adk_set_string(const char* manufacturer, const char* model,
|
||||
const char* description, const char* _version, const char* uri,
|
||||
const char* description, const char* _version, const char* uri,
|
||||
const char* serial)
|
||||
{
|
||||
_adk_manufacturer = manufacturer;
|
||||
@@ -62,31 +62,31 @@ RTM_EXPORT(rt_usbh_adk_set_string);
|
||||
* @param intf the interface instance.
|
||||
* @duration the idle period of requesting data.
|
||||
* @report_id the report id
|
||||
*
|
||||
*
|
||||
* @return the error code, RT_EOK on successfully.
|
||||
*/
|
||||
static rt_err_t rt_usbh_adk_get_protocol(struct uintf* intf, rt_uint16_t *protocol)
|
||||
{
|
||||
struct urequest setup;
|
||||
uinst_t device;
|
||||
uinst_t device;
|
||||
int timeout = 100;
|
||||
|
||||
|
||||
/* parameter check */
|
||||
RT_ASSERT(intf != RT_NULL);
|
||||
RT_ASSERT(intf->device != RT_NULL);
|
||||
|
||||
device = intf->device;
|
||||
|
||||
setup.request_type = USB_REQ_TYPE_DIR_IN | USB_REQ_TYPE_VENDOR |
|
||||
setup.request_type = USB_REQ_TYPE_DIR_IN | USB_REQ_TYPE_VENDOR |
|
||||
USB_REQ_TYPE_DEVICE;
|
||||
setup.request = USB_REQ_GET_PROTOCOL;
|
||||
setup.index = 0;
|
||||
setup.length = 2;
|
||||
setup.value = 0;
|
||||
|
||||
if(rt_usb_hcd_control_xfer(device->hcd, device, &setup, (void*)protocol, 2,
|
||||
if(rt_usb_hcd_control_xfer(device->hcd, device, &setup, (void*)protocol, 2,
|
||||
timeout) == 0) return RT_EOK;
|
||||
else return -RT_FALSE;
|
||||
else return -RT_FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -95,32 +95,32 @@ static rt_err_t rt_usbh_adk_get_protocol(struct uintf* intf, rt_uint16_t *protoc
|
||||
* @param intf the interface instance.
|
||||
* @duration the idle period of requesting data.
|
||||
* @report_id the report id
|
||||
*
|
||||
*
|
||||
* @return the error code, RT_EOK on successfully.
|
||||
*/
|
||||
static rt_err_t rt_usbh_adk_send_string(struct uintf* intf, rt_uint16_t index,
|
||||
static rt_err_t rt_usbh_adk_send_string(struct uintf* intf, rt_uint16_t index,
|
||||
const char* str)
|
||||
{
|
||||
struct urequest setup;
|
||||
uinst_t device;
|
||||
uinst_t device;
|
||||
int timeout = 100;
|
||||
|
||||
|
||||
/* parameter check */
|
||||
RT_ASSERT(intf != RT_NULL);
|
||||
RT_ASSERT(intf->device != RT_NULL);
|
||||
|
||||
device = intf->device;
|
||||
|
||||
setup.request_type = USB_REQ_TYPE_DIR_OUT | USB_REQ_TYPE_VENDOR |
|
||||
setup.request_type = USB_REQ_TYPE_DIR_OUT | USB_REQ_TYPE_VENDOR |
|
||||
USB_REQ_TYPE_DEVICE;
|
||||
setup.request = USB_REQ_SEND_STRING;
|
||||
setup.index = index;
|
||||
setup.length = rt_strlen(str) + 1;
|
||||
setup.value = 0;
|
||||
|
||||
if(rt_usb_hcd_control_xfer(device->hcd, device, &setup, (void*)str,
|
||||
if(rt_usb_hcd_control_xfer(device->hcd, device, &setup, (void*)str,
|
||||
rt_strlen(str) + 1, timeout) == 0) return RT_EOK;
|
||||
else return -RT_FALSE;
|
||||
else return -RT_FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -129,41 +129,41 @@ static rt_err_t rt_usbh_adk_send_string(struct uintf* intf, rt_uint16_t index,
|
||||
* @param intf the interface instance.
|
||||
* @duration the idle period of requesting data.
|
||||
* @report_id the report id
|
||||
*
|
||||
*
|
||||
* @return the error code, RT_EOK on successfully.
|
||||
*/
|
||||
static rt_err_t rt_usbh_adk_start(struct uintf* intf)
|
||||
{
|
||||
struct urequest setup;
|
||||
uinst_t device;
|
||||
uinst_t device;
|
||||
int timeout = 100;
|
||||
|
||||
|
||||
/* parameter check */
|
||||
RT_ASSERT(intf != RT_NULL);
|
||||
RT_ASSERT(intf->device != RT_NULL);
|
||||
|
||||
device = intf->device;
|
||||
|
||||
setup.request_type = USB_REQ_TYPE_DIR_OUT | USB_REQ_TYPE_VENDOR |
|
||||
setup.request_type = USB_REQ_TYPE_DIR_OUT | USB_REQ_TYPE_VENDOR |
|
||||
USB_REQ_TYPE_DEVICE;
|
||||
setup.request = USB_REQ_START;
|
||||
setup.index = 0;
|
||||
setup.length = 0;
|
||||
setup.value = 0;
|
||||
|
||||
if(rt_usb_hcd_control_xfer(device->hcd, device, &setup, RT_NULL, 0,
|
||||
if(rt_usb_hcd_control_xfer(device->hcd, device, &setup, RT_NULL, 0,
|
||||
timeout) == 0) return RT_EOK;
|
||||
else return -RT_FALSE;
|
||||
else return -RT_FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function will read data from usb adk device
|
||||
*
|
||||
* @param intf the interface instance.
|
||||
*
|
||||
*
|
||||
* @return the error code, RT_EOK on successfully.
|
||||
*/
|
||||
static rt_size_t rt_usbh_adk_read(rt_device_t device, rt_off_t pos, void* buffer,
|
||||
static rt_size_t rt_usbh_adk_read(rt_device_t device, rt_off_t pos, void* buffer,
|
||||
rt_size_t size)
|
||||
{
|
||||
uadk_t adk;
|
||||
@@ -177,9 +177,9 @@ static rt_size_t rt_usbh_adk_read(rt_device_t device, rt_off_t pos, void* buffer
|
||||
intf = (struct uintf*)device->user_data;
|
||||
adk = (uadk_t)intf->user_data;
|
||||
|
||||
length = rt_usb_hcd_bulk_xfer(intf->device->hcd, adk->pipe_in,
|
||||
length = rt_usb_hcd_bulk_xfer(intf->device->hcd, adk->pipe_in,
|
||||
buffer, size, 300);
|
||||
|
||||
|
||||
return length;
|
||||
|
||||
}
|
||||
@@ -188,33 +188,45 @@ static rt_size_t rt_usbh_adk_read(rt_device_t device, rt_off_t pos, void* buffer
|
||||
* This function will write data to usb adk device
|
||||
*
|
||||
* @param intf the interface instance.
|
||||
*
|
||||
*
|
||||
* @return the error code, RT_EOK on successfully.
|
||||
*/
|
||||
static rt_size_t rt_usbh_adk_write (rt_device_t device, rt_off_t pos, const void* buffer,
|
||||
static rt_size_t rt_usbh_adk_write (rt_device_t device, rt_off_t pos, const void* buffer,
|
||||
rt_size_t size)
|
||||
{
|
||||
uadk_t adk;
|
||||
rt_size_t length;
|
||||
struct uintf* intf;
|
||||
|
||||
RT_ASSERT(buffer != RT_NULL);
|
||||
RT_ASSERT(buffer != RT_NULL);
|
||||
|
||||
intf = (struct uintf*)device->user_data;
|
||||
adk = (uadk_t)intf->user_data;
|
||||
|
||||
length = rt_usb_hcd_bulk_xfer(intf->device->hcd, adk->pipe_out,
|
||||
length = rt_usb_hcd_bulk_xfer(intf->device->hcd, adk->pipe_out,
|
||||
(void*)buffer, size, 300);
|
||||
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
#ifdef RT_USING_DEVICE_OPS
|
||||
const static struct rt_device_ops adk_device_ops =
|
||||
{
|
||||
RT_NULL;
|
||||
RT_NULL;
|
||||
RT_NULL;
|
||||
rt_usbh_adk_read;
|
||||
rt_usbh_adk_write;
|
||||
RT_NULL;
|
||||
};
|
||||
#endif
|
||||
|
||||
/**
|
||||
* This function will run adk class driver when usb device is detected and identified
|
||||
* as a adk class device, it will continue the enumulate process.
|
||||
*
|
||||
* @param arg the argument.
|
||||
*
|
||||
*
|
||||
* @return the error code, RT_EOK on successfully.
|
||||
*/
|
||||
static rt_err_t rt_usbh_adk_enable(void* arg)
|
||||
@@ -224,8 +236,8 @@ static rt_err_t rt_usbh_adk_enable(void* arg)
|
||||
struct uintf* intf = (struct uintf*)arg;
|
||||
udev_desc_t dev_desc;
|
||||
rt_uint16_t protocol;
|
||||
rt_err_t ret;
|
||||
|
||||
rt_err_t ret;
|
||||
|
||||
/* parameter check */
|
||||
if(intf == RT_NULL)
|
||||
{
|
||||
@@ -234,72 +246,72 @@ static rt_err_t rt_usbh_adk_enable(void* arg)
|
||||
}
|
||||
|
||||
RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbh_adk_run\n"));
|
||||
|
||||
|
||||
dev_desc = &intf->device->dev_desc;
|
||||
if(dev_desc->idVendor == USB_ACCESSORY_VENDOR_ID &&
|
||||
(dev_desc->idProduct == USB_ACCESSORY_PRODUCT_ID ||
|
||||
if(dev_desc->idVendor == USB_ACCESSORY_VENDOR_ID &&
|
||||
(dev_desc->idProduct == USB_ACCESSORY_PRODUCT_ID ||
|
||||
dev_desc->idProduct == USB_ACCESSORY_ADB_PRODUCT_ID))
|
||||
{
|
||||
if(intf->intf_desc->bInterfaceSubClass != 0xFF) return -RT_ERROR;
|
||||
|
||||
RT_DEBUG_LOG(RT_DEBUG_USB, ("found android accessory device\n"));
|
||||
|
||||
RT_DEBUG_LOG(RT_DEBUG_USB, ("found android accessory device\n"));
|
||||
}
|
||||
else
|
||||
{
|
||||
RT_DEBUG_LOG(RT_DEBUG_USB, ("switch device\n"));
|
||||
|
||||
RT_DEBUG_LOG(RT_DEBUG_USB, ("switch device\n"));
|
||||
|
||||
if((ret = rt_usbh_adk_get_protocol(intf, &protocol)) != RT_EOK)
|
||||
{
|
||||
rt_kprintf("rt_usbh_adk_get_protocol failed\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if(protocol != 1)
|
||||
if(protocol != 1)
|
||||
{
|
||||
rt_kprintf("read protocol failed\n");
|
||||
return -RT_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
rt_usbh_adk_send_string(intf,
|
||||
rt_usbh_adk_send_string(intf,
|
||||
ACCESSORY_STRING_MANUFACTURER, _adk_manufacturer);
|
||||
rt_usbh_adk_send_string(intf,
|
||||
rt_usbh_adk_send_string(intf,
|
||||
ACCESSORY_STRING_MODEL, _adk_model);
|
||||
rt_usbh_adk_send_string(intf,
|
||||
rt_usbh_adk_send_string(intf,
|
||||
ACCESSORY_STRING_DESCRIPTION, _adk_description);
|
||||
rt_usbh_adk_send_string(intf,
|
||||
rt_usbh_adk_send_string(intf,
|
||||
ACCESSORY_STRING_VERSION, _adk_version);
|
||||
rt_usbh_adk_send_string(intf,
|
||||
ACCESSORY_STRING_URI, _adk_uri);
|
||||
rt_usbh_adk_send_string(intf,
|
||||
ACCESSORY_STRING_SERIAL, _adk_serial);
|
||||
rt_usbh_adk_send_string(intf,
|
||||
ACCESSORY_STRING_URI, _adk_uri);
|
||||
rt_usbh_adk_send_string(intf,
|
||||
ACCESSORY_STRING_SERIAL, _adk_serial);
|
||||
|
||||
RT_DEBUG_LOG(RT_DEBUG_USB, ("manufacturer %s\n", _adk_manufacturer));
|
||||
RT_DEBUG_LOG(RT_DEBUG_USB, ("model %s\n", _adk_model));
|
||||
RT_DEBUG_LOG(RT_DEBUG_USB, ("description %s\n", _adk_description));
|
||||
RT_DEBUG_LOG(RT_DEBUG_USB, ("version %s\n", _adk_version));
|
||||
RT_DEBUG_LOG(RT_DEBUG_USB, ("uri %s\n", _adk_uri));
|
||||
RT_DEBUG_LOG(RT_DEBUG_USB, ("serial %s\n", _adk_serial));
|
||||
|
||||
RT_DEBUG_LOG(RT_DEBUG_USB, ("uri %s\n", _adk_uri));
|
||||
RT_DEBUG_LOG(RT_DEBUG_USB, ("serial %s\n", _adk_serial));
|
||||
|
||||
if((ret = rt_usbh_adk_start(intf)) != RT_EOK)
|
||||
{
|
||||
rt_kprintf("rt_usbh_adk_start failed\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
|
||||
adk = rt_malloc(sizeof(struct uadkinst));
|
||||
RT_ASSERT(adk != RT_NULL);
|
||||
|
||||
/* initilize the data structure */
|
||||
rt_memset(adk, 0, sizeof(struct uadkinst));
|
||||
rt_memset(adk, 0, sizeof(struct uadkinst));
|
||||
intf->user_data = (void*)adk;
|
||||
|
||||
for(i=0; i<intf->intf_desc->bNumEndpoints; i++)
|
||||
{
|
||||
{
|
||||
uep_desc_t ep_desc;
|
||||
|
||||
|
||||
/* get endpoint descriptor from interface descriptor */
|
||||
rt_usbh_get_endpoint_descriptor(intf->intf_desc, i, &ep_desc);
|
||||
if(ep_desc == RT_NULL)
|
||||
@@ -307,24 +319,24 @@ static rt_err_t rt_usbh_adk_enable(void* arg)
|
||||
rt_kprintf("rt_usb_get_endpoint_descriptor error\n");
|
||||
return -RT_ERROR;
|
||||
}
|
||||
|
||||
/* the endpoint type of adk class should be BULK */
|
||||
|
||||
/* the endpoint type of adk class should be BULK */
|
||||
if((ep_desc->bmAttributes & USB_EP_ATTR_TYPE_MASK) != USB_EP_ATTR_BULK)
|
||||
continue;
|
||||
|
||||
|
||||
/* allocate pipes according to the endpoint type */
|
||||
if(ep_desc->bEndpointAddress & USB_DIR_IN)
|
||||
{
|
||||
/* allocate an in pipe for the adk instance */
|
||||
ret = rt_usb_hcd_alloc_pipe(intf->device->hcd, &adk->pipe_in,
|
||||
ret = rt_usb_hcd_alloc_pipe(intf->device->hcd, &adk->pipe_in,
|
||||
intf, ep_desc, RT_NULL);
|
||||
if(ret != RT_EOK) return ret;
|
||||
}
|
||||
else
|
||||
{
|
||||
{
|
||||
/* allocate an output pipe for the adk instance */
|
||||
ret = rt_usb_hcd_alloc_pipe(intf->device->hcd, &adk->pipe_out,
|
||||
intf, ep_desc, RT_NULL);
|
||||
ret = rt_usb_hcd_alloc_pipe(intf->device->hcd, &adk->pipe_out,
|
||||
intf, ep_desc, RT_NULL);
|
||||
if(ret != RT_EOK) return ret;
|
||||
}
|
||||
}
|
||||
@@ -334,33 +346,37 @@ static rt_err_t rt_usbh_adk_enable(void* arg)
|
||||
{
|
||||
rt_kprintf("pipe error, unsupported device\n");
|
||||
return -RT_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/* set configuration */
|
||||
ret = rt_usbh_set_configure(intf->device, 1);
|
||||
if(ret != RT_EOK) return ret;
|
||||
|
||||
/* register adk device */
|
||||
adk->device.type = RT_Device_Class_Char;
|
||||
adk->device.init = RT_NULL;
|
||||
adk->device.open = RT_NULL;
|
||||
adk->device.close = RT_NULL;
|
||||
adk->device.read = rt_usbh_adk_read;
|
||||
adk->device.write = rt_usbh_adk_write;
|
||||
adk->device.type = RT_Device_Class_Char;
|
||||
#ifdef RT_USING_DEVICE_OPS
|
||||
adk->device.ops = &adk_device_ops;
|
||||
#else
|
||||
adk->device.init = RT_NULL;
|
||||
adk->device.open = RT_NULL;
|
||||
adk->device.close = RT_NULL;
|
||||
adk->device.read = rt_usbh_adk_read;
|
||||
adk->device.write = rt_usbh_adk_write;
|
||||
adk->device.control = RT_NULL;
|
||||
#endif
|
||||
adk->device.user_data = (void*)intf;
|
||||
|
||||
rt_device_register(&adk->device, "adkdev", RT_DEVICE_FLAG_RDWR);
|
||||
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function will be invoked when usb device plug out is detected and it would clean
|
||||
* This function will be invoked when usb device plug out is detected and it would clean
|
||||
* and release all hub class related resources.
|
||||
*
|
||||
* @param arg the argument.
|
||||
*
|
||||
*
|
||||
* @return the error code, RT_EOK on successfully.
|
||||
*/
|
||||
static rt_err_t rt_usbh_adk_disable(void* arg)
|
||||
@@ -373,12 +389,12 @@ static rt_err_t rt_usbh_adk_disable(void* arg)
|
||||
RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbh_adk_stop\n"));
|
||||
|
||||
adk = (uadk_t)intf->user_data;
|
||||
if(adk == RT_NULL)
|
||||
if(adk == RT_NULL)
|
||||
{
|
||||
rt_free(intf);
|
||||
rt_free(intf);
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
|
||||
if(adk->pipe_in != RT_NULL)
|
||||
rt_usb_hcd_free_pipe(intf->device->hcd, adk->pipe_in);
|
||||
|
||||
@@ -389,11 +405,11 @@ static rt_err_t rt_usbh_adk_disable(void* arg)
|
||||
rt_device_unregister(&adk->device);
|
||||
|
||||
/* free adk instance */
|
||||
if(adk != RT_NULL)
|
||||
if(adk != RT_NULL)
|
||||
{
|
||||
rt_free(adk);
|
||||
}
|
||||
|
||||
|
||||
/* free interface instance */
|
||||
rt_free(intf);
|
||||
|
||||
@@ -403,13 +419,13 @@ static rt_err_t rt_usbh_adk_disable(void* arg)
|
||||
/**
|
||||
* This function will register adk class driver to the usb class driver manager.
|
||||
* and it should be invoked in the usb system initialization.
|
||||
*
|
||||
*
|
||||
* @return the error code, RT_EOK on successfully.
|
||||
*/
|
||||
ucd_t rt_usbh_class_driver_adk(void)
|
||||
{
|
||||
adk_driver.class_code = USB_CLASS_ADK;
|
||||
|
||||
|
||||
adk_driver.enable = rt_usbh_adk_enable;
|
||||
adk_driver.disable = rt_usbh_adk_disable;
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ static int udisk_get_id(void)
|
||||
if((_udisk_idset & (1 << i)) != 0) continue;
|
||||
else break;
|
||||
}
|
||||
|
||||
|
||||
/* it should not happen */
|
||||
if(i == UDISK_MAX_COUNT) RT_ASSERT(0);
|
||||
|
||||
@@ -43,14 +43,14 @@ static void udisk_free_id(int id)
|
||||
{
|
||||
RT_ASSERT(id < UDISK_MAX_COUNT)
|
||||
|
||||
_udisk_idset &= ~(1 << id);
|
||||
_udisk_idset &= ~(1 << id);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function will initialize the udisk device
|
||||
*
|
||||
* @param dev the pointer of device driver structure
|
||||
*
|
||||
*
|
||||
* @return RT_EOK
|
||||
*/
|
||||
static rt_err_t rt_udisk_init(rt_device_t dev)
|
||||
@@ -68,7 +68,7 @@ static rt_err_t rt_udisk_init(rt_device_t dev)
|
||||
*
|
||||
* @return the actually read size on successful, otherwise negative returned.
|
||||
*/
|
||||
static rt_size_t rt_udisk_read(rt_device_t dev, rt_off_t pos, void* buffer,
|
||||
static rt_size_t rt_udisk_read(rt_device_t dev, rt_off_t pos, void* buffer,
|
||||
rt_size_t size)
|
||||
{
|
||||
rt_err_t ret;
|
||||
@@ -81,18 +81,18 @@ static rt_size_t rt_udisk_read(rt_device_t dev, rt_off_t pos, void* buffer,
|
||||
RT_ASSERT(buffer != RT_NULL);
|
||||
|
||||
if(size > 4096) timeout = 800;
|
||||
|
||||
|
||||
data = (struct ustor_data*)dev->user_data;
|
||||
intf = data->intf;
|
||||
|
||||
ret = rt_usbh_storage_read10(intf, (rt_uint8_t*)buffer, pos, size, timeout);
|
||||
|
||||
|
||||
if (ret != RT_EOK)
|
||||
{
|
||||
rt_kprintf("usb mass_storage read failed\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
@@ -106,7 +106,7 @@ static rt_size_t rt_udisk_read(rt_device_t dev, rt_off_t pos, void* buffer,
|
||||
*
|
||||
* @return the actually written size on successful, otherwise negative returned.
|
||||
*/
|
||||
static rt_size_t rt_udisk_write (rt_device_t dev, rt_off_t pos, const void* buffer,
|
||||
static rt_size_t rt_udisk_write (rt_device_t dev, rt_off_t pos, const void* buffer,
|
||||
rt_size_t size)
|
||||
{
|
||||
rt_err_t ret;
|
||||
@@ -129,7 +129,7 @@ static rt_size_t rt_udisk_write (rt_device_t dev, rt_off_t pos, const void* buff
|
||||
rt_kprintf("usb mass_storage write %d sector failed\n", size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
@@ -138,9 +138,9 @@ static rt_size_t rt_udisk_write (rt_device_t dev, rt_off_t pos, const void* buff
|
||||
*
|
||||
* @param intf the interface instance.
|
||||
* @param buffer the data buffer to save inquiry data
|
||||
*
|
||||
*
|
||||
* @return the error code, RT_EOK on successfully.
|
||||
*/
|
||||
*/
|
||||
static rt_err_t rt_udisk_control(rt_device_t dev, int cmd, void *args)
|
||||
{
|
||||
ustor_t stor;
|
||||
@@ -164,14 +164,26 @@ static rt_err_t rt_udisk_control(rt_device_t dev, int cmd, void *args)
|
||||
geometry->sector_count = stor->capicity[0];
|
||||
}
|
||||
|
||||
return RT_EOK;
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
#ifdef RT_USING_DEVICE_OPS
|
||||
const static struct rt_device_ops udisk_device_ops =
|
||||
{
|
||||
rt_udisk_init,
|
||||
RT_NULL,
|
||||
RT_NULL,
|
||||
rt_udisk_read,
|
||||
rt_udisk_write,
|
||||
rt_udisk_control
|
||||
};
|
||||
#endif
|
||||
|
||||
/**
|
||||
* This function will run udisk driver when usb disk is detected.
|
||||
*
|
||||
* @param intf the usb interface instance.
|
||||
*
|
||||
*
|
||||
* @return the error code, RT_EOK on successfully.
|
||||
*/
|
||||
rt_err_t rt_udisk_run(struct uhintf* intf)
|
||||
@@ -179,10 +191,10 @@ rt_err_t rt_udisk_run(struct uhintf* intf)
|
||||
int i = 0;
|
||||
rt_err_t ret;
|
||||
char dname[4];
|
||||
char sname[8];
|
||||
char sname[8];
|
||||
rt_uint8_t max_lun, *sector, sense[18], inquiry[36];
|
||||
struct dfs_partition part[MAX_PARTITION_COUNT];
|
||||
ustor_t stor;
|
||||
struct dfs_partition part[MAX_PARTITION_COUNT];
|
||||
ustor_t stor;
|
||||
|
||||
/* check parameter */
|
||||
RT_ASSERT(intf != RT_NULL);
|
||||
@@ -193,40 +205,40 @@ rt_err_t rt_udisk_run(struct uhintf* intf)
|
||||
// rt_usbh_clear_feature(intf->device, 0, USB_FEATURE_ENDPOINT_HALT);
|
||||
/* reset mass storage class device */
|
||||
ret = rt_usbh_storage_reset(intf);
|
||||
if(ret != RT_EOK) return ret;
|
||||
if(ret != RT_EOK) return ret;
|
||||
|
||||
stor = (ustor_t)intf->user_data;
|
||||
|
||||
/* get max logic unit number */
|
||||
/* get max logic unit number */
|
||||
ret = rt_usbh_storage_get_max_lun(intf, &max_lun);
|
||||
if(ret != RT_EOK)
|
||||
if(ret != RT_EOK)
|
||||
rt_usbh_clear_feature(intf->device, 0, USB_FEATURE_ENDPOINT_HALT);
|
||||
|
||||
/* reset pipe in endpoint */
|
||||
if(stor->pipe_in->status == UPIPE_STATUS_STALL)
|
||||
{
|
||||
ret = rt_usbh_clear_feature(intf->device,
|
||||
ret = rt_usbh_clear_feature(intf->device,
|
||||
stor->pipe_in->ep.bEndpointAddress, USB_FEATURE_ENDPOINT_HALT);
|
||||
if(ret != RT_EOK) return ret;
|
||||
if(ret != RT_EOK) return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* reset pipe out endpoint */
|
||||
if(stor->pipe_out->status == UPIPE_STATUS_STALL)
|
||||
{
|
||||
ret = rt_usbh_clear_feature(intf->device,
|
||||
ret = rt_usbh_clear_feature(intf->device,
|
||||
stor->pipe_out->ep.bEndpointAddress, USB_FEATURE_ENDPOINT_HALT);
|
||||
if(ret != RT_EOK) return ret;
|
||||
if(ret != RT_EOK) return ret;
|
||||
}
|
||||
|
||||
while((ret = rt_usbh_storage_inquiry(intf, inquiry)) != RT_EOK)
|
||||
{
|
||||
{
|
||||
if(ret == -RT_EIO) return ret;
|
||||
|
||||
rt_thread_delay(5);
|
||||
rt_thread_delay(5);
|
||||
if(i++ < 10) continue;
|
||||
rt_kprintf("rt_usbh_storage_inquiry error\n");
|
||||
return -RT_ERROR;
|
||||
return -RT_ERROR;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
@@ -235,26 +247,26 @@ rt_err_t rt_udisk_run(struct uhintf* intf)
|
||||
while((ret = rt_usbh_storage_test_unit_ready(intf)) != RT_EOK)
|
||||
{
|
||||
if(ret == -RT_EIO) return ret;
|
||||
|
||||
|
||||
ret = rt_usbh_storage_request_sense(intf, sense);
|
||||
if(ret == -RT_EIO) return ret;
|
||||
|
||||
rt_thread_delay(10);
|
||||
|
||||
rt_thread_delay(10);
|
||||
if(i++ < 10) continue;
|
||||
|
||||
rt_kprintf("rt_usbh_storage_test_unit_ready error\n");
|
||||
return -RT_ERROR;
|
||||
return -RT_ERROR;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
rt_memset(stor->capicity, 0, sizeof(stor->capicity));
|
||||
|
||||
/* get storage capacity */
|
||||
while((ret = rt_usbh_storage_get_capacity(intf,
|
||||
while((ret = rt_usbh_storage_get_capacity(intf,
|
||||
(rt_uint8_t*)stor->capicity)) != RT_EOK)
|
||||
{
|
||||
if(ret == -RT_EIO) return ret;
|
||||
|
||||
{
|
||||
if(ret == -RT_EIO) return ret;
|
||||
|
||||
rt_thread_delay(50);
|
||||
if(i++ < 10) continue;
|
||||
|
||||
@@ -262,16 +274,16 @@ rt_err_t rt_udisk_run(struct uhintf* intf)
|
||||
stor->capicity[1] = 0x200;
|
||||
|
||||
rt_kprintf("rt_usbh_storage_get_capacity error\n");
|
||||
break;
|
||||
break;
|
||||
}
|
||||
|
||||
stor->capicity[0] = uswap_32(stor->capicity[0]);
|
||||
stor->capicity[1] = uswap_32(stor->capicity[1]);
|
||||
stor->capicity[0] += 1;
|
||||
|
||||
RT_DEBUG_LOG(RT_DEBUG_USB, ("capicity %d, block size %d\n",
|
||||
|
||||
RT_DEBUG_LOG(RT_DEBUG_USB, ("capicity %d, block size %d\n",
|
||||
stor->capicity[0], stor->capicity[1]));
|
||||
|
||||
|
||||
/* get the first sector to read partition table */
|
||||
sector = (rt_uint8_t*) rt_malloc (SECTOR_SIZE);
|
||||
if (sector == RT_NULL)
|
||||
@@ -283,42 +295,46 @@ rt_err_t rt_udisk_run(struct uhintf* intf)
|
||||
rt_memset(sector, 0, SECTOR_SIZE);
|
||||
|
||||
RT_DEBUG_LOG(RT_DEBUG_USB, ("read partition table\n"));
|
||||
|
||||
|
||||
/* get the partition table */
|
||||
ret = rt_usbh_storage_read10(intf, sector, 0, 1, 500);
|
||||
if(ret != RT_EOK)
|
||||
{
|
||||
rt_kprintf("read parition table error\n");
|
||||
|
||||
rt_free(sector);
|
||||
return -RT_ERROR;
|
||||
rt_free(sector);
|
||||
return -RT_ERROR;
|
||||
}
|
||||
|
||||
RT_DEBUG_LOG(RT_DEBUG_USB, ("finished reading partition\n"));
|
||||
|
||||
|
||||
for(i=0; i<MAX_PARTITION_COUNT; i++)
|
||||
{
|
||||
{
|
||||
/* get the first partition */
|
||||
ret = dfs_filesystem_get_partition(&part[i], sector, i);
|
||||
if (ret == RT_EOK)
|
||||
{
|
||||
struct ustor_data* data = rt_malloc(sizeof(struct ustor_data));
|
||||
{
|
||||
struct ustor_data* data = rt_malloc(sizeof(struct ustor_data));
|
||||
rt_memset(data, 0, sizeof(struct ustor_data));
|
||||
data->intf = intf;
|
||||
data->intf = intf;
|
||||
data->udisk_id = udisk_get_id();
|
||||
rt_snprintf(dname, 6, "ud%d-%d", data->udisk_id, i);
|
||||
rt_snprintf(sname, 8, "sem_ud%d", i);
|
||||
data->part.lock = rt_sem_create(sname, 1, RT_IPC_FLAG_FIFO);
|
||||
|
||||
/* register sdcard device */
|
||||
stor->dev[i].type = RT_Device_Class_Block;
|
||||
stor->dev[i].init = rt_udisk_init;
|
||||
stor->dev[i].read = rt_udisk_read;
|
||||
stor->dev[i].write = rt_udisk_write;
|
||||
stor->dev[i].type = RT_Device_Class_Block;
|
||||
#ifdef RT_USING_DEVICE_OPS
|
||||
stor->dev[i].ops = &udisk_device_ops;
|
||||
#else
|
||||
stor->dev[i].init = rt_udisk_init;
|
||||
stor->dev[i].read = rt_udisk_read;
|
||||
stor->dev[i].write = rt_udisk_write;
|
||||
stor->dev[i].control = rt_udisk_control;
|
||||
#endif
|
||||
stor->dev[i].user_data = (void*)data;
|
||||
|
||||
rt_device_register(&stor->dev[i], dname, RT_DEVICE_FLAG_RDWR |
|
||||
rt_device_register(&stor->dev[i], dname, RT_DEVICE_FLAG_RDWR |
|
||||
RT_DEVICE_FLAG_REMOVABLE | RT_DEVICE_FLAG_STANDALONE);
|
||||
|
||||
stor->dev_cnt++;
|
||||
@@ -330,16 +346,16 @@ rt_err_t rt_udisk_run(struct uhintf* intf)
|
||||
else
|
||||
{
|
||||
RT_DEBUG_LOG(RT_DEBUG_USB, ("udisk part %d mount failed\n", i));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(i == 0)
|
||||
{
|
||||
struct ustor_data* data = rt_malloc(sizeof(struct ustor_data));
|
||||
rt_memset(data, 0, sizeof(struct ustor_data));
|
||||
{
|
||||
struct ustor_data* data = rt_malloc(sizeof(struct ustor_data));
|
||||
rt_memset(data, 0, sizeof(struct ustor_data));
|
||||
data->udisk_id = udisk_get_id();
|
||||
|
||||
|
||||
/* there is no partition table */
|
||||
data->part.offset = 0;
|
||||
data->part.size = 0;
|
||||
@@ -349,23 +365,27 @@ rt_err_t rt_udisk_run(struct uhintf* intf)
|
||||
rt_snprintf(dname, 7, "udisk%d", data->udisk_id);
|
||||
|
||||
/* register sdcard device */
|
||||
stor->dev[0].type = RT_Device_Class_Block;
|
||||
stor->dev[0].init = rt_udisk_init;
|
||||
stor->dev[0].read = rt_udisk_read;
|
||||
stor->dev[0].write = rt_udisk_write;
|
||||
stor->dev[0].type = RT_Device_Class_Block;
|
||||
#ifdef RT_USING_DEVICE_OPS
|
||||
stor->dev[i].ops = &udisk_device_ops;
|
||||
#else
|
||||
stor->dev[0].init = rt_udisk_init;
|
||||
stor->dev[0].read = rt_udisk_read;
|
||||
stor->dev[0].write = rt_udisk_write;
|
||||
stor->dev[0].control = rt_udisk_control;
|
||||
#endif
|
||||
stor->dev[0].user_data = (void*)data;
|
||||
|
||||
rt_device_register(&stor->dev[0], dname,
|
||||
RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_REMOVABLE
|
||||
RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_REMOVABLE
|
||||
| RT_DEVICE_FLAG_STANDALONE);
|
||||
|
||||
stor->dev_cnt++;
|
||||
if (dfs_mount(stor->dev[0].parent.name, UDISK_MOUNTPOINT,
|
||||
if (dfs_mount(stor->dev[0].parent.name, UDISK_MOUNTPOINT,
|
||||
"elm", 0, 0) == 0)
|
||||
{
|
||||
{
|
||||
rt_kprintf("Mount FAT on Udisk successful.\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
rt_kprintf("Mount FAT on Udisk failed.\n");
|
||||
@@ -382,31 +402,31 @@ rt_err_t rt_udisk_run(struct uhintf* intf)
|
||||
}
|
||||
|
||||
/**
|
||||
* This function will be invoked when usb disk plug out is detected and it would clean
|
||||
* This function will be invoked when usb disk plug out is detected and it would clean
|
||||
* and release all udisk related resources.
|
||||
*
|
||||
* @param intf the usb interface instance.
|
||||
*
|
||||
*
|
||||
* @return the error code, RT_EOK on successfully.
|
||||
*/
|
||||
rt_err_t rt_udisk_stop(struct uhintf* intf)
|
||||
{
|
||||
int i;
|
||||
ustor_t stor;
|
||||
ustor_t stor;
|
||||
struct ustor_data* data;
|
||||
|
||||
/* check parameter */
|
||||
RT_ASSERT(intf != RT_NULL);
|
||||
RT_ASSERT(intf->device != RT_NULL);
|
||||
|
||||
stor = (ustor_t)intf->user_data;
|
||||
stor = (ustor_t)intf->user_data;
|
||||
RT_ASSERT(stor != RT_NULL);
|
||||
|
||||
for(i=0; i<stor->dev_cnt; i++)
|
||||
{
|
||||
rt_device_t dev = &stor->dev[i];
|
||||
data = (struct ustor_data*)dev->user_data;
|
||||
|
||||
|
||||
/* unmount filesystem */
|
||||
dfs_unmount(UDISK_MOUNTPOINT);
|
||||
|
||||
|
||||
@@ -78,6 +78,18 @@ static rt_err_t rt_watchdog_control(struct rt_device *dev,
|
||||
return (wtd->ops->control(wtd, cmd, args));
|
||||
}
|
||||
|
||||
#ifdef RT_USING_DEVICE_OPS
|
||||
const static struct rt_device_ops wdt_ops =
|
||||
{
|
||||
rt_watchdog_init,
|
||||
rt_watchdog_open,
|
||||
rt_watchdog_close,
|
||||
RT_NULL,
|
||||
RT_NULL,
|
||||
rt_watchdog_control,
|
||||
};
|
||||
#endif
|
||||
|
||||
/**
|
||||
* This function register a watchdog device
|
||||
*/
|
||||
@@ -95,12 +107,16 @@ rt_err_t rt_hw_watchdog_register(struct rt_watchdog_device *wtd,
|
||||
device->rx_indicate = RT_NULL;
|
||||
device->tx_complete = RT_NULL;
|
||||
|
||||
#ifdef RT_USING_DEVICE_OPS
|
||||
device->ops = &wdt_ops;
|
||||
#else
|
||||
device->init = rt_watchdog_init;
|
||||
device->open = rt_watchdog_open;
|
||||
device->close = rt_watchdog_close;
|
||||
device->read = RT_NULL;
|
||||
device->write = RT_NULL;
|
||||
device->control = rt_watchdog_control;
|
||||
#endif
|
||||
device->user_data = data;
|
||||
|
||||
/* register a character device */
|
||||
|
||||
@@ -614,113 +614,6 @@ int list_module(void)
|
||||
}
|
||||
FINSH_FUNCTION_EXPORT(list_module, list module in system);
|
||||
MSH_CMD_EXPORT(list_module, list module in system);
|
||||
|
||||
int list_mod_detail(const char *name)
|
||||
{
|
||||
int i;
|
||||
struct rt_module *module;
|
||||
|
||||
/* find module */
|
||||
if ((module = rt_module_find(name)) != RT_NULL)
|
||||
{
|
||||
/* module has entry point */
|
||||
if (!(module->parent.flag & RT_MODULE_FLAG_WITHOUTENTRY))
|
||||
{
|
||||
struct rt_thread *thread;
|
||||
struct rt_list_node *tlist;
|
||||
rt_uint8_t *ptr;
|
||||
|
||||
/* list main thread in module */
|
||||
if (module->module_thread != RT_NULL)
|
||||
{
|
||||
rt_uint8_t stat;
|
||||
|
||||
rt_kprintf("main thread pri status sp stack size max used left tick error\n");
|
||||
rt_kprintf("------------- ---- ------- ---------- ---------- ---------- ---------- ---\n");
|
||||
thread = module->module_thread;
|
||||
rt_kprintf("%-8.*s 0x%02x", RT_NAME_MAX, thread->name, thread->current_priority);
|
||||
|
||||
stat = (thread->stat & RT_THREAD_STAT_MASK);
|
||||
if (stat == RT_THREAD_READY) rt_kprintf(" ready ");
|
||||
else if (stat == RT_THREAD_SUSPEND) rt_kprintf(" suspend");
|
||||
else if (stat == RT_THREAD_INIT) rt_kprintf(" init ");
|
||||
|
||||
ptr = (rt_uint8_t *)thread->stack_addr;
|
||||
while (*ptr == '#')ptr ++;
|
||||
|
||||
rt_kprintf(" 0x%08x 0x%08x 0x%08x 0x%08x %03d\n",
|
||||
thread->stack_size + ((rt_uint32_t)thread->stack_addr - (rt_uint32_t)thread->sp),
|
||||
thread->stack_size,
|
||||
thread->stack_size - ((rt_uint32_t) ptr - (rt_uint32_t)thread->stack_addr),
|
||||
thread->remaining_tick,
|
||||
thread->error);
|
||||
}
|
||||
|
||||
/* list sub thread in module */
|
||||
tlist = &module->module_object[RT_Object_Class_Thread].object_list;
|
||||
if (!rt_list_isempty(tlist)) _list_thread(tlist);
|
||||
#ifdef RT_USING_SEMAPHORE
|
||||
/* list semaphored in module */
|
||||
tlist = &module->module_object[RT_Object_Class_Semaphore].object_list;
|
||||
if (!rt_list_isempty(tlist)) _list_sem(tlist);
|
||||
#endif
|
||||
#ifdef RT_USING_MUTEX
|
||||
/* list mutex in module */
|
||||
tlist = &module->module_object[RT_Object_Class_Mutex].object_list;
|
||||
if (!rt_list_isempty(tlist)) _list_mutex(tlist);
|
||||
#endif
|
||||
#ifdef RT_USING_EVENT
|
||||
/* list event in module */
|
||||
tlist = &module->module_object[RT_Object_Class_Event].object_list;
|
||||
if (!rt_list_isempty(tlist)) _list_event(tlist);
|
||||
#endif
|
||||
#ifdef RT_USING_MAILBOX
|
||||
/* list mailbox in module */
|
||||
tlist = &module->module_object[RT_Object_Class_MailBox].object_list;
|
||||
if (!rt_list_isempty(tlist)) _list_mailbox(tlist);
|
||||
#endif
|
||||
#ifdef RT_USING_MESSAGEQUEUE
|
||||
/* list message queue in module */
|
||||
tlist = &module->module_object[RT_Object_Class_MessageQueue].object_list;
|
||||
if (!rt_list_isempty(tlist)) _list_msgqueue(tlist);
|
||||
#endif
|
||||
#ifdef RT_USING_MEMHEAP
|
||||
/* list memory heap in module */
|
||||
tlist = &module->module_object[RT_Object_Class_MemHeap].object_list;
|
||||
if (!rt_list_isempty(tlist)) _list_memheap(tlist);
|
||||
#endif
|
||||
#ifdef RT_USING_MEMPOOL
|
||||
/* list memory pool in module */
|
||||
tlist = &module->module_object[RT_Object_Class_MemPool].object_list;
|
||||
if (!rt_list_isempty(tlist)) _list_mempool(tlist);
|
||||
#endif
|
||||
#ifdef RT_USING_DEVICE
|
||||
/* list device in module */
|
||||
tlist = &module->module_object[RT_Object_Class_Device].object_list;
|
||||
if (!rt_list_isempty(tlist)) _list_device(tlist);
|
||||
#endif
|
||||
/* list timer in module */
|
||||
tlist = &module->module_object[RT_Object_Class_Timer].object_list;
|
||||
if (!rt_list_isempty(tlist)) _list_timer(tlist);
|
||||
}
|
||||
|
||||
if (module->nsym > 0)
|
||||
{
|
||||
rt_kprintf("symbol address \n");
|
||||
rt_kprintf("-------- ----------\n");
|
||||
|
||||
/* list module export symbols */
|
||||
for (i = 0; i < module->nsym; i++)
|
||||
{
|
||||
rt_kprintf("%s 0x%x\n",
|
||||
module->symtab[i].name, module->symtab[i].addr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
FINSH_FUNCTION_EXPORT(list_mod_detail, list module objects in system)
|
||||
#endif
|
||||
|
||||
long list(void)
|
||||
|
||||
@@ -336,7 +336,7 @@ int msh_exec(char *cmd, rt_size_t length)
|
||||
{
|
||||
return cmd_ret;
|
||||
}
|
||||
#ifdef RT_USING_MODULE
|
||||
#if defined(RT_USING_MODULE) && defined(RT_USING_DFS)
|
||||
if (msh_exec_module(cmd, length) == 0)
|
||||
{
|
||||
return 0;
|
||||
|
||||
@@ -35,6 +35,8 @@
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
int _EXFUN(putenv,(char *__string));
|
||||
|
||||
int libc_system_init(void)
|
||||
{
|
||||
#if defined(RT_USING_DFS) & defined(RT_USING_DFS_DEVFS)
|
||||
|
||||
@@ -31,6 +31,8 @@
|
||||
|
||||
#define STDIO_DEVICE_NAME_MAX 32
|
||||
|
||||
int _EXFUN(fileno, (FILE *));
|
||||
|
||||
static FILE* std_console = NULL;
|
||||
|
||||
int libc_stdio_set_console(const char* device_name, int mode)
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#include <dfs_posix.h>
|
||||
#endif
|
||||
|
||||
#ifdef RT_USING_PTHREADS
|
||||
#ifdef RT_USING_PTHREADS
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
@@ -126,7 +126,7 @@ _open_r(struct _reent *ptr, const char *file, int flags, int mode)
|
||||
#endif
|
||||
}
|
||||
|
||||
_ssize_t
|
||||
_ssize_t
|
||||
_read_r(struct _reent *ptr, int fd, void *buf, size_t nbytes)
|
||||
{
|
||||
#ifndef RT_USING_DFS
|
||||
@@ -372,7 +372,7 @@ void *_calloc_r (struct _reent *ptr, size_t size, size_t len)
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
void
|
||||
_free_r (struct _reent *ptr, void *addr)
|
||||
{
|
||||
rt_free (addr);
|
||||
@@ -387,43 +387,20 @@ _exit (int status)
|
||||
module = rt_module_self();
|
||||
if (module != RT_NULL)
|
||||
{
|
||||
struct rt_list_node *list;
|
||||
struct rt_object *object;
|
||||
|
||||
rt_enter_critical();
|
||||
|
||||
/* delete all threads in the module */
|
||||
list = &module->module_object[RT_Object_Class_Thread].object_list;
|
||||
while (list->next != list)
|
||||
{
|
||||
object = rt_list_entry(list->next, struct rt_object, list);
|
||||
if (rt_object_is_systemobject(object) == RT_TRUE)
|
||||
{
|
||||
/* detach static object */
|
||||
rt_thread_detach((rt_thread_t)object);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* delete dynamic object */
|
||||
rt_thread_delete((rt_thread_t)object);
|
||||
}
|
||||
}
|
||||
/* delete main thread */
|
||||
rt_thread_delete(module->module_thread);
|
||||
rt_exit_critical();
|
||||
rt_thread_suspend(rt_thread_self());
|
||||
|
||||
/* re-schedule */
|
||||
rt_schedule();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
rt_kprintf("thread:%s exit with %d\n", rt_thread_self()->name, status);
|
||||
RT_ASSERT(0);
|
||||
|
||||
while (1);
|
||||
}
|
||||
|
||||
void
|
||||
void
|
||||
_system(const char *s)
|
||||
{
|
||||
/* not support this call */
|
||||
|
||||
@@ -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.
|
||||
@@ -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')
|
||||
@@ -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. */
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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. */
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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. */
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user