diff options
| author | armink <[email protected]> | 2019-12-17 20:11:46 +0800 |
|---|---|---|
| committer | armink <[email protected]> | 2019-12-17 20:11:46 +0800 |
| commit | 4875ee8a3ab95c4fbf1e09941d3f44d99a9a632b (patch) | |
| tree | 15c596c04a842bac747bbcf05a703b8da76f8eac /components | |
| parent | fa46d6ac861f26b472d62abdf1278c445431ce4c (diff) | |
Sync from master (75a3f3dd3a930eab1dc58fa0258a9d1605a0ac11)
Diffstat (limited to 'components')
234 files changed, 10689 insertions, 15119 deletions
diff --git a/components/Kconfig b/components/Kconfig index 7c6ca0150c..c3d2b53209 100644 --- a/components/Kconfig +++ b/components/Kconfig @@ -1,14 +1,13 @@ menu "RT-Thread Components" config RT_USING_COMPONENTS_INIT - bool "Use components automatically initialization" - default y - -if RT_USING_COMPONENTS_INIT - config RT_USING_USER_MAIN - bool "The main() function as user entry function" - default y - + bool + default n + +config RT_USING_USER_MAIN + bool + default n + if RT_USING_USER_MAIN config RT_MAIN_THREAD_STACK_SIZE int "Set main thread stack size" @@ -19,7 +18,6 @@ if RT_USING_COMPONENTS_INIT default 10 if RT_THREAD_PRIORITY_32 default 85 if RT_THREAD_PRIORITY_256 endif -endif source "$RTT_DIR/components/cplusplus/Kconfig" diff --git a/components/cplusplus/Queue.h b/components/cplusplus/Queue.h index 351e3ec66b..23a4638798 100644 --- a/components/cplusplus/Queue.h +++ b/components/cplusplus/Queue.h @@ -68,7 +68,7 @@ public: private: struct rt_messagequeue mID; - char mPool[(sizeof(struct rt_messagequeue) + sizeof(T)) * queue_sz]; + char mPool[(sizeof(void *) + RT_ALIGN(sizeof(T), RT_ALIGN_SIZE)) * queue_sz]; }; } diff --git a/components/cplusplus/Thread.cpp b/components/cplusplus/Thread.cpp index 0f6315d178..b21fbdce1f 100644 --- a/components/cplusplus/Thread.cpp +++ b/components/cplusplus/Thread.cpp @@ -14,7 +14,7 @@ Thread::Thread(rt_uint32_t stack_size, rt_uint8_t priority, rt_uint32_t tick, const char *name) -: _entry(RT_NULL), _param(RT_NULL), started(false) + : _entry(RT_NULL), _param(RT_NULL), started(false) { rt_event_init(&_event, name, 0); @@ -32,7 +32,7 @@ Thread::Thread(void (*entry)(void *p), rt_uint8_t priority, rt_uint32_t tick, const char *name) -: _entry(RT_NULL), _param(p), started(false) + : _entry(entry), _param(p), started(false) { rt_event_init(&_event, name, 0); @@ -46,6 +46,7 @@ Thread::Thread(void (*entry)(void *p), Thread::~Thread() { + rt_event_detach(&_event); rt_thread_delete(_thread); } @@ -79,23 +80,23 @@ void Thread::func(Thread *pThis) } else { - pThis->run(); + pThis->run(pThis->_param); } rt_event_send(&pThis->_event, 1); } -void Thread::run() +void Thread::run(void *parameter) { /* please overload this method */ } -void Thread::wait(int32_t millisec) +rt_err_t Thread::wait(int32_t millisec) { - join(millisec); + return join(millisec); } -void Thread::join(int32_t millisec) +rt_err_t Thread::join(int32_t millisec) { if (started) { @@ -106,6 +107,10 @@ void Thread::join(int32_t millisec) else tick = rt_tick_from_millisecond(millisec); - rt_event_recv(&_event, 1, RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, tick, RT_NULL); + return rt_event_recv(&_event, 1, RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, tick, RT_NULL); + } + else + { + return -RT_ENOSYS; } } diff --git a/components/cplusplus/Thread.h b/components/cplusplus/Thread.h index 71ee50e1f9..b578659489 100644 --- a/components/cplusplus/Thread.h +++ b/components/cplusplus/Thread.h @@ -45,16 +45,15 @@ public: static void sleep(int32_t millisec); - void wait(int32_t millisec); - void join(int32_t millisec = -1); + rt_err_t wait(int32_t millisec); + rt_err_t join(int32_t millisec = -1); protected: - virtual void run(); + virtual void run(void *parameter); private: static void func(Thread *pThis); -private: rt_thread_t _thread; thread_func_t _entry; diff --git a/components/dfs/filesystems/elmfat/dfs_elm.c b/components/dfs/filesystems/elmfat/dfs_elm.c index a45c15aa03..b4c4c627aa 100644 --- a/components/dfs/filesystems/elmfat/dfs_elm.c +++ b/components/dfs/filesystems/elmfat/dfs_elm.c @@ -202,7 +202,7 @@ int dfs_elm_mkfs(rt_device_t dev_id) int index; char logic_nbr[2] = {'0', ':'}; - work = rt_malloc(_MAX_SS); + work = (BYTE *)rt_malloc(_MAX_SS); if (RT_NULL == work) { return -ENOMEM; @@ -233,7 +233,7 @@ int dfs_elm_mkfs(rt_device_t dev_id) } else { - fat = rt_malloc(sizeof(FATFS)); + fat = (FATFS *)rt_malloc(sizeof(FATFS)); if (fat == RT_NULL) { rt_free(work); /* release memory */ @@ -340,7 +340,7 @@ int dfs_elm_open(struct dfs_fd *file) vol = elm_get_vol((FATFS *)fs->data); if (vol < 0) return -ENOENT; - drivers_fn = rt_malloc(256); + drivers_fn = (char *)rt_malloc(256); if (drivers_fn == RT_NULL) return -ENOMEM; @@ -478,6 +478,33 @@ int dfs_elm_close(struct dfs_fd *file) int dfs_elm_ioctl(struct dfs_fd *file, int cmd, void *args) { + switch (cmd) + { + case RT_FIOFTRUNCATE: + { + FIL *fd; + FSIZE_t fptr, length; + FRESULT result = FR_OK; + fd = (FIL *)(file->data); + RT_ASSERT(fd != RT_NULL); + + /* save file read/write point */ + fptr = fd->fptr; + length = *(off_t*)args; + if (length <= fd->obj.objsize) + { + fd->fptr = length; + result = f_truncate(fd); + } + else + { + result = f_lseek(fd, length); + } + /* restore file read/write point */ + fd->fptr = fptr; + return elm_result_to_dfs(result); + } + } return -ENOSYS; } @@ -648,7 +675,7 @@ int dfs_elm_unlink(struct dfs_filesystem *fs, const char *path) vol = elm_get_vol((FATFS *)fs->data); if (vol < 0) return -ENOENT; - drivers_fn = rt_malloc(256); + drivers_fn = (char *)rt_malloc(256); if (drivers_fn == RT_NULL) return -ENOMEM; @@ -680,7 +707,7 @@ int dfs_elm_rename(struct dfs_filesystem *fs, const char *oldpath, const char *n if (vol < 0) return -ENOENT; - drivers_oldfn = rt_malloc(256); + drivers_oldfn = (char *)rt_malloc(256); if (drivers_oldfn == RT_NULL) return -ENOMEM; drivers_newfn = newpath; @@ -714,7 +741,7 @@ int dfs_elm_stat(struct dfs_filesystem *fs, const char *path, struct stat *st) vol = elm_get_vol((FATFS *)fs->data); if (vol < 0) return -ENOENT; - drivers_fn = rt_malloc(256); + drivers_fn = (char *)rt_malloc(256); if (drivers_fn == RT_NULL) return -ENOMEM; diff --git a/components/dfs/filesystems/elmfat/ff.c b/components/dfs/filesystems/elmfat/ff.c index 4a2f0258b6..19df7450e2 100644 --- a/components/dfs/filesystems/elmfat/ff.c +++ b/components/dfs/filesystems/elmfat/ff.c @@ -569,7 +569,7 @@ static WCHAR LfnBuf[_MAX_LFN+1]; /* LFN enabled with static working buffer */ #define FREE_NAMBUF() ff_memfree(lfn) #else #define DEF_NAMBUF WCHAR *lfn; -#define INIT_NAMBUF(fs) { lfn = ff_memalloc((_MAX_LFN+1)*2); if (!lfn) LEAVE_FF(fs, FR_NOT_ENOUGH_CORE); (fs)->lfnbuf = lfn; } +#define INIT_NAMBUF(fs) { lfn = (WCHAR *)ff_memalloc((_MAX_LFN+1)*2); if (!lfn) LEAVE_FF(fs, FR_NOT_ENOUGH_CORE); (fs)->lfnbuf = lfn; } #define FREE_NAMBUF() ff_memfree(lfn) #endif diff --git a/components/dfs/filesystems/nfs/SConscript b/components/dfs/filesystems/nfs/SConscript index 8f1e6defcd..f830dfc754 100644 --- a/components/dfs/filesystems/nfs/SConscript +++ b/components/dfs/filesystems/nfs/SConscript @@ -6,6 +6,8 @@ cwd = GetCurrentDir() src = Glob('*.c') + Glob('rpc/*.c') CPPPATH = [cwd] +SrcRemove(src, ['rpc/auth_none.c']) + group = DefineGroup('Filesystem', src, depend = ['RT_USING_DFS', 'RT_USING_DFS_NFS'], CPPPATH = CPPPATH) Return('group') diff --git a/components/dfs/filesystems/nfs/dfs_nfs.c b/components/dfs/filesystems/nfs/dfs_nfs.c index f365314564..e60f6f98c0 100644 --- a/components/dfs/filesystems/nfs/dfs_nfs.c +++ b/components/dfs/filesystems/nfs/dfs_nfs.c @@ -225,7 +225,7 @@ static nfs_fh3 *get_dir_handle(nfs_filesystem *nfs, const char *name) copy_handle(handle, &nfs->current_handle); } - while ((file = strtok_r(NULL, "/", &path)) != NULL && path[0] != 0) + while ((file = strtok_r(NULL, "/", &path)) != NULL && path && path[0] != 0) { LOOKUP3args args; LOOKUP3res res; @@ -747,7 +747,7 @@ int nfs_open(struct dfs_fd *file) RT_ASSERT(file->data != NULL); struct dfs_filesystem *dfs_nfs = ((struct dfs_filesystem *)(file->data)); nfs = (struct nfs_filesystem *)(dfs_nfs->data); - + RT_ASSERT(nfs != NULL); if (file->flags & O_DIRECTORY) { @@ -1106,6 +1106,15 @@ int nfs_getdents(struct dfs_fd *file, struct dirent *dirp, uint32_t count) if (name == NULL) break; + if (rt_strcmp(name, ".") == 0) + { + continue; + } + else if (rt_strcmp(name, "..") == 0) + { + continue; + } + d->d_type = DT_REG; d->d_namlen = rt_strlen(name); diff --git a/components/dfs/filesystems/nfs/mount_xdr.c b/components/dfs/filesystems/nfs/mount_xdr.c index 8e191d3017..04faa3bb7a 100644 --- a/components/dfs/filesystems/nfs/mount_xdr.c +++ b/components/dfs/filesystems/nfs/mount_xdr.c @@ -101,6 +101,8 @@ xdr_mountres3(register XDR *xdrs, mountres3 *objp) if (!xdr_mountres3_ok(xdrs, &objp->mountres3_u.mountinfo)) return (FALSE); break; + default : + return (FALSE); } return (TRUE); } diff --git a/components/dfs/filesystems/nfs/nfs_auth.c b/components/dfs/filesystems/nfs/nfs_auth.c new file mode 100644 index 0000000000..c65a1126a6 --- /dev/null +++ b/components/dfs/filesystems/nfs/nfs_auth.c @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + */ + +#include <rpc/types.h> +#include <rpc/xdr.h> +#include <rpc/auth.h> + +#define MAX_MARSHEL_SIZE 64 + +struct nfs_credentia +{ + rt_uint32_t stamp; + char *name; + rt_uint32_t uid; + rt_uint32_t gid; + rt_uint32_t *auxi; + rt_uint32_t auxi_count; +}; + +static void authnone_verf(AUTH *); +static bool_t authnone_validate(AUTH *, struct opaque_auth *); +static bool_t authnone_refresh(AUTH *); +static void authnone_destroy(AUTH *); +static bool_t authnone_marshal(AUTH *client, XDR *xdrs); + +static struct nfs_credentia _credentia = { + .stamp = 0, + .name = "rt-thread", + .uid = 0, + .gid = 0, + .auxi = NULL, + .auxi_count = 0, +}; + +struct opaque_auth _null_auth; + +static struct auth_ops ops = +{ + authnone_verf, + authnone_marshal, + authnone_validate, + authnone_refresh, + authnone_destroy +}; + +static struct authnone_private +{ + AUTH no_client; + char marshalled_client[MAX_MARSHEL_SIZE]; + unsigned int mcnt; +} *authnone_private; + +AUTH *authnone_create(void) +{ + register struct authnone_private *ap = authnone_private; + XDR xdr_stream; + register XDR *xdrs; + extern bool_t xdr_opaque_auth(XDR * xdrs, struct opaque_auth * ap); + struct opaque_auth auth; + rt_uint32_t *auth_buf, *auth_base; + int buf_len = 0, str_len = 0; + + if (_credentia.name) + { + str_len = strlen(_credentia.name); + } + if (str_len == 0) + { + _credentia.name = "unknown"; + str_len = strlen(_credentia.name); + } + buf_len = ((str_len) + (sizeof(rt_uint32_t)) - 1) & ~((sizeof(rt_uint32_t)) - 1); + buf_len += sizeof(struct nfs_credentia); + if (_credentia.auxi && _credentia.auxi_count) + { + buf_len += sizeof(rt_uint32_t) * _credentia.auxi_count; + } + auth_buf = auth_base = rt_malloc(buf_len); + if (auth_buf == NULL) + { + return NULL; + } + memset(auth_buf, 0, buf_len); + *auth_buf++ = htonl(rt_tick_get()); + *auth_buf++ = htonl(str_len); + memcpy(auth_buf, _credentia.name, str_len); + auth_buf += (str_len + sizeof(rt_uint32_t) - 1) >> 2; + *auth_buf++ = htonl(_credentia.uid); + *auth_buf++ = htonl(_credentia.gid); + if (_credentia.auxi && _credentia.auxi_count) + { + rt_uint32_t tmp_cnt = 0; + *auth_buf++ = htonl(_credentia.auxi_count); + while (tmp_cnt < _credentia.auxi_count) + { + *auth_buf++ = htonl(_credentia.auxi[tmp_cnt]); + } + } + else + { + *auth_buf++ = htonl(0); + } + + if (ap == 0) + { + ap = (struct authnone_private *) rt_malloc(sizeof(*ap)); + if (ap == 0) + { + rt_free(auth_base); + return NULL; + } + memset(ap, 0, sizeof(*ap)); + authnone_private = ap; + } + + if (!ap->mcnt) + { + memset(&auth, 0, sizeof(auth)); + auth.oa_flavor = 1; + auth.oa_base = (char *)auth_base; + auth.oa_length = (auth_buf - auth_base) * sizeof(rt_uint32_t); + ap->no_client.ah_cred = auth; + ap->no_client.ah_verf = _null_auth; + ap->no_client.ah_ops = &ops; + xdrs = &xdr_stream; + xdrmem_create(xdrs, ap->marshalled_client, + (unsigned int) MAX_MARSHEL_SIZE, XDR_ENCODE); + (void) xdr_opaque_auth(xdrs, &ap->no_client.ah_cred); + (void) xdr_opaque_auth(xdrs, &ap->no_client.ah_verf); + ap->mcnt = XDR_GETPOS(xdrs); + XDR_DESTROY(xdrs); + } + rt_free(auth_base); + return (&ap->no_client); +} + +/*ARGSUSED*/ +static bool_t authnone_marshal(AUTH *client, XDR *xdrs) +{ + register struct authnone_private *ap = authnone_private; + + if (ap == 0) + return (0); + return ((*xdrs->x_ops->x_putbytes)(xdrs, + ap->marshalled_client, ap->mcnt)); +} + +static void authnone_verf(AUTH *x) +{ +} + +static bool_t authnone_validate(AUTH *x, struct opaque_auth *x1) +{ + + return (TRUE); +} + +static bool_t authnone_refresh(AUTH *x) +{ + + return (FALSE); +} + +static void authnone_destroy(AUTH *x) +{ +} diff --git a/components/dfs/filesystems/nfs/nfs_xdr.c b/components/dfs/filesystems/nfs/nfs_xdr.c index 4cd69ba743..33563976c3 100644 --- a/components/dfs/filesystems/nfs/nfs_xdr.c +++ b/components/dfs/filesystems/nfs/nfs_xdr.c @@ -496,6 +496,8 @@ xdr_GETATTR3res(register XDR *xdrs, GETATTR3res *objp) if (!xdr_GETATTR3resok(xdrs, &objp->GETATTR3res_u.resok)) return (FALSE); break; + default : + return (FALSE); } return (TRUE); } diff --git a/components/dfs/filesystems/uffs/dfs_uffs.c b/components/dfs/filesystems/uffs/dfs_uffs.c index c89102f3e3..fb8caf9dd7 100644 --- a/components/dfs/filesystems/uffs/dfs_uffs.c +++ b/components/dfs/filesystems/uffs/dfs_uffs.c @@ -226,7 +226,7 @@ static int dfs_uffs_mkfs(rt_device_t dev_id) } /*2. then unmount the partition */ - uffs_Mount(nand_part[index].mount_path); + uffs_UnMount(nand_part[index].mount_path); mtd = nand_part[index].dev; /*3. erase all blocks on the partition */ @@ -234,11 +234,13 @@ static int dfs_uffs_mkfs(rt_device_t dev_id) for (; block <= mtd->block_end; block++) { rt_mtd_nand_erase_block(mtd, block); +#if defined(RT_UFFS_USE_CHECK_MARK_FUNCITON) if (rt_mtd_nand_check_block(mtd, block) != RT_EOK) { rt_kprintf("found bad block %d\n", block); rt_mtd_nand_mark_badblock(mtd, block); } +#endif } /*4. remount it */ diff --git a/components/dfs/include/dfs_file.h b/components/dfs/include/dfs_file.h index aaff3f6e9c..2dfacd653e 100644 --- a/components/dfs/include/dfs_file.h +++ b/components/dfs/include/dfs_file.h @@ -66,6 +66,10 @@ int dfs_file_lseek(struct dfs_fd *fd, off_t offset); int dfs_file_stat(const char *path, struct stat *buf); int dfs_file_rename(const char *oldpath, const char *newpath); +int dfs_file_ftruncate(struct dfs_fd *fd, off_t length); + +/* 0x5254 is just a magic number to make these relatively unique ("RT") */ +#define RT_FIOFTRUNCATE 0x52540000U #ifdef __cplusplus } diff --git a/components/dfs/include/dfs_fs.h b/components/dfs/include/dfs_fs.h index d3a00fc542..58a9e5cf55 100644 --- a/components/dfs/include/dfs_fs.h +++ b/components/dfs/include/dfs_fs.h @@ -90,6 +90,7 @@ int dfs_unmount(const char *specialfile); int dfs_mkfs(const char *fs_name, const char *device_name); int dfs_statfs(const char *path, struct statfs *buffer); +int dfs_mount_device(rt_device_t dev); #ifdef __cplusplus } diff --git a/components/dfs/include/dfs_posix.h b/components/dfs/include/dfs_posix.h index 9fd76debe2..87d5f0771e 100644 --- a/components/dfs/include/dfs_posix.h +++ b/components/dfs/include/dfs_posix.h @@ -58,6 +58,7 @@ int fstat(int fildes, struct stat *buf); int fsync(int fildes); int fcntl(int fildes, int cmd, ...); int ioctl(int fildes, int cmd, ...); +int ftruncate(int fd, off_t length); /* directory api*/ int rmdir(const char *path); diff --git a/components/dfs/src/dfs.c b/components/dfs/src/dfs.c index 5bddb96930..b20de13988 100644 --- a/components/dfs/src/dfs.c +++ b/components/dfs/src/dfs.c @@ -141,7 +141,7 @@ static int fd_alloc(struct dfs_fdtable *fdt, int startfd) cnt = fdt->maxfd + 4; cnt = cnt > DFS_FD_MAX ? DFS_FD_MAX : cnt; - fds = rt_realloc(fdt->fds, cnt * sizeof(struct dfs_fd *)); + fds = (struct dfs_fd **)rt_realloc(fdt->fds, cnt * sizeof(struct dfs_fd *)); if (fds == NULL) goto __exit; /* return fdt->maxfd */ /* clean the new allocated fds */ @@ -157,7 +157,7 @@ static int fd_alloc(struct dfs_fdtable *fdt, int startfd) /* allocate 'struct dfs_fd' */ if (idx < (int)fdt->maxfd && fdt->fds[idx] == RT_NULL) { - fdt->fds[idx] = rt_calloc(1, sizeof(struct dfs_fd)); + fdt->fds[idx] = (struct dfs_fd *)rt_calloc(1, sizeof(struct dfs_fd)); if (fdt->fds[idx] == RT_NULL) idx = fdt->maxfd; } @@ -393,7 +393,7 @@ char *dfs_normalize_path(const char *directory, const char *filename) if (filename[0] != '/') /* it's a absolute path, use it directly */ { - fullpath = rt_malloc(strlen(directory) + strlen(filename) + 2); + fullpath = (char *)rt_malloc(strlen(directory) + strlen(filename) + 2); if (fullpath == NULL) return NULL; @@ -537,7 +537,7 @@ int list_fd(void) if (fd && fd->fops) { - rt_kprintf("%2d ", index); + rt_kprintf("%2d ", index + DFS_FD_OFFSET); if (fd->type == FT_DIRECTORY) rt_kprintf("%-7.7s ", "dir"); else if (fd->type == FT_REGULAR) rt_kprintf("%-7.7s ", "file"); else if (fd->type == FT_SOCKET) rt_kprintf("%-7.7s ", "socket"); diff --git a/components/dfs/src/dfs_file.c b/components/dfs/src/dfs_file.c index 65fd0c45e8..1063a278ab 100644 --- a/components/dfs/src/dfs_file.c +++ b/components/dfs/src/dfs_file.c @@ -482,6 +482,35 @@ __exit: return result; } +/** + * this function is will cause the regular file referenced by fd + * to be truncated to a size of precisely length bytes. + * + * @param fd the file descriptor. + * @param length the length to be truncated. + * + * @return the status of truncated. + */ +int dfs_file_ftruncate(struct dfs_fd *fd, off_t length) +{ + int result; + + /* fd is null or not a regular file system fd, or length is invalid */ + if (fd == NULL || fd->type != FT_REGULAR || length < 0) + return -EINVAL; + + if (fd->fops->ioctl == NULL) + return -ENOSYS; + + result = fd->fops->ioctl(fd, RT_FIOFTRUNCATE, (void*)&length); + + /* update current size */ + if (result == 0) + fd->size = length; + + return result; +} + #ifdef RT_USING_FINSH #include <finsh.h> @@ -600,7 +629,7 @@ static void copyfile(const char *src, const char *dst) rt_uint8_t *block_ptr; rt_int32_t read_bytes; - block_ptr = rt_malloc(BUF_SZ); + block_ptr = (rt_uint8_t *)rt_malloc(BUF_SZ); if (block_ptr == NULL) { rt_kprintf("out of memory\n"); @@ -715,7 +744,7 @@ static void copydir(const char *src, const char *dst) static const char *_get_path_lastname(const char *path) { char *ptr; - if ((ptr = strrchr(path, '/')) == NULL) + if ((ptr = (char *)strrchr(path, '/')) == NULL) return path; /* skip the '/' then return */ diff --git a/components/dfs/src/dfs_fs.c b/components/dfs/src/dfs_fs.c index 04d862e85d..164beed719 100644 --- a/components/dfs/src/dfs_fs.c +++ b/components/dfs/src/dfs_fs.c @@ -508,7 +508,7 @@ int dfs_mount_table(void) mount_table[index].rwflag, mount_table[index].data) != 0) { - rt_kprintf("mount fs[%s] on %s failed.\n", mount_table[index].filesystemtype, + LOG_E("mount fs[%s] on %s failed.\n", mount_table[index].filesystemtype, mount_table[index].path); return -RT_ERROR; } @@ -518,6 +518,43 @@ int dfs_mount_table(void) return 0; } INIT_ENV_EXPORT(dfs_mount_table); + +int dfs_mount_device(rt_device_t dev) +{ + int index = 0; + + if(dev == RT_NULL) { + rt_kprintf("the device is NULL to be mounted.\n"); + return -RT_ERROR; + } + + while (1) + { + if (mount_table[index].path == NULL) break; + + if(strcmp(mount_table[index].device_name, dev->parent.name) == 0) { + if (dfs_mount(mount_table[index].device_name, + mount_table[index].path, + mount_table[index].filesystemtype, + mount_table[index].rwflag, + mount_table[index].data) != 0) + { + LOG_E("mount fs[%s] device[%s] to %s failed.\n", mount_table[index].filesystemtype, dev->parent.name, + mount_table[index].path); + return -RT_ERROR; + } else { + LOG_D("mount fs[%s] device[%s] to %s ok.\n", mount_table[index].filesystemtype, dev->parent.name, + mount_table[index].path); + return RT_EOK; + } + } + + index ++; + } + + rt_kprintf("can't find device:%s to be mounted.\n", dev->parent.name); + return -RT_ERROR; +} #endif #ifdef RT_USING_FINSH diff --git a/components/dfs/src/dfs_posix.c b/components/dfs/src/dfs_posix.c index 6d643e2d4a..fc603df437 100644 --- a/components/dfs/src/dfs_posix.c +++ b/components/dfs/src/dfs_posix.c @@ -265,11 +265,11 @@ RTM_EXPORT(lseek); * * note: the old and new file name must be belong to a same file system. */ -int rename(const char *old, const char *new) +int rename(const char *old_file, const char *new_file) { int result; - result = dfs_file_rename(old, new); + result = dfs_file_rename(old_file, new_file); if (result < 0) { rt_set_errno(result); @@ -472,6 +472,52 @@ int ioctl(int fildes, int cmd, ...) RTM_EXPORT(ioctl); /** + * + * this function is a POSIX compliant version, which cause the regular file + * referenced by fd to be truncated to a size of precisely length bytes. + * @param fd the file descriptor. + * @param length the length to be truncated. + * + * @return Upon successful completion, ftruncate() shall return 0; + * otherwise, -1 shall be returned and errno set to indicate the error. + */ +int ftruncate(int fd, off_t length) +{ + int result; + struct dfs_fd *d; + + d = fd_get(fd); + if (d == NULL) + { + rt_set_errno(-EBADF); + + return -1; + } + + if (length < 0) + { + fd_put(d); + rt_set_errno(-EINVAL); + + return -1; + } + result = dfs_file_ftruncate(d, length); + if (result < 0) + { + fd_put(d); + rt_set_errno(result); + + return -1; + } + + /* release the ref-count of fd */ + fd_put(d); + + return 0; +} +RTM_EXPORT(ftruncate); + +/** * this function is a POSIX compliant version, which will return the * information about a mounted file system. * diff --git a/components/dfs/src/poll.c b/components/dfs/src/poll.c index aee157eed5..3f304549f7 100644 --- a/components/dfs/src/poll.c +++ b/components/dfs/src/poll.c @@ -19,6 +19,8 @@ #include <dfs_posix.h> #include <dfs_poll.h> +#ifdef RT_USING_POSIX + struct rt_poll_node; struct rt_poll_table @@ -54,7 +56,7 @@ static void _poll_add(rt_wqueue_t *wq, rt_pollreq_t *req) struct rt_poll_table *pt; struct rt_poll_node *node; - node = rt_malloc(sizeof(struct rt_poll_node)); + node = (struct rt_poll_node *)rt_malloc(sizeof(struct rt_poll_node)); if (node == RT_NULL) return; @@ -214,3 +216,4 @@ int poll(struct pollfd *fds, nfds_t nfds, int timeout) return num; } +#endif diff --git a/components/dfs/src/select.c b/components/dfs/src/select.c index b20f7cf656..181855bc74 100644 --- a/components/dfs/src/select.c +++ b/components/dfs/src/select.c @@ -14,6 +14,8 @@ #include <dfs_poll.h> #include <dfs_select.h> +#ifdef RT_USING_POSIX + static void fdszero(fd_set *set, int nfds) { fd_mask *m; @@ -178,3 +180,4 @@ int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struc return ret; } +#endif diff --git a/components/drivers/Kconfig b/components/drivers/Kconfig index 792dc1b028..c567233c84 100755 --- a/components/drivers/Kconfig +++ b/components/drivers/Kconfig @@ -48,7 +48,7 @@ config RT_USING_CAN if RT_USING_CAN config RT_CAN_USING_HDR bool "Enable CAN hardware filter" - default y + default n endif config RT_USING_HWTIMER @@ -88,11 +88,21 @@ config RT_USING_I2C default n if RT_USING_I2C + config RT_I2C_DEBUG + bool "Use I2C debug mesage" + default n + config RT_USING_I2C_BITOPS bool "Use GPIO to simulate I2C" default y endif +if RT_USING_I2C_BITOPS + config RT_I2C_BITOPS_DEBUG + bool "Use simulate I2C debug mesage" + default n +endif + config RT_USING_PIN bool "Using generic GPIO device drivers" default y @@ -119,27 +129,12 @@ config RT_USING_MTD_NAND default n endif -config RT_USING_MTD - bool "Using Memory Technology Device (MTD)" - default n - - if RT_USING_MTD - config MTD_USING_NOR - bool "Using MTD Nor Flash device" - default n - - config MTD_USING_NAND - bool "Using MTD Nand Flash device" - default n - endif - config RT_USING_PM bool "Using Power Management device drivers" default n config RT_USING_RTC bool "Using RTC device drivers" - select RT_USING_LIBC default n if RT_USING_RTC @@ -212,6 +207,9 @@ config RT_USING_SPI config RT_USING_SFUD bool "Using Serial Flash Universal Driver" default n + help + An using JEDEC's SFDP standard serial (SPI) flash universal driver library + if RT_USING_SFUD config RT_SFUD_USING_SFDP bool "Using auto probe flash JEDEC SFDP parameter" @@ -226,19 +224,18 @@ config RT_USING_SPI select RT_USING_QSPI default n + config RT_SFUD_SPI_MAX_HZ + int "Default spi maximum speed(HZ)" + range 0 50000000 + default 50000000 + help + Read the JEDEC SFDP command must run at 50 MHz or less,and you also can use rt_spi_configure(); to config spi speed. + config RT_DEBUG_SFUD bool "Show more SFUD debug information" default n endif - config RT_USING_W25QXX - bool "Using W25QXX SPI NorFlash" - default n - - config RT_USING_GD - bool "Using GD SPI NorFlash" - default n - config RT_USING_ENC28J60 bool "Using ENC28J60 SPI Ethernet network interface" select RT_USING_LWIP @@ -257,6 +254,20 @@ config RT_USING_WDT config RT_USING_AUDIO bool "Using Audio device drivers" default n + + if RT_USING_AUDIO + config RT_AUDIO_REPLAY_MP_BLOCK_SIZE + int "Replay memmory pool block size" + default 4096 + + config RT_AUDIO_REPLAY_MP_BLOCK_COUNT + int "Replay memmory pool block count" + default 2 + + config RT_AUDIO_RECORD_PIPE_SIZE + int "Record pipe size" + default 2048 + endif config RT_USING_SENSOR bool "Using Sensor device drivers" @@ -269,67 +280,309 @@ if RT_USING_SENSOR default y endif -menu "Using WiFi" - config RT_USING_WIFI - bool "Using Wi-Fi framework" +config RT_USING_TOUCH + bool "Using Touch device drivers" + default n + +menuconfig RT_USING_HWCRYPTO + bool "Using Hardware Crypto drivers" default n + if RT_USING_HWCRYPTO + config RT_HWCRYPTO_DEFAULT_NAME + string "Hardware crypto device name" + default "hwcryto" + + config RT_HWCRYPTO_IV_MAX_SIZE + int "IV max size" + default "16" + + config RT_HWCRYPTO_KEYBIT_MAX_SIZE + int "Key max bit length" + default 256 + + config RT_HWCRYPTO_USING_GCM + bool "Using Hardware GCM" + default n + + config RT_HWCRYPTO_USING_AES + bool "Using Hardware AES" + default n + + if RT_HWCRYPTO_USING_AES + config RT_HWCRYPTO_USING_AES_ECB + bool "Using Hardware AES ECB mode" + default y + + config RT_HWCRYPTO_USING_AES_CBC + bool "Using Hardware AES CBC mode" + default n + + config RT_HWCRYPTO_USING_AES_CFB + bool "Using Hardware AES CFB mode" + default n + + config RT_HWCRYPTO_USING_AES_CTR + bool "Using Hardware AES CTR mode" + default n + + config RT_HWCRYPTO_USING_AES_OFB + bool "Using Hardware AES OFB mode" + default n + endif + + config RT_HWCRYPTO_USING_DES + bool "Using Hardware DES" + default n + + if RT_HWCRYPTO_USING_DES + config RT_HWCRYPTO_USING_DES_ECB + bool "Using Hardware DES ECB mode" + default y + + config RT_HWCRYPTO_USING_DES_CBC + bool "Using Hardware DES CBC mode" + default n + endif + + config RT_HWCRYPTO_USING_3DES + bool "Using Hardware 3DES" + default n + + if RT_HWCRYPTO_USING_3DES + config RT_HWCRYPTO_USING_3DES_ECB + bool "Using Hardware 3DES ECB mode" + default y + + config RT_HWCRYPTO_USING_3DES_CBC + bool "Using Hardware 3DES CBC mode" + default n + endif + + config RT_HWCRYPTO_USING_RC4 + bool "Using Hardware RC4" + default n + + config RT_HWCRYPTO_USING_MD5 + bool "Using Hardware MD5" + default n + + config RT_HWCRYPTO_USING_SHA1 + bool "Using Hardware SHA1" + default n + + config RT_HWCRYPTO_USING_SHA2 + bool "Using Hardware SHA2" + default n + + if RT_HWCRYPTO_USING_SHA2 + config RT_HWCRYPTO_USING_SHA2_224 + bool "Using Hardware SHA2_224 mode" + default n + + config RT_HWCRYPTO_USING_SHA2_256 + bool "Using Hardware SHA2_256 mode" + default y + + config RT_HWCRYPTO_USING_SHA2_384 + bool "Using Hardware SHA2_384 mode" + default n + + config RT_HWCRYPTO_USING_SHA2_512 + bool "Using Hardware SHA2_512 mode" + default n + endif + + config RT_HWCRYPTO_USING_RNG + bool "Using Hardware RNG" + default n + + config RT_HWCRYPTO_USING_CRC + bool "Using Hardware CRC" + default n + + if RT_HWCRYPTO_USING_CRC + config RT_HWCRYPTO_USING_CRC_07 + bool "Using Hardware CRC-8 0x07 polynomial" + default n + + config RT_HWCRYPTO_USING_CRC_8005 + bool "Using Hardware CRC-16 0x8005 polynomial" + default n + + config RT_HWCRYPTO_USING_CRC_1021 + bool "Using Hardware CRC-16 0x1021 polynomial" + default n + + config RT_HWCRYPTO_USING_CRC_3D65 + bool "Using Hardware CRC-16 0x3D65 polynomial" + default n + + config RT_HWCRYPTO_USING_CRC_04C11DB7 + bool "Using Hardware CRC-32 0x04C11DB7 polynomial" + default n + endif + + config RT_HWCRYPTO_USING_BIGNUM + bool "Using Hardware bignum" + default n + + if RT_HWCRYPTO_USING_BIGNUM + config RT_HWCRYPTO_USING_BIGNUM_EXPTMOD + bool "Using Hardware bignum expt_mod operation" + default y + + config RT_HWCRYPTO_USING_BIGNUM_MULMOD + bool "Using Hardware bignum mul_mod operation" + default y + + config RT_HWCRYPTO_USING_BIGNUM_MUL + bool "Using Hardware bignum mul operation" + default n + + config RT_HWCRYPTO_USING_BIGNUM_ADD + bool "Using Hardware bignum add operation" + default n + + config RT_HWCRYPTO_USING_BIGNUM_SUB + bool "Using Hardware bignum sub operation" + default n + endif + endif + +config RT_USING_PULSE_ENCODER + bool "Using PULSE ENCODER device drivers" + default n + +config RT_USING_INPUT_CAPTURE + bool "Using INPUT CAPTURE device drivers" + default n + +if RT_USING_INPUT_CAPTURE + config RT_INPUT_CAPTURE_RB_SIZE + int "Set input capture ringbuffer size" + default 100 +endif + +menuconfig RT_USING_WIFI + bool "Using Wi-Fi framework" + default n + if RT_USING_WIFI config RT_WLAN_DEVICE_STA_NAME - string "The WiFi device name for station" + string "The device name for station" default "wlan0" config RT_WLAN_DEVICE_AP_NAME - string "The WiFi device name for ap" + string "The device name for ap" default "wlan1" - config RT_WLAN_DEFAULT_PROT - string "Default transport protocol" - default "lwip" - - config RT_WLAN_SCAN_WAIT_MS - int "Set scan timeout time(ms)" - default 10000 - - config RT_WLAN_CONNECT_WAIT_MS - int "Set connect timeout time(ms)" - default 10000 - config RT_WLAN_SSID_MAX_LENGTH - int "SSID name maximum length" + int "SSID maximum length" default 32 config RT_WLAN_PASSWORD_MAX_LENGTH - int "Maximum password length" + int "Password maximum length" default 32 - config RT_WLAN_SCAN_SORT - bool "Automatic sorting of scan results" + config RT_WLAN_DEV_EVENT_NUM + int "Driver events maxcount" + default 2 + + config RT_WLAN_MANAGE_ENABLE + bool "Connection management Enable" default y - config RT_WLAN_CFG_INFO_MAX - int "Maximum number of WiFi information automatically saved" - default 3 + if RT_WLAN_MANAGE_ENABLE + config RT_WLAN_SCAN_WAIT_MS + int "Set scan timeout time(ms)" + default 10000 - config RT_WLAN_WORKQUEUE_THREAD_NAME - string "WiFi work queue thread name" - default "wlan_job" + config RT_WLAN_CONNECT_WAIT_MS + int "Set connect timeout time(ms)" + default 10000 - config RT_WLAN_WORKQUEUE_THREAD_SIZE - int "wifi work queue thread size" - default 2048 + config RT_WLAN_SCAN_SORT + bool "Automatic sorting of scan results" + default y - config RT_WLAN_WORKQUEUE_THREAD_PRIO - int "WiFi work queue thread priority" - default 22 + config RT_WLAN_MSH_CMD_ENABLE + bool "MSH command Enable" + default y - config RT_WLAN_DEV_EVENT_NUM - int "Maximum number of driver events" - default 2 + config RT_WLAN_AUTO_CONNECT_ENABLE + bool "Auto connect Enable" + select RT_WLAN_CFG_ENABLE + select RT_WLAN_WORK_THREAD_ENABLE + default y - config RT_WLAN_PROT_LWIP_PBUF_FORCE - bool "Forced use of PBUF transmission" - default n + if RT_WLAN_AUTO_CONNECT_ENABLE + config AUTO_CONNECTION_PERIOD_MS + int "Auto connect period(ms)" + default 2000 + endif + endif + + config RT_WLAN_CFG_ENABLE + bool "WiFi information automatically saved Enable" + default y + + if RT_WLAN_CFG_ENABLE + config RT_WLAN_CFG_INFO_MAX + int "Maximum number of WiFi information automatically saved" + default 3 + endif + + config RT_WLAN_PROT_ENABLE + bool "Transport protocol manage Enable" + default y + + if RT_WLAN_PROT_ENABLE + config RT_WLAN_PROT_NAME_LEN + int "Transport protocol name length" + default 8 + + config RT_WLAN_PROT_MAX + int "Transport protocol maxcount" + default 2 + + config RT_WLAN_DEFAULT_PROT + string "Default transport protocol" + default "lwip" + + config RT_WLAN_PROT_LWIP_ENABLE + bool "LWIP transport protocol Enable" + select RT_USING_LWIP + default y + + if RT_WLAN_PROT_LWIP_ENABLE + config RT_WLAN_PROT_LWIP_NAME + string "LWIP transport protocol name" + default "lwip" + + config RT_WLAN_PROT_LWIP_PBUF_FORCE + bool "Forced use of PBUF transmission" + default n + endif + endif + + config RT_WLAN_WORK_THREAD_ENABLE + bool "WLAN work queue thread Enable" + default y + + if RT_WLAN_WORK_THREAD_ENABLE + config RT_WLAN_WORKQUEUE_THREAD_NAME + string "WLAN work queue thread name" + default "wlan" + + config RT_WLAN_WORKQUEUE_THREAD_SIZE + int "WLAN work queue thread size" + default 2048 + + config RT_WLAN_WORKQUEUE_THREAD_PRIO + int "WLAN work queue thread priority" + default 15 + endif menuconfig RT_WLAN_DEBUG bool "Enable WLAN Debugging Options" @@ -361,7 +614,6 @@ menu "Using WiFi" default n endif endif -endmenu menu "Using USB" config RT_USING_USB_HOST @@ -424,6 +676,9 @@ menu "Using USB" config _RT_USB_DEVICE_WINUSB bool "Enable to use device as winusb device" select RT_USB_DEVICE_WINUSB + config _RT_USB_DEVICE_AUDIO + bool "Enable to use device as audio device" + select RT_USB_DEVICE_AUDIO endchoice if RT_USB_DEVICE_COMPOSITE config RT_USB_DEVICE_CDC @@ -449,6 +704,9 @@ menu "Using USB" config RT_USB_DEVICE_WINUSB bool "Enable to use device as winusb device" default n + config RT_USB_DEVICE_AUDIO + bool "Enable to use device as audio device" + default n endif if RT_USB_DEVICE_CDC config RT_VCOM_TASK_STK_SIZE @@ -477,6 +735,14 @@ menu "Using USB" string "msc class disk name" default "flash0" endif + + if RT_USB_DEVICE_RNDIS + config RNDIS_DELAY_LINK_UP + bool "Delay linkup media connection" + select RT_USING_TIMER_SOFT + default n + endif + if RT_USB_DEVICE_HID config RT_USB_DEVICE_HID_KEYBOARD bool "Use to HID device as Keyboard" @@ -508,6 +774,24 @@ menu "Using USB" bool "Use to HID device as media keyboard" default y endif + if RT_USB_DEVICE_AUDIO + config RT_USB_DEVICE_AUDIO_MIC + bool "Use usb mic device as audio device" + default n + if RT_USB_DEVICE_AUDIO_MIC + config RT_USBD_MIC_DEVICE_NAME + string "audio mic device name" + default "mic0" + endif + config RT_USB_DEVICE_AUDIO_SPEAKER + bool "Use usb speaker device as audio device" + default n + if RT_USB_DEVICE_AUDIO_SPEAKER + config RT_USBD_SPEAKER_DEVICE_NAME + string "audio speaker device name" + default "sound0" + endif + endif endif endmenu endmenu diff --git a/components/drivers/audio/audio.c b/components/drivers/audio/audio.c index 6a5ebc8741..28ddf0fe56 100644 --- a/components/drivers/audio/audio.c +++ b/components/drivers/audio/audio.c @@ -5,83 +5,208 @@ * * Change Logs: * Date Author Notes - * 2017-05-09 Urey first version + * 2017-05-09 Urey first version + * 2019-07-09 Zero-Free improve device ops interface and data flows */ #include <stdio.h> +#include <string.h> #include <rthw.h> #include <rtthread.h> #include <rtdevice.h> -#include <drivers/audio.h> +#define DBG_TAG "audio" +#define DBG_LVL DBG_INFO +#include <rtdbg.h> -#include "audio_pipe.h" +#define MIN(a, b) ((a) < (b) ? (a) : (b)) - -#define AUDIO_DEBUG 0 -#if AUDIO_DEBUG -#define AUDIO_DBG(...) printf("[AUDIO]:"),printf(__VA_ARGS__) -#else -#define AUDIO_DBG(...) -#endif - -static struct rt_audio_pipe audio_pipe; +enum +{ + REPLAY_EVT_NONE = 0x00, + REPLAY_EVT_START = 0x01, + REPLAY_EVT_STOP = 0x02, +}; static rt_err_t _audio_send_replay_frame(struct rt_audio_device *audio) { rt_err_t result = RT_EOK; - rt_base_t level; - struct rt_audio_frame frame; + rt_uint8_t *data; + rt_size_t dst_size, src_size; + rt_uint16_t position, remain_bytes, index = 0; + struct rt_audio_buf_info *buf_info; RT_ASSERT(audio != RT_NULL); - //check repaly queue is empty - if (rt_data_queue_peak(&audio->replay->queue, &frame.data_ptr, &frame.data_size) != RT_EOK) + buf_info = &audio->replay->buf_info; + /* save current pos */ + position = audio->replay->pos; + dst_size = buf_info->block_size; + + /* check repaly queue is empty */ + if (rt_data_queue_peak(&audio->replay->queue, (const void **)&data, &src_size) != RT_EOK) { - AUDIO_DBG("TX queue is empty\n"); - result = -RT_EEMPTY; + /* ack stop event */ + if (audio->replay->event & REPLAY_EVT_STOP) + rt_completion_done(&audio->replay->cmp); - level = rt_hw_interrupt_disable(); - audio->replay->activated = RT_FALSE; - rt_hw_interrupt_enable(level); + /* send zero frames */ + memset(&buf_info->buffer[audio->replay->pos], 0, dst_size); - goto _exit; + audio->replay->pos += dst_size; + audio->replay->pos %= buf_info->total_size; } - - if (audio->ops->transmit != RT_NULL) + else { - AUDIO_DBG("audio transmit...\n"); - if (audio->ops->transmit(audio, frame.data_ptr, RT_NULL, frame.data_size) != frame.data_size) + memset(&buf_info->buffer[audio->replay->pos], 0, dst_size); + + /* copy data from memory pool to hardware device fifo */ + while (index < dst_size) { - result = -RT_EBUSY; + result = rt_data_queue_peak(&audio->replay->queue, (const void **)&data, &src_size); + if (result != RT_EOK) + { + LOG_D("under run %d, remain %d", audio->replay->pos, remain_bytes); + audio->replay->pos -= remain_bytes; + audio->replay->pos += dst_size; + audio->replay->pos %= buf_info->total_size; + audio->replay->read_index = 0; + result = -RT_EEMPTY; + break; + } + + remain_bytes = MIN((dst_size - index), (src_size - audio->replay->read_index)); + memcpy(&buf_info->buffer[audio->replay->pos], + &data[audio->replay->read_index], remain_bytes); + + index += remain_bytes; + audio->replay->read_index += remain_bytes; + audio->replay->pos += remain_bytes; + audio->replay->pos %= buf_info->total_size; + + if (audio->replay->read_index == src_size) + { + /* free memory */ + audio->replay->read_index = 0; + rt_data_queue_pop(&audio->replay->queue, (const void **)&data, &src_size, RT_WAITING_NO); + rt_mp_free(data); - goto _exit; + /* notify transmitted complete. */ + if (audio->parent.tx_complete != RT_NULL) + audio->parent.tx_complete(&audio->parent, (void *)data); + } } } - //pop the head frame... - rt_data_queue_pop(&audio->replay->queue, &frame.data_ptr, &frame.data_size, RT_WAITING_FOREVER); + if (audio->ops->transmit != RT_NULL) + { + if (audio->ops->transmit(audio, &buf_info->buffer[position], RT_NULL, dst_size) != dst_size) + result = -RT_ERROR; + } - _exit: return result; + return result; } static rt_err_t _audio_flush_replay_frame(struct rt_audio_device *audio) { - struct rt_audio_frame frame; + rt_err_t result = RT_EOK; - if (audio->replay == RT_NULL) - return -RT_EIO; - while (rt_data_queue_peak(&audio->replay->queue, &frame.data_ptr, &frame.data_size) == RT_EOK) + if (audio->replay->write_index) { - //pop the head frame... - rt_data_queue_pop(&audio->replay->queue, &frame.data_ptr, &frame.data_size, RT_WAITING_FOREVER); + result = rt_data_queue_push(&audio->replay->queue, + (const void **)audio->replay->write_data, + audio->replay->write_index, + RT_WAITING_FOREVER); - /* notify transmitted complete. */ - if (audio->parent.tx_complete != RT_NULL) - audio->parent.tx_complete(&audio->parent, (void *) frame.data_ptr); + audio->replay->write_index = 0; } - return RT_EOK; + return result; +} + +static rt_err_t _aduio_replay_start(struct rt_audio_device *audio) +{ + rt_err_t result = RT_EOK; + + if (audio->replay->activated != RT_TRUE) + { + /* start playback hardware device */ + if (audio->ops->start) + result = audio->ops->start(audio, AUDIO_STREAM_REPLAY); + + audio->replay->activated = RT_TRUE; + LOG_D("start audio replay device"); + } + + return result; +} + +static rt_err_t _aduio_replay_stop(struct rt_audio_device *audio) +{ + rt_err_t result = RT_EOK; + + if (audio->replay->activated == RT_TRUE) + { + /* flush replay remian frames */ + _audio_flush_replay_frame(audio); + + /* notify irq(or thread) to stop the data transmission */ + audio->replay->event |= REPLAY_EVT_STOP; + + /* waiting for the remaining data transfer to complete */ + rt_completion_init(&audio->replay->cmp); + rt_completion_wait(&audio->replay->cmp, RT_WAITING_FOREVER); + audio->replay->event &= ~REPLAY_EVT_STOP; + + /* stop playback hardware device */ + if (audio->ops->stop) + result = audio->ops->stop(audio, AUDIO_STREAM_REPLAY); + + audio->replay->activated = RT_FALSE; + LOG_D("stop audio replay device"); + } + + return result; +} + +static rt_err_t _audio_record_start(struct rt_audio_device *audio) +{ + rt_err_t result = RT_EOK; + + if (audio->record->activated != RT_TRUE) + { + /* open audio record pipe */ + rt_device_open(RT_DEVICE(&audio->record->pipe), RT_DEVICE_OFLAG_RDONLY); + + /* start record hardware device */ + if (audio->ops->start) + result = audio->ops->start(audio, AUDIO_STREAM_RECORD); + + audio->record->activated = RT_TRUE; + LOG_D("start audio record device"); + } + + return result; +} + +static rt_err_t _audio_record_stop(struct rt_audio_device *audio) +{ + rt_err_t result = RT_EOK; + + if (audio->record->activated == RT_TRUE) + { + /* stop record hardware device */ + if (audio->ops->stop) + result = audio->ops->stop(audio, AUDIO_STREAM_RECORD); + + /* close audio record pipe */ + rt_device_close(RT_DEVICE(&audio->record->pipe)); + + audio->record->activated = RT_FALSE; + LOG_D("stop audio record device"); + } + + return result; } static rt_err_t _audio_dev_init(struct rt_device *dev) @@ -96,9 +221,68 @@ static rt_err_t _audio_dev_init(struct rt_device *dev) audio->replay = RT_NULL; audio->record = RT_NULL; - /* apply configuration */ + /* initialize replay */ + if (dev->flag & RT_DEVICE_FLAG_WRONLY) + { + struct rt_audio_replay *replay = (struct rt_audio_replay *) rt_malloc(sizeof(struct rt_audio_replay)); + + if (replay == RT_NULL) + return -RT_ENOMEM; + memset(replay, 0, sizeof(struct rt_audio_replay)); + + /* init memory pool for replay */ + replay->mp = rt_mp_create("adu_mp", RT_AUDIO_REPLAY_MP_BLOCK_COUNT, RT_AUDIO_REPLAY_MP_BLOCK_SIZE); + if (replay->mp == RT_NULL) + { + rt_free(replay); + LOG_E("create memory pool for repaly failed"); + return -RT_ENOMEM; + } + + /* init queue for audio replay */ + rt_data_queue_init(&replay->queue, CFG_AUDIO_REPLAY_QUEUE_COUNT, 0, RT_NULL); + + /* init mutex lock for audio replay */ + rt_mutex_init(&replay->lock, "replay", RT_IPC_FLAG_PRIO); + + replay->activated = RT_FALSE; + audio->replay = replay; + } + + /* initialize record */ + if (dev->flag & RT_DEVICE_FLAG_RDONLY) + { + struct rt_audio_record *record = (struct rt_audio_record *) rt_malloc(sizeof(struct rt_audio_record)); + rt_uint8_t *buffer; + + if (record == RT_NULL) + return -RT_ENOMEM; + memset(record, 0, sizeof(struct rt_audio_record)); + + /* init pipe for record*/ + buffer = rt_malloc(RT_AUDIO_RECORD_PIPE_SIZE); + if (buffer == RT_NULL) + { + rt_free(record); + LOG_E("malloc memory for for record pipe failed"); + return -RT_ENOMEM; + } + rt_audio_pipe_init(&record->pipe, "record", + (rt_int32_t)(RT_PIPE_FLAG_FORCE_WR | RT_PIPE_FLAG_BLOCK_RD), + buffer, + RT_AUDIO_RECORD_PIPE_SIZE); + + record->activated = RT_FALSE; + audio->record = record; + } + + /* initialize hardware configuration */ if (audio->ops->init) - result = audio->ops->init(audio); + audio->ops->init(audio); + + /* get replay buffer information */ + if (audio->ops->buffer_info) + audio->ops->buffer_info(audio, &audio->replay->buf_info); return result; } @@ -122,65 +306,27 @@ static rt_err_t _audio_dev_open(struct rt_device *dev, rt_uint16_t oflag) /* initialize the Rx/Tx structure according to open flag */ if (oflag & RT_DEVICE_OFLAG_WRONLY) { - AUDIO_DBG("open audio device ,oflag = %x\n",oflag); - if (audio->replay == RT_NULL) + if (audio->replay->activated != RT_TRUE) { - struct rt_audio_replay *replay = (struct rt_audio_replay *) rt_malloc(sizeof(struct rt_audio_replay)); - - if (replay == RT_NULL) - { - AUDIO_DBG("request memory for replay error\n"); - return -RT_ENOMEM; - } - - //init queue for audio replay - rt_data_queue_init(&replay->queue, CFG_AUDIO_REPLAY_QUEUE_COUNT, CFG_AUDIO_REPLAY_QUEUE_COUNT / 2, RT_NULL); - - replay->activated = RT_FALSE; - audio->replay = replay; + LOG_D("open audio replay device, oflag = %x\n", oflag); + audio->replay->write_index = 0; + audio->replay->read_index = 0; + audio->replay->pos = 0; + audio->replay->event = REPLAY_EVT_NONE; } - dev->open_flag |= RT_DEVICE_OFLAG_WRONLY; } if (oflag & RT_DEVICE_OFLAG_RDONLY) { - if (audio->record == RT_NULL) + /* open record pipe */ + if (audio->record->activated != RT_TRUE) { - struct rt_audio_record *record = (struct rt_audio_record *) rt_malloc(sizeof(struct rt_audio_record)); - - if (record == RT_NULL) - { - AUDIO_DBG("request memory for record error\n"); - return -RT_ENOMEM; - } - - //init pipe for record - { - rt_uint8_t *buf = rt_malloc(CFG_AUDIO_RECORD_PIPE_SIZE); - - if (buf == RT_NULL) - { - rt_free(record); - AUDIO_DBG("request pipe memory error\n"); + LOG_D("open audio record device ,oflag = %x\n", oflag); - return -RT_ENOMEM; - } - - rt_audio_pipe_init(&audio_pipe, "recpipe", (rt_int32_t)(RT_PIPE_FLAG_FORCE_WR | RT_PIPE_FLAG_BLOCK_RD), buf, - CFG_AUDIO_RECORD_PIPE_SIZE); - } - - record->activated = RT_FALSE; - audio->record = record; - } - - //open record pipe - if (audio->record != RT_NULL) - { - rt_device_open(RT_DEVICE(&audio_pipe), RT_DEVICE_OFLAG_RDONLY); + _audio_record_start(audio); + audio->record->activated = RT_TRUE; } - dev->open_flag |= RT_DEVICE_OFLAG_RDONLY; } @@ -193,39 +339,17 @@ static rt_err_t _audio_dev_close(struct rt_device *dev) RT_ASSERT(dev != RT_NULL); audio = (struct rt_audio_device *) dev; - //shutdown the lower device - if (audio->ops->shutdown != RT_NULL) - audio->ops->shutdown(audio); - if (dev->open_flag & RT_DEVICE_OFLAG_WRONLY) { - struct rt_audio_frame frame; - //stop replay stream - audio->ops->stop(audio, AUDIO_STREAM_REPLAY); - - //flush all frame - while (rt_data_queue_peak(&audio->replay->queue, &frame.data_ptr, &frame.data_size) == RT_EOK) - { - //pop the head frame... - rt_data_queue_pop(&audio->replay->queue, &frame.data_ptr, &frame.data_size, RT_WAITING_FOREVER); - - /* notify transmitted complete. */ - if (audio->parent.tx_complete != RT_NULL) - audio->parent.tx_complete(&audio->parent, (void *) frame.data_ptr); - } - + /* stop replay stream */ + _aduio_replay_stop(audio); dev->open_flag &= ~RT_DEVICE_OFLAG_WRONLY; } if (dev->open_flag & RT_DEVICE_OFLAG_RDONLY) { - //stop record stream - audio->ops->stop(audio, AUDIO_STREAM_RECORD); - - //close record pipe - if (audio->record != RT_NULL) - rt_device_close(RT_DEVICE(&audio_pipe)); - + /* stop record stream */ + _audio_record_stop(audio); dev->open_flag &= ~RT_DEVICE_OFLAG_RDONLY; } @@ -237,17 +361,19 @@ static rt_size_t _audio_dev_read(struct rt_device *dev, rt_off_t pos, void *buff struct rt_audio_device *audio; RT_ASSERT(dev != RT_NULL); audio = (struct rt_audio_device *) dev; + if (!(dev->open_flag & RT_DEVICE_OFLAG_RDONLY) || (audio->record == RT_NULL)) return 0; - return rt_device_read(RT_DEVICE(&audio_pipe), pos, buffer, size); + return rt_device_read(RT_DEVICE(&audio->record->pipe), pos, buffer, size); } static rt_size_t _audio_dev_write(struct rt_device *dev, rt_off_t pos, const void *buffer, rt_size_t size) { - rt_err_t result = RT_EOK; - rt_base_t level; + struct rt_audio_device *audio; + rt_uint8_t *ptr; + rt_uint16_t block_size, remain_bytes, index = 0; RT_ASSERT(dev != RT_NULL); audio = (struct rt_audio_device *) dev; @@ -255,34 +381,46 @@ static rt_size_t _audio_dev_write(struct rt_device *dev, rt_off_t pos, const voi if (!(dev->open_flag & RT_DEVICE_OFLAG_WRONLY) || (audio->replay == RT_NULL)) return 0; - AUDIO_DBG("audio write : pos = %d,buffer = %x,size = %d\n",pos,(rt_uint32_t)buffer,size); - //push a new frame to tx queue + /* push a new frame to replay data queue */ + ptr = (rt_uint8_t *)buffer; + block_size = RT_AUDIO_REPLAY_MP_BLOCK_SIZE; + + rt_mutex_take(&audio->replay->lock, RT_WAITING_FOREVER); + while (index < size) { - result = rt_data_queue_push(&audio->replay->queue, buffer, size, - RT_WAITING_FOREVER); - if (result != RT_EOK) + /* request buffer from replay memory pool */ + if (audio->replay->write_index % block_size == 0) { - AUDIO_DBG("TX frame queue push error\n"); - rt_set_errno(-RT_EFULL); - return 0; + audio->replay->write_data = rt_mp_alloc(audio->replay->mp, RT_WAITING_FOREVER); + memset(audio->replay->write_data, 0, block_size); + } + + /* copy data to replay memory pool */ + remain_bytes = MIN((block_size - audio->replay->write_index), (size - index)); + memcpy(&audio->replay->write_data[audio->replay->write_index], &ptr[index], remain_bytes); + + index += remain_bytes; + audio->replay->write_index += remain_bytes; + audio->replay->write_index %= block_size; + + if (audio->replay->write_index == 0) + { + rt_data_queue_push(&audio->replay->queue, + audio->replay->write_data, + block_size, + RT_WAITING_FOREVER); } } + rt_mutex_release(&audio->replay->lock); - //check tx state... - level = rt_hw_interrupt_disable(); + /* check replay state */ if (audio->replay->activated != RT_TRUE) { + _aduio_replay_start(audio); audio->replay->activated = RT_TRUE; - rt_hw_interrupt_enable(level); - - _audio_send_replay_frame(audio); - } - else - { - rt_hw_interrupt_enable(level); } - return size; + return index; } static rt_err_t _audio_dev_control(struct rt_device *dev, int cmd, void *args) @@ -292,112 +430,70 @@ static rt_err_t _audio_dev_control(struct rt_device *dev, int cmd, void *args) RT_ASSERT(dev != RT_NULL); audio = (struct rt_audio_device *) dev; - //dev stat... + /* dev stat...*/ switch (cmd) { - case AUDIO_CTL_GETCAPS: - { - struct rt_audio_caps *caps = (struct rt_audio_caps *) args; + case AUDIO_CTL_GETCAPS: + { + struct rt_audio_caps *caps = (struct rt_audio_caps *) args; - AUDIO_DBG("AUDIO_CTL_GETCAPS: main_type = %d,sub_type = %d\n",caps->main_type,caps->sub_type); - if (audio->ops->getcaps != RT_NULL) - { - result = audio->ops->getcaps(audio, caps); - } - } - break; - case AUDIO_CTL_CONFIGURE: + LOG_D("AUDIO_CTL_GETCAPS: main_type = %d,sub_type = %d", caps->main_type, caps->sub_type); + if (audio->ops->getcaps != RT_NULL) { - struct rt_audio_caps *caps = (struct rt_audio_caps *) args; - - AUDIO_DBG("AUDIO_CTL_CONFIGURE: main_type = %d,sub_type = %d\n",caps->main_type,caps->sub_type); - if (audio->ops->configure != RT_NULL) - { - result = audio->ops->configure(audio, caps); - } + result = audio->ops->getcaps(audio, caps); } break; - case AUDIO_CTL_SHUTDOWN: - { - AUDIO_DBG("AUDIO_CTL_SHUTDOWN\n"); - - if (audio->ops->shutdown != RT_NULL) - result = audio->ops->shutdown(audio); + } - //flush replay frame... - _audio_flush_replay_frame(audio); - } - break; + case AUDIO_CTL_CONFIGURE: + { + struct rt_audio_caps *caps = (struct rt_audio_caps *) args; - case AUDIO_CTL_START: + LOG_D("AUDIO_CTL_CONFIGURE: main_type = %d,sub_type = %d", caps->main_type, caps->sub_type); + if (audio->ops->configure != RT_NULL) { - int stream = *(int *) args; - - AUDIO_DBG("AUDIO_CTL_START: stream = %d\n",stream); - if (audio->ops->start != RT_NULL) - result = audio->ops->start(audio, stream); + result = audio->ops->configure(audio, caps); } + break; - case AUDIO_CTL_STOP: - { - int stream = *(int *) args; + } - AUDIO_DBG("AUDIO_CTL_STOP: stream = %d\n",stream); - if (audio->ops->start != RT_NULL) - result = audio->ops->stop(audio, stream); + case AUDIO_CTL_START: + { + int stream = *(int *) args; - if (stream == AUDIO_STREAM_REPLAY) - { - _audio_flush_replay_frame(audio); - } - } - break; - case AUDIO_CTL_PAUSE: + LOG_D("AUDIO_CTL_START: stream = %d", stream); + if (stream == AUDIO_STREAM_REPLAY) { - int stream = *(int *) args; - - AUDIO_DBG("AUDIO_CTL_PAUSE: stream = %d\n",stream); - if (audio->ops->start != RT_NULL) - result = audio->ops->suspend(audio, stream); + result = _aduio_replay_start(audio); } - break; - case AUDIO_CTL_RESUME: + else { - int stream = *(int *) args; - - AUDIO_DBG("AUDIO_CTL_RESUME: stream = %d\n",stream); - if (audio->ops->start != RT_NULL) - result = audio->ops->resume(audio, stream); - - //resume tx frame... - if (stream == AUDIO_STREAM_REPLAY) - _audio_send_replay_frame(audio); + result = _audio_record_start(audio); } + break; - case AUDIO_CTL_ALLOCBUFFER: - { - struct rt_audio_buf_desc *desc = (struct rt_audio_buf_desc *) args; + } - if (desc) - { - desc->data_size = AUDIO_DEVICE_DECODE_MP_BLOCK_SZ * 2; - desc->data_ptr = rt_mp_alloc(&audio->mp, RT_WAITING_FOREVER); + case AUDIO_CTL_STOP: + { + int stream = *(int *) args; - result = RT_EOK; - } - else result = -RT_EIO; + LOG_D("AUDIO_CTL_STOP: stream = %d", stream); + if (stream == AUDIO_STREAM_REPLAY) + { + result = _aduio_replay_stop(audio); } - break; - case AUDIO_CTL_FREEBUFFER: + else { - rt_uint8_t *data_ptr = (rt_uint8_t *) args; - if (data_ptr) - rt_mp_free(data_ptr); + result = _audio_record_stop(audio); } + break; - default: - result = audio->ops->control(audio, cmd, args); + } + + default: break; } @@ -418,7 +514,9 @@ const static struct rt_device_ops audio_ops = rt_err_t rt_audio_register(struct rt_audio_device *audio, const char *name, rt_uint32_t flag, void *data) { + rt_err_t result = RT_EOK; struct rt_device *device; + RT_ASSERT(audio != RT_NULL); device = &(audio->parent); @@ -438,15 +536,14 @@ rt_err_t rt_audio_register(struct rt_audio_device *audio, const char *name, rt_u #endif device->user_data = data; - //init memory pool for replay - { - rt_uint8_t *mempool = rt_malloc(AUDIO_DEVICE_DECODE_MP_SZ); - rt_mp_init(&audio->mp, "adu_mp", mempool, AUDIO_DEVICE_DECODE_MP_SZ, - AUDIO_DEVICE_DECODE_MP_BLOCK_SZ * 2); - } - /* register a character device */ - return rt_device_register(device, name, flag | RT_DEVICE_FLAG_REMOVABLE); + result = rt_device_register(device, name, flag | RT_DEVICE_FLAG_REMOVABLE); + + /* initialize audio device */ + if (result == RT_EOK) + result = rt_device_init(device); + + return result; } int rt_audio_samplerate_to_speed(rt_uint32_t bitValue) @@ -454,43 +551,43 @@ int rt_audio_samplerate_to_speed(rt_uint32_t bitValue) int speed = 0; switch (bitValue) { - case AUDIO_SAMP_RATE_8K: - speed = 8000; + case AUDIO_SAMP_RATE_8K: + speed = 8000; break; - case AUDIO_SAMP_RATE_11K: - speed = 11052; + case AUDIO_SAMP_RATE_11K: + speed = 11052; break; - case AUDIO_SAMP_RATE_16K: - speed = 16000; + case AUDIO_SAMP_RATE_16K: + speed = 16000; break; - case AUDIO_SAMP_RATE_22K: - speed = 22050; + case AUDIO_SAMP_RATE_22K: + speed = 22050; break; - case AUDIO_SAMP_RATE_32K: - speed = 32000; + case AUDIO_SAMP_RATE_32K: + speed = 32000; break; - case AUDIO_SAMP_RATE_44K: - speed = 44100; + case AUDIO_SAMP_RATE_44K: + speed = 44100; break; - case AUDIO_SAMP_RATE_48K: - speed = 48000; + case AUDIO_SAMP_RATE_48K: + speed = 48000; break; - case AUDIO_SAMP_RATE_96K: - speed = 96000; + case AUDIO_SAMP_RATE_96K: + speed = 96000; break; - case AUDIO_SAMP_RATE_128K: - speed = 128000; + case AUDIO_SAMP_RATE_128K: + speed = 128000; break; - case AUDIO_SAMP_RATE_160K: - speed = 160000; + case AUDIO_SAMP_RATE_160K: + speed = 160000; break; - case AUDIO_SAMP_RATE_172K: - speed = 176400; + case AUDIO_SAMP_RATE_172K: + speed = 176400; break; - case AUDIO_SAMP_RATE_192K: - speed = 192000; + case AUDIO_SAMP_RATE_192K: + speed = 192000; break; - default: + default: break; } @@ -498,46 +595,18 @@ int rt_audio_samplerate_to_speed(rt_uint32_t bitValue) return speed; } -rt_uint32_t rt_audio_format_to_bits(rt_uint32_t format) +void rt_audio_tx_complete(struct rt_audio_device *audio) { - switch (format) - { - case AUDIO_FMT_PCM_U8: - case AUDIO_FMT_PCM_S8: - return 8; - case AUDIO_FMT_PCM_S16_LE: - case AUDIO_FMT_PCM_S16_BE: - case AUDIO_FMT_PCM_U16_LE: - case AUDIO_FMT_PCM_U16_BE: - return 16; - default: - return 32; - }; -} - -void rt_audio_tx_complete(struct rt_audio_device *audio, rt_uint8_t *pbuf) -{ - rt_err_t result; - AUDIO_DBG("audio tx complete ptr=%x...\n",(rt_uint32_t)pbuf); - - //try to send all frame - do - { - result = _audio_send_replay_frame(audio); - } while (result == RT_EOK); - - /* notify transmitted complete. */ - if (audio->parent.tx_complete != RT_NULL) - audio->parent.tx_complete(&audio->parent, (void *) pbuf); + /* try to send next frame */ + _audio_send_replay_frame(audio); } void rt_audio_rx_done(struct rt_audio_device *audio, rt_uint8_t *pbuf, rt_size_t len) { - //save data to record pipe - rt_device_write(RT_DEVICE(RT_DEVICE(&audio_pipe)), 0, pbuf, len); + /* save data to record pipe */ + rt_device_write(RT_DEVICE(&audio->record->pipe), 0, pbuf, len); /* invoke callback */ if (audio->parent.rx_indicate != RT_NULL) audio->parent.rx_indicate(&audio->parent, len); } - diff --git a/components/drivers/audio/audio_pipe.c b/components/drivers/audio/audio_pipe.c index 4df9fd8a49..d7c37009b6 100644 --- a/components/drivers/audio/audio_pipe.c +++ b/components/drivers/audio/audio_pipe.c @@ -24,8 +24,8 @@ static void _rt_pipe_resume_writer(struct rt_audio_pipe *pipe) /* get suspended thread */ thread = rt_list_entry(pipe->suspended_write_list.next, - struct rt_thread, - tlist); + struct rt_thread, + tlist); /* resume the write thread */ rt_thread_resume(thread); @@ -50,7 +50,7 @@ static rt_size_t rt_pipe_read(rt_device_t dev, if (!(pipe->flag & RT_PIPE_FLAG_BLOCK_RD)) { level = rt_hw_interrupt_disable(); - read_nbytes = rt_ringbuffer_get(&(pipe->ringbuffer), buffer, size); + read_nbytes = rt_ringbuffer_get(&(pipe->ringbuffer), (rt_uint8_t *)buffer, size); /* if the ringbuffer is empty, there won't be any writer waiting */ if (read_nbytes) @@ -66,9 +66,10 @@ static rt_size_t rt_pipe_read(rt_device_t dev, /* current context checking */ RT_DEBUG_NOT_IN_INTERRUPT; - do { + do + { level = rt_hw_interrupt_disable(); - read_nbytes = rt_ringbuffer_get(&(pipe->ringbuffer), buffer, size); + read_nbytes = rt_ringbuffer_get(&(pipe->ringbuffer), (rt_uint8_t *)buffer, size); if (read_nbytes == 0) { rt_thread_suspend(thread); @@ -85,7 +86,8 @@ static rt_size_t rt_pipe_read(rt_device_t dev, rt_hw_interrupt_enable(level); break; } - } while (read_nbytes == 0); + } + while (read_nbytes == 0); return read_nbytes; } @@ -104,8 +106,8 @@ static void _rt_pipe_resume_reader(struct rt_audio_pipe *pipe) /* get suspended thread */ thread = rt_list_entry(pipe->suspended_read_list.next, - struct rt_thread, - tlist); + struct rt_thread, + tlist); /* resume the read thread */ rt_thread_resume(thread); @@ -128,16 +130,16 @@ static rt_size_t rt_pipe_write(rt_device_t dev, RT_ASSERT(pipe != RT_NULL); if ((pipe->flag & RT_PIPE_FLAG_FORCE_WR) || - !(pipe->flag & RT_PIPE_FLAG_BLOCK_WR)) + !(pipe->flag & RT_PIPE_FLAG_BLOCK_WR)) { level = rt_hw_interrupt_disable(); if (pipe->flag & RT_PIPE_FLAG_FORCE_WR) write_nbytes = rt_ringbuffer_put_force(&(pipe->ringbuffer), - buffer, size); + (const rt_uint8_t *)buffer, size); else write_nbytes = rt_ringbuffer_put(&(pipe->ringbuffer), - buffer, size); + (const rt_uint8_t *)buffer, size); _rt_pipe_resume_reader(pipe); @@ -151,9 +153,10 @@ static rt_size_t rt_pipe_write(rt_device_t dev, /* current context checking */ RT_DEBUG_NOT_IN_INTERRUPT; - do { + do + { level = rt_hw_interrupt_disable(); - write_nbytes = rt_ringbuffer_put(&(pipe->ringbuffer), buffer, size); + write_nbytes = rt_ringbuffer_put(&(pipe->ringbuffer), (const rt_uint8_t *)buffer, size); if (write_nbytes == 0) { /* pipe full, waiting on suspended write list */ @@ -171,7 +174,8 @@ static rt_size_t rt_pipe_write(rt_device_t dev, rt_hw_interrupt_enable(level); break; } - } while (write_nbytes == 0); + } + while (write_nbytes == 0); return write_nbytes; } @@ -183,7 +187,7 @@ static rt_err_t rt_pipe_control(rt_device_t dev, int cmd, void *args) pipe = (struct rt_audio_pipe *)dev; if (cmd == PIPE_CTRL_GET_SPACE && args) - *(rt_size_t*)args = rt_ringbuffer_space_len(&pipe->ringbuffer); + *(rt_size_t *)args = rt_ringbuffer_space_len(&pipe->ringbuffer); return RT_EOK; } @@ -212,10 +216,10 @@ const static struct rt_device_ops audio_pipe_ops = * @return the operation status, RT_EOK on successful */ rt_err_t rt_audio_pipe_init(struct rt_audio_pipe *pipe, - const char *name, - rt_int32_t flag, - rt_uint8_t *buf, - rt_size_t size) + const char *name, + rt_int32_t flag, + rt_uint8_t *buf, + rt_size_t size) { RT_ASSERT(pipe); RT_ASSERT(buf); @@ -270,7 +274,7 @@ rt_err_t rt_audio_pipe_create(const char *name, rt_int32_t flag, rt_size_t size) return -RT_ENOMEM; /* create ring buffer of pipe */ - rb_memptr = rt_malloc(size); + rb_memptr = (rt_uint8_t *)rt_malloc(size); if (rb_memptr == RT_NULL) { rt_free(pipe); diff --git a/components/drivers/can/can.c b/components/drivers/can/can.c index 0769c79fd7..3d60dbaa55 100644 --- a/components/drivers/can/can.c +++ b/components/drivers/can/can.c @@ -27,10 +27,15 @@ static rt_err_t rt_can_init(struct rt_device *dev) /* initialize rx/tx */ can->can_rx = RT_NULL; can->can_tx = RT_NULL; +#ifdef RT_CAN_USING_HDR + can->hdr = RT_NULL; +#endif /* apply configuration */ if (can->ops->configure) result = can->ops->configure(can, &can->config); + else + result = -RT_ENOSYS; return result; } @@ -293,7 +298,7 @@ static rt_err_t rt_can_open(struct rt_device *dev, rt_uint16_t oflag) can->can_rx = rx_fifo; dev->open_flag |= RT_DEVICE_FLAG_INT_RX; - /* configure low level device */ + /* open can rx interrupt */ can->ops->control(can, RT_DEVICE_CTRL_SET_INT, (void *)RT_DEVICE_FLAG_INT_RX); } } @@ -311,7 +316,7 @@ static rt_err_t rt_can_open(struct rt_device *dev, rt_uint16_t oflag) tx_fifo->buffer = (struct rt_can_sndbxinx_list *)(tx_fifo + 1); rt_memset(tx_fifo->buffer, 0, - can->config.sndboxnumber * sizeof(struct rt_can_sndbxinx_list)); + can->config.sndboxnumber * sizeof(struct rt_can_sndbxinx_list)); rt_list_init(&tx_fifo->freelist); for (i = 0; i < can->config.sndboxnumber; i++) { @@ -325,7 +330,7 @@ static rt_err_t rt_can_open(struct rt_device *dev, rt_uint16_t oflag) can->can_tx = tx_fifo; dev->open_flag |= RT_DEVICE_FLAG_INT_TX; - /* configure low level device */ + /* open can tx interrupt */ can->ops->control(can, RT_DEVICE_CTRL_SET_INT, (void *)RT_DEVICE_FLAG_INT_TX); } } @@ -406,7 +411,7 @@ static rt_err_t rt_can_close(struct rt_device *dev) rt_free(rx_fifo); dev->open_flag &= ~RT_DEVICE_FLAG_INT_RX; can->can_rx = RT_NULL; - /* configure low level device */ + /* clear can rx interrupt */ can->ops->control(can, RT_DEVICE_CTRL_CLR_INT, (void *)RT_DEVICE_FLAG_INT_RX); } @@ -420,7 +425,7 @@ static rt_err_t rt_can_close(struct rt_device *dev) rt_free(tx_fifo); dev->open_flag &= ~RT_DEVICE_FLAG_INT_TX; can->can_tx = RT_NULL; - /* configure low level device */ + /* clear can tx interrupt */ can->ops->control(can, RT_DEVICE_CTRL_CLR_INT, (void *)RT_DEVICE_FLAG_INT_TX); } @@ -484,6 +489,7 @@ static rt_err_t rt_can_control(struct rt_device *dev, struct rt_can_device *can; rt_err_t res; + res = RT_EOK; RT_ASSERT(dev != RT_NULL); can = (struct rt_can_device *)dev; @@ -501,8 +507,9 @@ static rt_err_t rt_can_control(struct rt_device *dev, case RT_DEVICE_CTRL_CONFIG: /* configure device */ - can->ops->configure(can, (struct can_configure *)args); + res = can->ops->configure(can, (struct can_configure *)args); break; + case RT_CAN_CMD_SET_PRIV: /* configure device */ if ((rt_uint32_t)args != can->config.privmode) @@ -513,7 +520,6 @@ static rt_err_t rt_can_control(struct rt_device *dev, res = can->ops->control(can, cmd, args); if (res != RT_EOK) return res; - tx_fifo = (struct rt_can_tx_fifo *) can->can_tx; if (can->config.privmode) { @@ -522,11 +528,11 @@ static rt_err_t rt_can_control(struct rt_device *dev, level = rt_hw_interrupt_disable(); if(rt_list_isempty(&tx_fifo->buffer[i].list)) { - rt_sem_release(&(tx_fifo->sem)); + rt_sem_release(&(tx_fifo->sem)); } else { - rt_list_remove(&tx_fifo->buffer[i].list); + rt_list_remove(&tx_fifo->buffer[i].list); } rt_hw_interrupt_enable(level); } @@ -544,7 +550,6 @@ static rt_err_t rt_can_control(struct rt_device *dev, rt_hw_interrupt_enable(level); } } - return RT_EOK; } break; @@ -561,74 +566,73 @@ static rt_err_t rt_can_control(struct rt_device *dev, return res; } - { - struct rt_can_filter_config *pfilter; - struct rt_can_filter_item *pitem; - rt_uint32_t count; - rt_base_t level; + struct rt_can_filter_config *pfilter; + struct rt_can_filter_item *pitem; + rt_uint32_t count; + rt_base_t level; - pfilter = (struct rt_can_filter_config *)args; - count = pfilter->count; - pitem = pfilter->items; - if (pfilter->actived) + pfilter = (struct rt_can_filter_config *)args; + RT_ASSERT(pfilter); + count = pfilter->count; + pitem = pfilter->items; + if (pfilter->actived) + { + while (count) { - while (count) + if (pitem->hdr >= can->config.maxhdr || pitem->hdr < 0) { - if (pitem->hdr >= can->config.maxhdr || pitem->hdr < 0) - { - count--; - pitem++; - continue; - } - - level = rt_hw_interrupt_disable(); - if (!can->hdr[pitem->hdr].connected) - { - rt_hw_interrupt_enable(level); - rt_memcpy(&can->hdr[pitem->hdr].filter, pitem, - sizeof(struct rt_can_filter_item)); - level = rt_hw_interrupt_disable(); - can->hdr[pitem->hdr].connected = 1; - can->hdr[pitem->hdr].msgs = 0; - rt_list_init(&can->hdr[pitem->hdr].list); - } - rt_hw_interrupt_enable(level); - count--; pitem++; + continue; } + + level = rt_hw_interrupt_disable(); + if (!can->hdr[pitem->hdr].connected) + { + rt_hw_interrupt_enable(level); + rt_memcpy(&can->hdr[pitem->hdr].filter, pitem, + sizeof(struct rt_can_filter_item)); + level = rt_hw_interrupt_disable(); + can->hdr[pitem->hdr].connected = 1; + can->hdr[pitem->hdr].msgs = 0; + rt_list_init(&can->hdr[pitem->hdr].list); + } + rt_hw_interrupt_enable(level); + + count--; + pitem++; } - else + } + else + { + while (count) { - while (count) + if (pitem->hdr >= can->config.maxhdr || pitem->hdr < 0) { - if (pitem->hdr >= can->config.maxhdr || pitem->hdr < 0) - { - count--; - pitem++; - continue; - } - level = rt_hw_interrupt_disable(); + count--; + pitem++; + continue; + } + level = rt_hw_interrupt_disable(); - if (can->hdr[pitem->hdr].connected) + if (can->hdr[pitem->hdr].connected) + { + can->hdr[pitem->hdr].connected = 0; + can->hdr[pitem->hdr].msgs = 0; + if (!rt_list_isempty(&can->hdr[pitem->hdr].list)) { - can->hdr[pitem->hdr].connected = 0; - can->hdr[pitem->hdr].msgs = 0; - if (!rt_list_isempty(&can->hdr[pitem->hdr].list)) - { - rt_list_remove(can->hdr[pitem->hdr].list.next); - } - rt_hw_interrupt_enable(level); - rt_memset(&can->hdr[pitem->hdr].filter, 0, - sizeof(struct rt_can_filter_item)); + rt_list_remove(can->hdr[pitem->hdr].list.next); } - else - { - rt_hw_interrupt_enable(level); - } - count--; - pitem++; + rt_hw_interrupt_enable(level); + rt_memset(&can->hdr[pitem->hdr].filter, 0, + sizeof(struct rt_can_filter_item)); + } + else + { + rt_hw_interrupt_enable(level); } + count--; + pitem++; } } break; @@ -642,12 +646,16 @@ static rt_err_t rt_can_control(struct rt_device *dev, /* control device */ if (can->ops->control != RT_NULL) { - can->ops->control(can, cmd, args); + res = can->ops->control(can, cmd, args); + } + else + { + res = -RT_ENOSYS; } break; } - return RT_EOK; + return res; } /* @@ -655,8 +663,10 @@ static rt_err_t rt_can_control(struct rt_device *dev, */ static void cantimeout(void *arg) { - rt_can_t can = (rt_can_t)arg; + rt_can_t can; + can = (rt_can_t)arg; + RT_ASSERT(can); rt_device_control((rt_device_t)can, RT_CAN_CMD_GET_STATUS, (void *)&can->status); if (can->status_indicate.ind != RT_NULL) @@ -690,7 +700,7 @@ const static struct rt_device_ops can_device_ops = /* * can register */ -rt_err_t rt_hw_can_register(struct rt_can_device *can, +rt_err_t rt_hw_can_register(struct rt_can_device *can, const char *name, const struct rt_can_ops *ops, void *data) @@ -843,7 +853,10 @@ void rt_hw_can_isr(struct rt_can_device *can, int event) level = rt_hw_interrupt_disable(); rx_length = can->hdr[hdr].msgs * sizeof(struct rt_can_msg); rt_hw_interrupt_enable(level); - can->hdr[hdr].filter.ind(&can->parent, can->hdr[hdr].filter.args, hdr, rx_length); + if (rx_length) + { + can->hdr[hdr].filter.ind(&can->parent, can->hdr[hdr].filter.args, hdr, rx_length); + } } else #endif @@ -857,7 +870,10 @@ void rt_hw_can_isr(struct rt_can_device *can, int event) rx_length = rt_list_len(&rx_fifo->uselist)* sizeof(struct rt_can_msg); rt_hw_interrupt_enable(level); - can->parent.rx_indicate(&can->parent, rx_length); + if (rx_length) + { + can->parent.rx_indicate(&can->parent, rx_length); + } } } break; diff --git a/components/drivers/hwcrypto/SConscript b/components/drivers/hwcrypto/SConscript new file mode 100644 index 0000000000..90feff50b3 --- /dev/null +++ b/components/drivers/hwcrypto/SConscript @@ -0,0 +1,34 @@ +Import('RTT_ROOT') +Import('rtconfig') +from building import * + +cwd = GetCurrentDir() +CPPPATH = [cwd, str(Dir('#'))] + +src = ['hwcrypto.c'] + +if (GetDepend(['RT_HWCRYPTO_USING_AES']) or + GetDepend(['RT_HWCRYPTO_USING_DES']) or + GetDepend(['RT_HWCRYPTO_USING_3DES']) or + GetDepend(['RT_HWCRYPTO_USING_RC4'])): + src += ['hw_symmetric.c'] + if GetDepend(['RT_HWCRYPTO_USING_GCM']): + src += ['hw_gcm.c'] + +if (GetDepend(['RT_HWCRYPTO_USING_MD5']) or + GetDepend(['RT_HWCRYPTO_USING_SHA1']) or + GetDepend(['RT_HWCRYPTO_USING_SHA2'])): + src += ['hw_hash.c'] + +if GetDepend(['RT_HWCRYPTO_USING_RNG']): + src += ['hw_rng.c'] + +if GetDepend(['RT_HWCRYPTO_USING_CRC']): + src += ['hw_crc.c'] + +if GetDepend(['RT_HWCRYPTO_USING_BIGNUM']): + src += ['hw_bignum.c'] + +group = DefineGroup('DeviceDrivers', src, depend = ['RT_USING_HWCRYPTO'], CPPPATH = CPPPATH) + +Return('group') diff --git a/components/drivers/hwcrypto/hw_bignum.c b/components/drivers/hwcrypto/hw_bignum.c new file mode 100644 index 0000000000..88813566b1 --- /dev/null +++ b/components/drivers/hwcrypto/hw_bignum.c @@ -0,0 +1,315 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-04-25 tyx the first version + */ + +#include <rtthread.h> +#include <rtdevice.h> +#include <hw_bignum.h> + +static struct rt_hwcrypto_ctx *bignum_default; + +rt_inline rt_err_t hwcrypto_bignum_dev_is_init(void) +{ + struct rt_hwcrypto_device *dev; + + if (bignum_default) + { + return RT_EOK; + } + dev = rt_hwcrypto_dev_default(); + if (dev == RT_NULL) + { + return -RT_ERROR; + } + return rt_hwcrypto_bignum_default(dev); +} + +/** + * @brief Setting bignum default devices + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_bignum_default(struct rt_hwcrypto_device *device) +{ + if (bignum_default) + { + rt_hwcrypto_ctx_destroy(bignum_default); + bignum_default = RT_NULL; + } + if (device == RT_NULL) + { + return RT_EOK; + } + bignum_default = rt_hwcrypto_ctx_create(device, HWCRYPTO_TYPE_BIGNUM, sizeof(struct hwcrypto_bignum)); + if (bignum_default == RT_NULL) + { + return -RT_ERROR; + } + return RT_EOK; +} + +/** + * @brief Init bignum obj + * + * @param n bignum obj + */ +void rt_hwcrypto_bignum_init(struct hw_bignum_mpi *n) +{ + if(n == RT_NULL) + return; + + n->sign = 1; + n->total = 0; + n->p = RT_NULL; +} + +/** + * @brief free a bignum obj + * + * @param Pointer to bignum obj + */ +void rt_hwcrypto_bignum_free(struct hw_bignum_mpi *n) +{ + if (n) + { + rt_free(n->p); + n->sign = 0; + n->total = 0; + n->p = RT_NULL; + } +} + +/** + * @brief Get length of bignum as an unsigned binary buffer + * + * @param n bignum obj + * + * @return binary buffer length + */ +int rt_hwcrypto_bignum_get_len(const struct hw_bignum_mpi *n) +{ + int tmp_len, total; + + if (n == RT_NULL || n->p == RT_NULL) + { + return 0; + } + tmp_len = 0; + total = n->total; + while ((total > 0) && (n->p[total - 1] == 0)) + { + tmp_len++; + total--; + } + return n->total - tmp_len; +} + +/** + * @brief Export n into unsigned binary data, big endian + * + * @param n bignum obj + * @param buf Buffer for the binary number + * @param len Length of the buffer + * + * @return export bin length + */ +int rt_hwcrypto_bignum_export_bin(struct hw_bignum_mpi *n, rt_uint8_t *buf, int len) +{ + int cp_len, i, j; + + if (n == RT_NULL || buf == RT_NULL) + { + return 0; + } + rt_memset(buf, 0, len); + cp_len = n->total > len ? len : n->total; + for(i = cp_len, j = 0; i > 0; i--, j++) + { + buf[i - 1] = n->p[j]; + } + + return cp_len; +} + +/** + * @brief Import n from unsigned binary data, big endian + * + * @param n bignum obj + * @param buf Buffer for the binary number + * @param len Length of the buffer + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_bignum_import_bin(struct hw_bignum_mpi *n, rt_uint8_t *buf, int len) +{ + int cp_len, i, j; + void *temp_p; + + if (n == RT_NULL || buf == RT_NULL) + { + return 0; + } + if (n->total < len) + { + temp_p = rt_malloc(len); + if (temp_p == RT_NULL) + { + return 0; + } + rt_memset(temp_p, 0, len); + rt_free(n->p); + n->p = temp_p; + n->total = len; + } + cp_len = n->total > len ? len : n->total; + + for(i = cp_len, j = 0; i > 0; i--, j++) + { + n->p[j] = buf[i - 1]; + } + + return cp_len; +} + +/** + * @brief x = a + b + * + * @param a bignum obj + * @param b bignum obj + * @param c bignum obj + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_bignum_add(struct hw_bignum_mpi *x, + const struct hw_bignum_mpi *a, + const struct hw_bignum_mpi *b) +{ + struct hwcrypto_bignum *bignum_ctx; + + if (hwcrypto_bignum_dev_is_init() != RT_EOK) + { + return -RT_ERROR; + } + bignum_ctx = (struct hwcrypto_bignum *)bignum_default; + if (bignum_ctx->ops->add) + { + return bignum_ctx->ops->add(bignum_ctx, x, a, b); + } + return -RT_ERROR; +} + +/** + * @brief x = a - b + * + * @param a bignum obj + * @param b bignum obj + * @param c bignum obj + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_bignum_sub(struct hw_bignum_mpi *x, + const struct hw_bignum_mpi *a, + const struct hw_bignum_mpi *b) +{ + struct hwcrypto_bignum *bignum_ctx; + + if (hwcrypto_bignum_dev_is_init() != RT_EOK) + { + return -RT_ERROR; + } + bignum_ctx = (struct hwcrypto_bignum *)bignum_default; + if (bignum_ctx->ops->sub) + { + return bignum_ctx->ops->sub(bignum_ctx, x, a, b); + } + return -RT_ERROR; +} + +/** + * @brief x = a * b + * + * @param a bignum obj + * @param b bignum obj + * @param c bignum obj + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_bignum_mul(struct hw_bignum_mpi *x, + const struct hw_bignum_mpi *a, + const struct hw_bignum_mpi *b) +{ + struct hwcrypto_bignum *bignum_ctx; + + if (hwcrypto_bignum_dev_is_init() != RT_EOK) + { + return -RT_ERROR; + } + bignum_ctx = (struct hwcrypto_bignum *)bignum_default; + if (bignum_ctx->ops->mul) + { + return bignum_ctx->ops->mul(bignum_ctx, x, a, b); + } + return -RT_ERROR; +} + +/** + * @brief x = a * b (mod c) + * + * @param a bignum obj + * @param b bignum obj + * @param c bignum obj + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_bignum_mulmod(struct hw_bignum_mpi *x, + const struct hw_bignum_mpi *a, + const struct hw_bignum_mpi *b, + const struct hw_bignum_mpi *c) +{ + struct hwcrypto_bignum *bignum_ctx; + + if (hwcrypto_bignum_dev_is_init() != RT_EOK) + { + return -RT_ERROR; + } + bignum_ctx = (struct hwcrypto_bignum *)bignum_default; + if (bignum_ctx->ops->mulmod) + { + return bignum_ctx->ops->mulmod(bignum_ctx, x, a, b, c); + } + return -RT_ERROR; +} + +/** + * @brief x = a ^ b (mod c) + * + * @param a bignum obj + * @param b bignum obj + * @param c bignum obj + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_bignum_exptmod(struct hw_bignum_mpi *x, + const struct hw_bignum_mpi *a, + const struct hw_bignum_mpi *b, + const struct hw_bignum_mpi *c) +{ + struct hwcrypto_bignum *bignum_ctx; + + if (hwcrypto_bignum_dev_is_init() != RT_EOK) + { + return -RT_ERROR; + } + bignum_ctx = (struct hwcrypto_bignum *)bignum_default; + if (bignum_ctx->ops->exptmod) + { + return bignum_ctx->ops->exptmod(bignum_ctx, x, a, b, c); + } + return -RT_ERROR; +} diff --git a/components/drivers/hwcrypto/hw_bignum.h b/components/drivers/hwcrypto/hw_bignum.h new file mode 100644 index 0000000000..a1f567e68f --- /dev/null +++ b/components/drivers/hwcrypto/hw_bignum.h @@ -0,0 +1,186 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-04-25 tyx the first version + */ + +#ifndef __HW_BIGNUM_H__ +#define __HW_BIGNUM_H__ + +#include <hwcrypto.h> + +#ifdef __cplusplus +extern "C" { +#endif + +struct hwcrypto_bignum; + +/* bignum obj */ +struct hw_bignum_mpi +{ + int sign; /**< integer sign */ + rt_size_t total; /**< total of limbs */ + rt_uint8_t *p; /**< pointer to limbs */ +}; + +struct hwcrypto_bignum_ops +{ + rt_err_t (*add)(struct hwcrypto_bignum *bignum_ctx, + struct hw_bignum_mpi *x, + const struct hw_bignum_mpi *a, + const struct hw_bignum_mpi *b); /**< x = a + b */ + rt_err_t (*sub)(struct hwcrypto_bignum *bignum_ctx, + struct hw_bignum_mpi *x, + const struct hw_bignum_mpi *a, + const struct hw_bignum_mpi *b); /**< x = a - b */ + rt_err_t (*mul)(struct hwcrypto_bignum *bignum_ctx, + struct hw_bignum_mpi *x, + const struct hw_bignum_mpi *a, + const struct hw_bignum_mpi *b); /**< x = a * b */ + rt_err_t (*mulmod)(struct hwcrypto_bignum *bignum_ctx, + struct hw_bignum_mpi *x, + const struct hw_bignum_mpi *a, + const struct hw_bignum_mpi *b, + const struct hw_bignum_mpi *c); /**< x = a * b (mod c) */ + rt_err_t (*exptmod)(struct hwcrypto_bignum *bignum_ctx, + struct hw_bignum_mpi *x, + const struct hw_bignum_mpi *a, + const struct hw_bignum_mpi *b, + const struct hw_bignum_mpi *c); /**< x = a ^ b (mod c) */ +}; + +/** + * @brief bignum context. Hardware driver usage + */ +struct hwcrypto_bignum +{ + struct rt_hwcrypto_ctx parent; /**< Inheritance from hardware crypto context */ + const struct hwcrypto_bignum_ops *ops; /**< !! Hardware initializes this value when creating context !! */ +}; + +/** + * @brief Setting bignum default devices + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_bignum_default(struct rt_hwcrypto_device *device); + +/** + * @brief Init bignum obj + */ +void rt_hwcrypto_bignum_init(struct hw_bignum_mpi *n); + +/** + * @brief free a bignum obj + * + * @param Pointer to bignum obj + */ +void rt_hwcrypto_bignum_free(struct hw_bignum_mpi *n); + +/** + * @brief Get length of bignum as an unsigned binary buffer + * + * @param n bignum obj + * + * @return binary buffer Length + */ +int rt_hwcrypto_bignum_get_len(const struct hw_bignum_mpi *n); + +/** + * @brief Export n into unsigned binary data, big endian + * + * @param n bignum obj + * @param buf Buffer for the binary number + * @param len Length of the buffer + * + * @return export bin length + */ +int rt_hwcrypto_bignum_export_bin(struct hw_bignum_mpi *n, rt_uint8_t *buf, int len); + +/** + * @brief Import n from unsigned binary data, big endian + * + * @param n bignum obj + * @param buf Buffer for the binary number + * @param len Length of the buffer + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_bignum_import_bin(struct hw_bignum_mpi *n, rt_uint8_t *buf, int len); + +/** + * @brief x = a + b + * + * @param a bignum obj + * @param b bignum obj + * @param c bignum obj + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_bignum_add(struct hw_bignum_mpi *x, + const struct hw_bignum_mpi *a, + const struct hw_bignum_mpi *b); + +/** + * @brief x = a - b + * + * @param a bignum obj + * @param b bignum obj + * @param c bignum obj + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_bignum_sub(struct hw_bignum_mpi *x, + const struct hw_bignum_mpi *a, + const struct hw_bignum_mpi *b); + +/** + * @brief x = a * b + * + * @param a bignum obj + * @param b bignum obj + * @param c bignum obj + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_bignum_mul(struct hw_bignum_mpi *x, + const struct hw_bignum_mpi *a, + const struct hw_bignum_mpi *b); + +/** + * @brief x = a * b (mod c) + * + * @param a bignum obj + * @param b bignum obj + * @param c bignum obj + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_bignum_mulmod(struct hw_bignum_mpi *x, + const struct hw_bignum_mpi *a, + const struct hw_bignum_mpi *b, + const struct hw_bignum_mpi *c); + +/** + * @brief x = a ^ b (mod c) + * + * @param a bignum obj + * @param b bignum obj + * @param c bignum obj + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_bignum_exptmod(struct hw_bignum_mpi *x, + const struct hw_bignum_mpi *a, + const struct hw_bignum_mpi *b, + const struct hw_bignum_mpi *c); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/components/drivers/hwcrypto/hw_crc.c b/components/drivers/hwcrypto/hw_crc.c new file mode 100644 index 0000000000..20579711e2 --- /dev/null +++ b/components/drivers/hwcrypto/hw_crc.c @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-04-25 tyx the first version + */ + +#include <rtthread.h> +#include <rtdevice.h> +#include <hw_crc.h> + +/** + * @brief Creating CRC Context + * + * @param device Hardware crypto device + * @param mode Setting default mode or custom mode + * + * @return CRC context + */ +struct rt_hwcrypto_ctx *rt_hwcrypto_crc_create(struct rt_hwcrypto_device *device, + hwcrypto_crc_mode mode) +{ + struct hwcrypto_crc *crc_ctx; + + crc_ctx = (struct hwcrypto_crc *)rt_hwcrypto_ctx_create(device, HWCRYPTO_TYPE_CRC, sizeof(struct hwcrypto_crc)); + if (crc_ctx == RT_NULL) + { + return RT_NULL; + } + + switch (mode) + { + case HWCRYPTO_CRC_CRC8: + { + struct hwcrypto_crc_cfg temp = HWCRYPTO_CRC8_CFG; + crc_ctx->crc_cfg = temp; + break; + } + case HWCRYPTO_CRC_CRC16: + { + struct hwcrypto_crc_cfg temp = HWCRYPTO_CRC16_CFG; + crc_ctx->crc_cfg = temp; + break; + } + case HWCRYPTO_CRC_CRC32: + { + struct hwcrypto_crc_cfg temp = HWCRYPTO_CRC32_CFG; + crc_ctx->crc_cfg = temp; + break; + } + case HWCRYPTO_CRC_CCITT: + { + struct hwcrypto_crc_cfg temp = HWCRYPTO_CRC_CCITT_CFG; + crc_ctx->crc_cfg = temp; + break; + } + case HWCRYPTO_CRC_DNP: + { + struct hwcrypto_crc_cfg temp = HWCRYPTO_CRC_DNP_CFG; + crc_ctx->crc_cfg = temp; + break; + } + default: + break; + } + + return &crc_ctx->parent; +} + +/** + * @brief Destroy CRC Context + * + * @param ctx CRC context + */ +void rt_hwcrypto_crc_destroy(struct rt_hwcrypto_ctx *ctx) +{ + rt_hwcrypto_ctx_destroy(ctx); +} + +/** + * @brief Processing a packet of data + * + * @param ctx CRC context + * @param input Data buffer to be Processed + * @param length Data Buffer length + * + * @return RT_EOK on success. + */ +rt_uint32_t rt_hwcrypto_crc_update(struct rt_hwcrypto_ctx *ctx, + const rt_uint8_t *input, + rt_size_t length) +{ + struct hwcrypto_crc *crc_ctx = (struct hwcrypto_crc *)ctx; + if (ctx && crc_ctx->ops->update) + { + return crc_ctx->ops->update(crc_ctx, input, length); + } + return 0; +} + +/** + * @brief CRC context configuration + * + * @param ctx CRC context + * @param cfg CRC config + */ +void rt_hwcrypto_crc_cfg(struct rt_hwcrypto_ctx *ctx, + struct hwcrypto_crc_cfg *cfg) +{ + if (cfg) + { + ((struct hwcrypto_crc *)ctx)->crc_cfg = *cfg; + } +} diff --git a/components/drivers/hwcrypto/hw_crc.h b/components/drivers/hwcrypto/hw_crc.h new file mode 100644 index 0000000000..a6df92a2ef --- /dev/null +++ b/components/drivers/hwcrypto/hw_crc.h @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-04-25 tyx the first version + */ + +#ifndef __HW_CRC_H__ +#define __HW_CRC_H__ + +#include <hwcrypto.h> + +#define CRC_FLAG_REFIN (0x1 << 0) +#define CRC_FLAG_REFOUT (0x1 << 1) + +#define HWCRYPTO_CRC8_CFG \ +{ \ + .last_val = 0x00, \ + .poly = 0x07, \ + .width = 8, \ + .xorout = 0x00, \ + .flags = 0, \ +} + +#define HWCRYPTO_CRC16_CFG \ +{ \ + .last_val = 0x0000, \ + .poly = 0x8005, \ + .width = 16, \ + .xorout = 0x0000, \ + .flags = 0, \ +} + +#define HWCRYPTO_CRC32_CFG \ +{ \ + .last_val = 0x00000000, \ + .poly = 0x04C11DB7, \ + .width = 32, \ + .xorout = 0x00000000, \ + .flags = 0, \ +} + +#define HWCRYPTO_CRC_CCITT_CFG \ +{ \ + .last_val = 0x0000, \ + .poly = 0x1021, \ + .width = 16, \ + .xorout = 0x0000, \ + .flags = CRC_FLAG_REFIN | CRC_FLAG_REFOUT, \ +} + +#define HWCRYPTO_CRC_DNP_CFG \ +{ \ + .last_val = 0x0000, \ + .poly = 0x3D65, \ + .width = 16, \ + .xorout = 0xffff, \ + .flags = CRC_FLAG_REFIN | CRC_FLAG_REFOUT, \ +} + +#ifdef __cplusplus +extern "C" { +#endif + +struct hwcrypto_crc; + +typedef enum +{ + HWCRYPTO_CRC_CUSTOM, /**< Custom CRC mode */ + HWCRYPTO_CRC_CRC8, /**< poly : 0x07 */ + HWCRYPTO_CRC_CRC16, /**< poly : 0x8005 */ + HWCRYPTO_CRC_CRC32, /**< poly : 0x04C11DB7 */ + HWCRYPTO_CRC_CCITT, /**< poly : 0x1021 */ + HWCRYPTO_CRC_DNP, /**< poly : 0x3D65 */ +} hwcrypto_crc_mode; + +struct hwcrypto_crc_cfg +{ + rt_uint32_t last_val; /**< Last CRC value cache */ + rt_uint32_t poly; /**< CRC polynomial */ + rt_uint16_t width; /**< CRC value width */ + rt_uint32_t xorout; /**< Result XOR Value */ + rt_uint16_t flags; /**< Input or output data reverse. CRC_FLAG_REFIN or CRC_FLAG_REFOUT */ +}; + +struct hwcrypto_crc_ops +{ + rt_uint32_t (*update)(struct hwcrypto_crc *ctx, + const rt_uint8_t *in, rt_size_t length); /**< Perform a CRC calculation. return CRC value */ +}; + +/** + * @brief CRC context. Hardware driver usage + */ +struct hwcrypto_crc +{ + struct rt_hwcrypto_ctx parent; /**< Inherited from the standard device */ + struct hwcrypto_crc_cfg crc_cfg; /**< CRC configure */ + const struct hwcrypto_crc_ops *ops; /**< !! Hardware initializes this value when creating context !! */ +}; + +/** + * @brief Creating CRC Context + * + * @param device Hardware crypto device + * @param mode Setting default mode or custom mode + * + * @return CRC context + */ +struct rt_hwcrypto_ctx *rt_hwcrypto_crc_create(struct rt_hwcrypto_device *device, + hwcrypto_crc_mode mode); + +/** + * @brief Destroy CRC Context + * + * @param ctx CRC context + */ +void rt_hwcrypto_crc_destroy(struct rt_hwcrypto_ctx *ctx); + +/** + * @brief Processing a packet of data + * + * @param ctx CRC context + * @param input Data buffer to be Processed + * @param length Data Buffer length + * + * @return CRC value + */ +rt_uint32_t rt_hwcrypto_crc_update(struct rt_hwcrypto_ctx *ctx, + const rt_uint8_t *input, rt_size_t length); + +/** + * @brief CRC context configuration + * + * @param ctx CRC context + * @param cfg CRC config + */ +void rt_hwcrypto_crc_cfg(struct rt_hwcrypto_ctx *ctx, + struct hwcrypto_crc_cfg *cfg); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/components/drivers/hwcrypto/hw_gcm.c b/components/drivers/hwcrypto/hw_gcm.c new file mode 100644 index 0000000000..8d0f49149a --- /dev/null +++ b/components/drivers/hwcrypto/hw_gcm.c @@ -0,0 +1,218 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-05-14 tyx the first version + */ + +#include <rtthread.h> +#include <rtdevice.h> +#include <hw_gcm.h> + +/** + * @brief Creating GCM Context + * + * @param device Hardware crypto device + * @param type Type of symmetric crypto context + * + * @return GCM context + */ +struct rt_hwcrypto_ctx *rt_hwcrypto_gcm_create(struct rt_hwcrypto_device *device, + hwcrypto_type crypt_type) +{ + struct rt_hwcrypto_ctx *ctx; + + ctx = rt_hwcrypto_ctx_create(device, HWCRYPTO_TYPE_GCM, sizeof(struct hwcrypto_gcm)); + if (ctx) + { + ((struct hwcrypto_gcm *)ctx)->crypt_type = crypt_type; + } + return ctx; +} + +/** + * @brief Destroy GCM Context + * + * @param ctx GCM context + */ +void rt_hwcrypto_gcm_destroy(struct rt_hwcrypto_ctx *ctx) +{ + rt_hwcrypto_ctx_destroy(ctx); +} + +/** + * @brief This function starts a GCM encryption or decryption operation + * + * @param ctx GCM context + * @param add The buffer holding the additional data + * @param add_len The length of the additional data + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_gcm_start(struct rt_hwcrypto_ctx *ctx, const rt_uint8_t *add, + rt_size_t add_len) +{ + struct hwcrypto_gcm *gcm_ctx = (struct hwcrypto_gcm *)ctx; + + if (gcm_ctx && gcm_ctx->ops->start) + { + return gcm_ctx->ops->start(gcm_ctx, add, add_len); + } + return -RT_EINVAL; +} + +/** + * @brief This function finishes the GCM operation and generates the authentication tag + * + * @param ctx GCM context + * @param tag The buffer for holding the tag + * @param tag_len The length of the tag to generate + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_gcm_finish(struct rt_hwcrypto_ctx *ctx, const rt_uint8_t *tag, + rt_size_t tag_len) +{ + struct hwcrypto_gcm *gcm_ctx = (struct hwcrypto_gcm *)ctx; + + if (gcm_ctx && gcm_ctx->ops->finish) + { + return gcm_ctx->ops->finish(gcm_ctx, tag, tag_len); + } + return -RT_EINVAL; +} + +/** + * @brief This function performs a symmetric encryption or decryption operation + * + * @param ctx GCM context + * @param mode Operation mode. HWCRYPTO_MODE_ENCRYPT or HWCRYPTO_MODE_DECRYPT + * @param length The length of the input data in Bytes. This must be a multiple of the block size + * @param in The buffer holding the input data + * @param out The buffer holding the output data + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_gcm_crypt(struct rt_hwcrypto_ctx *ctx, hwcrypto_mode mode, + rt_size_t length, const rt_uint8_t *in, rt_uint8_t *out) +{ + return rt_hwcrypto_symmetric_crypt(ctx, mode, length, in, out); +} + +/** + * @brief Set Symmetric Encryption and Decryption Key + * + * @param ctx GCM context + * @param key The crypto key + * @param bitlen The crypto key bit length + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_gcm_setkey(struct rt_hwcrypto_ctx *ctx, + const rt_uint8_t *key, rt_uint32_t bitlen) +{ + return rt_hwcrypto_symmetric_setkey(ctx, key, bitlen); +} + +/** + * @brief Get Symmetric Encryption and Decryption Key + * + * @param ctx GCM context + * @param key The crypto key buffer + * @param bitlen The crypto key bit length + * + * @return Key length of copy + */ +rt_err_t rt_hwcrypto_gcm_getkey(struct rt_hwcrypto_ctx *ctx, + rt_uint8_t *key, rt_uint32_t bitlen) +{ + return rt_hwcrypto_symmetric_getkey(ctx, key, bitlen); +} + +/** + * @brief Set Symmetric Encryption and Decryption initialization vector + * + * @param ctx GCM context + * @param iv The crypto initialization vector + * @param len The crypto initialization vector length + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_gcm_setiv(struct rt_hwcrypto_ctx *ctx, + const rt_uint8_t *iv, rt_size_t len) +{ + return rt_hwcrypto_symmetric_setiv(ctx, iv, len); +} + +/** + * @brief Get Symmetric Encryption and Decryption initialization vector + * + * @param ctx GCM context + * @param iv The crypto initialization vector buffer + * @param len The crypto initialization vector buffer length + * + * @return IV length of copy + */ +rt_err_t rt_hwcrypto_gcm_getiv(struct rt_hwcrypto_ctx *ctx, + rt_uint8_t *iv, rt_size_t len) +{ + return rt_hwcrypto_symmetric_getiv(ctx, iv, len); +} + +/** + * @brief Set offset in initialization vector + * + * @param ctx GCM context + * @param iv_off The offset in IV + */ +void rt_hwcrypto_gcm_set_ivoff(struct rt_hwcrypto_ctx *ctx, rt_int32_t iv_off) +{ + rt_hwcrypto_symmetric_set_ivoff(ctx, iv_off); +} + +/** + * @brief Get offset in initialization vector + * + * @param ctx GCM context + * @param iv_off It must point to a valid memory + */ +void rt_hwcrypto_gcm_get_ivoff(struct rt_hwcrypto_ctx *ctx, rt_int32_t *iv_off) +{ + rt_hwcrypto_symmetric_get_ivoff(ctx, iv_off); +} + +/** + * @brief This function copy GCM context + * + * @param des The destination GCM context + * @param src The GCM context to be copy + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_gcm_cpy(struct rt_hwcrypto_ctx *des, + const struct rt_hwcrypto_ctx *src) +{ + struct hwcrypto_gcm *gcm_des = (struct hwcrypto_gcm *)des; + struct hwcrypto_gcm *gcm_src = (struct hwcrypto_gcm *)src; + + if (des != RT_NULL && src != RT_NULL) + { + gcm_des->crypt_type = gcm_src->crypt_type; + /* symmetric crypto context copy */ + return rt_hwcrypto_symmetric_cpy(des, src); + } + return -RT_EINVAL; +} + +/** + * @brief Reset GCM context + * + * @param ctx GCM context + */ +void rt_hwcrypto_gcm_reset(struct rt_hwcrypto_ctx *ctx) +{ + rt_hwcrypto_symmetric_reset(ctx); +} diff --git a/components/drivers/hwcrypto/hw_gcm.h b/components/drivers/hwcrypto/hw_gcm.h new file mode 100644 index 0000000000..a73b2b0634 --- /dev/null +++ b/components/drivers/hwcrypto/hw_gcm.h @@ -0,0 +1,182 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-05-14 tyx the first version + */ + +#ifndef __HW_GCM_H__ +#define __HW_GCM_H__ + +#include "hw_symmetric.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct hwcrypto_gcm; + +struct hwcrypto_gcm_ops +{ + rt_err_t (*start)(struct hwcrypto_gcm *gcm_ctx, + const unsigned char *add, size_t add_len); /**< Set additional data. start GCM operation */ + rt_err_t (*finish)(struct hwcrypto_gcm *gcm_ctx, + const unsigned char *tag, size_t tag_len); /**< finish GCM operation. get tag */ +}; + +/** + * @brief GCM context. Hardware driver usage + */ +struct hwcrypto_gcm +{ + struct hwcrypto_symmetric parent; /**< Inheritance from hardware symmetric crypto context */ + hwcrypto_type crypt_type; /**< symmetric crypto type. eg: AES/DES */ + const struct hwcrypto_gcm_ops *ops; /**< !! Hardware initializes this value when creating context !! */ +}; + +/** + * @brief Creating GCM Context + * + * @param device Hardware crypto device + * @param type Type of symmetric crypto context + * + * @return GCM context + */ +struct rt_hwcrypto_ctx *rt_hwcrypto_gcm_create(struct rt_hwcrypto_device *device, + hwcrypto_type crypt_type); + +/** + * @brief Destroy GCM Context + * + * @param ctx GCM context + */ +void rt_hwcrypto_gcm_destroy(struct rt_hwcrypto_ctx *ctx); + +/** + * @brief This function starts a GCM encryption or decryption operation + * + * @param ctx GCM context + * @param add The buffer holding the additional data + * @param add_len The length of the additional data + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_gcm_start(struct rt_hwcrypto_ctx *ctx, const rt_uint8_t *add, + rt_size_t add_len); + +/** + * @brief This function finishes the GCM operation and generates the authentication tag + * + * @param ctx GCM context + * @param tag The buffer for holding the tag + * @param tag_len The length of the tag to generate + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_gcm_finish(struct rt_hwcrypto_ctx *ctx, const rt_uint8_t *tag, + rt_size_t tag_len); + +/** + * @brief This function performs a symmetric encryption or decryption operation + * + * @param ctx GCM context + * @param mode Operation mode. HWCRYPTO_MODE_ENCRYPT or HWCRYPTO_MODE_DECRYPT + * @param length The length of the input data in Bytes. This must be a multiple of the block size + * @param in The buffer holding the input data + * @param out The buffer holding the output data + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_gcm_crypt(struct rt_hwcrypto_ctx *ctx, hwcrypto_mode mode, + rt_size_t length, const rt_uint8_t *in, rt_uint8_t *out); + +/** + * @brief Set Symmetric Encryption and Decryption Key + * + * @param ctx GCM context + * @param key The crypto key + * @param bitlen The crypto key bit length + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_gcm_setkey(struct rt_hwcrypto_ctx *ctx, + const rt_uint8_t *key, rt_uint32_t bitlen); + +/** + * @brief Get Symmetric Encryption and Decryption Key + * + * @param ctx GCM context + * @param key The crypto key buffer + * @param bitlen The crypto key bit length + * + * @return Key length of copy + */ +rt_err_t rt_hwcrypto_gcm_getkey(struct rt_hwcrypto_ctx *ctx, + rt_uint8_t *key, rt_uint32_t bitlen); + +/** + * @brief Set Symmetric Encryption and Decryption initialization vector + * + * @param ctx GCM context + * @param iv The crypto initialization vector + * @param len The crypto initialization vector length + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_gcm_setiv(struct rt_hwcrypto_ctx *ctx, + const rt_uint8_t *iv, rt_size_t len); + +/** + * @brief Get Symmetric Encryption and Decryption initialization vector + * + * @param ctx GCM context + * @param iv The crypto initialization vector buffer + * @param len The crypto initialization vector buffer length + * + * @return IV length of copy + */ +rt_err_t rt_hwcrypto_gcm_getiv(struct rt_hwcrypto_ctx *ctx, + rt_uint8_t *iv, rt_size_t len); + +/** + * @brief Set offset in initialization vector + * + * @param ctx GCM context + * @param iv_off The offset in IV + */ +void rt_hwcrypto_gcm_set_ivoff(struct rt_hwcrypto_ctx *ctx, rt_int32_t iv_off); + +/** + * @brief Get offset in initialization vector + * + * @param ctx GCM context + * @param iv_off It must point to a valid memory + */ +void rt_hwcrypto_gcm_get_ivoff(struct rt_hwcrypto_ctx *ctx, rt_int32_t *iv_off); + +/** + * @brief This function copy GCM context + * + * @param des The destination GCM context + * @param src The GCM context to be copy + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_gcm_cpy(struct rt_hwcrypto_ctx *des, + const struct rt_hwcrypto_ctx *src); + +/** + * @brief Reset GCM context + * + * @param ctx GCM context + */ +void rt_hwcrypto_gcm_reset(struct rt_hwcrypto_ctx *ctx); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/components/drivers/hwcrypto/hw_hash.c b/components/drivers/hwcrypto/hw_hash.c new file mode 100644 index 0000000000..b20069ac0e --- /dev/null +++ b/components/drivers/hwcrypto/hw_hash.c @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-04-23 tyx the first version + */ + +#include <rtthread.h> +#include <rtdevice.h> +#include <hw_hash.h> + +/** + * @brief Creating hash Context + * + * @param device Hardware crypto device + * @param type Type of hash context + * + * @return Hash context + */ +struct rt_hwcrypto_ctx *rt_hwcrypto_hash_create(struct rt_hwcrypto_device *device, hwcrypto_type type) +{ + struct rt_hwcrypto_ctx *ctx; + + ctx = rt_hwcrypto_ctx_create(device, type, sizeof(struct hwcrypto_hash)); + return ctx; +} + +/** + * @brief Destroy hash Context + * + * @param ctx Hash context + */ +void rt_hwcrypto_hash_destroy(struct rt_hwcrypto_ctx *ctx) +{ + rt_hwcrypto_ctx_destroy(ctx); +} + +/** + * @brief Get the final hash value + * + * @param ctx Hash context + * @param output Hash value buffer + * @param length Hash value buffer length + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_hash_finish(struct rt_hwcrypto_ctx *ctx, rt_uint8_t *output, rt_size_t length) +{ + if (ctx && ((struct hwcrypto_hash *)ctx)->ops->finish) + { + return ((struct hwcrypto_hash *)ctx)->ops->finish((struct hwcrypto_hash *)ctx, output, length); + } + return -RT_ERROR; +} + +/** + * @brief Processing a packet of data + * + * @param ctx Hash context + * @param input Data buffer to be Processed + * @param length Data Buffer length + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_hash_update(struct rt_hwcrypto_ctx *ctx, const rt_uint8_t *input, rt_size_t length) +{ + if (ctx && ((struct hwcrypto_hash *)ctx)->ops->update) + { + return ((struct hwcrypto_hash *)ctx)->ops->update((struct hwcrypto_hash *)ctx, input, length); + } + return -RT_ERROR; +} + +/** + * @brief This function copy hash context + * + * @param des The destination hash context + * @param src The hash context to be copy + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_hash_cpy(struct rt_hwcrypto_ctx *des, const struct rt_hwcrypto_ctx *src) +{ + return rt_hwcrypto_ctx_cpy(des, src); +} + +/** + * @brief Reset hash context + * + * @param ctx Hash context + */ +void rt_hwcrypto_hash_reset(struct rt_hwcrypto_ctx *ctx) +{ + rt_hwcrypto_ctx_reset(ctx); +} + +/** + * @brief Setting hash context type + * + * @param ctx Hash context + * @param type Types of settings + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_hash_set_type(struct rt_hwcrypto_ctx *ctx, hwcrypto_type type) +{ + return rt_hwcrypto_set_type(ctx, type); +} diff --git a/components/drivers/hwcrypto/hw_hash.h b/components/drivers/hwcrypto/hw_hash.h new file mode 100644 index 0000000000..de0310e84c --- /dev/null +++ b/components/drivers/hwcrypto/hw_hash.h @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-04-23 tyx the first version + */ + +#ifndef __HW_HASH_H__ +#define __HW_HASH_H__ + +#include <hwcrypto.h> + +#ifdef __cplusplus +extern "C" { +#endif + +struct hwcrypto_hash; + +struct hwcrypto_hash_ops +{ + rt_err_t (*update)(struct hwcrypto_hash *hash_ctx, + const rt_uint8_t *in, rt_size_t length); /**< Processing a packet of data */ + rt_err_t (*finish)(struct hwcrypto_hash *hash_ctx, + rt_uint8_t *out, rt_size_t length); /**< Get the final hash value */ +}; + +/** + * @brief hash context. Hardware driver usage + */ +struct hwcrypto_hash +{ + struct rt_hwcrypto_ctx parent; /**< Inheritance from hardware crypto context */ + const struct hwcrypto_hash_ops *ops; /**< !! Hardware initializes this value when creating context !! */ +}; + +/** + * @brief Creating hash Context + * + * @param device Hardware crypto device + * @param type Type of hash context + * + * @return Hash context + */ +struct rt_hwcrypto_ctx *rt_hwcrypto_hash_create(struct rt_hwcrypto_device *device, + hwcrypto_type type); + +/** + * @brief Destroy hash Context + * + * @param ctx Hash context + */ +void rt_hwcrypto_hash_destroy(struct rt_hwcrypto_ctx *ctx); + +/** + * @brief Get the final hash value + * + * @param ctx Hash context + * @param output Hash value buffer + * @param length Hash value buffer length + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_hash_finish(struct rt_hwcrypto_ctx *ctx, rt_uint8_t *output, rt_size_t length); + +/** + * @brief Processing a packet of data + * + * @param ctx Hash context + * @param input Data buffer to be Processed + * @param length Data Buffer length + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_hash_update(struct rt_hwcrypto_ctx *ctx, const rt_uint8_t *input, rt_size_t length); + +/** + * @brief This function copy hash context + * + * @param des The destination hash context + * @param src The hash context to be copy + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_hash_cpy(struct rt_hwcrypto_ctx *des, const struct rt_hwcrypto_ctx *src); + +/** + * @brief Reset hash context + * + * @param ctx Hash context + */ +void rt_hwcrypto_hash_reset(struct rt_hwcrypto_ctx *ctx); + +/** + * @brief Setting hash context type + * + * @param ctx Hash context + * @param type Types of settings + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_hash_set_type(struct rt_hwcrypto_ctx *ctx, hwcrypto_type type); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/components/drivers/hwcrypto/hw_rng.c b/components/drivers/hwcrypto/hw_rng.c new file mode 100644 index 0000000000..13a17cc6be --- /dev/null +++ b/components/drivers/hwcrypto/hw_rng.c @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-04-25 tyx the first version + */ + +#include <rtthread.h> +#include <rtdevice.h> +#include <hw_rng.h> + +/* Used to save default RNG Context */ +static struct rt_hwcrypto_ctx *ctx_default; + +/** + * @brief Creating RNG Context + * + * @param device Hardware crypto device + * + * @return RNG context + */ +struct rt_hwcrypto_ctx *rt_hwcrypto_rng_create(struct rt_hwcrypto_device *device) +{ + struct rt_hwcrypto_ctx *ctx; + + ctx = rt_hwcrypto_ctx_create(device, HWCRYPTO_TYPE_RNG, sizeof(struct hwcrypto_rng)); + return ctx; +} + +/** + * @brief Destroy RNG Context + * + * @param ctx RNG context + */ +void rt_hwcrypto_rng_destroy(struct rt_hwcrypto_ctx *ctx) +{ + /* Destroy the defaule RNG Context ? */ + if (ctx == ctx_default) + { + ctx_default = RT_NULL; + } + rt_hwcrypto_ctx_destroy(ctx); +} + +/** + * @brief Setting RNG default devices + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_rng_default(struct rt_hwcrypto_device *device) +{ + struct rt_hwcrypto_ctx *tmp_ctx; + + /* if device is null, destroy default RNG Context */ + if (device == RT_NULL) + { + if (ctx_default) + { + rt_hwcrypto_rng_destroy(ctx_default); + ctx_default = RT_NULL; + } + return RT_EOK; + } + /* Try create RNG Context */ + tmp_ctx = rt_hwcrypto_rng_create(device); + if (tmp_ctx == RT_NULL) + { + return -RT_ERROR; + } + /* create RNG Context success, update default RNG Context */ + rt_hwcrypto_rng_destroy(ctx_default); + ctx_default = tmp_ctx; + + return RT_EOK; +} + +/** + * @brief Getting Random Numbers from RNG Context + * + * @param ctx RNG context + * + * @return Random number + */ +rt_uint32_t rt_hwcrypto_rng_update_ctx(struct rt_hwcrypto_ctx *ctx) +{ + if (ctx) + { + return ((struct hwcrypto_rng *)ctx)->ops->update((struct hwcrypto_rng *)ctx); + } + return 0; +} + +/** + * @brief Return a random number + * + * @return Random number + */ +rt_uint32_t rt_hwcrypto_rng_update(void) +{ + /* Default device does not exist ? */ + if (ctx_default == RT_NULL) + { + /* try create Context from default device */ + rt_hwcrypto_rng_default(rt_hwcrypto_dev_default()); + } + return rt_hwcrypto_rng_update_ctx(ctx_default); +} diff --git a/components/drivers/hwcrypto/hw_rng.h b/components/drivers/hwcrypto/hw_rng.h new file mode 100644 index 0000000000..fc28afdb1e --- /dev/null +++ b/components/drivers/hwcrypto/hw_rng.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-04-25 tyx the first version + */ + +#ifndef __HW_RNG_H__ +#define __HW_RNG_H__ + +#include <hwcrypto.h> + +#ifdef __cplusplus +extern "C" { +#endif + +struct hwcrypto_rng; + +struct hwcrypto_rng_ops +{ + rt_uint32_t (*update)(struct hwcrypto_rng *ctx); /**< Return a random number */ +}; + +/** + * @brief random context. Hardware driver usage + */ +struct hwcrypto_rng +{ + struct rt_hwcrypto_ctx parent; /**< Inheritance from hardware crypto context */ + const struct hwcrypto_rng_ops *ops; /**< !! Hardware initializes this value when creating context !! */ +}; + +/** + * @brief Creating RNG Context + * + * @param device Hardware crypto device + * + * @return RNG context + */ +struct rt_hwcrypto_ctx *rt_hwcrypto_rng_create(struct rt_hwcrypto_device *device); + +/** + * @brief Destroy RNG Context + * + * @param ctx RNG context + */ +void rt_hwcrypto_rng_destroy(struct rt_hwcrypto_ctx *ctx); + +/** + * @brief Setting RNG default devices + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_rng_default(struct rt_hwcrypto_device *device); + +/** + * @brief Getting Random Numbers from RNG Context + * + * @param ctx RNG context + * + * @return Random number + */ +rt_uint32_t rt_hwcrypto_rng_update_ctx(struct rt_hwcrypto_ctx *ctx); + +/** + * @brief Return a random number + * + * @return Random number + */ +rt_uint32_t rt_hwcrypto_rng_update(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/components/drivers/hwcrypto/hw_symmetric.c b/components/drivers/hwcrypto/hw_symmetric.c new file mode 100644 index 0000000000..789c5c1a2c --- /dev/null +++ b/components/drivers/hwcrypto/hw_symmetric.c @@ -0,0 +1,276 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-04-25 tyx the first version + */ + +#include <rtthread.h> +#include <rtdevice.h> +#include <hw_symmetric.h> + +/** + * @brief Creating Symmetric Encryption and Decryption Context + * + * @param device Hardware crypto device + * @param type Type of symmetric crypto context + * + * @return Symmetric crypto context + */ +struct rt_hwcrypto_ctx *rt_hwcrypto_symmetric_create(struct rt_hwcrypto_device *device, hwcrypto_type type) +{ + struct rt_hwcrypto_ctx *ctx; + + ctx = rt_hwcrypto_ctx_create(device, type, sizeof(struct hwcrypto_symmetric)); + return ctx; +} + +/** + * @brief Destroy Symmetric Encryption and Decryption Context + * + * @param ctx Symmetric crypto context + */ +void rt_hwcrypto_symmetric_destroy(struct rt_hwcrypto_ctx *ctx) +{ + rt_hwcrypto_ctx_destroy(ctx); +} + +/** + * @brief This function performs a symmetric encryption or decryption operation + * + * @param ctx Symmetric crypto context + * @param mode Operation mode. HWCRYPTO_MODE_ENCRYPT or HWCRYPTO_MODE_DECRYPT + * @param length The length of the input data in Bytes. This must be a multiple of the block size + * @param in The buffer holding the input data + * @param out The buffer holding the output data + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_symmetric_crypt(struct rt_hwcrypto_ctx *ctx, hwcrypto_mode mode, rt_size_t length, const rt_uint8_t *in, rt_uint8_t *out) +{ + struct hwcrypto_symmetric *symmetric_ctx; + struct hwcrypto_symmetric_info symmetric_info; + rt_err_t err; + + if (ctx == RT_NULL) + { + return -RT_EINVAL; + } + symmetric_ctx = (struct hwcrypto_symmetric *)ctx; + if (symmetric_ctx->ops->crypt == RT_NULL) + { + return -RT_ERROR; + } + if (mode != HWCRYPTO_MODE_ENCRYPT && mode != HWCRYPTO_MODE_DECRYPT) + { + return -EINVAL; + } + + /* Input information packaging */ + symmetric_info.mode = mode; + symmetric_info.in = in; + symmetric_info.out = out; + symmetric_info.length = length; + + /* Calling Hardware Encryption and Decryption Function */ + err = symmetric_ctx->ops->crypt(symmetric_ctx, &symmetric_info); + + /* clean up flags */ + symmetric_ctx->flags &= ~(SYMMTRIC_MODIFY_KEY | SYMMTRIC_MODIFY_IV | SYMMTRIC_MODIFY_IVOFF); + return err; +} + +/** + * @brief Set Symmetric Encryption and Decryption Key + * + * @param ctx Symmetric crypto context + * @param key The crypto key + * @param bitlen The crypto key bit length + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_symmetric_setkey(struct rt_hwcrypto_ctx *ctx, const rt_uint8_t *key, rt_uint32_t bitlen) +{ + struct hwcrypto_symmetric *symmetric_ctx; + + if (ctx && bitlen <= RT_HWCRYPTO_KEYBIT_MAX_SIZE) + { + symmetric_ctx = (struct hwcrypto_symmetric *)ctx; + rt_memcpy(symmetric_ctx->key, key, bitlen >> 3); + /* Record key length */ + symmetric_ctx->key_bitlen = bitlen; + /* Key change flag set up */ + symmetric_ctx->flags |= SYMMTRIC_MODIFY_KEY; + return RT_EOK; + } + + return -RT_EINVAL; +} + +/** + * @brief Get Symmetric Encryption and Decryption Key + * + * @param ctx Symmetric crypto context + * @param key The crypto key buffer + * @param bitlen The crypto key bit length + * + * @return Key length of copy + */ +int rt_hwcrypto_symmetric_getkey(struct rt_hwcrypto_ctx *ctx, rt_uint8_t *key, rt_uint32_t bitlen) +{ + struct hwcrypto_symmetric *symmetric_ctx = (struct hwcrypto_symmetric *)ctx; + + if (ctx && bitlen >= symmetric_ctx->key_bitlen) + { + rt_memcpy(key, symmetric_ctx->key, symmetric_ctx->key_bitlen >> 3); + return symmetric_ctx->key_bitlen; + } + + return 0; +} + +/** + * @brief Set Symmetric Encryption and Decryption initialization vector + * + * @param ctx Symmetric crypto context + * @param iv The crypto initialization vector + * @param len The crypto initialization vector length + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_symmetric_setiv(struct rt_hwcrypto_ctx *ctx, const rt_uint8_t *iv, rt_size_t len) +{ + struct hwcrypto_symmetric *symmetric_ctx; + + if (ctx && len <= RT_HWCRYPTO_IV_MAX_SIZE) + { + symmetric_ctx = (struct hwcrypto_symmetric *)ctx; + rt_memcpy(symmetric_ctx->iv, iv, len); + symmetric_ctx->iv_len = len; + /* IV change flag set up */ + symmetric_ctx->flags |= SYMMTRIC_MODIFY_IV; + return RT_EOK; + } + + return -RT_EINVAL; +} + +/** + * @brief Get Symmetric Encryption and Decryption initialization vector + * + * @param ctx Symmetric crypto context + * @param iv The crypto initialization vector buffer + * @param len The crypto initialization vector buffer length + * + * @return IV length of copy + */ +int rt_hwcrypto_symmetric_getiv(struct rt_hwcrypto_ctx *ctx, rt_uint8_t *iv, rt_size_t len) +{ + struct hwcrypto_symmetric *symmetric_ctx = (struct hwcrypto_symmetric *)ctx;; + + if (ctx && len >= symmetric_ctx->iv_len) + { + rt_memcpy(iv, symmetric_ctx->iv, symmetric_ctx->iv_len); + return symmetric_ctx->iv_len; + } + + return 0; +} + +/** + * @brief Set offset in initialization vector + * + * @param ctx Symmetric crypto context + * @param iv_off The offset in IV + */ +void rt_hwcrypto_symmetric_set_ivoff(struct rt_hwcrypto_ctx *ctx, rt_int32_t iv_off) +{ + if (ctx) + { + ((struct hwcrypto_symmetric *)ctx)->iv_off = iv_off; + /* iv_off change flag set up */ + ((struct hwcrypto_symmetric *)ctx)->flags |= SYMMTRIC_MODIFY_IVOFF; + } +} + +/** + * @brief Get offset in initialization vector + * + * @param ctx Symmetric crypto context + * @param iv_off It must point to a valid memory + */ +void rt_hwcrypto_symmetric_get_ivoff(struct rt_hwcrypto_ctx *ctx, rt_int32_t *iv_off) +{ + if (ctx && iv_off) + { + *iv_off = ((struct hwcrypto_symmetric *)ctx)->iv_off; + } +} + +/** + * @brief This function copy symmetric crypto context + * + * @param des The destination symmetric crypto context + * @param src The symmetric crypto context to be copy + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_symmetric_cpy(struct rt_hwcrypto_ctx *des, const struct rt_hwcrypto_ctx *src) +{ + struct hwcrypto_symmetric *symmetric_des = (struct hwcrypto_symmetric *)des; + struct hwcrypto_symmetric *symmetric_src = (struct hwcrypto_symmetric *)src; + + if (des != RT_NULL && src != RT_NULL) + { + /* Copy Symmetric Encryption and Decryption Context Information */ + symmetric_des->flags = symmetric_src->flags ; + symmetric_des->iv_len = symmetric_src->iv_len ; + symmetric_des->iv_off = symmetric_src->iv_off ; + symmetric_des->key_bitlen = symmetric_src->key_bitlen; + rt_memcpy(symmetric_des->iv, symmetric_src->iv, symmetric_src->iv_len); + rt_memcpy(symmetric_des->key, symmetric_src->key, symmetric_src->key_bitlen >> 3); + + /* Hardware context copy */ + return rt_hwcrypto_ctx_cpy(des, src); + } + return -RT_EINVAL; +} + +/** + * @brief Reset symmetric crypto context + * + * @param ctx Symmetric crypto context + */ +void rt_hwcrypto_symmetric_reset(struct rt_hwcrypto_ctx *ctx) +{ + struct hwcrypto_symmetric *symmetric_ctx = (struct hwcrypto_symmetric *)ctx; + if (ctx != RT_NULL) + { + /* Copy Symmetric Encryption and Decryption Context Information */ + symmetric_ctx->flags = 0x00; + symmetric_ctx->iv_len = 0x00; + symmetric_ctx->iv_off = 0x00; + symmetric_ctx->key_bitlen = 0x00; + rt_memset(symmetric_ctx->iv, 0, RT_HWCRYPTO_IV_MAX_SIZE); + rt_memset(symmetric_ctx->key, 0, RT_HWCRYPTO_KEYBIT_MAX_SIZE >> 3); + + /* Hardware context reset */ + rt_hwcrypto_ctx_reset(ctx); + } +} + +/** + * @brief Setting symmetric crypto context type + * + * @param ctx Symmetric crypto context + * @param type Types of settings + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_symmetric_set_type(struct rt_hwcrypto_ctx *ctx, hwcrypto_type type) +{ + return rt_hwcrypto_set_type(ctx, type); +} diff --git a/components/drivers/hwcrypto/hw_symmetric.h b/components/drivers/hwcrypto/hw_symmetric.h new file mode 100644 index 0000000000..12f4dbec30 --- /dev/null +++ b/components/drivers/hwcrypto/hw_symmetric.h @@ -0,0 +1,189 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-04-25 tyx the first version + */ + +#ifndef __HW_SYMMETRIC_H__ +#define __HW_SYMMETRIC_H__ + +#include <hwcrypto.h> + +#ifndef RT_HWCRYPTO_IV_MAX_SIZE +#define RT_HWCRYPTO_IV_MAX_SIZE (16) +#endif +#ifndef RT_HWCRYPTO_KEYBIT_MAX_SIZE +#define RT_HWCRYPTO_KEYBIT_MAX_SIZE (256) +#endif + +#define SYMMTRIC_MODIFY_KEY (0x1 << 0) +#define SYMMTRIC_MODIFY_IV (0x1 << 1) +#define SYMMTRIC_MODIFY_IVOFF (0x1 << 2) + +#ifdef __cplusplus +extern "C" { +#endif + +struct hwcrypto_symmetric; +struct hwcrypto_symmetric_info; + +struct hwcrypto_symmetric_ops +{ + rt_err_t (*crypt)(struct hwcrypto_symmetric *symmetric_ctx, + struct hwcrypto_symmetric_info *symmetric_info); /**< Hardware Symmetric Encryption and Decryption Callback */ +}; + +/** + * @brief Hardware driver usage, including input and output information + */ +struct hwcrypto_symmetric_info +{ + hwcrypto_mode mode; /**< crypto mode. HWCRYPTO_MODE_ENCRYPT or HWCRYPTO_MODE_DECRYPT */ + const rt_uint8_t *in; /**< Input data */ + rt_uint8_t *out; /**< Output data will be written */ + rt_size_t length; /**< The length of the input data in Bytes. It's a multiple of block size. */ +}; + +/** + * @brief Symmetric crypto context. Hardware driver usage + */ +struct hwcrypto_symmetric +{ + struct rt_hwcrypto_ctx parent; /**< Inheritance from hardware crypto context */ + rt_uint32_t flags; /**< key or iv or ivoff has been changed. The flag will be set up */ + rt_int32_t iv_len; /**< initialization vector effective length */ + rt_int32_t iv_off; /**< The offset in IV */ + rt_uint8_t iv[RT_HWCRYPTO_IV_MAX_SIZE]; /**< The initialization vector */ + rt_uint8_t key[RT_HWCRYPTO_KEYBIT_MAX_SIZE >> 3]; /**< The crypto key */ + rt_int32_t key_bitlen; /**< The crypto key bit length */ + const struct hwcrypto_symmetric_ops *ops; /**< !! Hardware initializes this value when creating context !! */ +}; + +/** + * @brief Creating Symmetric Encryption and Decryption Context + * + * @param device Hardware crypto device + * @param type Type of symmetric crypto context + * + * @return Symmetric crypto context + */ +struct rt_hwcrypto_ctx *rt_hwcrypto_symmetric_create(struct rt_hwcrypto_device *device, + hwcrypto_type type); + +/** + * @brief Destroy Symmetric Encryption and Decryption Context + * + * @param ctx Symmetric crypto context + */ +void rt_hwcrypto_symmetric_destroy(struct rt_hwcrypto_ctx *ctx); + +/** + * @brief This function performs a symmetric encryption or decryption operation + * + * @param ctx Symmetric crypto context + * @param mode Operation mode. HWCRYPTO_MODE_ENCRYPT or HWCRYPTO_MODE_DECRYPT + * @param length The length of the input data in Bytes. This must be a multiple of the block size + * @param in The buffer holding the input data + * @param out The buffer holding the output data + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_symmetric_crypt(struct rt_hwcrypto_ctx *ctx, hwcrypto_mode mode, + rt_size_t length, const rt_uint8_t *in, rt_uint8_t *out); + +/** + * @brief Set Symmetric Encryption and Decryption Key + * + * @param ctx Symmetric crypto context + * @param key The crypto key + * @param bitlen The crypto key bit length + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_symmetric_setkey(struct rt_hwcrypto_ctx *ctx, const rt_uint8_t *key, rt_uint32_t bitlen); + +/** + * @brief Get Symmetric Encryption and Decryption Key + * + * @param ctx Symmetric crypto context + * @param key The crypto key buffer + * @param bitlen The crypto key bit length + * + * @return Key length of copy + */ +int rt_hwcrypto_symmetric_getkey(struct rt_hwcrypto_ctx *ctx, rt_uint8_t *key, rt_uint32_t bitlen); + +/** + * @brief Set Symmetric Encryption and Decryption initialization vector + * + * @param ctx Symmetric crypto context + * @param iv The crypto initialization vector + * @param len The crypto initialization vector length + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_symmetric_setiv(struct rt_hwcrypto_ctx *ctx, const rt_uint8_t *iv, rt_size_t len); + +/** + * @brief Get Symmetric Encryption and Decryption initialization vector + * + * @param ctx Symmetric crypto context + * @param iv The crypto initialization vector buffer + * @param len The crypto initialization vector buffer length + * + * @return IV length of copy + */ +int rt_hwcrypto_symmetric_getiv(struct rt_hwcrypto_ctx *ctx, rt_uint8_t *iv, rt_size_t len); + +/** + * @brief Set offset in initialization vector + * + * @param ctx Symmetric crypto context + * @param iv_off The offset in IV + */ +void rt_hwcrypto_symmetric_set_ivoff(struct rt_hwcrypto_ctx *ctx, rt_int32_t iv_off); + +/** + * @brief Get offset in initialization vector + * + * @param ctx Symmetric crypto context + * @param iv_off It must point to a valid memory + */ +void rt_hwcrypto_symmetric_get_ivoff(struct rt_hwcrypto_ctx *ctx, rt_int32_t *iv_off); + +/** + * @brief This function copy symmetric crypto context + * + * @param des The destination symmetric crypto context + * @param src The symmetric crypto context to be copy + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_symmetric_cpy(struct rt_hwcrypto_ctx *des, const struct rt_hwcrypto_ctx *src); + +/** + * @brief Reset symmetric crypto context + * + * @param ctx Symmetric crypto context + */ +void rt_hwcrypto_symmetric_reset(struct rt_hwcrypto_ctx *ctx); + +/** + * @brief Setting symmetric crypto context type + * + * @param ctx Symmetric crypto context + * @param type Types of settings + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_symmetric_set_type(struct rt_hwcrypto_ctx *ctx, hwcrypto_type type); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/components/drivers/hwcrypto/hwcrypto.c b/components/drivers/hwcrypto/hwcrypto.c new file mode 100644 index 0000000000..bbe1ff63fb --- /dev/null +++ b/components/drivers/hwcrypto/hwcrypto.c @@ -0,0 +1,255 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-04-23 tyx the first version + */ + +#include <rtthread.h> +#include <rtdevice.h> +#include <hwcrypto.h> + +/** + * @brief Setting context type (Direct calls are not recommended) + * + * @param ctx Crypto context + * @param type Types of settings + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_set_type(struct rt_hwcrypto_ctx *ctx, hwcrypto_type type) +{ + if (ctx) + { + /* Is it the same category? */ + if ((ctx->type & HWCRYPTO_MAIN_TYPE_MASK) == (type & HWCRYPTO_MAIN_TYPE_MASK)) + { + ctx->type = type; + return RT_EOK; + } + /* Context is empty type */ + else if (ctx->type == HWCRYPTO_TYPE_NULL) + { + ctx->type = type; + return RT_EOK; + } + else + { + return -RT_ERROR; + } + } + return -RT_EINVAL; +} + +/** + * @brief Reset context type (Direct calls are not recommended) + * + * @param ctx Crypto context + * + */ +void rt_hwcrypto_ctx_reset(struct rt_hwcrypto_ctx *ctx) +{ + if (ctx && ctx->device->ops->reset) + { + ctx->device->ops->reset(ctx); + } +} + +/** + * @brief Init crypto context + * + * @param ctx The context to initialize + * @param device Hardware crypto device + * @param type Type of context + * @param obj_size Size of context object + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_ctx_init(struct rt_hwcrypto_ctx *ctx, struct rt_hwcrypto_device *device, hwcrypto_type type) +{ + rt_err_t err; + + /* Setting context type */ + rt_hwcrypto_set_type(ctx, type); + ctx->device = device; + /* Create hardware context */ + err = ctx->device->ops->create(ctx); + if (err != RT_EOK) + { + return err; + } + return RT_EOK; +} + +/** + * @brief Create crypto context + * + * @param device Hardware crypto device + * @param type Type of context + * @param obj_size Size of context object + * + * @return Crypto context + */ +struct rt_hwcrypto_ctx *rt_hwcrypto_ctx_create(struct rt_hwcrypto_device *device, hwcrypto_type type, rt_uint32_t obj_size) +{ + struct rt_hwcrypto_ctx *ctx; + rt_err_t err; + + /* Parameter checking */ + if (device == RT_NULL || obj_size < sizeof(struct rt_hwcrypto_ctx)) + { + return RT_NULL; + } + ctx = rt_malloc(obj_size); + if (ctx == RT_NULL) + { + return ctx; + } + rt_memset(ctx, 0, obj_size); + /* Init context */ + err = rt_hwcrypto_ctx_init(ctx, device, type); + if (err != RT_EOK) + { + rt_free(ctx); + ctx = RT_NULL; + } + return ctx; +} + +/** + * @brief Destroy crypto context + * + * @param device Crypto context + */ +void rt_hwcrypto_ctx_destroy(struct rt_hwcrypto_ctx *ctx) +{ + if (ctx == RT_NULL) + { + return; + } + /* Destroy hardware context */ + if (ctx->device->ops->destroy) + { + ctx->device->ops->destroy(ctx); + } + /* Free the resources */ + rt_free(ctx); +} + +/** + * @brief Copy crypto context + * + * @param des The destination context + * @param src The context to be copy + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_ctx_cpy(struct rt_hwcrypto_ctx *des, const struct rt_hwcrypto_ctx *src) +{ + if (des == RT_NULL || src == RT_NULL) + { + return -RT_EINVAL; + } + + /* The equipment is different or of different types and cannot be copied */ + if (des->device != src->device || + (des->type & HWCRYPTO_MAIN_TYPE_MASK) != (src->type & HWCRYPTO_MAIN_TYPE_MASK)) + { + return -RT_EINVAL; + } + des->type = src->type; + /* Calling Hardware Context Copy Function */ + return src->device->ops->copy(des, src); +} + +/** + * @brief Get the default hardware crypto device + * + * @return Hardware crypto device + * + */ +struct rt_hwcrypto_device *rt_hwcrypto_dev_default(void) +{ + static struct rt_hwcrypto_device *hwcrypto_dev; + + /* If there is a default device, return the device */ + if (hwcrypto_dev) + { + return hwcrypto_dev; + } + /* Find by default device name */ + hwcrypto_dev = (struct rt_hwcrypto_device *)rt_device_find(RT_HWCRYPTO_DEFAULT_NAME); + return hwcrypto_dev; +} + +/** + * @brief Get the unique ID of the device + * + * @param device Device object + * + * @return Device unique ID + */ +rt_uint64_t rt_hwcrypto_id(struct rt_hwcrypto_device *device) +{ + if (device) + { + return device->id; + } + return 0; +} + +#ifdef RT_USING_DEVICE_OPS +const static struct rt_device_ops hwcrypto_ops = +{ + RT_NULL, + RT_NULL, + RT_NULL, + RT_NULL, + RT_NULL, + RT_NULL +}; +#endif + +/** + * @brief Register hardware crypto device + * + * @param device Hardware crypto device + * @param name Name of device + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_register(struct rt_hwcrypto_device *device, const char *name) +{ + rt_err_t err; + + RT_ASSERT(device != RT_NULL); + RT_ASSERT(name != RT_NULL); + RT_ASSERT(device->ops != RT_NULL); + RT_ASSERT(device->ops->create != RT_NULL); + RT_ASSERT(device->ops->destroy != RT_NULL); + RT_ASSERT(device->ops->copy != RT_NULL); + RT_ASSERT(device->ops->reset != RT_NULL); + + rt_memset(&device->parent, 0, sizeof(struct rt_device)); +#ifdef RT_USING_DEVICE_OPS + device->parent.ops = &hwcrypto_ops; +#else + device->parent.init = RT_NULL; + device->parent.open = RT_NULL; + device->parent.close = RT_NULL; + device->parent.read = RT_NULL; + device->parent.write = RT_NULL; + device->parent.control = RT_NULL; +#endif + + device->parent.user_data = RT_NULL; + device->parent.type = RT_Device_Class_Miscellaneous; + + /* Register device */ + err = rt_device_register(&device->parent, name, RT_DEVICE_FLAG_RDWR); + + return err; +} diff --git a/components/drivers/hwcrypto/hwcrypto.h b/components/drivers/hwcrypto/hwcrypto.h new file mode 100644 index 0000000000..a428f4437d --- /dev/null +++ b/components/drivers/hwcrypto/hwcrypto.h @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-04-23 tyx the first version + */ + +#ifndef __HWCRYPTO_H__ +#define __HWCRYPTO_H__ + +#include <rtthread.h> + +#ifndef RT_HWCRYPTO_DEFAULT_NAME +#define RT_HWCRYPTO_DEFAULT_NAME ("hwcryto") +#endif + +#define HWCRYPTO_MAIN_TYPE_MASK (0xffffUL << 16) +#define HWCRYPTO_SUB_TYPE_MASK (0xffUL << 8) + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum +{ + HWCRYPTO_TYPE_NULL = 0x00000000, + + /* Main Type */ + /* symmetric Type */ + HWCRYPTO_TYPE_HEAD = __LINE__, + HWCRYPTO_TYPE_AES = ((__LINE__ - HWCRYPTO_TYPE_HEAD) & 0xffff) << 16, /**< AES */ + HWCRYPTO_TYPE_DES = ((__LINE__ - HWCRYPTO_TYPE_HEAD) & 0xffff) << 16, /**< DES */ + HWCRYPTO_TYPE_3DES = ((__LINE__ - HWCRYPTO_TYPE_HEAD) & 0xffff) << 16, /**< 3DES */ + HWCRYPTO_TYPE_RC4 = ((__LINE__ - HWCRYPTO_TYPE_HEAD) & 0xffff) << 16, /**< RC4 */ + HWCRYPTO_TYPE_GCM = ((__LINE__ - HWCRYPTO_TYPE_HEAD) & 0xffff) << 16, /**< GCM */ + /* HASH Type */ + HWCRYPTO_TYPE_MD5 = ((__LINE__ - HWCRYPTO_TYPE_HEAD) & 0xffff) << 16, /**< MD5 */ + HWCRYPTO_TYPE_SHA1 = ((__LINE__ - HWCRYPTO_TYPE_HEAD) & 0xffff) << 16, /**< SHA1 */ + HWCRYPTO_TYPE_SHA2 = ((__LINE__ - HWCRYPTO_TYPE_HEAD) & 0xffff) << 16, /**< SHA2 */ + /* Other Type */ + HWCRYPTO_TYPE_RNG = ((__LINE__ - HWCRYPTO_TYPE_HEAD) & 0xffff) << 16, /**< RNG */ + HWCRYPTO_TYPE_CRC = ((__LINE__ - HWCRYPTO_TYPE_HEAD) & 0xffff) << 16, /**< CRC */ + HWCRYPTO_TYPE_BIGNUM = ((__LINE__ - HWCRYPTO_TYPE_HEAD) & 0xffff) << 16, /**< BIGNUM */ + + /* AES Subtype */ + HWCRYPTO_TYPE_AES_ECB = HWCRYPTO_TYPE_AES | (0x01 << 8), + HWCRYPTO_TYPE_AES_CBC = HWCRYPTO_TYPE_AES | (0x02 << 8), + HWCRYPTO_TYPE_AES_CFB = HWCRYPTO_TYPE_AES | (0x03 << 8), + HWCRYPTO_TYPE_AES_CTR = HWCRYPTO_TYPE_AES | (0x04 << 8), + HWCRYPTO_TYPE_AES_OFB = HWCRYPTO_TYPE_AES | (0x05 << 8), + + /* DES Subtype */ + HWCRYPTO_TYPE_DES_ECB = HWCRYPTO_TYPE_DES | (0x01 << 8), + HWCRYPTO_TYPE_DES_CBC = HWCRYPTO_TYPE_DES | (0x02 << 8), + + /* 3DES Subtype */ + HWCRYPTO_TYPE_3DES_ECB = HWCRYPTO_TYPE_3DES | (0x01 << 8), + HWCRYPTO_TYPE_3DES_CBC = HWCRYPTO_TYPE_3DES | (0x02 << 8), + + /* SHA2 Subtype */ + HWCRYPTO_TYPE_SHA224 = HWCRYPTO_TYPE_SHA2 | (0x01 << 8), + HWCRYPTO_TYPE_SHA256 = HWCRYPTO_TYPE_SHA2 | (0x02 << 8), + HWCRYPTO_TYPE_SHA384 = HWCRYPTO_TYPE_SHA2 | (0x03 << 8), + HWCRYPTO_TYPE_SHA512 = HWCRYPTO_TYPE_SHA2 | (0x04 << 8), +} hwcrypto_type; + +typedef enum +{ + HWCRYPTO_MODE_ENCRYPT = 0x1, /**< Encryption operations */ + HWCRYPTO_MODE_DECRYPT = 0x2, /**< Decryption operations */ + HWCRYPTO_MODE_UNKNOWN = 0x7fffffff, /**< Unknown */ +} hwcrypto_mode; + +struct rt_hwcrypto_ctx; + +struct rt_hwcrypto_ops +{ + rt_err_t (*create)(struct rt_hwcrypto_ctx *ctx); /**< Creating hardware context */ + void (*destroy)(struct rt_hwcrypto_ctx *ctx); /**< Delete hardware context */ + rt_err_t (*copy)(struct rt_hwcrypto_ctx *des, + const struct rt_hwcrypto_ctx *src); /**< Cpoy hardware context */ + void (*reset)(struct rt_hwcrypto_ctx *ctx); /**< Reset hardware context */ +}; + +struct rt_hwcrypto_device +{ + struct rt_device parent; /**< Inherited from the standard device */ + const struct rt_hwcrypto_ops *ops; /**< Hardware crypto ops */ + rt_uint64_t id; /**< Unique id */ + void *user_data; /**< Device user data */ +}; + +struct rt_hwcrypto_ctx +{ + struct rt_hwcrypto_device *device; /**< Binding device */ + hwcrypto_type type; /**< Encryption and decryption types */ + void *contex; /**< Hardware context */ +}; + +/** + * @brief Setting context type (Direct calls are not recommended) + * + * @param ctx Crypto context + * @param type Types of settings + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_set_type(struct rt_hwcrypto_ctx *ctx, hwcrypto_type type); + +/** + * @brief Reset context type (Direct calls are not recommended) + * + * @param ctx Crypto context + */ +void rt_hwcrypto_ctx_reset(struct rt_hwcrypto_ctx *ctx); + +/** + * @brief Init crypto context (Direct calls are not recommended) + * + * @param ctx The context to initialize + * @param device Hardware crypto device + * @param type Type of context + * @param obj_size Size of context object + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_ctx_init(struct rt_hwcrypto_ctx *ctx, + struct rt_hwcrypto_device *device, hwcrypto_type type); + +/** + * @brief Create crypto context (Direct calls are not recommended) + * + * @param device Hardware crypto device + * @param type Type of context + * @param obj_size Size of context object + * + * @return Crypto context + */ +struct rt_hwcrypto_ctx *rt_hwcrypto_ctx_create(struct rt_hwcrypto_device *device, + hwcrypto_type type, rt_uint32_t obj_size); + +/** + * @brief Destroy crypto context (Direct calls are not recommended) + * + * @param device Crypto context + */ +void rt_hwcrypto_ctx_destroy(struct rt_hwcrypto_ctx *ctx); + +/** + * @brief Copy crypto context (Direct calls are not recommended) + * + * @param des The destination context + * @param src The context to be copy + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_ctx_cpy(struct rt_hwcrypto_ctx *des, const struct rt_hwcrypto_ctx *src); + +/** + * @brief Register hardware crypto device + * + * @param device Hardware crypto device + * @param name Name of device + * + * @return RT_EOK on success. + */ +rt_err_t rt_hwcrypto_register(struct rt_hwcrypto_device *device, const char *name); + +/** + * @brief Get the default hardware crypto device + * + * @return Hardware crypto device + * + */ +struct rt_hwcrypto_device *rt_hwcrypto_dev_default(void); + +/** + * @brief Get the unique ID of the device + * + * @param device Device object + * + * @return Device unique ID + */ +rt_uint64_t rt_hwcrypto_id(struct rt_hwcrypto_device *device); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/components/drivers/i2c/fm24clxx.c b/components/drivers/i2c/fm24clxx.c deleted file mode 100644 index eecf3d455a..0000000000 --- a/components/drivers/i2c/fm24clxx.c +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Copyright (c) 2006-2018, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2017-07-14 aubr.cool 1st version - */ -#include <rtthread.h> -#include <rtdevice.h> -#include "fm24clxx.h" - -struct fm24clxx_device -{ - struct rt_device parent; - struct rt_i2c_bus_device *bus; -}; - -/* RT-Thread device interface */ - -static rt_err_t fm24clxx_init(rt_device_t dev) -{ - return RT_EOK; -} -static rt_err_t fm24clxx_open(rt_device_t dev, rt_uint16_t oflag) -{ - return RT_EOK; -} - -static rt_err_t fm24clxx_close(rt_device_t dev) -{ - return RT_EOK; -} - -static rt_err_t fm24clxx_control(rt_device_t dev, int cmd, void *args) -{ - return RT_EOK; -} - -static rt_size_t fm24clxx_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size) -{ - struct fm24clxx_device *fm24clxx; - const struct fm24clxx_config *cfg; - struct rt_i2c_msg msg[2]; - rt_uint8_t mem_addr[2] = {0,}; - rt_size_t ret = 0; - RT_ASSERT(dev != 0); - - fm24clxx = (struct fm24clxx_device *) dev; - - RT_ASSERT(fm24clxx->parent.user_data != 0); - cfg = (const struct fm24clxx_config *) fm24clxx->parent.user_data; - - if(pos > cfg->size) - { - return 0; - } - - if(pos + size > cfg->size) - { - size = cfg->size - pos; - } - - msg[0].addr = cfg->addr; - msg[0].flags = cfg->flags | RT_I2C_WR; - mem_addr[0] = (pos >> 8); - mem_addr[1] = (rt_uint8_t) pos; - msg[0].buf = (rt_uint8_t *) mem_addr; - msg[0].len = 2; - - msg[1].addr = cfg->addr; - msg[1].flags = cfg->flags | RT_I2C_RD; - msg[1].buf = (rt_uint8_t *) buffer; - msg[1].len = size; - - ret = rt_i2c_transfer(fm24clxx->bus, msg, 2); - return (ret == 2) ? size : 0; -} - -static rt_size_t fm24clxx_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size) -{ - struct fm24clxx_device *fm24clxx; - const struct fm24clxx_config *cfg; - struct rt_i2c_msg msg[2]; - rt_uint8_t mem_addr[2] = {0,}; - rt_size_t ret = 0; - RT_ASSERT(dev != 0); - - fm24clxx = (struct fm24clxx_device *) dev; - - RT_ASSERT(fm24clxx->parent.user_data != 0); - cfg = (const struct fm24clxx_config *) fm24clxx->parent.user_data; - - if(pos > cfg->size) - { - return 0; - } - - if(pos + size > cfg->size) - { - size = cfg->size - pos; - } - - msg[0].addr = cfg->addr; - msg[0].flags = cfg->flags | RT_I2C_WR; - mem_addr[0] = (pos >> 8); - mem_addr[1] = (rt_uint8_t) pos; - msg[0].buf = (rt_uint8_t *) mem_addr; - msg[0].len = 2; - - msg[1].addr = cfg->addr; - msg[1].flags = cfg->flags | RT_I2C_WR | RT_I2C_NO_START; - msg[1].buf = (rt_uint8_t *) buffer; - msg[1].len = size; - - ret = rt_i2c_transfer(fm24clxx->bus, msg, 2); - 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; - struct rt_i2c_bus_device *bus; - - bus = rt_i2c_bus_device_find(i2c_bus); - if (bus == RT_NULL) - { - return RT_ENOSYS; - } - - 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); -}
\ No newline at end of file diff --git a/components/drivers/i2c/fm24clxx.h b/components/drivers/i2c/fm24clxx.h deleted file mode 100644 index 74ee065470..0000000000 --- a/components/drivers/i2c/fm24clxx.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (c) 2006-2018, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2017-07-14 aubr.cool 1st version - */ - -#ifndef __FM24CLXX_H__ -#define __FM24CLXX_H__ - -#include <rtthread.h> - -struct fm24clxx_config -{ - rt_uint32_t size; - rt_uint16_t addr; - rt_uint16_t flags; -}; - -extern rt_err_t fm24clxx_register(const char *e2m_device_name, - const char *i2c_bus, void *user_data); - -#endif /*__FM24CLXX_H__*/
\ No newline at end of file diff --git a/components/drivers/i2c/i2c-bit-ops.c b/components/drivers/i2c/i2c-bit-ops.c index 26479a1d68..99338eef54 100644 --- a/components/drivers/i2c/i2c-bit-ops.c +++ b/components/drivers/i2c/i2c-bit-ops.c @@ -10,11 +10,13 @@ #include <rtdevice.h> -#ifdef RT_I2C_BIT_DEBUG -#define bit_dbg(fmt, ...) rt_kprintf(fmt, ##__VA_ARGS__) +#define DBG_TAG "I2C" +#ifdef RT_I2C_BITOPS_DEBUG +#define DBG_LVL DBG_LOG #else -#define bit_dbg(fmt, ...) +#define DBG_LVL DBG_INFO #endif +#include <rtdbg.h> #define SET_SDA(ops, val) ops->set_sda(ops->data, val) #define SET_SCL(ops, val) ops->set_scl(ops->data, val) @@ -54,11 +56,11 @@ static rt_err_t SCL_H(struct rt_i2c_bit_ops *ops) return -RT_ETIMEOUT; rt_thread_delay((ops->timeout + 1) >> 1); } -#ifdef RT_I2C_BIT_DEBUG +#ifdef RT_I2C_BITOPS_DEBUG if (rt_tick_get() != start) { - bit_dbg("wait %ld tick for SCL line to go high\n", - rt_tick_get() - start); + LOG_D("wait %ld tick for SCL line to go high", + rt_tick_get() - start); } #endif @@ -70,14 +72,14 @@ done: static void i2c_start(struct rt_i2c_bit_ops *ops) { -#ifdef RT_I2C_BIT_DEBUG +#ifdef RT_I2C_BITOPS_DEBUG if (ops->get_scl && !GET_SCL(ops)) { - bit_dbg("I2C bus error, SCL line low\n"); + LOG_E("I2C bus error, SCL line low"); } if (ops->get_sda && !GET_SDA(ops)) { - bit_dbg("I2C bus error, SDA line low\n"); + LOG_E("I2C bus error, SDA line low"); } #endif SDA_L(ops); @@ -114,13 +116,13 @@ rt_inline rt_bool_t i2c_waitack(struct rt_i2c_bit_ops *ops) if (SCL_H(ops) < 0) { - bit_dbg("wait ack timeout\n"); + LOG_W("wait ack timeout"); return -RT_ETIMEOUT; } ack = !GET_SDA(ops); /* ACK : SDA pin is pulled low */ - bit_dbg("%s\n", ack ? "ACK" : "NACK"); + LOG_D("%s", ack ? "ACK" : "NACK"); SCL_L(ops); @@ -132,7 +134,7 @@ static rt_int32_t i2c_writeb(struct rt_i2c_bus_device *bus, rt_uint8_t data) rt_int32_t i; rt_uint8_t bit; - struct rt_i2c_bit_ops *ops = bus->priv; + struct rt_i2c_bit_ops *ops = (struct rt_i2c_bit_ops *)bus->priv; for (i = 7; i >= 0; i--) { @@ -142,8 +144,8 @@ static rt_int32_t i2c_writeb(struct rt_i2c_bus_device *bus, rt_uint8_t data) i2c_delay(ops); if (SCL_H(ops) < 0) { - bit_dbg("i2c_writeb: 0x%02x, " - "wait scl pin high timeout at bit %d\n", + LOG_D("i2c_writeb: 0x%02x, " + "wait scl pin high timeout at bit %d", data, i); return -RT_ETIMEOUT; @@ -159,7 +161,7 @@ static rt_int32_t i2c_readb(struct rt_i2c_bus_device *bus) { rt_uint8_t i; rt_uint8_t data = 0; - struct rt_i2c_bit_ops *ops = bus->priv; + struct rt_i2c_bit_ops *ops = (struct rt_i2c_bit_ops *)bus->priv; SDA_H(ops); i2c_delay(ops); @@ -169,8 +171,8 @@ static rt_int32_t i2c_readb(struct rt_i2c_bus_device *bus) if (SCL_H(ops) < 0) { - bit_dbg("i2c_readb: wait scl pin high " - "timeout at bit %d\n", 7 - i); + LOG_D("i2c_readb: wait scl pin high " + "timeout at bit %d", 7 - i); return -RT_ETIMEOUT; } @@ -205,13 +207,13 @@ static rt_size_t i2c_send_bytes(struct rt_i2c_bus_device *bus, } else if (ret == 0) { - i2c_dbg("send bytes: NACK.\n"); + LOG_D("send bytes: NACK."); return 0; } else { - i2c_dbg("send bytes: error %d\n", ret); + LOG_E("send bytes: error %d", ret); return ret; } @@ -222,14 +224,14 @@ static rt_size_t i2c_send_bytes(struct rt_i2c_bus_device *bus, static rt_err_t i2c_send_ack_or_nack(struct rt_i2c_bus_device *bus, int ack) { - struct rt_i2c_bit_ops *ops = bus->priv; + struct rt_i2c_bit_ops *ops = (struct rt_i2c_bit_ops *)bus->priv; if (ack) SET_SDA(ops, 0); i2c_delay(ops); if (SCL_H(ops) < 0) { - bit_dbg("ACK or NACK timeout\n"); + LOG_E("ACK or NACK timeout."); return -RT_ETIMEOUT; } @@ -263,7 +265,7 @@ static rt_size_t i2c_recv_bytes(struct rt_i2c_bus_device *bus, ptr ++; count --; - bit_dbg("recieve bytes: 0x%02x, %s\n", + LOG_D("recieve bytes: 0x%02x, %s", val, (flags & RT_I2C_NO_READ_ACK) ? "(No ACK/NACK)" : (count ? "ACK" : "NACK")); @@ -282,7 +284,7 @@ static rt_int32_t i2c_send_address(struct rt_i2c_bus_device *bus, rt_uint8_t addr, rt_int32_t retries) { - struct rt_i2c_bit_ops *ops = bus->priv; + struct rt_i2c_bit_ops *ops = (struct rt_i2c_bit_ops *)bus->priv; rt_int32_t i; rt_err_t ret = 0; @@ -291,10 +293,10 @@ static rt_int32_t i2c_send_address(struct rt_i2c_bus_device *bus, ret = i2c_writeb(bus, addr); if (ret == 1 || i == retries) break; - bit_dbg("send stop condition\n"); + LOG_D("send stop condition"); i2c_stop(ops); i2c_delay2(ops); - bit_dbg("send start condition\n"); + LOG_D("send start condition"); i2c_start(ops); } @@ -306,7 +308,7 @@ static rt_err_t i2c_bit_send_address(struct rt_i2c_bus_device *bus, { rt_uint16_t flags = msg->flags; rt_uint16_t ignore_nack = msg->flags & RT_I2C_IGNORE_NACK; - struct rt_i2c_bit_ops *ops = bus->priv; + struct rt_i2c_bit_ops *ops = (struct rt_i2c_bit_ops *)bus->priv; rt_uint8_t addr1, addr2; rt_int32_t retries; @@ -319,12 +321,12 @@ static rt_err_t i2c_bit_send_address(struct rt_i2c_bus_device *bus, addr1 = 0xf0 | ((msg->addr >> 7) & 0x06); addr2 = msg->addr & 0xff; - bit_dbg("addr1: %d, addr2: %d\n", addr1, addr2); + LOG_D("addr1: %d, addr2: %d", addr1, addr2); ret = i2c_send_address(bus, addr1, retries); if ((ret != 1) && !ignore_nack) { - bit_dbg("NACK: sending first addr\n"); + LOG_W("NACK: sending first addr"); return -RT_EIO; } @@ -332,19 +334,19 @@ static rt_err_t i2c_bit_send_address(struct rt_i2c_bus_device *bus, ret = i2c_writeb(bus, addr2); if ((ret != 1) && !ignore_nack) { - bit_dbg("NACK: sending second addr\n"); + LOG_W("NACK: sending second addr"); return -RT_EIO; } if (flags & RT_I2C_RD) { - bit_dbg("send repeated start condition\n"); + LOG_D("send repeated start condition"); i2c_restart(ops); addr1 |= 0x01; ret = i2c_send_address(bus, addr1, retries); if ((ret != 1) && !ignore_nack) { - bit_dbg("NACK: sending repeated addr\n"); + LOG_E("NACK: sending repeated addr"); return -RT_EIO; } @@ -369,11 +371,11 @@ static rt_size_t i2c_bit_xfer(struct rt_i2c_bus_device *bus, rt_uint32_t num) { struct rt_i2c_msg *msg; - struct rt_i2c_bit_ops *ops = bus->priv; + struct rt_i2c_bit_ops *ops = (struct rt_i2c_bit_ops *)bus->priv; rt_int32_t i, ret; rt_uint16_t ignore_nack; - bit_dbg("send start condition\n"); + LOG_D("send start condition"); i2c_start(ops); for (i = 0; i < num; i++) { @@ -388,7 +390,7 @@ static rt_size_t i2c_bit_xfer(struct rt_i2c_bus_device *bus, ret = i2c_bit_send_address(bus, msg); if ((ret != RT_EOK) && !ignore_nack) { - bit_dbg("receive NACK from device addr 0x%02x msg %d\n", + LOG_D("receive NACK from device addr 0x%02x msg %d", msgs[i].addr, i); goto out; } @@ -397,7 +399,7 @@ static rt_size_t i2c_bit_xfer(struct rt_i2c_bus_device *bus, { ret = i2c_recv_bytes(bus, msg); if (ret >= 1) - bit_dbg("read %d byte%s\n", ret, ret == 1 ? "" : "s"); + LOG_D("read %d byte%s", ret, ret == 1 ? "" : "s"); if (ret < msg->len) { if (ret >= 0) @@ -409,7 +411,7 @@ static rt_size_t i2c_bit_xfer(struct rt_i2c_bus_device *bus, { ret = i2c_send_bytes(bus, msg); if (ret >= 1) - bit_dbg("write %d byte%s\n", ret, ret == 1 ? "" : "s"); + LOG_D("write %d byte%s", ret, ret == 1 ? "" : "s"); if (ret < msg->len) { if (ret >= 0) @@ -421,7 +423,7 @@ static rt_size_t i2c_bit_xfer(struct rt_i2c_bus_device *bus, ret = i; out: - bit_dbg("send stop condition\n"); + LOG_D("send stop condition"); i2c_stop(ops); return ret; diff --git a/components/drivers/i2c/i2c_core.c b/components/drivers/i2c/i2c_core.c index f245abb9ca..f358c2b758 100644 --- a/components/drivers/i2c/i2c_core.c +++ b/components/drivers/i2c/i2c_core.c @@ -10,6 +10,14 @@ #include <rtdevice.h> +#define DBG_TAG "I2C" +#ifdef RT_I2C_DEBUG +#define DBG_LVL DBG_LOG +#else +#define DBG_LVL DBG_INFO +#endif +#include <rtdbg.h> + rt_err_t rt_i2c_bus_device_register(struct rt_i2c_bus_device *bus, const char *bus_name) { @@ -21,7 +29,7 @@ rt_err_t rt_i2c_bus_device_register(struct rt_i2c_bus_device *bus, res = rt_i2c_bus_device_device_init(bus, bus_name); - i2c_dbg("I2C bus [%s] registered\n", bus_name); + LOG_I("I2C bus [%s] registered", bus_name); return res; } @@ -32,7 +40,7 @@ struct rt_i2c_bus_device *rt_i2c_bus_device_find(const char *bus_name) rt_device_t dev = rt_device_find(bus_name); if (dev == RT_NULL || dev->type != RT_Device_Class_I2CBUS) { - i2c_dbg("I2C bus %s not exist\n", bus_name); + LOG_E("I2C bus %s not exist", bus_name); return RT_NULL; } @@ -53,9 +61,9 @@ rt_size_t rt_i2c_transfer(struct rt_i2c_bus_device *bus, #ifdef RT_I2C_DEBUG for (ret = 0; ret < num; ret++) { - i2c_dbg("msgs[%d] %c, addr=0x%02x, len=%d\n", ret, - (msgs[ret].flags & RT_I2C_RD) ? 'R' : 'W', - msgs[ret].addr, msgs[ret].len); + LOG_D("msgs[%d] %c, addr=0x%02x, len=%d", ret, + (msgs[ret].flags & RT_I2C_RD) ? 'R' : 'W', + msgs[ret].addr, msgs[ret].len); } #endif @@ -67,7 +75,7 @@ rt_size_t rt_i2c_transfer(struct rt_i2c_bus_device *bus, } else { - i2c_dbg("I2C bus operation not supported\n"); + LOG_E("I2C bus operation not supported"); return 0; } @@ -83,7 +91,7 @@ rt_size_t rt_i2c_master_send(struct rt_i2c_bus_device *bus, struct rt_i2c_msg msg; msg.addr = addr; - msg.flags = flags & RT_I2C_ADDR_10BIT; + msg.flags = flags; msg.len = count; msg.buf = (rt_uint8_t *)buf; @@ -103,8 +111,7 @@ rt_size_t rt_i2c_master_recv(struct rt_i2c_bus_device *bus, RT_ASSERT(bus != RT_NULL); msg.addr = addr; - msg.flags = flags & RT_I2C_ADDR_10BIT; - msg.flags |= RT_I2C_RD; + msg.flags = flags | RT_I2C_RD; msg.len = count; msg.buf = buf; diff --git a/components/drivers/i2c/i2c_dev.c b/components/drivers/i2c/i2c_dev.c index 6c7df8e427..59f728be09 100644 --- a/components/drivers/i2c/i2c_dev.c +++ b/components/drivers/i2c/i2c_dev.c @@ -11,6 +11,14 @@ #include <rtdevice.h> +#define DBG_TAG "I2C" +#ifdef RT_I2C_DEBUG +#define DBG_LVL DBG_LOG +#else +#define DBG_LVL DBG_INFO +#endif +#include <rtdbg.h> + static rt_size_t i2c_bus_device_read(rt_device_t dev, rt_off_t pos, void *buffer, @@ -23,12 +31,12 @@ static rt_size_t i2c_bus_device_read(rt_device_t dev, RT_ASSERT(bus != RT_NULL); RT_ASSERT(buffer != RT_NULL); - i2c_dbg("I2C bus dev [%s] reading %u bytes.\n", dev->parent.name, count); + LOG_D("I2C bus dev [%s] reading %u bytes.", dev->parent.name, count); addr = pos & 0xffff; flags = (pos >> 16) & 0xffff; - return rt_i2c_master_recv(bus, addr, flags, buffer, count); + return rt_i2c_master_recv(bus, addr, flags, (rt_uint8_t *)buffer, count); } static rt_size_t i2c_bus_device_write(rt_device_t dev, @@ -43,12 +51,12 @@ static rt_size_t i2c_bus_device_write(rt_device_t dev, RT_ASSERT(bus != RT_NULL); RT_ASSERT(buffer != RT_NULL); - i2c_dbg("I2C bus dev [%s] writing %u bytes.\n", dev->parent.name, count); + LOG_D("I2C bus dev [%s] writing %u bytes.", dev->parent.name, count); addr = pos & 0xffff; flags = (pos >> 16) & 0xffff; - return rt_i2c_master_send(bus, addr, flags, buffer, count); + return rt_i2c_master_send(bus, addr, flags, (const rt_uint8_t *)buffer, count); } static rt_err_t i2c_bus_device_control(rt_device_t dev, diff --git a/components/drivers/include/drivers/audio.h b/components/drivers/include/drivers/audio.h index 7d2cb36728..86057e7626 100644 --- a/components/drivers/include/drivers/audio.h +++ b/components/drivers/include/drivers/audio.h @@ -5,52 +5,30 @@ * * Change Logs: * Date Author Notes - * 2017-05-09 Urey first version + * 2017-05-09 Urey first version + * 2019-07-09 Zero-Free improve device ops interface and data flows + * */ #ifndef __AUDIO_H__ #define __AUDIO_H__ +#include "audio_pipe.h" + /* AUDIO command */ #define _AUDIO_CTL(a) (0x10 + a) #define AUDIO_CTL_GETCAPS _AUDIO_CTL(1) #define AUDIO_CTL_CONFIGURE _AUDIO_CTL(2) -#define AUDIO_CTL_SHUTDOWN _AUDIO_CTL(3) -#define AUDIO_CTL_START _AUDIO_CTL(4) -#define AUDIO_CTL_STOP _AUDIO_CTL(5) -#define AUDIO_CTL_PAUSE _AUDIO_CTL(6) -#define AUDIO_CTL_RESUME _AUDIO_CTL(7) -#define AUDIO_CTL_GETBUFFERINFO _AUDIO_CTL(8) -#define AUDIO_CTL_ALLOCBUFFER _AUDIO_CTL(9) -#define AUDIO_CTL_FREEBUFFER _AUDIO_CTL(10) -#define AUDIO_CTL_HWRESET _AUDIO_CTL(11) - +#define AUDIO_CTL_START _AUDIO_CTL(3) +#define AUDIO_CTL_STOP _AUDIO_CTL(4) +#define AUDIO_CTL_GETBUFFERINFO _AUDIO_CTL(5) /* Audio Device Types */ #define AUDIO_TYPE_QUERY 0x00 #define AUDIO_TYPE_INPUT 0x01 #define AUDIO_TYPE_OUTPUT 0x02 #define AUDIO_TYPE_MIXER 0x04 -#define AUDIO_TYPE_SELECTOR 0x08 -#define AUDIO_TYPE_EFFECT 0x10 - -/* Audio Format Types */ -#define AUDIO_FMT_PCM_U8 0x0001 -#define AUDIO_FMT_PCM_S8 0x0002 - -#define AUDIO_FMT_PCM_U16_LE 0x0010 -#define AUDIO_FMT_PCM_S16_BE 0x0020 -#define AUDIO_FMT_PCM_S16_LE 0x0040 -#define AUDIO_FMT_PCM_U16_BE 0x0080 -#define AUDIO_FMT_PCM_U24_LE 0x0100 -#define AUDIO_FMT_PCM_S24_BE 0x0200 -#define AUDIO_FMT_PCM_S24_LE 0x0400 -#define AUDIO_FMT_PCM_U24_BE 0x0800 -#define AUDIO_FMT_PCM_U32_LE 0x1000 -#define AUDIO_FMT_PCM_S32_BE 0x2000 -#define AUDIO_FMT_PCM_S32_LE 0x4000 -#define AUDIO_FMT_PCM_U32_BE 0x8000 /* Supported Sampling Rates */ #define AUDIO_SAMP_RATE_8K 0x0001 @@ -76,13 +54,11 @@ #define AUDIO_BIT_RATE_172K 0x40 #define AUDIO_BIT_RATE_192K 0x80 - - /* Support Dsp(input/output) Units controls */ #define AUDIO_DSP_PARAM 0 /* get/set all params */ -#define AUDIO_DSP_SAMPLERATE 1 /* é‡‡æ ·é¢‘çŽ‡ */ -#define AUDIO_DSP_FMT 2 -#define AUDIO_DSP_CHANNELS 3 +#define AUDIO_DSP_SAMPLERATE 1 /* samplerate */ +#define AUDIO_DSP_CHANNELS 2 /* channels */ +#define AUDIO_DSP_SAMPLEBITS 3 /* sample bits width */ /* Supported Mixer Units controls */ #define AUDIO_MIXER_QUERY 0x0000 @@ -95,15 +71,13 @@ #define AUDIO_MIXER_LINE 0x0040 #define AUDIO_MIXER_DIGITAL 0x0080 #define AUDIO_MIXER_MIC 0x0100 +#define AUDIO_MIXER_VITURAL 0x0200 +#define AUDIO_MIXER_EXTEND 0x8000 /* extend mixer command */ -#define AUDIO_MIXER_EXTEND 0x8000 //extend mixer command +#define AUDIO_VOLUME_MAX (100) +#define AUDIO_VOLUME_MIN (0) #define CFG_AUDIO_REPLAY_QUEUE_COUNT 4 -#define CFG_AUDIO_RECORD_PIPE_SIZE (8 * 1024) -#define AUDIO_DEVICE_MP_CNT (4) -#define AUDIO_DEVICE_DECODE_MP_BLOCK_SZ (4352 * 4) -#define AUDIO_DEVICE_DECODE_MP_SZ ((AUDIO_DEVICE_DECODE_MP_BLOCK_SZ*2 + 4)*AUDIO_DEVICE_MP_CNT) - enum { @@ -115,19 +89,10 @@ enum /* the preferred number and size of audio pipeline buffer for the audio device */ struct rt_audio_buf_info { - rt_uint32_t buffer_size; /* Preferred qty of buffers */ - rt_uint32_t buffer_count; /* Preferred size of the buffers */ -}; -struct rt_audio_buf_desc -{ - rt_uint8_t *data_ptr; - rt_size_t data_size; -}; - -struct rt_audio_frame -{ - const void *data_ptr; - rt_size_t data_size; + rt_uint8_t *buffer; + rt_uint16_t block_size; + rt_uint16_t block_count; + rt_uint32_t total_size; }; struct rt_audio_device; @@ -135,73 +100,68 @@ struct rt_audio_caps; struct rt_audio_configure; struct rt_audio_ops { - rt_err_t (*getcaps) (struct rt_audio_device *audio,struct rt_audio_caps *caps); - rt_err_t (*configure) (struct rt_audio_device *audio,struct rt_audio_caps *caps); - - rt_err_t (*init) (struct rt_audio_device *audio); - rt_err_t (*shutdown) (struct rt_audio_device *audio); - rt_err_t (*start) (struct rt_audio_device *audio,int stream); - rt_err_t (*stop) (struct rt_audio_device *audio,int stream); - rt_err_t (*suspend) (struct rt_audio_device *audio,int stream); - rt_err_t (*resume) (struct rt_audio_device *audio,int stream); - - rt_err_t (*control) (struct rt_audio_device *audio, int cmd, void *arg); - rt_size_t (*transmit) (struct rt_audio_device *audio, const void *writeBuf,void *readBuf, rt_size_t size); - - //get page size of codec or private buffer's info - void (*buffer_info) (struct rt_audio_device *audio,struct rt_audio_buf_info *info ); + rt_err_t (*getcaps)(struct rt_audio_device *audio, struct rt_audio_caps *caps); + rt_err_t (*configure)(struct rt_audio_device *audio, struct rt_audio_caps *caps); + rt_err_t (*init)(struct rt_audio_device *audio); + rt_err_t (*start)(struct rt_audio_device *audio, int stream); + rt_err_t (*stop)(struct rt_audio_device *audio, int stream); + rt_size_t (*transmit)(struct rt_audio_device *audio, const void *writeBuf, void *readBuf, rt_size_t size); + /* get page size of codec or private buffer's info */ + void (*buffer_info)(struct rt_audio_device *audio, struct rt_audio_buf_info *info); }; - struct rt_audio_configure { - rt_uint32_t channels; - - rt_uint32_t samplefmt; rt_uint32_t samplerate; - rt_uint32_t samplefmts; + rt_uint16_t channels; + rt_uint16_t samplebits; }; struct rt_audio_caps { - int main_type; - int sub_type; + int main_type; + int sub_type; - union - { - rt_uint32_t mask; - int value; - struct rt_audio_configure config; - }udata; + union + { + rt_uint32_t mask; + int value; + struct rt_audio_configure config; + } udata; }; struct rt_audio_replay { - rt_bool_t activated; + struct rt_mempool *mp; struct rt_data_queue queue; + struct rt_mutex lock; + struct rt_completion cmp; + struct rt_audio_buf_info buf_info; + rt_uint8_t *write_data; + rt_uint16_t write_index; + rt_uint16_t read_index; + rt_uint32_t pos; + rt_uint8_t event; + rt_bool_t activated; }; struct rt_audio_record { + struct rt_audio_pipe pipe; rt_bool_t activated; }; struct rt_audio_device { - struct rt_device parent; + struct rt_device parent; struct rt_audio_ops *ops; - - struct rt_mempool mp; - struct rt_audio_replay *replay; struct rt_audio_record *record; }; -rt_err_t rt_audio_register (struct rt_audio_device *audio, const char *name, rt_uint32_t flag, void *data); -void rt_audio_tx_complete (struct rt_audio_device *audio,rt_uint8_t *pbuf); -void rt_audio_rx_done (struct rt_audio_device *audio,rt_uint8_t *pbuf,rt_size_t len); -rt_uint32_t rt_audio_format_to_bits (rt_uint32_t format); - +rt_err_t rt_audio_register(struct rt_audio_device *audio, const char *name, rt_uint32_t flag, void *data); +void rt_audio_tx_complete(struct rt_audio_device *audio); +void rt_audio_rx_done(struct rt_audio_device *audio, rt_uint8_t *pbuf, rt_size_t len); /* Device Control Commands */ #define CODEC_CMD_RESET 0 diff --git a/components/drivers/include/drivers/can.h b/components/drivers/include/drivers/can.h index c61fb19eaa..d4fcc845b4 100644 --- a/components/drivers/include/drivers/can.h +++ b/components/drivers/include/drivers/can.h @@ -221,7 +221,7 @@ struct rt_can_msg rt_uint32_t rsv : 1; rt_uint32_t len : 8; rt_uint32_t priv : 8; - rt_uint32_t hdr : 8; + rt_int32_t hdr : 8; rt_uint32_t reserved : 8; rt_uint8_t data[8]; }; @@ -252,7 +252,7 @@ struct rt_can_rx_fifo #define RT_CAN_EVENT_RX_IND 0x01 /* Rx indication */ #define RT_CAN_EVENT_TX_DONE 0x02 /* Tx complete */ -#define RT_CAN_EVENT_TX_FAIL 0x03 /* Tx complete */ +#define RT_CAN_EVENT_TX_FAIL 0x03 /* Tx fail */ #define RT_CAN_EVENT_RX_TIMEOUT 0x05 /* Rx timeout */ #define RT_CAN_EVENT_RXOF_IND 0x06 /* Rx overflow */ @@ -278,7 +278,7 @@ struct rt_can_ops int (*recvmsg)(struct rt_can_device *can, void *buf, rt_uint32_t boxno); }; -rt_err_t rt_hw_can_register(struct rt_can_device *can, +rt_err_t rt_hw_can_register(struct rt_can_device *can, const char *name, const struct rt_can_ops *ops, void *data); diff --git a/components/drivers/include/drivers/crypto.h b/components/drivers/include/drivers/crypto.h new file mode 100644 index 0000000000..5341d9ee48 --- /dev/null +++ b/components/drivers/include/drivers/crypto.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-05-17 tyx the first version + */ + +#ifndef __CRYPTO_H__ +#define __CRYPTO_H__ + +#include <rtthread.h> +#include <hwcrypto.h> +#include <hw_symmetric.h> +#include <hw_rng.h> +#include <hw_hash.h> +#include <hw_crc.h> +#include <hw_gcm.h> +#include <hw_bignum.h> + +#endif diff --git a/components/drivers/include/drivers/i2c.h b/components/drivers/include/drivers/i2c.h index e2a9e7d0b8..17d57288cd 100644 --- a/components/drivers/include/drivers/i2c.h +++ b/components/drivers/include/drivers/i2c.h @@ -60,11 +60,12 @@ struct rt_i2c_bus_device void *priv; }; -#ifdef RT_I2C_DEBUG -#define i2c_dbg(fmt, ...) rt_kprintf(fmt, ##__VA_ARGS__) -#else -#define i2c_dbg(fmt, ...) -#endif +struct rt_i2c_client +{ + struct rt_device parent; + struct rt_i2c_bus_device *bus; + rt_uint16_t client_addr; +}; rt_err_t rt_i2c_bus_device_register(struct rt_i2c_bus_device *bus, const char *bus_name); diff --git a/components/drivers/include/drivers/mtd.h b/components/drivers/include/drivers/mtd.h deleted file mode 100644 index fb7ea4389d..0000000000 --- a/components/drivers/include/drivers/mtd.h +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (c) 2006-2018, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - 2018-09-10 heyuanjie87 first version - - */ - -#ifndef __MTD_H__ -#define __MTD_H__ - -#include <rtthread.h> -#include <stddef.h> -#include <stdint.h> - -#define MTD_TYPE_NOR 1 -#define MTD_TYPE_NAND 2 - - /** - * MTD operation modes - * - * @MTD_OPM_PLACE_OOB: OOB data are placed at the given offset (default) - * @MTD_OPM_AUTO_OOB: OOB data are automatically placed at the free areas - * @MTD_OPM_RAW: data are transferred as-is, with no error correction; - */ -enum mtd_opm -{ - MTD_OPM_PLACE_OOB = 0, - MTD_OPM_AUTO_OOB = 1, - MTD_OPM_RAW = 2, -}; - -#ifndef loff_t -typedef long loff_t; -#endif - -struct mtd_oob_region -{ - uint8_t offset; - uint8_t length; -}; - -typedef struct mtd_info -{ - struct rt_device parent; - - const struct mtd_ops *ops; - - uint16_t oob_size; - uint16_t sector_size; /* Minimal writable flash unit size */ - uint32_t block_size:28; /* Erase size for the device */ - uint32_t type:4; - - size_t size; /* Total size of the MTD */ - loff_t offset; /* At which this MTD starts, from the beginning of the MEMORY */ - struct mtd_info *master; - - void *priv; -}rt_mtd_t; - -struct mtd_io_desc -{ - uint8_t mode; /* operation mode(enum mtd_opm) */ - uint8_t ooblen; /* number of oob bytes to write/read */ - uint8_t oobretlen; /* number of oob bytes written/read */ - uint8_t ooboffs; /* offset in the oob area */ - uint8_t *oobbuf; - - size_t datlen; /* number of data bytes to write/read */ - size_t datretlen; /* number of data bytes written/read */ - uint8_t *datbuf; /* if NULL only oob are read/written */ -}; - -struct mtd_ops -{ - int(*erase)(rt_mtd_t *mtd, loff_t addr, size_t len); /* return 0 if success */ - int(*read) (rt_mtd_t *mtd, loff_t from, struct mtd_io_desc *ops); /* return 0 if success */ - int(*write) (rt_mtd_t *mtd, loff_t to, struct mtd_io_desc *ops); /* return 0 if success */ - int(*isbad) (rt_mtd_t *mtd, uint32_t block); /* return 1 if bad, 0 not bad */ - int(*markbad) (rt_mtd_t *mtd, uint32_t block); /* return 0 if success */ -}; - -struct mtd_part -{ - const char *name; /* name of the MTD partion */ - loff_t offset; /* start addr of partion */ - size_t size; /* size of partion */ -}; - -int rt_mtd_erase(rt_mtd_t *mtd, loff_t addr, size_t size); -int rt_mtd_block_erase(rt_mtd_t *mtd, uint32_t block); -int rt_mtd_read_oob(rt_mtd_t *mtd, loff_t from, struct mtd_io_desc *desc); -int rt_mtd_write_oob(rt_mtd_t *mtd, loff_t to, struct mtd_io_desc *desc); -int rt_mtd_read(rt_mtd_t *mtd, loff_t from, uint8_t *buf, size_t len); -int rt_mtd_write(rt_mtd_t *mtd, loff_t to, const uint8_t *buf, size_t len); -int rt_mtd_block_markbad(rt_mtd_t *mtd, uint32_t block); -int rt_mtd_block_isbad(rt_mtd_t *mtd, uint32_t block); - -rt_mtd_t* rt_mtd_get(const char *name); -int rt_mtd_register(rt_mtd_t *master, const struct mtd_part *parts, int np); - -#endif diff --git a/components/drivers/include/drivers/mtd_nand.h b/components/drivers/include/drivers/mtd_nand.h index 8afed000dd..f7675aede6 100644 --- a/components/drivers/include/drivers/mtd_nand.h +++ b/components/drivers/include/drivers/mtd_nand.h @@ -21,13 +21,13 @@ struct rt_mtd_nand_driver_ops; #define RT_MTD_NAND_DEVICE(device) ((struct rt_mtd_nand_device*)(device)) -#define RT_MTD_EOK 0 /* NO error */ -#define RT_MTD_EECC 1 /* ECC error */ -#define RT_MTD_EBUSY 2 /* hardware busy */ -#define RT_MTD_EIO 3 /* generic IO issue */ -#define RT_MTD_ENOMEM 4 /* out of memory */ -#define RT_MTD_ESRC 5 /* source issue */ -#define RT_MTD_EECC_CORRECT 6 /* ECC error but correct */ +#define RT_MTD_EOK 0 /* NO error */ +#define RT_MTD_EECC 101 /* ECC error */ +#define RT_MTD_EBUSY 102 /* hardware busy */ +#define RT_MTD_EIO 103 /* generic IO issue */ +#define RT_MTD_ENOMEM 104 /* out of memory */ +#define RT_MTD_ESRC 105 /* source issue */ +#define RT_MTD_EECC_CORRECT 106 /* ECC error but correct */ struct rt_mtd_nand_device { @@ -41,77 +41,97 @@ struct rt_mtd_nand_device rt_uint32_t pages_per_block; /* The number of page a block */ rt_uint16_t block_total; + /* Only be touched by driver */ rt_uint32_t block_start; /* The start of available block*/ rt_uint32_t block_end; /* The end of available block */ /* operations interface */ - const struct rt_mtd_nand_driver_ops* ops; + const struct rt_mtd_nand_driver_ops *ops; }; struct rt_mtd_nand_driver_ops { - rt_err_t (*read_id) (struct rt_mtd_nand_device* device); + rt_err_t (*read_id)(struct rt_mtd_nand_device *device); - rt_err_t (*read_page)(struct rt_mtd_nand_device* device, + rt_err_t (*read_page)(struct rt_mtd_nand_device *device, rt_off_t page, - rt_uint8_t* data, rt_uint32_t data_len, - rt_uint8_t * spare, rt_uint32_t spare_len); + rt_uint8_t *data, rt_uint32_t data_len, + rt_uint8_t *spare, rt_uint32_t spare_len); - rt_err_t (*write_page)(struct rt_mtd_nand_device * device, + rt_err_t (*write_page)(struct rt_mtd_nand_device *device, rt_off_t page, - const rt_uint8_t * data, rt_uint32_t data_len, - const rt_uint8_t * spare, rt_uint32_t spare_len); - rt_err_t (*move_page) (struct rt_mtd_nand_device *device, rt_off_t src_page, rt_off_t dst_page); + const rt_uint8_t *data, rt_uint32_t data_len, + const rt_uint8_t *spare, rt_uint32_t spare_len); + rt_err_t (*move_page)(struct rt_mtd_nand_device *device, rt_off_t src_page, rt_off_t dst_page); - rt_err_t (*erase_block)(struct rt_mtd_nand_device* device, rt_uint32_t block); - rt_err_t (*check_block)(struct rt_mtd_nand_device* device, rt_uint32_t block); - rt_err_t (*mark_badblock)(struct rt_mtd_nand_device* device, rt_uint32_t block); + rt_err_t (*erase_block)(struct rt_mtd_nand_device *device, rt_uint32_t block); + rt_err_t (*check_block)(struct rt_mtd_nand_device *device, rt_uint32_t block); + rt_err_t (*mark_badblock)(struct rt_mtd_nand_device *device, rt_uint32_t block); }; -rt_err_t rt_mtd_nand_register_device(const char* name, struct rt_mtd_nand_device* device); +rt_err_t rt_mtd_nand_register_device(const char *name, struct rt_mtd_nand_device *device); -rt_inline rt_uint32_t rt_mtd_nand_read_id(struct rt_mtd_nand_device* device) +rt_inline rt_uint32_t rt_mtd_nand_read_id(struct rt_mtd_nand_device *device) { + RT_ASSERT(device->ops->read_id); return device->ops->read_id(device); } rt_inline rt_err_t rt_mtd_nand_read( - struct rt_mtd_nand_device* device, + struct rt_mtd_nand_device *device, rt_off_t page, - rt_uint8_t* data, rt_uint32_t data_len, - rt_uint8_t * spare, rt_uint32_t spare_len) + rt_uint8_t *data, rt_uint32_t data_len, + rt_uint8_t *spare, rt_uint32_t spare_len) { + RT_ASSERT(device->ops->read_page); return device->ops->read_page(device, page, data, data_len, spare, spare_len); } rt_inline rt_err_t rt_mtd_nand_write( - struct rt_mtd_nand_device* device, + struct rt_mtd_nand_device *device, rt_off_t page, - const rt_uint8_t* data, rt_uint32_t data_len, - const rt_uint8_t * spare, rt_uint32_t spare_len) + const rt_uint8_t *data, rt_uint32_t data_len, + const rt_uint8_t *spare, rt_uint32_t spare_len) { + RT_ASSERT(device->ops->write_page); return device->ops->write_page(device, page, data, data_len, spare, spare_len); } -rt_inline rt_err_t rt_mtd_nand_move_page(struct rt_mtd_nand_device* device, - rt_off_t src_page, rt_off_t dst_page) +rt_inline rt_err_t rt_mtd_nand_move_page(struct rt_mtd_nand_device *device, + rt_off_t src_page, rt_off_t dst_page) { + RT_ASSERT(device->ops->move_page); return device->ops->move_page(device, src_page, dst_page); } -rt_inline rt_err_t rt_mtd_nand_erase_block(struct rt_mtd_nand_device* device, rt_uint32_t block) +rt_inline rt_err_t rt_mtd_nand_erase_block(struct rt_mtd_nand_device *device, rt_uint32_t block) { + RT_ASSERT(device->ops->erase_block); return device->ops->erase_block(device, block); } -rt_inline rt_err_t rt_mtd_nand_check_block(struct rt_mtd_nand_device* device, rt_uint32_t block) +rt_inline rt_err_t rt_mtd_nand_check_block(struct rt_mtd_nand_device *device, rt_uint32_t block) { - return device->ops->check_block(device, block); + if (device->ops->check_block) + { + return device->ops->check_block(device, block); + } + else + { + return -RT_ENOSYS; + } } -rt_inline rt_err_t rt_mtd_nand_mark_badblock(struct rt_mtd_nand_device* device, rt_uint32_t block) +rt_inline rt_err_t rt_mtd_nand_mark_badblock(struct rt_mtd_nand_device *device, rt_uint32_t block) { - return device->ops->mark_badblock(device, block); + if (device->ops->mark_badblock) + { + return device->ops->mark_badblock(device, block); + } + else + { + return -RT_ENOSYS; + } } #endif /* MTD_NAND_H_ */ diff --git a/components/drivers/include/drivers/mtdnand.h b/components/drivers/include/drivers/mtdnand.h deleted file mode 100644 index 2e836cb2fb..0000000000 --- a/components/drivers/include/drivers/mtdnand.h +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (c) 2006-2018, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - 2018-09-10 heyuanjie87 first version - - */ - -#ifndef _MTDNAND_H_ -#define _MTDNAND_H_ - -#include "mtd.h" - - /* Status bits */ -#define NAND_STATUS_FAIL 0x01 -#define NAND_STATUS_FAIL_N1 0x02 -#define NAND_STATUS_WP 0x80 - -typedef enum -{ - NAND_CMD_PAGE_RD, /* read data to chip's page buffer,do WaitBusy after this cmd in low driver */ - NAND_CMD_PAGE_WR0, /* write data to chip's page buffer */ - NAND_CMD_PAGE_WR1, /* do flash programe */ - NAND_CMD_BLK_ERASE, /* erase block */ - NAND_CMD_ECC_EN, /* enable gen HWECC */ - NAND_CMD_ECC_DIS /* disable gen HWECC */ -} nand_cmd_t; - -typedef enum -{ - NAND_ECCM_NONE, - NAND_ECCM_HW, -} nand_eccmode_t; - -struct nand_chip; -struct nand_ops; - -/** -* struct nand_buffers - buffer structure for read/write -* @ecccalc: buffer pointer for calculated ECC, size is oobsize. -* @ecccode: buffer pointer for ECC read from flash, size is oobsize. -* -*/ -struct nand_buffers -{ - uint8_t *ecccalc; - uint8_t *ecccode; -}; - -struct nand_ecc -{ - uint8_t mode; /* nand_eccmode_t */ - uint8_t bytes; /* gen ecc bytes per ecc step(usually 3) */ - uint16_t stepsize:12; /* min 256 */ - uint16_t _step:4; /* */ - - /* driver must set the two interface if HWECC */ - void (*calculate)(struct nand_chip *chip, const uint8_t *dat, uint8_t *ecc_code); - /* return max bit flips if can't correct,return -1 ECC is error(0 success) */ - int(*correct)(struct nand_chip *chip, uint8_t *dat, uint8_t *read_ecc, uint8_t *calc_ecc); - /* ignore if NONECC */ - const struct mtd_oob_region *layout; -}; - -typedef struct nand_chip -{ - rt_mtd_t parent; - - /* driver must init these */ - const struct nand_ops *ops; - struct nand_ecc ecc; - const struct mtd_oob_region *freelayout; - - /* driver do not touch */ - struct nand_buffers buffers; - uint8_t *oob_poi; - uint8_t *pagebuf; - uint32_t size; - uint16_t oobsize; - uint8_t pages_pb; - uint16_t page_size; - int(*read_page)(struct nand_chip *chip, uint8_t *buf, int oob_required, int page); - int(*write_page)(struct nand_chip *chip, const uint8_t *buf, int oob_required, int page); -}rt_nand_t; - -struct nand_ops -{ - int(*cmdfunc)(rt_nand_t *nand, int cmd, int page, int offset); /* send nand operation cmd, return Status bits(0 success), - if nand is busy please wait in low driver */ - int(*read_buf)(rt_nand_t *nand, uint8_t *buf, int len); /* read data from nand chip's page buffer */ - int(*write_buf)(rt_nand_t *nand, const uint8_t *buf, int len);/* write data to nand chip's page buffer */ - int(*isbad)(rt_nand_t *nand, uint32_t blk); /* if NULL OOB[0] used as bad mark(not 0xff is bad) */ - int(*markbad)(rt_nand_t *nand, uint32_t blk); /* if NULL OOB[0] used as bad mark(set to 0x00) */ -}; - -int rt_mtd_nand_init(rt_nand_t *nand, int blk_size, int page_size, int oob_size); - -#endif /* MTD_NAND_H_ */ diff --git a/components/drivers/include/drivers/mtdnor.h b/components/drivers/include/drivers/mtdnor.h deleted file mode 100644 index ccb7466b4b..0000000000 --- a/components/drivers/include/drivers/mtdnor.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2006-2018, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - 2018-09-10 heyuanjie87 first version - - */ - -#ifndef __MTDNOR_H__ -#define __MTDNOR_H__ - -#include <drivers/mtd.h> - -struct nor_ops; - -typedef struct -{ - rt_mtd_t parent; - - const struct nor_ops *ops; /* operations interface */ -}rt_nor_t; - -struct nor_ops -{ - int (*erase)(rt_nor_t *nor, loff_t addr, size_t len); /* return success erased len or error code */ - int (*read)(rt_nor_t *nor, loff_t addr, uint8_t *buf, size_t len); /* return success data size or error code */ - int (*write)(rt_nor_t *nor, loff_t addr, const uint8_t *buf, size_t len); /* return success data size or error code */ -}; - -int rt_mtd_nor_init(rt_nor_t *nor, int blksize); - -#endif diff --git a/components/drivers/include/drivers/pm.h b/components/drivers/include/drivers/pm.h index e35b21cd48..dd5875aa1d 100644 --- a/components/drivers/include/drivers/pm.h +++ b/components/drivers/include/drivers/pm.h @@ -86,8 +86,8 @@ struct rt_pm; */ struct rt_pm_ops { - void (*sleep)(struct rt_pm *pm, uint8_t mode); - void (*run)(struct rt_pm *pm, uint8_t mode); + void (*sleep)(struct rt_pm *pm, rt_uint8_t mode); + void (*run)(struct rt_pm *pm, rt_uint8_t mode); void (*timer_start)(struct rt_pm *pm, rt_uint32_t timeout); void (*timer_stop)(struct rt_pm *pm); rt_tick_t (*timer_get_tick)(struct rt_pm *pm); @@ -95,9 +95,9 @@ struct rt_pm_ops struct rt_device_pm_ops { - int (*suspend)(const struct rt_device *device, uint8_t mode); - void (*resume)(const struct rt_device *device, uint8_t mode); - int (*frequency_change)(const struct rt_device *device, uint8_t mode); + int (*suspend)(const struct rt_device *device, rt_uint8_t mode); + void (*resume)(const struct rt_device *device, rt_uint8_t mode); + int (*frequency_change)(const struct rt_device *device, rt_uint8_t mode); }; struct rt_device_pm @@ -137,22 +137,22 @@ enum struct rt_pm_notify { - void (*notify)(uint8_t event, uint8_t mode, void *data); + void (*notify)(rt_uint8_t event, rt_uint8_t mode, void *data); void *data; }; -void rt_pm_request(uint8_t sleep_mode); -void rt_pm_release(uint8_t sleep_mode); -int rt_pm_run_enter(uint8_t run_mode); +void rt_pm_request(rt_uint8_t sleep_mode); +void rt_pm_release(rt_uint8_t sleep_mode); +int rt_pm_run_enter(rt_uint8_t run_mode); void rt_pm_device_register(struct rt_device *device, const struct rt_device_pm_ops *ops); void rt_pm_device_unregister(struct rt_device *device); -void rt_pm_notify_set(void (*notify)(uint8_t event, uint8_t mode, void *data), void *data); -void rt_pm_default_set(uint8_t sleep_mode); +void rt_pm_notify_set(void (*notify)(rt_uint8_t event, rt_uint8_t mode, void *data), void *data); +void rt_pm_default_set(rt_uint8_t sleep_mode); void rt_system_pm_init(const struct rt_pm_ops *ops, - uint8_t timer_mask, + rt_uint8_t timer_mask, void *user_data); #endif /* __PM_H__ */ diff --git a/components/drivers/include/drivers/pulse_encoder.h b/components/drivers/include/drivers/pulse_encoder.h new file mode 100644 index 0000000000..0c7df04cd6 --- /dev/null +++ b/components/drivers/include/drivers/pulse_encoder.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-08-08 balanceTWK the first version + */ + +#ifndef __PULSE_ENCODER_H__ +#define __PULSE_ENCODER_H__ + +#include <rtthread.h> +#include <rtdevice.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* pulse_encoder control command */ +#define PULSE_ENCODER_CMD_GET_TYPE (128 + 0) /* get a pulse_encoder type information */ +#define PULSE_ENCODER_CMD_ENABLE (128 + 1) /* enable pulse_encoder */ +#define PULSE_ENCODER_CMD_DISABLE (128 + 2) /* disable pulse_encoder */ +#define PULSE_ENCODER_CMD_CLEAR_COUNT (128 + 3) /* clear pulse_encoder count */ + +/* pulse_encoder type */ +enum rt_pulse_encoder_type +{ + UNKNOWN_PULSE_ENCODER_TYPE = 0x00, /* Unknown pulse_encoder type */ + SINGLE_PHASE_PULSE_ENCODER, /* single phase pulse_encoder */ + AB_PHASE_PULSE_ENCODER /* two phase pulse_encoder */ +}; + +struct rt_pulse_encoder_device; + +struct rt_pulse_encoder_ops +{ + rt_err_t (*init)(struct rt_pulse_encoder_device *pulse_encoder); + rt_int32_t (*get_count)(struct rt_pulse_encoder_device *pulse_encoder); + rt_err_t (*clear_count)(struct rt_pulse_encoder_device *pulse_encoder); + rt_err_t (*control)(struct rt_pulse_encoder_device *pulse_encoder, rt_uint32_t cmd, void *args); +}; + +struct rt_pulse_encoder_device +{ + struct rt_device parent; + const struct rt_pulse_encoder_ops *ops; + enum rt_pulse_encoder_type type; +}; + +rt_err_t rt_device_pulse_encoder_register(struct rt_pulse_encoder_device *pulse_encoder, const char *name, void *user_data); + +#ifdef __cplusplus +} +#endif + +#endif /* __PULSE_ENCODER_H__ */ diff --git a/components/drivers/include/drivers/rt_inputcapture.h b/components/drivers/include/drivers/rt_inputcapture.h new file mode 100644 index 0000000000..0cadf6444c --- /dev/null +++ b/components/drivers/include/drivers/rt_inputcapture.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-08-13 balanceTWK first version. + */ + +#ifndef __RT_INPUT_CAPTURE_H__ +#define __RT_INPUT_CAPTURE_H__ + +#include <rtthread.h> +#include <rtdevice.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* capture control command */ +#define INPUTCAPTURE_CMD_CLEAR_BUF (128 + 0) /* clear capture buf */ +#define INPUTCAPTURE_CMD_SET_WATERMARK (128 + 1) /* Set the callback threshold */ + +struct rt_inputcapture_data +{ + rt_uint32_t pulsewidth_us; + rt_bool_t is_high; +}; + +struct rt_inputcapture_device +{ + struct rt_device parent; + + const struct rt_inputcapture_ops *ops; + struct rt_ringbuffer *ringbuff; + rt_size_t watermark; +}; + +/** + * capture operators + */ +struct rt_inputcapture_ops +{ + rt_err_t (*init)(struct rt_inputcapture_device *inputcapture); + rt_err_t (*open)(struct rt_inputcapture_device *inputcapture); + rt_err_t (*close)(struct rt_inputcapture_device *inputcapture); + rt_err_t (*get_pulsewidth)(struct rt_inputcapture_device *inputcapture, rt_uint32_t *pulsewidth_us); +}; + +void rt_hw_capture_isr(struct rt_inputcapture_device *inputcapture, rt_bool_t level); + +rt_err_t rt_device_inputcapture_register(struct rt_inputcapture_device *inputcapture, + const char *name, + void *data); +#ifdef __cplusplus +} +#endif + +#endif /* __RT_INPUT_CAPTURE_H__ */ diff --git a/components/drivers/include/ipc/workqueue.h b/components/drivers/include/ipc/workqueue.h index 354a30c04e..23e256c420 100644 --- a/components/drivers/include/ipc/workqueue.h +++ b/components/drivers/include/ipc/workqueue.h @@ -43,13 +43,13 @@ struct rt_work void *work_data; rt_uint16_t flags; rt_uint16_t type; + struct rt_timer timer; + struct rt_workqueue *workqueue; }; struct rt_delayed_work { struct rt_work work; - struct rt_timer timer; - struct rt_workqueue *workqueue; }; #ifdef RT_USING_HEAP @@ -74,6 +74,7 @@ rt_inline void rt_work_init(struct rt_work *work, void (*work_func)(struct rt_wo rt_list_init(&(work->list)); work->work_func = work_func; work->work_data = work_data; + work->workqueue = RT_NULL; work->flags = 0; work->type = 0; } @@ -81,6 +82,7 @@ rt_inline void rt_work_init(struct rt_work *work, void (*work_func)(struct rt_wo void rt_delayed_work_init(struct rt_delayed_work *work, void (*work_func)(struct rt_work *work, void *work_data), void *work_data); +int rt_work_sys_workqueue_init(void); #endif #endif diff --git a/components/drivers/include/rtdevice.h b/components/drivers/include/rtdevice.h index d59b40cc47..623c085430 100644 --- a/components/drivers/include/rtdevice.h +++ b/components/drivers/include/rtdevice.h @@ -122,6 +122,18 @@ extern "C" { #include "drivers/mtdnand.h" #endif +#ifdef RT_USING_HWCRYPTO +#include "drivers/crypto.h" +#endif + +#ifdef RT_USING_PULSE_ENCODER +#include "drivers/pulse_encoder.h" +#endif + +#ifdef RT_USING_INPUT_CAPTURE +#include "drivers/rt_inputcapture.h" +#endif + #ifdef __cplusplus } #endif diff --git a/components/drivers/misc/SConscript b/components/drivers/misc/SConscript index c45ba524c5..8a9fdb5eb9 100644 --- a/components/drivers/misc/SConscript +++ b/components/drivers/misc/SConscript @@ -13,6 +13,12 @@ if GetDepend(['RT_USING_ADC']): if GetDepend(['RT_USING_PWM']): src = src + ['rt_drv_pwm.c'] + +if GetDepend(['RT_USING_PULSE_ENCODER']): + src = src + ['pulse_encoder.c'] + +if GetDepend(['RT_USING_INPUT_CAPTURE']): + src = src + ['rt_inputcapture.c'] if len(src): group = DefineGroup('DeviceDrivers', src, depend = [''], CPPPATH = CPPPATH) diff --git a/components/drivers/misc/pulse_encoder.c b/components/drivers/misc/pulse_encoder.c new file mode 100644 index 0000000000..3145c24675 --- /dev/null +++ b/components/drivers/misc/pulse_encoder.c @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-08-08 balanceTWK the first version + */ + +#include <rtthread.h> +#include <rtdevice.h> + +static rt_err_t rt_pulse_encoder_init(struct rt_device *dev) +{ + struct rt_pulse_encoder_device *pulse_encoder; + + pulse_encoder = (struct rt_pulse_encoder_device *)dev; + if (pulse_encoder->ops->init) + { + return pulse_encoder->ops->init(pulse_encoder); + } + else + { + return -RT_ENOSYS; + } +} + +static rt_err_t rt_pulse_encoder_open(struct rt_device *dev, rt_uint16_t oflag) +{ + struct rt_pulse_encoder_device *pulse_encoder; + + pulse_encoder = (struct rt_pulse_encoder_device *)dev; + if (pulse_encoder->ops->control) + { + return pulse_encoder->ops->control(pulse_encoder, PULSE_ENCODER_CMD_ENABLE, RT_NULL); + } + else + { + return -RT_ENOSYS; + } +} + +static rt_err_t rt_pulse_encoder_close(struct rt_device *dev) +{ + struct rt_pulse_encoder_device *pulse_encoder; + + pulse_encoder = (struct rt_pulse_encoder_device *)dev; + if (pulse_encoder->ops->control) + { + return pulse_encoder->ops->control(pulse_encoder, PULSE_ENCODER_CMD_DISABLE, RT_NULL); + } + else + { + return -RT_ENOSYS; + } +} + +static rt_size_t rt_pulse_encoder_read(struct rt_device *dev, rt_off_t pos, void *buffer, rt_size_t size) +{ + struct rt_pulse_encoder_device *pulse_encoder; + + pulse_encoder = (struct rt_pulse_encoder_device *)dev; + if (pulse_encoder->ops->get_count) + { + *(rt_int32_t *)buffer = pulse_encoder->ops->get_count(pulse_encoder); + } + return 1; +} + +static rt_err_t rt_pulse_encoder_control(struct rt_device *dev, int cmd, void *args) +{ + rt_err_t result; + struct rt_pulse_encoder_device *pulse_encoder; + + result = RT_EOK; + pulse_encoder = (struct rt_pulse_encoder_device *)dev; + switch (cmd) + { + case PULSE_ENCODER_CMD_CLEAR_COUNT: + result = pulse_encoder->ops->clear_count(pulse_encoder); + break; + case PULSE_ENCODER_CMD_GET_TYPE: + *(enum rt_pulse_encoder_type *)args = pulse_encoder->type; + break; + case PULSE_ENCODER_CMD_ENABLE: + case PULSE_ENCODER_CMD_DISABLE: + result = pulse_encoder->ops->control(pulse_encoder, cmd, args); + break; + default: + result = -RT_ENOSYS; + break; + } + + return result; +} + +#ifdef RT_USING_DEVICE_OPS +const static struct rt_device_ops pulse_encoder_ops = +{ + rt_pulse_encoder_init, + rt_pulse_encoder_open, + rt_pulse_encoder_close, + rt_pulse_encoder_read, + RT_NULL, + rt_pulse_encoder_control +}; +#endif + +rt_err_t rt_device_pulse_encoder_register(struct rt_pulse_encoder_device *pulse_encoder, const char *name, void *user_data) +{ + struct rt_device *device; + + RT_ASSERT(pulse_encoder != RT_NULL); + RT_ASSERT(pulse_encoder->ops != RT_NULL); + + device = &(pulse_encoder->parent); + + device->type = RT_Device_Class_Miscellaneous; + device->rx_indicate = RT_NULL; + device->tx_complete = RT_NULL; + +#ifdef RT_USING_DEVICE_OPS + device->ops = &pulse_encoder_ops; +#else + device->init = rt_pulse_encoder_init; + device->open = rt_pulse_encoder_open; + device->close = rt_pulse_encoder_close; + device->read = rt_pulse_encoder_read; + device->write = RT_NULL; + device->control = rt_pulse_encoder_control; +#endif + device->user_data = user_data; + + return rt_device_register(device, name, RT_DEVICE_FLAG_RDONLY | RT_DEVICE_FLAG_STANDALONE); +} diff --git a/components/drivers/misc/rt_drv_pwm.c b/components/drivers/misc/rt_drv_pwm.c index 2b7986b4d8..97d38d51b3 100644 --- a/components/drivers/misc/rt_drv_pwm.c +++ b/components/drivers/misc/rt_drv_pwm.c @@ -259,7 +259,7 @@ static int pwm_set(int argc, char **argv) _exit: return result; } -MSH_CMD_EXPORT(pwm_set, pwm_set 1 100 50); +MSH_CMD_EXPORT(pwm_set, pwm_set pwm1 1 100 50); #endif /* FINSH_USING_MSH */ #endif /* RT_USING_FINSH */ diff --git a/components/drivers/misc/rt_inputcapture.c b/components/drivers/misc/rt_inputcapture.c new file mode 100644 index 0000000000..d1886186d7 --- /dev/null +++ b/components/drivers/misc/rt_inputcapture.c @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-08-13 balanceTWK the first version + */ + +#include <rtthread.h> +#include <rtdevice.h> +#include <rtdbg.h> + +static rt_err_t rt_inputcapture_init(struct rt_device *dev) +{ + rt_err_t ret; + struct rt_inputcapture_device *inputcapture; + + RT_ASSERT(dev != RT_NULL); + + ret = RT_EOK; + inputcapture = (struct rt_inputcapture_device *)dev; + inputcapture->watermark = RT_INPUT_CAPTURE_RB_SIZE / 2; + if (inputcapture->ops->init) + { + ret = inputcapture->ops->init(inputcapture); + } + + return ret; +} + +static rt_err_t rt_inputcapture_open(struct rt_device *dev, rt_uint16_t oflag) +{ + rt_err_t ret; + struct rt_inputcapture_device *inputcapture; + + RT_ASSERT(dev != RT_NULL); + + ret = RT_EOK; + inputcapture = (struct rt_inputcapture_device *)dev; + if (inputcapture->ringbuff == RT_NULL) + { + inputcapture->ringbuff = rt_ringbuffer_create(sizeof(struct rt_inputcapture_data) * RT_INPUT_CAPTURE_RB_SIZE); + } + if (inputcapture->ops->open) + { + ret = inputcapture->ops->open(inputcapture); + } + + return ret; +} + +static rt_err_t rt_inputcapture_close(struct rt_device *dev) +{ + rt_err_t ret; + struct rt_inputcapture_device *inputcapture; + + RT_ASSERT(dev != RT_NULL); + + ret = -RT_ERROR; + inputcapture = (struct rt_inputcapture_device *)dev; + + if (inputcapture->ops->close) + { + ret = inputcapture->ops->close(inputcapture); + } + + if (ret != RT_EOK) + { + return ret; + } + + if (inputcapture->ringbuff) + { + rt_ringbuffer_destroy(inputcapture->ringbuff); + inputcapture->ringbuff = RT_NULL; + } + return ret; +} + +static rt_size_t rt_inputcapture_read(struct rt_device *dev, + rt_off_t pos, + void *buffer, + rt_size_t size) +{ + rt_size_t receive_size; + struct rt_inputcapture_device *inputcapture; + + RT_ASSERT(dev != RT_NULL); + + inputcapture = (struct rt_inputcapture_device *)dev; + receive_size = rt_ringbuffer_get(inputcapture->ringbuff, (rt_uint8_t *)buffer, sizeof(struct rt_inputcapture_data) * size); + + return receive_size / sizeof(struct rt_inputcapture_data); +} + +static rt_err_t rt_inputcapture_control(struct rt_device *dev, int cmd, void *args) +{ + rt_err_t result; + struct rt_inputcapture_device *inputcapture; + + RT_ASSERT(dev != RT_NULL); + + result = RT_EOK; + inputcapture = (struct rt_inputcapture_device *)dev; + switch (cmd) + { + case INPUTCAPTURE_CMD_CLEAR_BUF: + if (inputcapture->ringbuff) + { + rt_ringbuffer_reset(inputcapture->ringbuff); + } + break; + case INPUTCAPTURE_CMD_SET_WATERMARK: + inputcapture->watermark = *(rt_size_t *)args; + break; + default: + result = -RT_ENOSYS; + break; + } + + return result; +} + +#ifdef RT_USING_DEVICE_OPS +const static struct rt_device_ops inputcapture_ops = +{ + rt_inputcapture_init, + rt_inputcapture_open, + rt_inputcapture_close, + rt_inputcapture_read, + RT_NULL, + rt_inputcapture_control +}; +#endif + +rt_err_t rt_device_inputcapture_register(struct rt_inputcapture_device *inputcapture, const char *name, void *user_data) +{ + struct rt_device *device; + + RT_ASSERT(inputcapture != RT_NULL); + RT_ASSERT(inputcapture->ops != RT_NULL); + RT_ASSERT(inputcapture->ops->get_pulsewidth != RT_NULL); + + device = &(inputcapture->parent); + + device->type = RT_Device_Class_Miscellaneous; + device->rx_indicate = RT_NULL; + device->tx_complete = RT_NULL; + inputcapture->ringbuff = RT_NULL; + +#ifdef RT_USING_DEVICE_OPS + device->ops = &inputcapture_ops; +#else + device->init = rt_inputcapture_init; + device->open = rt_inputcapture_open; + device->close = rt_inputcapture_close; + device->read = rt_inputcapture_read; + device->write = RT_NULL; + device->control = rt_inputcapture_control; +#endif + device->user_data = user_data; + + return rt_device_register(device, name, RT_DEVICE_FLAG_RDONLY | RT_DEVICE_FLAG_STANDALONE); +} + +/** + * This function is ISR for inputcapture interrupt. + * level: RT_TRUE denotes high level pulse, and RT_FALSE denotes low level pulse. + */ +void rt_hw_inputcapture_isr(struct rt_inputcapture_device *inputcapture, rt_bool_t level) +{ + struct rt_inputcapture_data data; + rt_size_t receive_size; + if (inputcapture->ops->get_pulsewidth(inputcapture, &data.pulsewidth_us) != RT_EOK) + { + return; + } + + data.is_high = level; + if (rt_ringbuffer_put(inputcapture->ringbuff, (rt_uint8_t *)&data, sizeof(struct rt_inputcapture_data)) == 0) + { + LOG_W("inputcapture ringbuffer doesn't have enough space."); + } + + receive_size = rt_ringbuffer_data_len(inputcapture->ringbuff) / sizeof(struct rt_inputcapture_data); + + if (receive_size >= inputcapture->watermark) + { + /* indicate to upper layer application */ + if (inputcapture->parent.rx_indicate != RT_NULL) + inputcapture->parent.rx_indicate(&inputcapture->parent, receive_size); + } +} diff --git a/components/drivers/mtd/SConscript b/components/drivers/mtd/SConscript index 462c38194c..6f86656187 100644 --- a/components/drivers/mtd/SConscript +++ b/components/drivers/mtd/SConscript @@ -1,5 +1,3 @@ -Import('RTT_ROOT') -Import('rtconfig') from building import * cwd = GetCurrentDir() @@ -9,17 +7,6 @@ depend = [] CPPPATH = [cwd + '/../include'] group = [] -if GetDepend(['RT_USING_MTD']): - src += ['mtd.c'] - depend += ['RT_USING_MTD'] - - if GetDepend(['MTD_USING_NOR']): - src += ['mtdnor.c'] - depend += ['MTD_USING_NOR'] - if GetDepend(['MTD_USING_NAND']): - src += ['mtdnand.c'] - depend += ['MTD_USING_NAND'] - if GetDepend(['RT_USING_MTD_NOR']): src += ['mtd_nor.c'] depend += ['RT_USING_MTD_NOR'] @@ -31,4 +18,4 @@ if GetDepend(['RT_USING_MTD_NAND']): if src: group = DefineGroup('DeviceDrivers', src, depend = depend, CPPPATH = CPPPATH) -Return('group')
\ No newline at end of file +Return('group') diff --git a/components/drivers/mtd/mtd.c b/components/drivers/mtd/mtd.c deleted file mode 100644 index 3e7b4f2b54..0000000000 --- a/components/drivers/mtd/mtd.c +++ /dev/null @@ -1,236 +0,0 @@ -/* - * Copyright (c) 2006-2018, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - 2018-09-10 heyuanjie87 first version - - */ - -#include <drivers/mtd.h> - -static rt_mtd_t* mtd_part_alloc(rt_mtd_t *master, const struct mtd_part *part) -{ - rt_mtd_t *slave; - - slave = rt_malloc(sizeof(rt_mtd_t)); - if (slave == RT_NULL) - goto out; - - slave->master = master; - - *slave = *master; - slave->size = part->size; - slave->offset = part->offset; - -out: - - return slave; -} - -rt_mtd_t* rt_mtd_get(const char *name) -{ - rt_mtd_t *mtd; - - mtd = (rt_mtd_t *)rt_device_find(name); - if (mtd == RT_NULL) - return RT_NULL; - - if (mtd->parent.type != RT_Device_Class_MTD) - return RT_NULL; - - return mtd; -} - -/* - * Register MTD driver - * - * @parts partion description - * @np number of partitions - * @return number of unregistered partitions - * -*/ -int rt_mtd_register(rt_mtd_t *master, const struct mtd_part *parts, int np) -{ - int ret; - rt_mtd_t *slave; - - master->master = master; - master->parent.type = RT_Device_Class_MTD; - - if (np > 0) - { - master->offset = parts->offset; - master->size = parts->size; - - ret = rt_device_register((rt_device_t)master, parts->name, 0); - if (ret != 0) - goto _out; - - np --; - parts ++; - } - - while (np > 0) - { - slave = mtd_part_alloc(master, parts); - if (!slave) - break; - ret = rt_device_register((rt_device_t)slave, parts->name, 0); - if (ret) - break; - parts ++; - np --; - } - -_out: - return np; -} - -int rt_mtd_block_erase(rt_mtd_t *mtd, uint32_t block) -{ - uint32_t total_blks; - loff_t addr; - - total_blks = mtd->size/mtd->block_size; - if (block >= total_blks) - return -EINVAL; - addr = mtd->offset + mtd->block_size * block; - - return mtd->ops->erase(mtd->master, addr, mtd->block_size); -} - -int rt_mtd_block_isbad(rt_mtd_t *mtd, uint32_t block) -{ - uint32_t total_blks, offset_blk; - - if (!mtd->ops->isbad) - return 0; - - total_blks = mtd->size / mtd->block_size; - if (block >= total_blks) - return -EINVAL; - offset_blk = mtd->offset / mtd->block_size; - - return mtd->ops->isbad(mtd->master, block + offset_blk); -} - -int rt_mtd_block_markbad(rt_mtd_t *mtd, uint32_t block) -{ - uint32_t total_blks, offset_blk; - - if (!mtd->ops->markbad) - return -EOPNOTSUPP; - - total_blks = mtd->size / mtd->block_size; - if (block >= total_blks) - return -EINVAL; - offset_blk = mtd->offset / mtd->block_size; - - return mtd->ops->markbad(mtd->master, block + offset_blk); -} - -int rt_mtd_erase(rt_mtd_t *mtd, loff_t addr, size_t size) -{ - if (addr > mtd->size || (addr + size) > mtd->size) - return -EINVAL; - addr += mtd->offset; - - return mtd->ops->erase(mtd->master, addr, size); -} - -/* -* Read data only -* -* @from offset to read from -* @return success size or error code -*/ -int rt_mtd_read(rt_mtd_t *mtd, loff_t from, uint8_t *buf, size_t len) -{ - int ret; - struct mtd_io_desc desc = {0}; - - if (from < 0 || from >= (loff_t)mtd->size || len > mtd->size - from) - return -EINVAL; - if (!len) - return 0; - - desc.datbuf = buf; - desc.datlen = len; - ret = mtd->ops->read(mtd->master, from + mtd->offset, &desc); - if (ret) - return ret; - - return desc.datretlen; -} - -/** -* Write data only -* -* @to offset to write from -* @return success size or error code -*/ -int rt_mtd_write(rt_mtd_t *mtd, loff_t to, const uint8_t *buf, size_t len) -{ - int ret; - struct mtd_io_desc desc = {0}; - - if (to < 0 || to >= (loff_t)mtd->size || len > mtd->size - to) - return -EINVAL; - if (!mtd->ops->write) - return -EROFS; - if (!len) - return 0; - - desc.datbuf = (uint8_t*)buf; - desc.datlen = len; - ret = mtd->ops->write(mtd->master, to + mtd->offset, &desc); - if (ret) - return ret; - - return desc.datretlen; -} - -/** -* Read data and/or out-of-band -* -* @from offset to read from -* @desc sector operation description structure -* @return error code, 0 success -*/ -int rt_mtd_read_oob(rt_mtd_t *mtd, loff_t from, struct mtd_io_desc *desc) -{ - desc->datretlen = 0; - desc->oobretlen = 0; - - if (from < 0 || from >= (loff_t)mtd->size) - return -EINVAL; - - if (desc->datbuf && (desc->datlen > (mtd->size - from))) - return -EINVAL; - - return mtd->ops->read(mtd->master, from + mtd->offset, desc); -} - -/** -* Write data and/or out-of-band -* -* @to offset to read from -* @desc sector operation description structure -* @return error code, 0 success -*/ -int rt_mtd_write_oob(rt_mtd_t *mtd, loff_t to, struct mtd_io_desc *desc) -{ - desc->datretlen = 0; - desc->oobretlen = 0; - - if (to < 0 || to >= (loff_t)mtd->size) - return -EINVAL; - - if (desc->datbuf && (desc->datlen >(mtd->size - to))) - return -EINVAL; - - return mtd->ops->write(mtd->master, to + mtd->offset, desc); -} diff --git a/components/drivers/mtd/mtd_nand.c b/components/drivers/mtd/mtd_nand.c index 3e4582ceaf..ae5aa9c172 100644 --- a/components/drivers/mtd/mtd_nand.c +++ b/components/drivers/mtd/mtd_nand.c @@ -56,7 +56,7 @@ static rt_err_t _mtd_control(rt_device_t dev, int cmd, void *args) } #ifdef RT_USING_DEVICE_OPS -const static struct rt_device_ops mtd_nand_ops = +const static struct rt_device_ops mtd_nand_ops = { _mtd_init, _mtd_open, @@ -78,7 +78,7 @@ 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; + dev->ops = &mtd_nand_ops; #else dev->init = _mtd_init; dev->open = _mtd_open; @@ -101,188 +101,262 @@ rt_err_t rt_mtd_nand_register_device(const char *name, static void mtd_dump_hex(const rt_uint8_t *ptr, rt_size_t buflen) { - unsigned char *buf = (unsigned char*)ptr; - int i, j; - for (i=0; i<buflen; i+=16) - { - rt_kprintf("%06x: ", i); - for (j=0; j<16; j++) - if (i+j < buflen) - rt_kprintf("%02x ", buf[i+j]); - else - rt_kprintf(" "); - rt_kprintf(" "); - for (j=0; j<16; j++) - if (i+j < buflen) - rt_kprintf("%c", __is_print(buf[i+j]) ? buf[i+j] : '.'); - rt_kprintf("\n"); - } + unsigned char *buf = (unsigned char *)ptr; + int i, j; + for (i = 0; i < buflen; i += 16) + { + rt_kprintf("%06x: ", i); + for (j = 0; j < 16; j++) + if (i + j < buflen) + rt_kprintf("%02x ", buf[i + j]); + else + rt_kprintf(" "); + rt_kprintf(" "); + for (j = 0; j < 16; j++) + if (i + j < buflen) + rt_kprintf("%c", __is_print(buf[i + j]) ? buf[i + j] : '.'); + rt_kprintf("\n"); + } } -int mtd_nandid(const char* name) +int mtd_nandid(const char *name) { - struct rt_mtd_nand_device *nand; - nand = RT_MTD_NAND_DEVICE(rt_device_find(name)); - if (nand == RT_NULL) - { - rt_kprintf("no nand device found!\n"); - return -RT_ERROR; - } + struct rt_mtd_nand_device *nand; + nand = RT_MTD_NAND_DEVICE(rt_device_find(name)); + if (nand == RT_NULL) + { + rt_kprintf("no nand device found!\n"); + return -RT_ERROR; + } - return rt_mtd_nand_read_id(nand); + return rt_mtd_nand_read_id(nand); } -FINSH_FUNCTION_EXPORT_ALIAS(mtd_nandid, nand_id, read ID - nandid(name)); -int mtd_nand_read(const char* name, int block, int page) +int mtd_nand_read(const char *name, int block, int page) { - rt_err_t result; - rt_uint8_t *page_ptr; - rt_uint8_t *oob_ptr; - struct rt_mtd_nand_device *nand; + rt_err_t result; + rt_uint8_t *page_ptr; + rt_uint8_t *oob_ptr; + struct rt_mtd_nand_device *nand; - nand = RT_MTD_NAND_DEVICE(rt_device_find(name)); - if (nand == RT_NULL) - { - rt_kprintf("no nand device found!\n"); - return -RT_ERROR; - } + nand = RT_MTD_NAND_DEVICE(rt_device_find(name)); + if (nand == RT_NULL) + { + rt_kprintf("no nand device found!\n"); + return -RT_ERROR; + } - page_ptr = rt_malloc(nand->page_size + nand->oob_size); - if (page_ptr == RT_NULL) - { - rt_kprintf("out of memory!\n"); - return -RT_ENOMEM; - } + page_ptr = rt_malloc(nand->page_size + nand->oob_size); + if (page_ptr == RT_NULL) + { + rt_kprintf("out of memory!\n"); + return -RT_ENOMEM; + } - oob_ptr = page_ptr + nand->page_size; - rt_memset(page_ptr, 0xff, nand->page_size + nand->oob_size); + oob_ptr = page_ptr + nand->page_size; + rt_memset(page_ptr, 0xff, nand->page_size + nand->oob_size); - /* calculate the page number */ - page = block * nand->pages_per_block + page; - result = rt_mtd_nand_read(nand, page, page_ptr, nand->page_size, - oob_ptr, nand->oob_size); + /* calculate the page number */ + page = block * nand->pages_per_block + page; + result = rt_mtd_nand_read(nand, page, page_ptr, nand->page_size, + oob_ptr, nand->oob_size); - rt_kprintf("read page, rc=%d\n", result); - mtd_dump_hex(page_ptr, nand->page_size); - mtd_dump_hex(oob_ptr, nand->oob_size); + rt_kprintf("read page, rc=%d\n", result); + mtd_dump_hex(page_ptr, nand->page_size); + mtd_dump_hex(oob_ptr, nand->oob_size); - rt_free(page_ptr); - return 0; + rt_free(page_ptr); + return 0; } -FINSH_FUNCTION_EXPORT_ALIAS(mtd_nand_read, nand_read, read page in nand - nand_read(name, block, page)); -int mtd_nand_readoob(const char* name, int block, int page) +int mtd_nand_readoob(const char *name, int block, int page) { - struct rt_mtd_nand_device *nand; - rt_uint8_t *oob_ptr; + struct rt_mtd_nand_device *nand; + rt_uint8_t *oob_ptr; - nand = RT_MTD_NAND_DEVICE(rt_device_find(name)); - if (nand == RT_NULL) - { - rt_kprintf("no nand device found!\n"); - return -RT_ERROR; - } + nand = RT_MTD_NAND_DEVICE(rt_device_find(name)); + if (nand == RT_NULL) + { + rt_kprintf("no nand device found!\n"); + return -RT_ERROR; + } - oob_ptr = rt_malloc(nand->oob_size); - if (oob_ptr == RT_NULL) - { - rt_kprintf("out of memory!\n"); - return -RT_ENOMEM; - } + oob_ptr = rt_malloc(nand->oob_size); + if (oob_ptr == RT_NULL) + { + rt_kprintf("out of memory!\n"); + return -RT_ENOMEM; + } - /* calculate the page number */ - page = block * nand->pages_per_block + page; - rt_mtd_nand_read(nand, page, RT_NULL, nand->page_size, - oob_ptr, nand->oob_size); - mtd_dump_hex(oob_ptr, nand->oob_size); + /* calculate the page number */ + page = block * nand->pages_per_block + page; + rt_mtd_nand_read(nand, page, RT_NULL, nand->page_size, + oob_ptr, nand->oob_size); + mtd_dump_hex(oob_ptr, nand->oob_size); - rt_free(oob_ptr); - return 0; + rt_free(oob_ptr); + return 0; } -FINSH_FUNCTION_EXPORT_ALIAS(mtd_nand_readoob, nand_readoob, read spare data in nand - nand_readoob(name, block, page)); -int mtd_nand_write(const char* name, int block, int page) +int mtd_nand_write(const char *name, int block, int page) { - rt_err_t result; - rt_uint8_t *page_ptr; - rt_uint8_t *oob_ptr; - rt_uint32_t index; - struct rt_mtd_nand_device *nand; + rt_err_t result; + rt_uint8_t *page_ptr; + rt_uint8_t *oob_ptr; + rt_uint32_t index; + struct rt_mtd_nand_device *nand; - nand = RT_MTD_NAND_DEVICE(rt_device_find(name)); - if (nand == RT_NULL) - { - rt_kprintf("no nand device found!\n"); - return -RT_ERROR; - } + nand = RT_MTD_NAND_DEVICE(rt_device_find(name)); + if (nand == RT_NULL) + { + rt_kprintf("no nand device found!\n"); + return -RT_ERROR; + } - page_ptr = rt_malloc(nand->page_size + nand->oob_size); - if (page_ptr == RT_NULL) - { - rt_kprintf("out of memory!\n"); - return -RT_ENOMEM; - } + page_ptr = rt_malloc(nand->page_size + nand->oob_size); + if (page_ptr == RT_NULL) + { + rt_kprintf("out of memory!\n"); + return -RT_ENOMEM; + } - oob_ptr = page_ptr + nand->page_size; - /* prepare page data */ - for (index = 0; index < nand->page_size; index ++) - { - page_ptr[index] = index & 0xff; - } - /* prepare oob data */ - for (index = 0; index < nand->oob_size; index ++) - { - oob_ptr[index] = index & 0xff; - } + oob_ptr = page_ptr + nand->page_size; + /* prepare page data */ + for (index = 0; index < nand->page_size; index ++) + { + page_ptr[index] = index & 0xff; + } + /* prepare oob data */ + for (index = 0; index < nand->oob_size; index ++) + { + oob_ptr[index] = index & 0xff; + } - /* calculate the page number */ - page = block * nand->pages_per_block + page; - result = rt_mtd_nand_write(nand, page, page_ptr, nand->page_size, - oob_ptr, nand->oob_size); - if (result != RT_MTD_EOK) - { - rt_kprintf("write page failed!, rc=%d\n", result); - } + /* calculate the page number */ + page = block * nand->pages_per_block + page; + result = rt_mtd_nand_write(nand, page, page_ptr, nand->page_size, + oob_ptr, nand->oob_size); + if (result != RT_MTD_EOK) + { + rt_kprintf("write page failed!, rc=%d\n", result); + } - rt_free(page_ptr); - return 0; + rt_free(page_ptr); + return 0; } -FINSH_FUNCTION_EXPORT_ALIAS(mtd_nand_write, nand_write, write dump data to nand - nand_write(name, block, page)); -int mtd_nand_erase(const char* name, int block) +int mtd_nand_erase(const char *name, int block) { - struct rt_mtd_nand_device *nand; - nand = RT_MTD_NAND_DEVICE(rt_device_find(name)); - if (nand == RT_NULL) - { - rt_kprintf("no nand device found!\n"); - return -RT_ERROR; - } + struct rt_mtd_nand_device *nand; + nand = RT_MTD_NAND_DEVICE(rt_device_find(name)); + if (nand == RT_NULL) + { + rt_kprintf("no nand device found!\n"); + return -RT_ERROR; + } - return rt_mtd_nand_erase_block(nand, block); + return rt_mtd_nand_erase_block(nand, block); } -FINSH_FUNCTION_EXPORT_ALIAS(mtd_nand_erase, nand_erase, nand_erase(name, block)); -int mtd_nand_erase_all(const char* name) +int mtd_nand_erase_all(const char *name) { - rt_uint32_t index = 0; - struct rt_mtd_nand_device *nand; - - nand = RT_MTD_NAND_DEVICE(rt_device_find(name)); - if (nand == RT_NULL) - { - rt_kprintf("no nand device found!\n"); - return -RT_ERROR; - } + rt_uint32_t index = 0; + struct rt_mtd_nand_device *nand; - for (index = 0; index < (nand->block_end - nand->block_start); index ++) - { - rt_mtd_nand_erase_block(nand, index); - } - - return 0; + nand = RT_MTD_NAND_DEVICE(rt_device_find(name)); + if (nand == RT_NULL) + { + rt_kprintf("no nand device found!\n"); + return -RT_ERROR; + } + + for (index = 0; index < (nand->block_end - nand->block_start); index ++) + { + rt_mtd_nand_erase_block(nand, index); + } + + return 0; +} + +#ifdef FINSH_USING_MSH +static void mtd_nand(int argc, char **argv) +{ + /* If the number of arguments less than 2 */ + if (argc < 3) + { +help: + rt_kprintf("\n"); + rt_kprintf("mtd_nand [OPTION] [PARAM ...]\n"); + rt_kprintf(" id <name> Get nandid by given name\n"); + rt_kprintf(" read <name> <bn> <pn> Read data on page <pn> of block <bn> of device <name>\n"); + rt_kprintf(" readoob <name> <bn> <pn> Read oob on page <pn> of block <bn> of device <name>\n"); + rt_kprintf(" write <name> <bn> <pn> Run write test on page <pn> of block <bn> of device <name>\n"); + rt_kprintf(" erase <name> <bn> Erase on block <bn> of device <name>\n"); + rt_kprintf(" eraseall <name> Erase all block on device <name>\n"); + return ; + } + else if (!strcmp(argv[1], "id")) + { + mtd_nandid(argv[2]); + } + else if (!strcmp(argv[1], "read")) + { + if (argc < 5) + { + rt_kprintf("The input parameters are too few!\n"); + goto help; + } + mtd_nand_read(argv[2], atoi(argv[3]), atoi(argv[4])); + } + else if (!strcmp(argv[1], "readoob")) + { + if (argc < 5) + { + rt_kprintf("The input parameters are too few!\n"); + goto help; + } + mtd_nand_readoob(argv[2], atoi(argv[3]), atoi(argv[4])); + } + else if (!strcmp(argv[1], "write")) + { + if (argc < 5) + { + rt_kprintf("The input parameters are too few!\n"); + goto help; + } + mtd_nand_write(argv[2], atoi(argv[3]), atoi(argv[4])); + } + else if (!strcmp(argv[1], "erase")) + { + if (argc < 4) + { + rt_kprintf("The input parameters are too few!\n"); + goto help; + } + mtd_nand_erase(argv[2], atoi(argv[3])); + } + else if (!strcmp(argv[1], "eraseall")) + { + mtd_nand_erase_all(argv[2]); + } + else + { + rt_kprintf("Input parameters are not supported!\n"); + goto help; + } } +MSH_CMD_EXPORT(mtd_nand, MTD nand device test function); +#endif /* FINSH_USING_MSH */ + +#ifndef FINSH_USING_MSH_ONLY +FINSH_FUNCTION_EXPORT_ALIAS(mtd_nandid, nand_id, read ID - nandid(name)); +FINSH_FUNCTION_EXPORT_ALIAS(mtd_nand_read, nand_read, read page in nand - nand_read(name, block, page)); +FINSH_FUNCTION_EXPORT_ALIAS(mtd_nand_readoob, nand_readoob, read spare data in nand - nand_readoob(name, block, page)); +FINSH_FUNCTION_EXPORT_ALIAS(mtd_nand_write, nand_write, write dump data to nand - nand_write(name, block, page)); +FINSH_FUNCTION_EXPORT_ALIAS(mtd_nand_erase, nand_erase, nand_erase(name, block)); FINSH_FUNCTION_EXPORT_ALIAS(mtd_nand_erase_all, nand_erase_all, erase all of nand device - nand_erase_all(name, block)); -#endif +#endif /* FINSH_USING_MSH_ONLY */ -#endif +#endif /* defined(RT_MTD_NAND_DEBUG) && defined(RT_USING_FINSH) */ + +#endif /* RT_USING_MTD_NAND */ diff --git a/components/drivers/mtd/mtdnand.c b/components/drivers/mtd/mtdnand.c deleted file mode 100644 index 50012219fb..0000000000 --- a/components/drivers/mtd/mtdnand.c +++ /dev/null @@ -1,645 +0,0 @@ -/* - * Copyright (c) 2006-2018, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2018-09-10 heyuanjie87 first version - */ - -#include <rtdevice.h> - -#define MTDTONAND(x) ((rt_nand_t*)(x)) -#define NOTALIGNED(x) ((x & (chip->page_size - 1)) != 0) -#ifndef min -#define min(a,b) (a>b? b:a) -#endif - -static uint8_t *nand_fill_oob(rt_nand_t *chip, uint8_t *oob, size_t len, struct mtd_io_desc *desc) -{ - rt_memset(chip->oob_poi, 0xff, chip->oobsize); - - switch (desc->mode) - { - case MTD_OPM_PLACE_OOB: - case MTD_OPM_RAW: - rt_memcpy(chip->oob_poi + desc->ooboffs, oob, len); - return oob + len; - - case MTD_OPM_AUTO_OOB: - { - const struct mtd_oob_region *free = chip->freelayout; - uint32_t boffs; - size_t bytes; - - bytes = min(len, free->length); - boffs = free->offset; - - rt_memcpy(chip->oob_poi + boffs, oob, bytes); - oob += bytes; - - return oob; - } - } - - return NULL; -} - -static uint8_t *nand_transfer_oob(rt_nand_t *chip, uint8_t *oob, struct mtd_io_desc *desc, size_t len) -{ - switch (desc->mode) - { - case MTD_OPM_PLACE_OOB: - case MTD_OPM_RAW: - rt_memcpy(oob, chip->oob_poi + desc->ooboffs, len); - return oob + len; - - case MTD_OPM_AUTO_OOB: - { - struct mtd_oob_region *free = (struct mtd_oob_region *)chip->freelayout; - uint32_t boffs = 0, roffs = desc->ooboffs; - size_t bytes = 0; - - for (; free->length && len; free++, len -= bytes) - { - /* Read request not from offset 0? */ - if (roffs) - { - if (roffs >= free->length) - { - roffs -= free->length; - continue; - } - boffs = free->offset + roffs; - bytes = min(len, (free->length - roffs)); - roffs = 0; - } - else - { - bytes = min(len, free->length); - boffs = free->offset; - } - - rt_memcpy(oob, chip->oob_poi + boffs, bytes); - oob += bytes; - } - - return oob; - } - } - - return NULL; -} - -static int nand_read_page_raw(rt_nand_t *chip, uint8_t *buf, int oob_required, int page) -{ - chip->ops->read_buf(chip, buf, chip->page_size); - - if (oob_required) - chip->ops->read_buf(chip, chip->oob_poi, chip->oobsize); - - return 0; -} - -static int nand_write_page_raw(rt_nand_t *chip, const uint8_t *buf, int oob_required, int page) -{ - chip->ops->write_buf(chip, buf, chip->page_size); - - if (oob_required) - chip->ops->write_buf(chip, chip->oob_poi, chip->oobsize); - - return 0; -} - -static int nand_write_page_hwecc(rt_nand_t *chip, const uint8_t *buf, int oob_required, int page) -{ - uint16_t i; - uint16_t stepsize = chip->ecc.stepsize; - uint16_t eccbytes = chip->ecc.bytes; - uint16_t eccsteps = chip->ecc._step; - uint16_t eccpos = chip->ecc.layout->offset; - uint8_t *ecc_calc = chip->buffers.ecccalc; - const uint8_t *p = buf; - - for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += stepsize) - { - chip->ops->cmdfunc(chip, NAND_CMD_ECC_EN, 0, 0); - chip->ops->write_buf(chip, p, stepsize); - chip->ecc.calculate(chip, p, &ecc_calc[i]); - chip->ops->cmdfunc(chip, NAND_CMD_ECC_DIS, 0, 0); - } - - rt_memcpy(&chip->oob_poi[eccpos], ecc_calc, chip->ecc.layout->length); - - chip->ops->write_buf(chip, chip->oob_poi, chip->oobsize); - - return 0; -} - -static int nand_read_page_hwecc(rt_nand_t *chip, uint8_t *buf, int oob_required, int page) -{ - uint16_t i; - uint16_t eccsize = chip->ecc.stepsize; - uint16_t eccbytes = chip->ecc.bytes; - uint16_t eccsteps = chip->ecc._step; - uint16_t eccpos = chip->ecc.layout->offset; - uint8_t *p = buf; - uint8_t *ecc_calc = chip->buffers.ecccalc; - uint8_t *ecc_code = chip->buffers.ecccode; - int ret = 0; - - for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) - { - chip->ops->cmdfunc(chip, NAND_CMD_ECC_EN, 0, 0); - chip->ops->read_buf(chip, p, eccsize); - chip->ecc.calculate(chip, p, &ecc_calc[i]); - chip->ops->cmdfunc(chip, NAND_CMD_ECC_DIS, 0, 0); - } - - chip->ops->read_buf(chip, chip->oob_poi, chip->oobsize); - rt_memcpy(ecc_code, &chip->oob_poi[eccpos], chip->ecc.layout->length); - - eccsteps = chip->ecc._step; - p = buf; - - for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) - { - int stat; - - stat = chip->ecc.correct(chip, p, &ecc_code[i], &ecc_calc[i]); - if (stat != 0) - ret = -1; - } - - return ret; -} - -static int nand_write_page(rt_nand_t *chip, const uint8_t *buf, - int oob_required, int page, int raw) -{ - int status; - - chip->ops->cmdfunc(chip, NAND_CMD_PAGE_WR0, page, 0x00); - - if (raw) - { - nand_write_page_raw(chip, buf, oob_required, page); - } - else - { - chip->write_page(chip, buf, oob_required, page); - } - - status = chip->ops->cmdfunc(chip, NAND_CMD_PAGE_WR1, -1, -1); - - return status; -} - -static int nand_do_read_desc(rt_nand_t *chip, loff_t from, struct mtd_io_desc *desc) -{ - int page, bytes; - char oob_required; - char ecc_fail = 0; - int ret = 0; - uint32_t readlen = desc->datlen; - uint16_t oobreadlen = desc->ooblen; - uint16_t max_oobsize = desc->mode == MTD_OPM_AUTO_OOB ? - chip->freelayout->length : chip->oobsize; - - uint8_t *oob, *buf, *notalign = 0; - - /* Reject reads, which are not page aligned */ - if (NOTALIGNED(from)) - { - return -EINVAL; - } - - buf = desc->datbuf; - if (NOTALIGNED(desc->datlen) && !chip->pagebuf) - { - chip->pagebuf = rt_malloc(chip->page_size); - if (!chip->pagebuf) - return -ENOMEM; - } - - page = (int)(from / chip->page_size); - - oob = desc->oobbuf; - oob_required = oob ? 1 : 0; - - while (1) - { - bytes = min(chip->page_size, readlen); - - chip->ops->cmdfunc(chip, NAND_CMD_PAGE_RD, page, 0x00); - if (NOTALIGNED(bytes)) - { - notalign = buf; - buf = chip->pagebuf; - } - /* - * Now read the page into the buffer. Absent an error, - * the read methods return max bitflips per ecc step. - */ - if (desc->mode == MTD_OPM_RAW) - { - ret = nand_read_page_raw(chip, buf, oob_required, page); - } - else - { - ret = chip->read_page(chip, buf, oob_required, page); - } - - if (ret != 0) - { - ret = -EBADMSG; - break; - } - - if (oob) - { - int toread = min(oobreadlen, max_oobsize); - - if (toread) - { - oob = nand_transfer_oob(chip, oob, desc, toread); - oobreadlen -= toread; - } - } - - if (notalign) - { - rt_memcpy(notalign, buf, bytes); - } - - buf += bytes; - readlen -= bytes; - - if (!readlen) - break; - - page++; - } - - desc->datretlen = desc->datlen - (size_t)readlen; - if (oob) - desc->oobretlen = desc->ooblen - oobreadlen; - - return ret; -} - -/* - * write with ECC - * -*/ -static int nand_do_write_desc(rt_nand_t *chip, loff_t to, struct mtd_io_desc *desc) -{ - int page; - uint16_t writelen = desc->datlen; - uint16_t oob_required = desc->oobbuf ? 1 : 0; - uint16_t oobwritelen = desc->ooblen; - uint16_t oobmaxlen = desc->mode == MTD_OPM_AUTO_OOB ? - chip->freelayout->length : chip->oobsize; - - uint8_t *oob = desc->oobbuf; - uint8_t *buf = desc->datbuf; - int ret; - - if (!writelen) - return 0; - - /* Reject writes, which are not page aligned */ - if (NOTALIGNED(to)) - { - return -EINVAL; - } - - page = (int)(to / chip->page_size); - - /* Don't allow multipage oob writes with offset */ - if (oob && desc->ooboffs && (desc->ooboffs + desc->ooblen > oobmaxlen)) - { - ret = -EINVAL; - goto err_out; - } - - if (NOTALIGNED(desc->datlen) && !chip->pagebuf) - { - chip->pagebuf = rt_malloc(chip->page_size); - if (!chip->pagebuf) - return -ENOMEM; - } - - while (1) - { - uint16_t bytes = min(chip->page_size, writelen); - - if (oob) - { - size_t len = min(oobwritelen, oobmaxlen); - oob = nand_fill_oob(chip, oob, len, desc); - oobwritelen -= len; - } - else - { - /* We still need to erase leftover OOB data */ - rt_memset(chip->oob_poi, 0xff, chip->oobsize); - } - - if (NOTALIGNED(bytes)) - { - uint8_t *dbtmp = buf; - buf = chip->pagebuf; - rt_memset(&buf[bytes], 0xff, chip->page_size - bytes); - rt_memcpy(buf, dbtmp, bytes); - } - ret = nand_write_page(chip, buf, oob_required, page, (desc->mode == MTD_OPM_RAW)); - if (ret) - break; - - writelen -= bytes; - if (!writelen) - break; - - buf += bytes; - page++; - } - - desc->datretlen = desc->datlen - writelen; - if (oob) - desc->oobretlen = desc->ooblen; - -err_out: - - return ret; -} - -static int nand_read_oob_std(rt_nand_t *chip, int page) -{ - chip->ops->cmdfunc(chip, NAND_CMD_PAGE_RD, page, chip->page_size); - chip->ops->read_buf(chip, chip->oob_poi, chip->oobsize); - - return 0; -} - -/* - * read one page of OOB -*/ -static int nand_only_read_oob(rt_nand_t *chip, loff_t from, struct mtd_io_desc *desc) -{ - int page; - int readlen = desc->ooblen; - int len; - uint8_t *buf = desc->oobbuf; - int ret = 0; - - if (desc->mode == MTD_OPM_AUTO_OOB) - len = chip->freelayout->length; - else - len = chip->oobsize; - - if (desc->ooboffs >= len) //attempt to start read outside oob - { - return -EINVAL; - } - - page = (int)(from / chip->page_size); - - ret = nand_read_oob_std(chip, page); - if (ret == 0) - { - len = min(len, readlen); - buf = nand_transfer_oob(chip, buf, desc, len); - desc->oobretlen = len; - } - - return ret; -} - -static int nand_write_oob_std(rt_nand_t *chip, int page) -{ - int status; - - chip->ops->cmdfunc(chip, NAND_CMD_PAGE_WR0, page, chip->page_size); - chip->ops->write_buf(chip, chip->oob_poi, chip->oobsize); - /* Send command to program the OOB data */ - status = chip->ops->cmdfunc(chip, NAND_CMD_PAGE_WR1, -1, -1); - - return status & NAND_STATUS_FAIL ? -EIO : 0; -} - -static int nand_only_write_oob(rt_nand_t *chip, loff_t to, struct mtd_io_desc *desc) -{ - int page, ret, len; - - if (desc->mode == MTD_OPM_AUTO_OOB) - len = chip->freelayout->length; - else - len = chip->oobsize; - - /* Do not allow write past end of page */ - if ((desc->ooboffs + desc->ooblen) > len) - { - return -EINVAL; - } - - if (desc->ooblen == 0) - { - return -EINVAL; - } - - /* get page */ - page = (int)(to / chip->page_size); - - nand_fill_oob(chip, desc->oobbuf, desc->ooblen, desc); - - ret = nand_write_oob_std(chip, page); - if (ret == 0) - desc->oobretlen = len; - - return ret; -} - -static int nand_erase(rt_mtd_t *mtd, loff_t addr, size_t size) -{ - rt_nand_t *chip; - int status; - int page; - uint32_t blksize; - - chip = MTDTONAND(mtd); - blksize = mtd->block_size; - page = addr / chip->page_size; - - while (size >= blksize) - { - status = chip->ops->cmdfunc(chip, NAND_CMD_BLK_ERASE, page, 0); - if (status & NAND_STATUS_FAIL) - { - break; - } - size -= blksize; - page += chip->pages_pb; - } - - return size; -} - -static int nand_read(rt_mtd_t *mtd, loff_t from, struct mtd_io_desc *desc) -{ - int ret = -ENOTSUP; - rt_nand_t *chip; - - chip = MTDTONAND(mtd); - - switch (desc->mode) - { - case MTD_OPM_PLACE_OOB: - case MTD_OPM_AUTO_OOB: - case MTD_OPM_RAW: - break; - - default: - goto out; - } - - if (!desc->datbuf || !desc->datlen) - ret = nand_only_read_oob(chip, from, desc); - else - ret = nand_do_read_desc(chip, from, desc); - -out: - - return ret; -} - -static int nand_write(rt_mtd_t *mtd, loff_t to, struct mtd_io_desc *desc) -{ - int ret = -ENOTSUP; - rt_nand_t *chip; - - chip = MTDTONAND(mtd); - - switch (desc->mode) - { - case MTD_OPM_PLACE_OOB: - case MTD_OPM_AUTO_OOB: - case MTD_OPM_RAW: - break; - - default: - goto out; - } - - if (!desc->datbuf || !desc->datlen) - ret = nand_only_write_oob(chip, to, desc); - else - ret = nand_do_write_desc(chip, to, desc); - -out: - - return ret; -} - -static int nand_block_isbad(rt_mtd_t *mtd, uint32_t blk) -{ - int ret; - rt_nand_t *chip = MTDTONAND(mtd); - - if (chip->ops->isbad) - { - ret = chip->ops->isbad(chip, blk); - } - else - { - int page; - - page = blk * chip->pages_pb; - nand_read_oob_std(chip, page); - ret = chip->oob_poi[0] != 0xFF; - } - - return ret; -} - -static int nand_block_markbad(rt_mtd_t *mtd, uint32_t blk) -{ - int ret; - rt_nand_t *chip; - - chip = MTDTONAND(mtd); - - if (chip->ops->markbad) - { - ret = chip->ops->markbad(chip, blk); - } - else - { - int page; - - page = blk * chip->pages_pb; - rt_memset(chip->oob_poi, 0xff, chip->oobsize); - chip->oob_poi[0] = 0; - ret = nand_write_oob_std(chip, page); - } - - return ret; -} - -static const struct mtd_ops _ops = -{ - nand_erase, - nand_read, - nand_write, - nand_block_isbad, - nand_block_markbad, -}; - -int rt_mtd_nand_init(rt_nand_t *nand, int blk_size, int page_size, int oob_size) -{ - uint8_t *buf; - - buf = rt_malloc(oob_size * 3); - if (buf == RT_NULL) - return -ENOMEM; - - nand->oob_poi = buf; - buf += oob_size; - nand->buffers.ecccalc = buf; - buf += oob_size; - nand->buffers.ecccode = buf; - nand->pagebuf = 0; /* alloc when unaligen access */ - - nand->pages_pb = blk_size / page_size; - nand->ecc._step = page_size / nand->ecc.stepsize; - nand->page_size = page_size; - nand->oobsize = oob_size; - - nand->parent.type = MTD_TYPE_NAND; - nand->parent.ops = &_ops; - nand->parent.sector_size = page_size; - nand->parent.block_size = blk_size; - nand->parent.oob_size = oob_size; - - switch (nand->ecc.mode) - { - case NAND_ECCM_NONE: - { - nand->read_page = nand_read_page_raw; - nand->write_page = nand_write_page_raw; - }break; - case NAND_ECCM_HW: - { - nand->read_page = nand_read_page_hwecc; - nand->write_page = nand_write_page_hwecc; - }break; - default: - { - rt_free(buf); - return -1; - } - } - - return 0; -} diff --git a/components/drivers/mtd/mtdnor.c b/components/drivers/mtd/mtdnor.c deleted file mode 100644 index 481d26167e..0000000000 --- a/components/drivers/mtd/mtdnor.c +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2006-2018, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - 2018-09-10 heyuanjie87 first version - - */ - -#include <drivers/mtdnor.h> - -#ifdef MTD_USING_NOR -static int _nor_erase(rt_mtd_t *mtd, loff_t addr, size_t len) -{ - rt_nor_t *nor; - - nor = (rt_nor_t *)mtd; - return nor->ops->erase(nor, addr, len); -} - -static int _nor_read(rt_mtd_t *mtd, loff_t from, struct mtd_io_desc *desc) -{ - rt_nor_t *nor; - int ret; - - nor = (rt_nor_t *)mtd; - ret = nor->ops->read(nor, from, desc->datbuf, desc->datlen); - if (ret > 0) - { - desc->datretlen = ret; - ret = 0; - } - - return ret; -} - -static int _nor_write(rt_mtd_t *mtd, loff_t to, struct mtd_io_desc *desc) -{ - rt_nor_t *nor; - int ret; - - nor = (rt_nor_t *)mtd; - ret = nor->ops->write(nor, to, desc->datbuf, desc->datlen); - if (ret > 0) - { - desc->datretlen = ret; - ret = 0; - } - - return ret; -} - -static const struct mtd_ops _ops = -{ - _nor_erase, - _nor_read, - _nor_write, - 0, - 0 -}; - -int rt_mtd_nor_init(rt_nor_t *nor, int blksize) -{ - nor->parent.sector_size = 1; - nor->parent.block_size = blksize; - nor->parent.ops = &_ops; - nor->parent.type = MTD_TYPE_NOR; - nor->parent.oob_size = 0; - - return 0; -} -#endif diff --git a/components/drivers/pm/pm.c b/components/drivers/pm/pm.c index 3e9cf56c76..dd7cc2ae63 100644 --- a/components/drivers/pm/pm.c +++ b/components/drivers/pm/pm.c @@ -17,18 +17,18 @@ #ifdef RT_USING_PM static struct rt_pm _pm; -static uint8_t _pm_default_sleep = RT_PM_DEFAULT_SLEEP_MODE; +static rt_uint8_t _pm_default_sleep = RT_PM_DEFAULT_SLEEP_MODE; static struct rt_pm_notify _pm_notify; -static uint8_t _pm_init_flag = 0; +static rt_uint8_t _pm_init_flag = 0; #define RT_PM_TICKLESS_THRESH (2) -RT_WEAK uint32_t rt_pm_enter_critical(uint8_t sleep_mode) +RT_WEAK rt_uint32_t rt_pm_enter_critical(rt_uint8_t sleep_mode) { return rt_hw_interrupt_disable(); } -RT_WEAK void rt_pm_exit_critical(uint32_t ctx, uint8_t sleep_mode) +RT_WEAK void rt_pm_exit_critical(rt_uint32_t ctx, rt_uint8_t sleep_mode) { rt_hw_interrupt_enable(ctx); } @@ -36,7 +36,7 @@ RT_WEAK void rt_pm_exit_critical(uint32_t ctx, uint8_t sleep_mode) /** * This function will suspend all registered devices */ -static int _pm_device_suspend(uint8_t mode) +static int _pm_device_suspend(rt_uint8_t mode) { int index, ret = RT_EOK; @@ -56,7 +56,7 @@ static int _pm_device_suspend(uint8_t mode) /** * This function will resume all registered devices */ -static void _pm_device_resume(uint8_t mode) +static void _pm_device_resume(rt_uint8_t mode) { int index; @@ -72,7 +72,7 @@ static void _pm_device_resume(uint8_t mode) /** * This function will update the frequency of all registered devices */ -static void _pm_device_frequency_change(uint8_t mode) +static void _pm_device_frequency_change(rt_uint8_t mode) { rt_uint32_t index; @@ -106,10 +106,10 @@ static void _pm_frequency_scaling(struct rt_pm *pm) /** * This function selects the sleep mode according to the rt_pm_request/rt_pm_release count. */ -static uint8_t _pm_select_sleep_mode(struct rt_pm *pm) +static rt_uint8_t _pm_select_sleep_mode(struct rt_pm *pm) { int index; - uint8_t mode; + rt_uint8_t mode; mode = _pm_default_sleep; for (index = PM_SLEEP_MODE_NONE; index < PM_SLEEP_MODE_MAX; index ++) @@ -128,7 +128,7 @@ static uint8_t _pm_select_sleep_mode(struct rt_pm *pm) /** * This function changes the power sleep mode base on the result of selection */ -static void _pm_change_sleep_mode(struct rt_pm *pm, uint8_t mode) +static void _pm_change_sleep_mode(struct rt_pm *pm, rt_uint8_t mode) { rt_tick_t timeout_tick, delta_tick; rt_base_t level; @@ -214,7 +214,7 @@ static void _pm_change_sleep_mode(struct rt_pm *pm, uint8_t mode) */ void rt_system_power_manager(void) { - uint8_t mode; + rt_uint8_t mode; if (_pm_init_flag == 0) return; @@ -233,7 +233,7 @@ void rt_system_power_manager(void) * * @param parameter the parameter of run mode or sleep mode */ -void rt_pm_request(uint8_t mode) +void rt_pm_request(rt_uint8_t mode) { rt_base_t level; struct rt_pm *pm; @@ -258,7 +258,7 @@ void rt_pm_request(uint8_t mode) * @param parameter the parameter of run mode or sleep mode * */ -void rt_pm_release(uint8_t mode) +void rt_pm_release(rt_uint8_t mode) { rt_ubase_t level; struct rt_pm *pm; @@ -342,7 +342,7 @@ void rt_pm_device_unregister(struct rt_device *device) /** * This function set notification callback for application */ -void rt_pm_notify_set(void (*notify)(uint8_t event, uint8_t mode, void *data), void *data) +void rt_pm_notify_set(void (*notify)(rt_uint8_t event, rt_uint8_t mode, void *data), void *data) { _pm_notify.notify = notify; _pm_notify.data = data; @@ -351,7 +351,7 @@ void rt_pm_notify_set(void (*notify)(uint8_t event, uint8_t mode, void *data), v /** * This function set default sleep mode when no pm_request */ -void rt_pm_default_set(uint8_t sleep_mode) +void rt_pm_default_set(rt_uint8_t sleep_mode) { _pm_default_sleep = sleep_mode; } @@ -428,7 +428,7 @@ static rt_err_t _rt_pm_device_control(rt_device_t dev, return RT_EOK; } -int rt_pm_run_enter(uint8_t mode) +int rt_pm_run_enter(rt_uint8_t mode) { rt_base_t level; struct rt_pm *pm; @@ -458,6 +458,18 @@ int rt_pm_run_enter(uint8_t mode) return RT_EOK; } +#ifdef RT_USING_DEVICE_OPS +const static struct rt_device_ops pm_ops = +{ + RT_NULL, + RT_NULL, + RT_NULL, + _rt_pm_device_read, + _rt_pm_device_write, + _rt_pm_device_control, +}; +#endif + /** * This function will initialize power management. * @@ -479,12 +491,16 @@ void rt_system_pm_init(const struct rt_pm_ops *ops, device->rx_indicate = RT_NULL; device->tx_complete = RT_NULL; +#ifdef RT_USING_DEVICE_OPS + device->ops = &pm_ops; +#else device->init = RT_NULL; device->open = RT_NULL; device->close = RT_NULL; device->read = _rt_pm_device_read; device->write = _rt_pm_device_write; device->control = _rt_pm_device_control; +#endif device->user_data = user_data; /* register PM device to the system */ diff --git a/components/drivers/sdio/block_dev.c b/components/drivers/sdio/block_dev.c index cac4fc5036..5db0f38c08 100644 --- a/components/drivers/sdio/block_dev.c +++ b/components/drivers/sdio/block_dev.c @@ -472,7 +472,7 @@ rt_int32_t rt_mmcsd_blk_probe(struct rt_mmcsd_card *card) } #ifdef RT_USING_DFS_MNTTABLE - if (0) // if (blk_dev) + if (blk_dev) { LOG_I("try to mount file system!"); /* try to mount file system on this block device */ @@ -507,9 +507,10 @@ void rt_mmcsd_blk_remove(struct rt_mmcsd_card *card) const char * mounted_path = dfs_filesystem_get_mounted_path(&(blk_dev->dev)); if (mounted_path) { - dfs_unmount(mounted_path); + dfs_unmount(mounted_path); + LOG_D("unmount file system %s for device %s.\r\n", mounted_path, blk_dev->dev.parent.name); } - + rt_sem_delete(blk_dev->part.lock); rt_device_unregister(&blk_dev->dev); rt_list_remove(&blk_dev->list); rt_free(blk_dev); diff --git a/components/drivers/sdio/mmc.c b/components/drivers/sdio/mmc.c index 5c7ddcb258..7b1f7ee193 100644 --- a/components/drivers/sdio/mmc.c +++ b/components/drivers/sdio/mmc.c @@ -4,8 +4,8 @@ * SPDX-License-Identifier: Apache-2.0 * * Change Logs: - * Date Author Notes - * 2015-06-15 hichard first version + * Date Author Notes + * 2015-06-15 hichard first version */ #include <drivers/mmcsd_core.h> @@ -182,6 +182,8 @@ static int mmc_get_ext_csd(struct rt_mmcsd_card *card, rt_uint8_t **new_ext_csd) */ static int mmc_parse_ext_csd(struct rt_mmcsd_card *card, rt_uint8_t *ext_csd) { + rt_uint64_t card_capacity = 0; + if(card == RT_NULL || ext_csd == RT_NULL) { LOG_E("emmc parse ext csd fail, invaild args"); @@ -191,9 +193,10 @@ static int mmc_parse_ext_csd(struct rt_mmcsd_card *card, rt_uint8_t *ext_csd) card->flags |= CARD_FLAG_HIGHSPEED; card->hs_max_data_rate = 200000000; - card->card_capacity = *((rt_uint32_t *)&ext_csd[EXT_CSD_SEC_CNT]); - card->card_capacity *= card->card_blksize; - card->card_capacity >>= 10; /* unit:KB */ + card_capacity = *((rt_uint32_t *)&ext_csd[EXT_CSD_SEC_CNT]); + card_capacity *= card->card_blksize; + card_capacity >>= 10; /* unit:KB */ + card->card_capacity = card_capacity; LOG_I("emmc card capacity %d KB.", card->card_capacity); return 0; diff --git a/components/drivers/sdio/sdio.c b/components/drivers/sdio/sdio.c index f31f5b81a8..65bf87b895 100644 --- a/components/drivers/sdio/sdio.c +++ b/components/drivers/sdio/sdio.c @@ -709,6 +709,16 @@ static rt_int32_t sdio_initialize_function(struct rt_mmcsd_card *card, if (ret) goto err1; + /* + * product/manufacturer id is optional for function CIS, so + * copy it from the card structure as needed. + */ + if (func->product == 0) + { + func->manufacturer = card->cis.manufacturer; + func->product = card->cis.product; + } + card->sdio_function[func_num] = func; return 0; diff --git a/components/drivers/sensors/sensor.c b/components/drivers/sensors/sensor.c index e76ac51f12..91b256bd66 100644 --- a/components/drivers/sensors/sensor.c +++ b/components/drivers/sensors/sensor.c @@ -30,7 +30,7 @@ static char *const sensor_name_str[] = "hr_", /* Heart Rate */ "tvoc_", /* TVOC Level */ "noi_", /* Noise Loudness */ - "step_" /* Step sensor */ + "step_", /* Step sensor */ "forc_" /* Force sensor */ }; @@ -44,7 +44,7 @@ void rt_sensor_cb(rt_sensor_t sen) { return; } - + if (sen->irq_handle != RT_NULL) { sen->irq_handle(sen); @@ -69,7 +69,7 @@ void rt_sensor_cb(rt_sensor_t sen) /* ISR for sensor interrupt */ static void irq_callback(void *args) { - rt_sensor_t sensor = args; + rt_sensor_t sensor = (rt_sensor_t)args; rt_uint8_t i; if (sensor->module) @@ -116,30 +116,18 @@ static rt_err_t rt_sensor_irq_init(rt_sensor_t sensor) return 0; } -/* Sensor interrupt enable */ -static void rt_sensor_irq_enable(rt_sensor_t sensor) -{ - if (sensor->config.irq_pin.pin != RT_PIN_NONE) - { - rt_pin_irq_enable(sensor->config.irq_pin.pin, RT_TRUE); - } -} - -/* Sensor interrupt disable */ -static void rt_sensor_irq_disable(rt_sensor_t sensor) -{ - if (sensor->config.irq_pin.pin != RT_PIN_NONE) - { - rt_pin_irq_enable(sensor->config.irq_pin.pin, RT_FALSE); - } -} - /* RT-Thread Device Interface */ - -static rt_err_t rt_sensor_init(rt_device_t dev) +static rt_err_t rt_sensor_open(rt_device_t dev, rt_uint16_t oflag) { rt_sensor_t sensor = (rt_sensor_t)dev; RT_ASSERT(dev != RT_NULL); + rt_err_t res = RT_EOK; + + if (sensor->module) + { + /* take the module mutex */ + rt_mutex_take(sensor->module->lock, RT_WAITING_FOREVER); + } if (sensor->module != RT_NULL && sensor->info.fifo_max > 0 && sensor->data_buf == RT_NULL) { @@ -147,55 +135,46 @@ static rt_err_t rt_sensor_init(rt_device_t dev) sensor->data_buf = rt_malloc(sizeof(struct rt_sensor_data) * sensor->info.fifo_max); if (sensor->data_buf == RT_NULL) { - return -RT_ENOMEM; + res = -RT_ENOMEM; + goto __exit; } } - return RT_EOK; -} - -static rt_err_t rt_sensor_open(rt_device_t dev, rt_uint16_t oflag) -{ - rt_sensor_t sensor = (rt_sensor_t)dev; - RT_ASSERT(dev != RT_NULL); - - if (sensor->module) - { - /* take the module mutex */ - rt_mutex_take(sensor->module->lock, RT_WAITING_FOREVER); - } - if (oflag & RT_DEVICE_FLAG_RDONLY && dev->flag & RT_DEVICE_FLAG_RDONLY) { - /* If polling mode is supported, configure it to polling mode */ - if (sensor->ops->control(sensor, RT_SENSOR_CTRL_SET_MODE, (void *)RT_SENSOR_MODE_POLLING) == RT_EOK) + if (sensor->ops->control != RT_NULL) { - sensor->config.mode = RT_SENSOR_MODE_POLLING; + /* If polling mode is supported, configure it to polling mode */ + sensor->ops->control(sensor, RT_SENSOR_CTRL_SET_MODE, (void *)RT_SENSOR_MODE_POLLING); } + sensor->config.mode = RT_SENSOR_MODE_POLLING; } else if (oflag & RT_DEVICE_FLAG_INT_RX && dev->flag & RT_DEVICE_FLAG_INT_RX) { - /* If interrupt mode is supported, configure it to interrupt mode */ - if (sensor->ops->control(sensor, RT_SENSOR_CTRL_SET_MODE, (void *)RT_SENSOR_MODE_INT) == RT_EOK) + if (sensor->ops->control != RT_NULL) { - sensor->config.mode = RT_SENSOR_MODE_INT; - /* Initialization sensor interrupt */ - rt_sensor_irq_init(sensor); + /* If interrupt mode is supported, configure it to interrupt mode */ + sensor->ops->control(sensor, RT_SENSOR_CTRL_SET_MODE, (void *)RT_SENSOR_MODE_INT); } + /* Initialization sensor interrupt */ + rt_sensor_irq_init(sensor); + sensor->config.mode = RT_SENSOR_MODE_INT; } else if (oflag & RT_DEVICE_FLAG_FIFO_RX && dev->flag & RT_DEVICE_FLAG_FIFO_RX) { - /* If fifo mode is supported, configure it to fifo mode */ - if (sensor->ops->control(sensor, RT_SENSOR_CTRL_SET_MODE, (void *)RT_SENSOR_MODE_FIFO) == RT_EOK) + if (sensor->ops->control != RT_NULL) { - sensor->config.mode = RT_SENSOR_MODE_FIFO; - /* Initialization sensor interrupt */ - rt_sensor_irq_init(sensor); + /* If fifo mode is supported, configure it to fifo mode */ + sensor->ops->control(sensor, RT_SENSOR_CTRL_SET_MODE, (void *)RT_SENSOR_MODE_FIFO); } + /* Initialization sensor interrupt */ + rt_sensor_irq_init(sensor); + sensor->config.mode = RT_SENSOR_MODE_FIFO; } else { - return -RT_EINVAL; + res = -RT_EINVAL; + goto __exit; } /* Configure power mode to normal mode */ @@ -204,18 +183,21 @@ static rt_err_t rt_sensor_open(rt_device_t dev, rt_uint16_t oflag) sensor->config.power = RT_SENSOR_POWER_NORMAL; } +__exit: if (sensor->module) { /* release the module mutex */ rt_mutex_release(sensor->module->lock); } - return RT_EOK; + return res; } -static rt_err_t rt_sensor_close(rt_device_t dev) +static rt_err_t rt_sensor_close(rt_device_t dev) { rt_sensor_t sensor = (rt_sensor_t)dev; + int i; + RT_ASSERT(dev != RT_NULL); if (sensor->module) @@ -230,8 +212,31 @@ static rt_err_t rt_sensor_close(rt_device_t dev) } /* Sensor disable interrupt */ - rt_sensor_irq_disable(sensor); + if (sensor->config.irq_pin.pin != RT_PIN_NONE) + { + rt_pin_irq_enable(sensor->config.irq_pin.pin, RT_FALSE); + } + + if (sensor->module != RT_NULL && sensor->info.fifo_max > 0 && sensor->data_buf != RT_NULL) + { + for (i = 0; i < sensor->module->sen_num; i ++) + { + if (sensor->module->sen[i]->parent.ref_count > 0) + goto __exit; + } + /* Free memory for the sensor buffer */ + for (i = 0; i < sensor->module->sen_num; i ++) + { + if (sensor->module->sen[i]->data_buf != RT_NULL) + { + rt_free(sensor->module->sen[i]->data_buf); + sensor->module->sen[i]->data_buf = RT_NULL; + } + } + } + +__exit: if (sensor->module) { rt_mutex_release(sensor->module->lock); @@ -320,7 +325,7 @@ static rt_err_t rt_sensor_control(rt_device_t dev, int cmd, void *args) } break; case RT_SENSOR_CTRL_SET_ODR: - + /* Configuration data output rate */ result = sensor->ops->control(sensor, RT_SENSOR_CTRL_SET_ODR, args); if (result == RT_EOK) @@ -329,27 +334,8 @@ static rt_err_t rt_sensor_control(rt_device_t dev, int cmd, void *args) LOG_D("set odr %d", sensor->config.odr); } break; - case RT_SENSOR_CTRL_SET_MODE: - - /* Configuration sensor work mode */ - result = sensor->ops->control(sensor, RT_SENSOR_CTRL_SET_MODE, args); - if (result == RT_EOK) - { - sensor->config.mode = (rt_uint32_t)args & 0xFF; - LOG_D("set work mode code:", sensor->config.mode); - - if (sensor->config.mode == RT_SENSOR_MODE_POLLING) - { - rt_sensor_irq_disable(sensor); - } - else if (sensor->config.mode == RT_SENSOR_MODE_INT || sensor->config.mode == RT_SENSOR_MODE_FIFO) - { - rt_sensor_irq_enable(sensor); - } - } - break; case RT_SENSOR_CTRL_SET_POWER: - + /* Configuration sensor power mode */ result = sensor->ops->control(sensor, RT_SENSOR_CTRL_SET_POWER, args); if (result == RT_EOK) @@ -359,7 +345,7 @@ static rt_err_t rt_sensor_control(rt_device_t dev, int cmd, void *args) } break; case RT_SENSOR_CTRL_SELF_TEST: - + /* Device self-test */ result = sensor->ops->control(sensor, RT_SENSOR_CTRL_SELF_TEST, args); break; @@ -378,7 +364,7 @@ static rt_err_t rt_sensor_control(rt_device_t dev, int cmd, void *args) #ifdef RT_USING_DEVICE_OPS const static struct rt_device_ops rt_sensor_ops = { - rt_sensor_init, + RT_NULL, rt_sensor_open, rt_sensor_close, rt_sensor_read, @@ -403,7 +389,7 @@ int rt_hw_sensor_register(rt_sensor_t sensor, /* Add a type name for the sensor device */ sensor_name = sensor_name_str[sensor->info.type]; - device_name = rt_calloc(1, rt_strlen(sensor_name) + 1 + rt_strlen(name)); + device_name = (char *)rt_calloc(1, rt_strlen(sensor_name) + 1 + rt_strlen(name)); if (device_name == RT_NULL) { LOG_E("device_name calloc failed!"); @@ -429,7 +415,7 @@ int rt_hw_sensor_register(rt_sensor_t sensor, #ifdef RT_USING_DEVICE_OPS device->ops = &rt_sensor_ops; #else - device->init = rt_sensor_init; + device->init = RT_NULL; device->open = rt_sensor_open; device->close = rt_sensor_close; device->read = rt_sensor_read; @@ -444,10 +430,12 @@ int rt_hw_sensor_register(rt_sensor_t sensor, result = rt_device_register(device, device_name, flag | RT_DEVICE_FLAG_STANDALONE); if (result != RT_EOK) { + rt_free(device_name); LOG_E("rt_sensor register err code: %d", result); return result; } + rt_free(device_name); LOG_I("rt_sensor init success"); return RT_EOK; } diff --git a/components/drivers/sensors/sensor.h b/components/drivers/sensors/sensor.h index a9b6684457..9c6e5ecc55 100644 --- a/components/drivers/sensors/sensor.h +++ b/components/drivers/sensors/sensor.h @@ -55,6 +55,7 @@ extern "C" { #define RT_SENSOR_VENDOR_SEMTECH (4) /* Semtech */ #define RT_SENSOR_VENDOR_GOERTEK (5) /* Goertek */ #define RT_SENSOR_VENDOR_MIRAMEMS (6) /* MiraMEMS */ +#define RT_SENSOR_VENDOR_DALLAS (7) /* Dallas */ /* Sensor unit types */ diff --git a/components/drivers/sensors/sensor_cmd.c b/components/drivers/sensors/sensor_cmd.c index 6babf12db3..dd1aa1ef95 100644 --- a/components/drivers/sensors/sensor_cmd.c +++ b/components/drivers/sensors/sensor_cmd.c @@ -4,8 +4,9 @@ * SPDX-License-Identifier: Apache-2.0 * * Change Logs: - * Date Author Notes - * 2019-01-31 flybreak first version + * Date Author Notes + * 2019-01-31 flybreak first version + * 2019-07-16 WillianChan Increase the output of sensor information */ #include "sensor.h" @@ -55,7 +56,7 @@ static void sensor_show_data(rt_size_t num, rt_sensor_t sensor, struct rt_sensor } } -rt_err_t rx_callback(rt_device_t dev, rt_size_t size) +static rt_err_t rx_callback(rt_device_t dev, rt_size_t size) { rt_sem_release(sensor_rx_sem); return 0; @@ -63,15 +64,15 @@ rt_err_t rx_callback(rt_device_t dev, rt_size_t size) static void sensor_fifo_rx_entry(void *parameter) { - rt_device_t dev = parameter; - rt_sensor_t sensor = parameter; + rt_device_t dev = (rt_device_t)parameter; + rt_sensor_t sensor = (rt_sensor_t)parameter; struct rt_sensor_data *data = RT_NULL; struct rt_sensor_info info; rt_size_t res, i; rt_device_control(dev, RT_SENSOR_CTRL_GET_INFO, &info); - data = rt_malloc(sizeof(struct rt_sensor_data) * info.fifo_max); + data = (struct rt_sensor_data *)rt_malloc(sizeof(struct rt_sensor_data) * info.fifo_max); if (data == RT_NULL) { LOG_E("Memory allocation failed!"); @@ -137,8 +138,8 @@ MSH_CMD_EXPORT(sensor_fifo, Sensor fifo mode test function); static void sensor_irq_rx_entry(void *parameter) { - rt_device_t dev = parameter; - rt_sensor_t sensor = parameter; + rt_device_t dev = (rt_device_t)parameter; + rt_sensor_t sensor = (rt_sensor_t)parameter; struct rt_sensor_data data; rt_size_t res, i = 0; @@ -268,13 +269,88 @@ static void sensor(int argc, char **argv) else if (!strcmp(argv[1], "info")) { struct rt_sensor_info info; + if (dev == RT_NULL) + { + LOG_W("Please probe sensor device first!"); + return ; + } rt_device_control(dev, RT_SENSOR_CTRL_GET_INFO, &info); - rt_kprintf("vendor :%d\n", info.vendor); - rt_kprintf("model :%s\n", info.model); - rt_kprintf("unit :%d\n", info.unit); + switch (info.vendor) + { + case RT_SENSOR_VENDOR_UNKNOWN: + rt_kprintf("vendor :unknown vendor\n"); + break; + case RT_SENSOR_VENDOR_STM: + rt_kprintf("vendor :STMicroelectronics\n"); + break; + case RT_SENSOR_VENDOR_BOSCH: + rt_kprintf("vendor :Bosch\n"); + break; + case RT_SENSOR_VENDOR_INVENSENSE: + rt_kprintf("vendor :Invensense\n"); + break; + case RT_SENSOR_VENDOR_SEMTECH: + rt_kprintf("vendor :Semtech\n"); + break; + case RT_SENSOR_VENDOR_GOERTEK: + rt_kprintf("vendor :Goertek\n"); + break; + case RT_SENSOR_VENDOR_MIRAMEMS: + rt_kprintf("vendor :MiraMEMS\n"); + break; + case RT_SENSOR_VENDOR_DALLAS: + rt_kprintf("vendor :Dallas\n"); + break; + } + rt_kprintf("model :%s\n", info.model); + switch (info.unit) + { + case RT_SENSOR_UNIT_NONE: + rt_kprintf("unit :none\n"); + break; + case RT_SENSOR_UNIT_MG: + rt_kprintf("unit :mG\n"); + break; + case RT_SENSOR_UNIT_MDPS: + rt_kprintf("unit :mdps\n"); + break; + case RT_SENSOR_UNIT_MGAUSS: + rt_kprintf("unit :mGauss\n"); + break; + case RT_SENSOR_UNIT_LUX: + rt_kprintf("unit :lux\n"); + break; + case RT_SENSOR_UNIT_CM: + rt_kprintf("unit :cm\n"); + break; + case RT_SENSOR_UNIT_PA: + rt_kprintf("unit :pa\n"); + break; + case RT_SENSOR_UNIT_PERMILLAGE: + rt_kprintf("unit :permillage\n"); + break; + case RT_SENSOR_UNIT_DCELSIUS: + rt_kprintf("unit :Celsius\n"); + break; + case RT_SENSOR_UNIT_HZ: + rt_kprintf("unit :HZ\n"); + break; + case RT_SENSOR_UNIT_ONE: + rt_kprintf("unit :1\n"); + break; + case RT_SENSOR_UNIT_BPM: + rt_kprintf("unit :bpm\n"); + break; + case RT_SENSOR_UNIT_MM: + rt_kprintf("unit :mm\n"); + break; + case RT_SENSOR_UNIT_MN: + rt_kprintf("unit :mN\n"); + break; + } rt_kprintf("range_max :%d\n", info.range_max); rt_kprintf("range_min :%d\n", info.range_min); - rt_kprintf("period_min:%d\n", info.period_min); + rt_kprintf("period_min:%dms\n", info.period_min); rt_kprintf("fifo_max :%d\n", info.fifo_max); } else if (!strcmp(argv[1], "read")) diff --git a/components/drivers/serial/serial.c b/components/drivers/serial/serial.c index c3e96fc77b..50dd7e188b 100644 --- a/components/drivers/serial/serial.c +++ b/components/drivers/serial/serial.c @@ -327,6 +327,18 @@ rt_inline int _serial_int_tx(struct rt_serial_device *serial, const rt_uint8_t * return size - length; } +static void _serial_check_buffer_size(void) +{ + static rt_bool_t already_output = RT_FALSE; + + if (already_output == RT_FALSE) + { + LOG_W("Warning: There is no enough buffer for saving data," + " please increase the RT_SERIAL_RB_BUFSZ option."); + already_output = RT_TRUE; + } +} + #if defined(RT_USING_POSIX) || defined(RT_SERIAL_USING_DMA) static rt_size_t _serial_fifo_calc_recved_len(struct rt_serial_device *serial) { @@ -428,12 +440,11 @@ static void rt_dma_recv_update_put_index(struct rt_serial_device *serial, rt_siz } } - if(rx_fifo->is_full == RT_TRUE) + if(rx_fifo->is_full == RT_TRUE) { - rx_fifo->get_index = rx_fifo->put_index; - } - - if (rx_fifo->get_index >= serial->config.bufsz) rx_fifo->get_index = 0; + _serial_check_buffer_size(); + rx_fifo->get_index = rx_fifo->put_index; + } } /* @@ -791,16 +802,16 @@ static rt_size_t rt_serial_read(struct rt_device *dev, if (dev->open_flag & RT_DEVICE_FLAG_INT_RX) { - return _serial_int_rx(serial, buffer, size); + return _serial_int_rx(serial, (rt_uint8_t *)buffer, size); } #ifdef RT_SERIAL_USING_DMA else if (dev->open_flag & RT_DEVICE_FLAG_DMA_RX) { - return _serial_dma_rx(serial, buffer, size); + return _serial_dma_rx(serial, (rt_uint8_t *)buffer, size); } #endif /* RT_SERIAL_USING_DMA */ - return _serial_poll_rx(serial, buffer, size); + return _serial_poll_rx(serial, (rt_uint8_t *)buffer, size); } static rt_size_t rt_serial_write(struct rt_device *dev, @@ -817,17 +828,17 @@ static rt_size_t rt_serial_write(struct rt_device *dev, if (dev->open_flag & RT_DEVICE_FLAG_INT_TX) { - return _serial_int_tx(serial, buffer, size); + return _serial_int_tx(serial, (const rt_uint8_t *)buffer, size); } #ifdef RT_SERIAL_USING_DMA else if (dev->open_flag & RT_DEVICE_FLAG_DMA_TX) { - return _serial_dma_tx(serial, buffer, size); + return _serial_dma_tx(serial, (const rt_uint8_t *)buffer, size); } #endif /* RT_SERIAL_USING_DMA */ else { - return _serial_poll_tx(serial, buffer, size); + return _serial_poll_tx(serial, (const rt_uint8_t *)buffer, size); } } @@ -1172,6 +1183,8 @@ void rt_hw_serial_isr(struct rt_serial_device *serial, int event) rx_fifo->get_index += 1; rx_fifo->is_full = RT_TRUE; if (rx_fifo->get_index >= serial->config.bufsz) rx_fifo->get_index = 0; + + _serial_check_buffer_size(); } /* enable interrupt */ diff --git a/components/drivers/spi/SConscript b/components/drivers/spi/SConscript index b88671ebc9..e19f30861f 100644 --- a/components/drivers/spi/SConscript +++ b/components/drivers/spi/SConscript @@ -14,24 +14,9 @@ src_device = [] if GetDepend('RT_USING_SPI_WIFI'): src_device += ['spi_wifi_rw009.c'] -if GetDepend('RT_USING_W25QXX'): - src_device += ['spi_flash_w25qxx.c'] - -if GetDepend('RT_USING_W25QXX_MTD'): - src_device += ['spi_flash_w25qxx_mtd.c'] - if GetDepend('RT_USING_ENC28J60'): src_device += ['enc28j60.c'] -if GetDepend('RT_USING_AT45DBXX'): - src_device += ['spi_flash_at45dbxx.c'] - -if GetDepend('RT_USING_SST25VFXX'): - src_device += ['spi_flash_sst25vfxx.c'] - -if GetDepend('RT_USING_GD'): - src_device += ['spi_flash_gd.c'] - if GetDepend('RT_USING_SPI_MSD'): src_device += ['spi_msd.c'] diff --git a/components/drivers/spi/device_driver_list.txt b/components/drivers/spi/device_driver_list.txt index 2c9d6a16b8..939baa7531 100644 --- a/components/drivers/spi/device_driver_list.txt +++ b/components/drivers/spi/device_driver_list.txt @@ -5,11 +5,5 @@ http://www.rt-thread.com/ enc28j60.c/enc28j60.h http://www.microchip.com/ -spi_flash_at45dbxx.c/spi_flash_at45dbxx.h -http://www.atmel.com/ - -spi_flash_sst25vfxx.c/spi_flash_sst25vfxx.h -http://www.microchip.com/ - -spi_flash_w25qxx.c/spi_flash_w25qxx.h -http://www.winbond.com/ +spi_flash_sfud: Serial Flash Universal Driver +https://github.com/armink/SFUD
\ No newline at end of file diff --git a/components/drivers/spi/sfud/inc/sfud_cfg.h b/components/drivers/spi/sfud/inc/sfud_cfg.h index 051de6d577..3b7860062d 100644 --- a/components/drivers/spi/sfud/inc/sfud_cfg.h +++ b/components/drivers/spi/sfud/inc/sfud_cfg.h @@ -59,6 +59,6 @@ #define SFUD_USING_FLASH_INFO_TABLE #endif -#define SFUD_FLASH_DEVICE_TABLE {0} +#define SFUD_FLASH_DEVICE_TABLE {{0}} #endif /* _SFUD_CFG_H_ */ diff --git a/components/drivers/spi/sfud/inc/sfud_flash_def.h b/components/drivers/spi/sfud/inc/sfud_flash_def.h index 8922375557..13a0e702a8 100644 --- a/components/drivers/spi/sfud/inc/sfud_flash_def.h +++ b/components/drivers/spi/sfud/inc/sfud_flash_def.h @@ -124,6 +124,7 @@ typedef struct { {"AT45DB161E", SFUD_MF_ID_ATMEL, 0x26, 0x00, 2L*1024L*1024L, SFUD_WM_BYTE|SFUD_WM_DUAL_BUFFER, 512, 0x81}, \ {"W25Q40BV", SFUD_MF_ID_WINBOND, 0x40, 0x13, 512L*1024L, SFUD_WM_PAGE_256B, 4096, 0x20}, \ {"W25Q16BV", SFUD_MF_ID_WINBOND, 0x40, 0x15, 2L*1024L*1024L, SFUD_WM_PAGE_256B, 4096, 0x20}, \ + {"W25Q64DW", SFUD_MF_ID_WINBOND, 0x60, 0x17, 8L*1024L*1024L, SFUD_WM_PAGE_256B, 4096, 0x20}, \ {"W25Q128BV", SFUD_MF_ID_WINBOND, 0x40, 0x18, 16L*1024L*1024L, SFUD_WM_PAGE_256B, 4096, 0x20}, \ {"W25Q256FV", SFUD_MF_ID_WINBOND, 0x40, 0x19, 32L*1024L*1024L, SFUD_WM_PAGE_256B, 4096, 0x20}, \ {"SST25VF016B", SFUD_MF_ID_SST, 0x25, 0x41, 2L*1024L*1024L, SFUD_WM_BYTE|SFUD_WM_AAI, 4096, 0x20}, \ diff --git a/components/drivers/spi/spi_flash_at45dbxx.c b/components/drivers/spi/spi_flash_at45dbxx.c deleted file mode 100644 index 0a30f0a328..0000000000 --- a/components/drivers/spi/spi_flash_at45dbxx.c +++ /dev/null @@ -1,433 +0,0 @@ -/* - * Copyright (c) 2006-2018, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2011-12-16 aozima the first version - */ - -#include <stdint.h> -#include "spi_flash_at45dbxx.h" - -#define FLASH_DEBUG -#define DMA_BUFFER_SIZE 512 - -#ifdef FLASH_DEBUG -#define FLASH_TRACE rt_kprintf -#else -#define FLASH_TRACE(...) -#endif /**< #ifdef FLASH_DEBUG */ - -/* JEDEC Manufacturer’s ID */ -#define MF_ID (0x1F) /* atmel */ -#define DENSITY_CODE_011D (0x02) /* AT45DB011D Density Code : 00010 = 1-Mbit */ -#define DENSITY_CODE_021D (0x03) /* AT45DB021D Density Code : 00011 = 2-Mbit */ -#define DENSITY_CODE_041D (0x04) /* AT45DB041D Density Code : 00100 = 4-Mbit */ -#define DENSITY_CODE_081D (0x05) /* AT45DB081D Density Code : 00101 = 8-Mbit */ -#define DENSITY_CODE_161D (0x06) /* AT45DB161D Density Code : 00110 = 16-Mbit */ -#define DENSITY_CODE_321D (0x07) /* AT45DB321D Density Code : 00111 = 32-Mbit */ -#define DENSITY_CODE_642D (0x08) /* AT45DB642D Density Code : 01000 = 64-Mbit */ - -struct JEDEC_ID -{ - uint8_t manufacturer_id; /* Manufacturer ID */ - uint8_t density_code:5; /* Density Code */ - uint8_t family_code:3; /* Family Code */ - uint8_t version_code:5; /* Product Version Code */ - uint8_t mlc_code:3; /* MLC Code */ - uint8_t byte_count; /* Byte Count */ -}; - -#define AT45DB_BUFFER_1_WRITE 0x84 -#define AT45DB_BUFFER_2_WRITE 0x87 -#define AT45DB_BUFFER_1_READ 0xD4 -#define AT45DB_BUFFER_2_READ 0xD6 -#define AT45DB_B1_TO_MM_PAGE_PROG_WITH_ERASE 0x83 -#define AT45DB_B2_TO_MM_PAGE_PROG_WITH_ERASE 0x86 -#define AT45DB_MM_PAGE_TO_B1_XFER 0x53 -#define AT45DB_MM_PAGE_TO_B2_XFER 0x55 -#define AT45DB_PAGE_ERASE 0x81 -#define AT45DB_SECTOR_ERASE 0x7C -#define AT45DB_READ_STATE_REGISTER 0xD7 -#define AT45DB_MM_PAGE_READ 0xD2 -#define AT45DB_MM_PAGE_PROG_THRU_BUFFER1 0x82 -#define AT45DB_CMD_JEDEC_ID 0x9F - -static struct spi_flash_at45dbxx spi_flash_at45dbxx; - -/*****************************************************************************/ -/*Status Register Format: */ -/* ------------------------------------------------------------------------- */ -/* | bit7 | bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0 | */ -/* |--------|--------|--------|--------|--------|--------|--------|--------| */ -/* |RDY/BUSY| COMP | device density | X | X | */ -/* ------------------------------------------------------------------------- */ -/* 0:busy | | AT45DB041:0111 | protect|page size */ -/* 1:ready | | AT45DB161:1011 | */ -/* --------------------------------------------------------------------------*/ -/*****************************************************************************/ -static uint8_t AT45DB_StatusRegisterRead(void) -{ - return rt_spi_sendrecv8(spi_flash_at45dbxx.rt_spi_device, AT45DB_READ_STATE_REGISTER); -} - -static void wait_busy(void) -{ - uint16_t i = 0; - while (i++ < 10000) - { - if (AT45DB_StatusRegisterRead() & 0x80) - { - return; - } - } - FLASH_TRACE("\r\nSPI_FLASH timeout!!!\r\n"); -} - -/* RT-Thread Device Driver Interface */ -static rt_err_t AT45DB_flash_init(rt_device_t dev) -{ - return RT_EOK; -} - -static rt_err_t AT45DB_flash_open(rt_device_t dev, rt_uint16_t oflag) -{ - - return RT_EOK; -} - -static rt_err_t AT45DB_flash_close(rt_device_t dev) -{ - return RT_EOK; -} - -static rt_err_t AT45DB_flash_control(rt_device_t dev, int cmd, void *args) -{ - RT_ASSERT(dev != RT_NULL); - - if (cmd == RT_DEVICE_CTRL_BLK_GETGEOME) - { - struct rt_device_blk_geometry *geometry; - - geometry = (struct rt_device_blk_geometry *)args; - if (geometry == RT_NULL) return -RT_ERROR; - - geometry->bytes_per_sector = 512; - geometry->sector_count = 4096; - geometry->block_size = 4096; /* block erase: 4k */ - } - - return RT_EOK; -} - -static rt_size_t AT45DB_flash_read_page_256(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size) -{ - uint32_t index, nr; - uint8_t * read_buffer = buffer; - uint32_t page = pos; - - nr = size; - - for (index = 0; index < nr; index++) - { - uint8_t send_buffer[8]; - uint32_t i; - - for(i=0; i<sizeof(send_buffer); i++) - { - send_buffer[i] = 0; - } - - send_buffer[0] = AT45DB_MM_PAGE_READ; - send_buffer[1] = (uint8_t)(page >> 7); - send_buffer[2] = (uint8_t)(page << 1); - - rt_spi_send_then_recv(spi_flash_at45dbxx.rt_spi_device, send_buffer, 8, read_buffer, 256); - read_buffer += 256; - page++; - } - - return size; -} - -static rt_size_t AT45DB_flash_read_page_512(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size) -{ - uint32_t index, nr; - uint8_t * read_buffer = buffer; - uint32_t page = pos; - - nr = size; - - for (index = 0; index < nr; index++) - { - uint8_t send_buffer[8]; - uint32_t i; - - for(i=0; i<sizeof(send_buffer); i++) - { - send_buffer[i] = 0; - } - - send_buffer[0] = AT45DB_MM_PAGE_READ; - send_buffer[1] = (uint8_t)(page >> 6); - send_buffer[2] = (uint8_t)(page << 2); - - rt_spi_send_then_recv(spi_flash_at45dbxx.rt_spi_device, send_buffer, 8, read_buffer, 512); - read_buffer += 512; - page++; - } - - return size; -} - -static rt_size_t AT45DB_flash_read_page_1024(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size) -{ - uint32_t index, nr; - uint8_t * read_buffer = buffer; - uint32_t page = pos; - - nr = size; - - for (index = 0; index < nr; index++) - { - uint8_t send_buffer[8]; - uint32_t i; - - for(i=0; i<sizeof(send_buffer); i++) - { - send_buffer[i] = 0; - } - - send_buffer[0] = AT45DB_MM_PAGE_READ; - send_buffer[1] = (uint8_t)(page >> 5); - send_buffer[2] = (uint8_t)(page << 3); - - rt_spi_send_then_recv(spi_flash_at45dbxx.rt_spi_device, send_buffer, 8, read_buffer, 1024); - read_buffer += 1024; - page++; - } - - return size; -} - -static rt_size_t AT45DB_flash_write_page_256(rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size) -{ - rt_uint32_t index, nr; - const uint8_t * write_buffer = buffer; - uint32_t page = pos; - - nr = size; - - for (index = 0; index < nr; index++) - { - uint8_t send_buffer[4]; - - send_buffer[0] = AT45DB_MM_PAGE_PROG_THRU_BUFFER1; - send_buffer[1] = (uint8_t) (page >> 7); - send_buffer[2] = (uint8_t) (page << 1); - send_buffer[3] = 0; - - rt_spi_send_then_send(spi_flash_at45dbxx.rt_spi_device, send_buffer, 4, write_buffer, 256); - - write_buffer += 256; - page++; - - wait_busy(); - } - - return size; -} - -static rt_size_t AT45DB_flash_write_page_512(rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size) -{ - rt_uint32_t index, nr; - const uint8_t * write_buffer = buffer; - uint32_t page = pos; - - nr = size; - - for (index = 0; index < nr; index++) - { - uint8_t send_buffer[4]; - - send_buffer[0] = AT45DB_MM_PAGE_PROG_THRU_BUFFER1; - send_buffer[1] = (uint8_t) (page >> 6); - send_buffer[2] = (uint8_t) (page << 2); - send_buffer[3] = 0; - - rt_spi_send_then_send(spi_flash_at45dbxx.rt_spi_device, send_buffer, 4, write_buffer, 512); - - write_buffer += 512; - page++; - - wait_busy(); - } - - return size; -} - -static rt_size_t AT45DB_flash_write_page_1024(rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size) -{ - rt_uint32_t index, nr; - const uint8_t * write_buffer = buffer; - uint32_t page = pos; - - nr = size; - - for (index = 0; index < nr; index++) - { - uint8_t send_buffer[4]; - - send_buffer[0] = AT45DB_MM_PAGE_PROG_THRU_BUFFER1; - send_buffer[1] = (uint8_t) (page >> 5); - send_buffer[2] = (uint8_t) (page << 3); - send_buffer[3] = 0; - - rt_spi_send_then_send(spi_flash_at45dbxx.rt_spi_device, send_buffer, 4, write_buffer, 1024); - - write_buffer += 1024; - page++; - - wait_busy(); - } - - return size; -} - -rt_err_t at45dbxx_init(const char * flash_device_name, const char * spi_device_name) -{ - struct rt_spi_device * rt_spi_device; - struct JEDEC_ID * JEDEC_ID; - - rt_spi_device = (struct rt_spi_device *)rt_device_find(spi_device_name); - if(rt_spi_device == RT_NULL) - { - FLASH_TRACE("spi device %s not found!\r\n", spi_device_name); - return -RT_ENOSYS; - } - spi_flash_at45dbxx.rt_spi_device = rt_spi_device; - - /* config spi */ - { - struct rt_spi_configuration cfg; - cfg.data_width = 8; - cfg.mode = RT_SPI_MODE_0 | RT_SPI_MSB; /* SPI Compatible Modes 0 and 3 */ - cfg.max_hz = 66000000; /* Atmel RapidS Serial Interface: 66MHz Maximum Clock Frequency */ - rt_spi_configure(spi_flash_at45dbxx.rt_spi_device, &cfg); - } - - /* read JEDEC ID */ - { - uint8_t cmd; - uint8_t id_recv[6]; - JEDEC_ID = (struct JEDEC_ID *)id_recv; - - cmd = AT45DB_CMD_JEDEC_ID; - rt_spi_send_then_recv(spi_flash_at45dbxx.rt_spi_device, &cmd, 1, id_recv, 6); - - /**< 1FH = Atmel */ - /**< 001 = Atmel DataFlash */ - if(JEDEC_ID->manufacturer_id != 0x1F || JEDEC_ID->family_code != 0x01) - { - FLASH_TRACE("Manufacturer’s ID or Memory Type error!\r\n"); - FLASH_TRACE("JEDEC Read-ID Data : %02X %02X %02X\r\n", id_recv[0], id_recv[1], id_recv[2]); - return -RT_ENOSYS; - } - - if(JEDEC_ID->density_code == DENSITY_CODE_011D) - { - /**< AT45DB011D Density Code : 00010 = 1-Mbit */ - FLASH_TRACE("AT45DB011D detection\r\n"); - spi_flash_at45dbxx.geometry.bytes_per_sector = 256; /* Page Erase (256 Bytes) */ - spi_flash_at45dbxx.geometry.sector_count = 512; /* 1-Mbit / 8 / 256 = 512 */ - spi_flash_at45dbxx.geometry.block_size = 1024*2; /* Block Erase (2-Kbytes) */ - } - else if(JEDEC_ID->density_code == DENSITY_CODE_021D) - { - /**< AT45DB021D Density Code : 00011 = 2-Mbit */ - FLASH_TRACE("AT45DB021D detection\r\n"); - spi_flash_at45dbxx.geometry.bytes_per_sector = 256; /* Page Erase (256 Bytes) */ - spi_flash_at45dbxx.geometry.sector_count = 512*2; /* 2-Mbit / 8 / 256 = 1024 */ - spi_flash_at45dbxx.geometry.block_size = 1024*2; /* Block Erase (2-Kbytes) */ - } - else if(JEDEC_ID->density_code == DENSITY_CODE_041D) - { - /**< AT45DB041D Density Code : 00100 = 4-Mbit */ - FLASH_TRACE("AT45DB041D detection\r\n"); - spi_flash_at45dbxx.geometry.bytes_per_sector = 256; /* Page Erase (256 Bytes) */ - spi_flash_at45dbxx.geometry.sector_count = 512*4; /* 4-Mbit / 8 / 256 = 2048 */ - spi_flash_at45dbxx.geometry.block_size = 1024*2; /* Block Erase (2-Kbytes) */ - } - else if(JEDEC_ID->density_code == DENSITY_CODE_081D) - { - /**< AT45DB081D Density Code : 00101 = 8-Mbit */ - FLASH_TRACE("AT45DB081D detection\r\n"); - spi_flash_at45dbxx.geometry.bytes_per_sector = 256; /* Page Erase (256 Bytes) */ - spi_flash_at45dbxx.geometry.sector_count = 512*8; /* 8-Mbit / 8 / 256 = 4096 */ - spi_flash_at45dbxx.geometry.block_size = 1024*2; /* Block Erase (2-Kbytes) */ - } - else if(JEDEC_ID->density_code == DENSITY_CODE_161D) - { - /**< AT45DB161D Density Code : 00110 = 16-Mbit */ - FLASH_TRACE("AT45DB161D detection\r\n"); - spi_flash_at45dbxx.geometry.bytes_per_sector = 512; /* Page Erase (512 Bytes) */ - spi_flash_at45dbxx.geometry.sector_count = 256*16; /* 16-Mbit / 8 / 512 = 4096 */ - spi_flash_at45dbxx.geometry.block_size = 1024*4; /* Block Erase (4-Kbytes) */ - } - else if(JEDEC_ID->density_code == DENSITY_CODE_321D) - { - /**< AT45DB321D Density Code : 00111 = 32-Mbit */ - FLASH_TRACE("AT45DB321D detection\r\n"); - spi_flash_at45dbxx.geometry.bytes_per_sector = 512; /* Page Erase (512 Bytes) */ - spi_flash_at45dbxx.geometry.sector_count = 256*32; /* 32-Mbit / 8 / 512 = 8192 */ - spi_flash_at45dbxx.geometry.block_size = 1024*4; /* Block Erase (4-Kbytes) */ - } - else if(JEDEC_ID->density_code == DENSITY_CODE_642D) - { - /**< AT45DB642D Density Code : 01000 = 64-Mbit */ - FLASH_TRACE("AT45DB642D detection\r\n"); - spi_flash_at45dbxx.geometry.bytes_per_sector = 1024; /* Page Erase (1 Kbyte) */ - spi_flash_at45dbxx.geometry.sector_count = 128*64; /* 64-Mbit / 8 / 1024 = 8192 */ - spi_flash_at45dbxx.geometry.block_size = 1024*8; /* Block Erase (8 Kbytes) */ - } - else - { - FLASH_TRACE("Memory Capacity error!\r\n"); - return -RT_ENOSYS; - } - } - - /* register device */ - spi_flash_at45dbxx.flash_device.type = RT_Device_Class_Block; - spi_flash_at45dbxx.flash_device.init = AT45DB_flash_init; - spi_flash_at45dbxx.flash_device.open = AT45DB_flash_open; - spi_flash_at45dbxx.flash_device.close = AT45DB_flash_close; - spi_flash_at45dbxx.flash_device.control = AT45DB_flash_control; - - if(JEDEC_ID->density_code == DENSITY_CODE_642D) - { - spi_flash_at45dbxx.flash_device.read = AT45DB_flash_read_page_1024; - spi_flash_at45dbxx.flash_device.write = AT45DB_flash_write_page_1024; - } - else if(JEDEC_ID->density_code == DENSITY_CODE_161D - || JEDEC_ID->density_code == DENSITY_CODE_321D ) - { - spi_flash_at45dbxx.flash_device.read = AT45DB_flash_read_page_512; - spi_flash_at45dbxx.flash_device.write = AT45DB_flash_write_page_512; - } - else - { - spi_flash_at45dbxx.flash_device.read = AT45DB_flash_read_page_256; - spi_flash_at45dbxx.flash_device.write = AT45DB_flash_write_page_256; - } - - /* no private */ - spi_flash_at45dbxx.flash_device.user_data = RT_NULL; - - rt_device_register(&spi_flash_at45dbxx.flash_device, flash_device_name, - RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_STANDALONE); - - return RT_EOK; -} diff --git a/components/drivers/spi/spi_flash_at45dbxx.h b/components/drivers/spi/spi_flash_at45dbxx.h deleted file mode 100644 index d1bc1a2aeb..0000000000 --- a/components/drivers/spi/spi_flash_at45dbxx.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (c) 2006-2018, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2011-12-16 aozima the first version - */ - -#ifndef SPI_FLASH_AT45DBXX_H_INCLUDED -#define SPI_FLASH_AT45DBXX_H_INCLUDED - -#include <rtthread.h> -#include <drivers/spi.h> - -struct spi_flash_at45dbxx -{ - struct rt_device flash_device; - struct rt_device_blk_geometry geometry; - struct rt_spi_device * rt_spi_device; -}; - -extern rt_err_t at45dbxx_init(const char * flash_device_name, const char * spi_device_name); - - -#endif // SPI_FLASH_AT45DBXX_H_INCLUDED diff --git a/components/drivers/spi/spi_flash_gd.c b/components/drivers/spi/spi_flash_gd.c deleted file mode 100644 index 3c52035372..0000000000 --- a/components/drivers/spi/spi_flash_gd.c +++ /dev/null @@ -1,347 +0,0 @@ -/* - * Copyright (c) 2006-2018, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2015-10-11 fullhan copy from winbond flash - */ - -#include <stdint.h> -#include <rtthread.h> -#include <rtdevice.h> - -#include "spi_flash.h" -#include "spi_flash_gd.h" - -#define FLASH_DEBUG - -#ifdef FLASH_DEBUG -#define FLASH_TRACE rt_kprintf -#else -#define FLASH_TRACE(...) -#endif /* #ifdef FLASH_DEBUG */ - -#define PAGE_SIZE 4096 - -/* JEDEC Manufacturer's ID */ -#define MF_ID (0xC8) -/* JEDEC Device ID: Memory type and Capacity */ -#define MTC_GD25Q128 (0x4018) - -/* command list */ -#define CMD_WRSR (0x01) /* Write Status Register */ -#define CMD_PP (0x02) /* Page Program */ -#define CMD_READ (0x03) /* Read Data */ -#define CMD_WRDI (0x04) /* Write Disable */ -#define CMD_RDSR1 (0x05) /* Read Status Register-1 */ -#define CMD_WREN (0x06) /* Write Enable */ -#define CMD_FAST_READ (0x0B) /* Fast Read */ -#define CMD_ERASE_4K (0x20) /* Sector Erase:4K */ -#define CMD_RDSR2 (0x35) /* Read Status Register-2 */ -#define CMD_ERASE_32K (0x52) /* 32KB Block Erase */ -#define CMD_JEDEC_ID (0x9F) /* Read JEDEC ID */ -#define CMD_ERASE_full (0xC7) /* Chip Erase */ -#define CMD_ERASE_64K (0xD8) /* 64KB Block Erase */ - -#define DUMMY (0xFF) - -static struct spi_flash_device spi_flash_device; - -static void flash_lock(struct spi_flash_device * flash_device) -{ - rt_mutex_take(&flash_device->lock, RT_WAITING_FOREVER); -} - -static void flash_unlock(struct spi_flash_device * flash_device) -{ - rt_mutex_release(&flash_device->lock); -} - -static uint8_t w25qxx_read_status(void) -{ - return rt_spi_sendrecv8(spi_flash_device.rt_spi_device, CMD_RDSR1); -} - -static void w25qxx_wait_busy(void) -{ - while( w25qxx_read_status() & (0x01)); -} - -/** \brief read [size] byte from [offset] to [buffer] - * - * \param offset uint32_t unit : byte - * \param buffer uint8_t* - * \param size uint32_t unit : byte - * \return uint32_t byte for read - * - */ -static uint32_t w25qxx_read(uint32_t offset, uint8_t * buffer, uint32_t size) -{ - uint8_t send_buffer[4]; - - send_buffer[0] = CMD_WRDI; - rt_spi_send(spi_flash_device.rt_spi_device, send_buffer, 1); - - send_buffer[0] = CMD_READ; - send_buffer[1] = (uint8_t)(offset>>16); - send_buffer[2] = (uint8_t)(offset>>8); - send_buffer[3] = (uint8_t)(offset); - - rt_spi_send_then_recv(spi_flash_device.rt_spi_device, - send_buffer, 4, - buffer, size); - - return size; -} - -/** \brief write N page on [page] - * - * \param page_addr uint32_t unit : byte (4096 * N,1 page = 4096byte) - * \param buffer const uint8_t* - * \return uint32_t - * - */ -static uint32_t w25qxx_page_write(uint32_t page_addr, const uint8_t* buffer) -{ - uint32_t index; - uint8_t send_buffer[4]; - - RT_ASSERT((page_addr&0xFF) == 0); /* page addr must align to 256byte. */ - - send_buffer[0] = CMD_WREN; - rt_spi_send(spi_flash_device.rt_spi_device, send_buffer, 1); - - send_buffer[0] = CMD_ERASE_4K; - send_buffer[1] = (page_addr >> 16); - send_buffer[2] = (page_addr >> 8); - send_buffer[3] = (page_addr); - rt_spi_send(spi_flash_device.rt_spi_device, send_buffer, 4); - - w25qxx_wait_busy(); // wait erase done. - - for(index=0; index < (PAGE_SIZE / 256); index++) - { - send_buffer[0] = CMD_WREN; - rt_spi_send(spi_flash_device.rt_spi_device, send_buffer, 1); - - send_buffer[0] = CMD_PP; - send_buffer[1] = (uint8_t)(page_addr >> 16); - send_buffer[2] = (uint8_t)(page_addr >> 8); - send_buffer[3] = (uint8_t)(page_addr); - - rt_spi_send_then_send(spi_flash_device.rt_spi_device, - send_buffer, - 4, - buffer, - 256); - - buffer += 256; - page_addr += 256; - w25qxx_wait_busy(); - } - - send_buffer[0] = CMD_WRDI; - rt_spi_send(spi_flash_device.rt_spi_device, send_buffer, 1); - - return PAGE_SIZE; -} - -/* RT-Thread device interface */ -static rt_err_t w25qxx_flash_init(rt_device_t dev) -{ - return RT_EOK; -} - -static rt_err_t w25qxx_flash_open(rt_device_t dev, rt_uint16_t oflag) -{ - uint8_t send_buffer[3]; - - flash_lock((struct spi_flash_device *)dev); - - send_buffer[0] = CMD_WREN; - rt_spi_send(spi_flash_device.rt_spi_device, send_buffer, 1); - - send_buffer[0] = CMD_WRSR; - send_buffer[1] = 0; - send_buffer[2] = 0; - rt_spi_send(spi_flash_device.rt_spi_device, send_buffer, 3); - - w25qxx_wait_busy(); - - flash_unlock((struct spi_flash_device *)dev); - - return RT_EOK; -} - -static rt_err_t w25qxx_flash_close(rt_device_t dev) -{ - return RT_EOK; -} - -static rt_err_t w25qxx_flash_control(rt_device_t dev, int cmd, void *args) -{ - RT_ASSERT(dev != RT_NULL); - - if (cmd == RT_DEVICE_CTRL_BLK_GETGEOME) - { - struct rt_device_blk_geometry *geometry; - - geometry = (struct rt_device_blk_geometry *)args; - if (geometry == RT_NULL) return -RT_ERROR; - - geometry->bytes_per_sector = spi_flash_device.geometry.bytes_per_sector; - geometry->sector_count = spi_flash_device.geometry.sector_count; - geometry->block_size = spi_flash_device.geometry.block_size; - } - - return RT_EOK; -} - -static rt_size_t w25qxx_flash_read(rt_device_t dev, - rt_off_t pos, - void* buffer, - rt_size_t size) -{ - flash_lock((struct spi_flash_device *)dev); - - w25qxx_read(pos*spi_flash_device.geometry.bytes_per_sector, - buffer, - size*spi_flash_device.geometry.bytes_per_sector); - - flash_unlock((struct spi_flash_device *)dev); - - return size; -} - -static rt_size_t w25qxx_flash_write(rt_device_t dev, - rt_off_t pos, - const void* buffer, - rt_size_t size) -{ - rt_size_t i = 0; - rt_size_t block = size; - const uint8_t * ptr = buffer; - - flash_lock((struct spi_flash_device *)dev); - - while(block--) - { - w25qxx_page_write((pos + i)*spi_flash_device.geometry.bytes_per_sector, - ptr); - ptr += PAGE_SIZE; - i++; - } - - flash_unlock((struct spi_flash_device *)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; - - /* initialize mutex */ - if (rt_mutex_init(&spi_flash_device.lock, spi_device_name, RT_IPC_FLAG_FIFO) != RT_EOK) - { - rt_kprintf("init sd lock mutex failed\n"); - return -RT_ENOSYS; - } - - rt_spi_device = (struct rt_spi_device *)rt_device_find(spi_device_name); - if(rt_spi_device == RT_NULL) - { - FLASH_TRACE("spi device %s not found!\r\n", spi_device_name); - return -RT_ENOSYS; - } - spi_flash_device.rt_spi_device = rt_spi_device; - - /* config spi */ - { - struct rt_spi_configuration cfg; - cfg.data_width = 8; - cfg.mode = RT_SPI_MODE_0 | RT_SPI_MSB; /* SPI Compatible: Mode 0 and Mode 3 */ - cfg.max_hz = 50 * 1000 * 1000; /* 50M */ - rt_spi_configure(spi_flash_device.rt_spi_device, &cfg); - } - - /* init flash */ - { - rt_uint8_t cmd; - rt_uint8_t id_recv[3]; - uint16_t memory_type_capacity; - - flash_lock(&spi_flash_device); - - cmd = 0xFF; /* reset SPI FLASH, cancel all cmd in processing. */ - rt_spi_send(spi_flash_device.rt_spi_device, &cmd, 1); - - cmd = CMD_WRDI; - rt_spi_send(spi_flash_device.rt_spi_device, &cmd, 1); - - /* read flash id */ - cmd = CMD_JEDEC_ID; - rt_spi_send_then_recv(spi_flash_device.rt_spi_device, &cmd, 1, id_recv, 3); - - flash_unlock(&spi_flash_device); - - if(id_recv[0] != MF_ID) - { - FLASH_TRACE("Manufacturers ID error!\r\n"); - FLASH_TRACE("JEDEC Read-ID Data : %02X %02X %02X\r\n", id_recv[0], id_recv[1], id_recv[2]); - return -RT_ENOSYS; - } - - spi_flash_device.geometry.bytes_per_sector = 4096; - spi_flash_device.geometry.block_size = 4096; /* block erase: 4k */ - - /* get memory type and capacity */ - memory_type_capacity = id_recv[1]; - memory_type_capacity = (memory_type_capacity << 8) | id_recv[2]; - - if(memory_type_capacity == MTC_GD25Q128) - { - FLASH_TRACE("GD128 detection\r\n"); - spi_flash_device.geometry.sector_count = 4096; - } - else - { - FLASH_TRACE("Memory Capacity error!\r\n"); - return -RT_ENOSYS; - } - } - - /* 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; - - rt_device_register(&spi_flash_device.flash_device, flash_device_name, - RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_STANDALONE); - - return RT_EOK; -} diff --git a/components/drivers/spi/spi_flash_gd.h b/components/drivers/spi/spi_flash_gd.h deleted file mode 100644 index 904d976ed0..0000000000 --- a/components/drivers/spi/spi_flash_gd.h +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright (c) 2006-2018, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2015-10-11 fullhan copy from winbond flash - */ - -#ifndef SPI_FLASH_GD_H_ -#define SPI_FLASH_GD_H_ - -#include <rtthread.h> - -extern rt_err_t gd_init(const char * flash_device_name, const char * spi_device_name); - -#endif /* SPI_FLASH_GD_H_ */ diff --git a/components/drivers/spi/spi_flash_sfud.c b/components/drivers/spi/spi_flash_sfud.c index 7fa7de6ad5..ce67ce9a72 100644 --- a/components/drivers/spi/spi_flash_sfud.c +++ b/components/drivers/spi/spi_flash_sfud.c @@ -22,12 +22,17 @@ #endif /* RT_DEBUG_SFUD */ #ifndef RT_SFUD_DEFAULT_SPI_CFG + +#ifndef RT_SFUD_SPI_MAX_HZ +#define RT_SFUD_SPI_MAX_HZ 50000000 +#endif + /* read the JEDEC SFDP command must run at 50 MHz or less */ #define RT_SFUD_DEFAULT_SPI_CFG \ { \ .mode = RT_SPI_MODE_0 | RT_SPI_MSB, \ .data_width = 8, \ - .max_hz = 50 * 1000 * 1000, \ + .max_hz = RT_SFUD_SPI_MAX_HZ, \ } #endif diff --git a/components/drivers/spi/spi_flash_sst25vfxx.c b/components/drivers/spi/spi_flash_sst25vfxx.c deleted file mode 100644 index bd618a8e9b..0000000000 --- a/components/drivers/spi/spi_flash_sst25vfxx.c +++ /dev/null @@ -1,358 +0,0 @@ -/* - * Copyright (c) 2006-2018, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2011-12-16 aozima the first version - */ - -#include <stdint.h> -#include "spi_flash_sst25vfxx.h" - -#define FLASH_DEBUG - -#ifdef FLASH_DEBUG -#define FLASH_TRACE rt_kprintf -#else -#define FLASH_TRACE(...) -#endif /* #ifdef FLASH_DEBUG */ - -/* JEDEC Manufacturer’s ID */ -#define MF_ID (0xBF) -/* JEDEC Device ID : Memory Type */ -#define MT_ID (0x25) -/* JEDEC Device ID: Memory Capacity */ -#define MC_ID_SST25VF020B (0x8C) /* 2Mbit */ -#define MC_ID_SST25VF040B (0x8D) /* 4Mbit */ -#define MC_ID_SST25VF080B (0x8E) /* 8Mbit */ -#define MC_ID_SST25VF016B (0x41) /* 16Mbit */ -#define MC_ID_SST25VF032B (0x4A) /* 32Mbit */ -#define MC_ID_SST25VF064C (0x4B) /* 64Mbit */ - -/* command list */ -#define CMD_RDSR (0x05) -#define CMD_WRSR (0x01) -#define CMD_EWSR (0x50) -#define CMD_WRDI (0x04) -#define CMD_WREN (0x06) -#define CMD_READ (0x03) -#define CMD_FAST_READ (0x0B) -#define CMD_BP (0x02) -#define CMD_AAIP (0xAD) -#define CMD_ERASE_4K (0x20) -#define CMD_ERASE_32K (0x52) -#define CMD_ERASE_64K (0xD8) -#define CMD_ERASE_full (0xC7) -#define CMD_JEDEC_ID (0x9F) -#define CMD_EBSY (0x70) -#define CMD_DBSY (0x80) - -#define DUMMY (0xFF) - -static struct spi_flash_sst25vfxx spi_flash_sst25vfxx; - -static uint8_t sst25vfxx_read_status(struct spi_flash_sst25vfxx * spi_flash) -{ - return rt_spi_sendrecv8(spi_flash->rt_spi_device, CMD_RDSR); -} - -static void sst25vfxx_wait_busy(struct spi_flash_sst25vfxx * spi_flash) -{ - while( sst25vfxx_read_status(spi_flash) & (0x01)); -} - -/** \brief write N page on [page] - * - * \param page uint32_t unit : byte (4096 * N,1 page = 4096byte) - * \param buffer const uint8_t* - * \param size uint32_t unit : byte ( 4096*N ) - * \return uint32_t - * - */ -static uint32_t sst25vfxx_page_write(struct spi_flash_sst25vfxx * spi_flash, uint32_t page, const uint8_t * buffer, uint32_t size) -{ - uint32_t index; - uint32_t need_wirte = size; - uint8_t send_buffer[6]; - - page &= ~0xFFF; // page size = 4096byte - - send_buffer[0] = CMD_WREN; - rt_spi_send(spi_flash->rt_spi_device, send_buffer, 1); - - send_buffer[0] = CMD_ERASE_4K; - send_buffer[1] = (page >> 16); - send_buffer[2] = (page >> 8); - send_buffer[3] = (page); - rt_spi_send(spi_flash->rt_spi_device, send_buffer, 4); - - sst25vfxx_wait_busy(spi_flash); // wait erase done. - - send_buffer[0] = CMD_WREN; - rt_spi_send(spi_flash->rt_spi_device, send_buffer, 1); - - send_buffer[0] = CMD_AAIP; - send_buffer[1] = (uint8_t)(page >> 16); - send_buffer[2] = (uint8_t)(page >> 8); - send_buffer[3] = (uint8_t)(page); - send_buffer[4] = *buffer++; - send_buffer[5] = *buffer++; - need_wirte -= 2; - rt_spi_send(spi_flash->rt_spi_device, send_buffer, 6); - - sst25vfxx_wait_busy(spi_flash); - - for(index=0; index < need_wirte/2; index++) - { - send_buffer[0] = CMD_AAIP; - send_buffer[1] = *buffer++; - send_buffer[2] = *buffer++; - rt_spi_send(spi_flash->rt_spi_device, send_buffer, 3); - sst25vfxx_wait_busy(spi_flash); - } - - send_buffer[0] = CMD_WRDI; - rt_spi_send(spi_flash->rt_spi_device, send_buffer, 1); - - return size; -} - -/* RT-Thread device interface */ -static rt_err_t sst25vfxx_flash_init(rt_device_t dev) -{ - return RT_EOK; -} - -static rt_err_t sst25vfxx_flash_open(rt_device_t dev, rt_uint16_t oflag) -{ - rt_err_t result; - uint8_t send_buffer[2]; - struct spi_flash_sst25vfxx * spi_flash = (struct spi_flash_sst25vfxx *)dev; - - /* lock spi flash */ - result = rt_mutex_take(&(spi_flash->lock), RT_WAITING_FOREVER); - if(result != RT_EOK) - { - return result; - } - - send_buffer[0] = CMD_DBSY; - rt_spi_send(spi_flash->rt_spi_device, send_buffer, 1); - - send_buffer[0] = CMD_EWSR; - rt_spi_send(spi_flash->rt_spi_device, send_buffer, 1); - - send_buffer[0] = CMD_WRSR; - send_buffer[1] = 0; - rt_spi_send(spi_flash->rt_spi_device, send_buffer, 2); - - /* release lock */ - rt_mutex_release(&(spi_flash->lock)); - - return RT_EOK; -} - -static rt_err_t sst25vfxx_flash_close(rt_device_t dev) -{ - return RT_EOK; -} - -static rt_err_t sst25vfxx_flash_control(rt_device_t dev, int cmd, void *args) -{ - struct spi_flash_sst25vfxx * spi_flash; - - spi_flash = (struct spi_flash_sst25vfxx *)dev; - - RT_ASSERT(dev != RT_NULL); - - if (cmd == RT_DEVICE_CTRL_BLK_GETGEOME) - { - struct rt_device_blk_geometry *geometry; - - geometry = (struct rt_device_blk_geometry *)args; - if (geometry == RT_NULL) return -RT_ERROR; - - geometry->bytes_per_sector = spi_flash->geometry.bytes_per_sector; - geometry->sector_count = spi_flash->geometry.sector_count; - geometry->block_size = spi_flash->geometry.block_size; - } - - return RT_EOK; -} - -static rt_size_t sst25vfxx_flash_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size) -{ - rt_err_t result; - uint8_t send_buffer[4]; - struct spi_flash_sst25vfxx * spi_flash = (struct spi_flash_sst25vfxx *)dev; - uint32_t offset = pos * spi_flash->geometry.bytes_per_sector; - - /* lock spi flash */ - result = rt_mutex_take(&(spi_flash->lock), RT_WAITING_FOREVER); - if(result != RT_EOK) - { - return 0; - } - - send_buffer[0] = CMD_WRDI; - rt_spi_send(spi_flash->rt_spi_device, send_buffer, 1); - - send_buffer[0] = CMD_READ; - send_buffer[1] = (uint8_t)(offset>>16); - send_buffer[2] = (uint8_t)(offset>>8); - send_buffer[3] = (uint8_t)(offset); - rt_spi_send_then_recv(spi_flash->rt_spi_device, send_buffer, 4, buffer, size * spi_flash->geometry.bytes_per_sector); - - /* release lock */ - rt_mutex_release(&(spi_flash->lock)); - - return size; -} - -static rt_size_t sst25vfxx_flash_write(rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size) -{ - uint32_t i; - rt_err_t result; - const uint8_t * write_buffer = buffer; - struct spi_flash_sst25vfxx * spi_flash = (struct spi_flash_sst25vfxx *)dev; - - /* lock spi flash */ - result = rt_mutex_take(&(spi_flash->lock), RT_WAITING_FOREVER); - if(result != RT_EOK) - { - return 0; - } - - for(i=0; i<size; i++) - { - sst25vfxx_page_write(spi_flash, - (pos + i) * spi_flash->geometry.bytes_per_sector, - write_buffer, - spi_flash->geometry.bytes_per_sector); - write_buffer += spi_flash->geometry.bytes_per_sector; - } - - /* release lock */ - rt_mutex_release(&(spi_flash->lock)); - - 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; - struct spi_flash_sst25vfxx * spi_flash = &spi_flash_sst25vfxx; - - rt_spi_device = (struct rt_spi_device *)rt_device_find(spi_device_name); - if(rt_spi_device == RT_NULL) - { - FLASH_TRACE("spi device %s not found!\r\n", spi_device_name); - return -RT_ENOSYS; - } - spi_flash->rt_spi_device = rt_spi_device; - - /* config spi */ - { - struct rt_spi_configuration cfg; - cfg.data_width = 8; - cfg.mode = RT_SPI_MODE_0 | RT_SPI_MSB; /* SPI Compatible: Mode 0 and Mode 3 */ - cfg.max_hz = 50000000; /* 50M */ - rt_spi_configure(spi_flash->rt_spi_device, &cfg); - } - - /* init flash */ - { - rt_uint8_t cmd; - rt_uint8_t id_recv[3]; - - cmd = CMD_WRDI; - rt_spi_send(spi_flash->rt_spi_device, &cmd, 1); - - /* read flash id */ - cmd = CMD_JEDEC_ID; - rt_spi_send_then_recv(spi_flash->rt_spi_device, &cmd, 1, id_recv, 3); - - if(id_recv[0] != MF_ID || id_recv[1] != MT_ID) - { - FLASH_TRACE("Manufacturer’s ID or Memory Type error!\r\n"); - FLASH_TRACE("JEDEC Read-ID Data : %02X %02X %02X\r\n", id_recv[0], id_recv[1], id_recv[2]); - return -RT_ENOSYS; - } - - spi_flash->geometry.bytes_per_sector = 4096; - spi_flash->geometry.block_size = 4096; /* block erase: 4k */ - - if(id_recv[2] == MC_ID_SST25VF020B) - { - FLASH_TRACE("SST25VF020B detection\r\n"); - spi_flash->geometry.sector_count = 64; - } - else if(id_recv[2] == MC_ID_SST25VF040B) - { - FLASH_TRACE("SST25VF040B detection\r\n"); - spi_flash->geometry.sector_count = 128; - } - else if(id_recv[2] == MC_ID_SST25VF080B) - { - FLASH_TRACE("SST25VF080B detection\r\n"); - spi_flash->geometry.sector_count = 256; - } - else if(id_recv[2] == MC_ID_SST25VF016B) - { - FLASH_TRACE("SST25VF016B detection\r\n"); - spi_flash->geometry.sector_count = 512; - } - else if(id_recv[2] == MC_ID_SST25VF032B) - { - FLASH_TRACE("SST25VF032B detection\r\n"); - spi_flash->geometry.sector_count = 1024; - } - else if(id_recv[2] == MC_ID_SST25VF064C) - { - FLASH_TRACE("SST25VF064C detection\r\n"); - spi_flash->geometry.sector_count = 2048; - } - else - { - FLASH_TRACE("Memory Capacity error!\r\n"); - return -RT_ENOSYS; - } - } - - /* initialize mutex lock */ - rt_mutex_init(&spi_flash->lock, flash_device_name, RT_IPC_FLAG_PRIO); - - /* 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; - - rt_device_register(&spi_flash->flash_device, flash_device_name, - RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_STANDALONE); - - return RT_EOK; -} diff --git a/components/drivers/spi/spi_flash_sst25vfxx.h b/components/drivers/spi/spi_flash_sst25vfxx.h deleted file mode 100644 index 7a7283f753..0000000000 --- a/components/drivers/spi/spi_flash_sst25vfxx.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) 2006-2018, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2011-12-16 aozima the first version - */ - -#ifndef SPI_FLASH_SST25VFXX_H_INCLUDED -#define SPI_FLASH_SST25VFXX_H_INCLUDED - -#include <rtthread.h> -#include <drivers/spi.h> - -struct spi_flash_sst25vfxx -{ - struct rt_device flash_device; - struct rt_device_blk_geometry geometry; - struct rt_spi_device * rt_spi_device; - struct rt_mutex lock; -}; - -extern rt_err_t sst25vfxx_init(const char * flash_device_name, const char * spi_device_name); - - -#endif // SPI_FLASH_SST25VFXX_H_INCLUDED diff --git a/components/drivers/spi/spi_flash_w25qxx.c b/components/drivers/spi/spi_flash_w25qxx.c deleted file mode 100644 index bba9c0b5cc..0000000000 --- a/components/drivers/spi/spi_flash_w25qxx.c +++ /dev/null @@ -1,393 +0,0 @@ -/* - * Copyright (c) 2006-2018, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2011-12-16 aozima the first version - * 2012-05-06 aozima can page write. - * 2012-08-23 aozima add flash lock. - * 2012-08-24 aozima fixed write status register BUG. - */ - -#include <stdint.h> -#include <rtdevice.h> - -#include "spi_flash.h" -#include "spi_flash_w25qxx.h" - -#define FLASH_DEBUG - -#ifdef FLASH_DEBUG -#define FLASH_TRACE rt_kprintf -#else -#define FLASH_TRACE(...) -#endif /* #ifdef FLASH_DEBUG */ - -#define PAGE_SIZE 4096 - -/* JEDEC Manufacturer ID */ -#define MF_ID (0xEF) - -/* JEDEC Device ID: Memory type and Capacity */ -#define MTC_W25Q80_BV (0x4014) /* W25Q80BV */ -#define MTC_W25Q16_BV_CL_CV (0x4015) /* W25Q16BV W25Q16CL W25Q16CV */ -#define MTC_W25Q16_DW (0x6015) /* W25Q16DW */ -#define MTC_W25Q32_BV (0x4016) /* W25Q32BV */ -#define MTC_W25Q32_DW (0x6016) /* W25Q32DW */ -#define MTC_W25Q64_BV_CV (0x4017) /* W25Q64BV W25Q64CV */ -#define MTC_W25Q64_DW (0x4017) /* W25Q64DW */ -#define MTC_W25Q128_BV (0x4018) /* W25Q128BV */ -#define MTC_W25Q256_FV (TBD) /* W25Q256FV */ - -/* command list */ -#define CMD_WRSR (0x01) /* Write Status Register */ -#define CMD_PP (0x02) /* Page Program */ -#define CMD_READ (0x03) /* Read Data */ -#define CMD_WRDI (0x04) /* Write Disable */ -#define CMD_RDSR1 (0x05) /* Read Status Register-1 */ -#define CMD_WREN (0x06) /* Write Enable */ -#define CMD_FAST_READ (0x0B) /* Fast Read */ -#define CMD_ERASE_4K (0x20) /* Sector Erase:4K */ -#define CMD_RDSR2 (0x35) /* Read Status Register-2 */ -#define CMD_ERASE_32K (0x52) /* 32KB Block Erase */ -#define CMD_JEDEC_ID (0x9F) /* Read JEDEC ID */ -#define CMD_ERASE_full (0xC7) /* Chip Erase */ -#define CMD_ERASE_64K (0xD8) /* 64KB Block Erase */ - -#define DUMMY (0xFF) - -static struct spi_flash_device spi_flash_device; - -static void flash_lock(struct spi_flash_device * flash_device) -{ - rt_mutex_take(&flash_device->lock, RT_WAITING_FOREVER); -} - -static void flash_unlock(struct spi_flash_device * flash_device) -{ - rt_mutex_release(&flash_device->lock); -} - -static uint8_t w25qxx_read_status(void) -{ - return rt_spi_sendrecv8(spi_flash_device.rt_spi_device, CMD_RDSR1); -} - -static void w25qxx_wait_busy(void) -{ - while( w25qxx_read_status() & (0x01)); -} - -/** \brief read [size] byte from [offset] to [buffer] - * - * \param offset uint32_t unit : byte - * \param buffer uint8_t* - * \param size uint32_t unit : byte - * \return uint32_t byte for read - * - */ -static uint32_t w25qxx_read(uint32_t offset, uint8_t * buffer, uint32_t size) -{ - uint8_t send_buffer[4]; - - send_buffer[0] = CMD_WRDI; - rt_spi_send(spi_flash_device.rt_spi_device, send_buffer, 1); - - send_buffer[0] = CMD_READ; - send_buffer[1] = (uint8_t)(offset>>16); - send_buffer[2] = (uint8_t)(offset>>8); - send_buffer[3] = (uint8_t)(offset); - - rt_spi_send_then_recv(spi_flash_device.rt_spi_device, - send_buffer, 4, - buffer, size); - - return size; -} - -/** \brief write N page on [page] - * - * \param page_addr uint32_t unit : byte (4096 * N,1 page = 4096byte) - * \param buffer const uint8_t* - * \return uint32_t - * - */ -uint32_t w25qxx_page_write(uint32_t page_addr, const uint8_t* buffer) -{ - uint32_t index; - uint8_t send_buffer[4]; - - RT_ASSERT((page_addr&0xFF) == 0); /* page addr must align to 256byte. */ - - send_buffer[0] = CMD_WREN; - rt_spi_send(spi_flash_device.rt_spi_device, send_buffer, 1); - - send_buffer[0] = CMD_ERASE_4K; - send_buffer[1] = (page_addr >> 16); - send_buffer[2] = (page_addr >> 8); - send_buffer[3] = (page_addr); - rt_spi_send(spi_flash_device.rt_spi_device, send_buffer, 4); - - w25qxx_wait_busy(); // wait erase done. - - for(index=0; index < (PAGE_SIZE / 256); index++) - { - send_buffer[0] = CMD_WREN; - rt_spi_send(spi_flash_device.rt_spi_device, send_buffer, 1); - - send_buffer[0] = CMD_PP; - send_buffer[1] = (uint8_t)(page_addr >> 16); - send_buffer[2] = (uint8_t)(page_addr >> 8); - send_buffer[3] = (uint8_t)(page_addr); - - rt_spi_send_then_send(spi_flash_device.rt_spi_device, - send_buffer, - 4, - buffer, - 256); - - buffer += 256; - page_addr += 256; - w25qxx_wait_busy(); - } - - send_buffer[0] = CMD_WRDI; - rt_spi_send(spi_flash_device.rt_spi_device, send_buffer, 1); - - return PAGE_SIZE; -} - -/* RT-Thread device interface */ -static rt_err_t w25qxx_flash_init(rt_device_t dev) -{ - return RT_EOK; -} - -static rt_err_t w25qxx_flash_open(rt_device_t dev, rt_uint16_t oflag) -{ - uint8_t send_buffer[3]; - - flash_lock((struct spi_flash_device *)dev); - - send_buffer[0] = CMD_WREN; - rt_spi_send(spi_flash_device.rt_spi_device, send_buffer, 1); - - send_buffer[0] = CMD_WRSR; - send_buffer[1] = 0; - send_buffer[2] = 0; - rt_spi_send(spi_flash_device.rt_spi_device, send_buffer, 3); - - w25qxx_wait_busy(); - - flash_unlock((struct spi_flash_device *)dev); - - return RT_EOK; -} - -static rt_err_t w25qxx_flash_close(rt_device_t dev) -{ - return RT_EOK; -} - -static rt_err_t w25qxx_flash_control(rt_device_t dev, int cmd, void *args) -{ - RT_ASSERT(dev != RT_NULL); - - if (cmd == RT_DEVICE_CTRL_BLK_GETGEOME) - { - struct rt_device_blk_geometry *geometry; - - geometry = (struct rt_device_blk_geometry *)args; - if (geometry == RT_NULL) return -RT_ERROR; - - geometry->bytes_per_sector = spi_flash_device.geometry.bytes_per_sector; - geometry->sector_count = spi_flash_device.geometry.sector_count; - geometry->block_size = spi_flash_device.geometry.block_size; - } - - return RT_EOK; -} - -static rt_size_t w25qxx_flash_read(rt_device_t dev, - rt_off_t pos, - void* buffer, - rt_size_t size) -{ - flash_lock((struct spi_flash_device *)dev); - - w25qxx_read(pos*spi_flash_device.geometry.bytes_per_sector, - buffer, - size*spi_flash_device.geometry.bytes_per_sector); - - flash_unlock((struct spi_flash_device *)dev); - - return size; -} - -static rt_size_t w25qxx_flash_write(rt_device_t dev, - rt_off_t pos, - const void* buffer, - rt_size_t size) -{ - rt_size_t i = 0; - rt_size_t block = size; - const uint8_t * ptr = buffer; - - flash_lock((struct spi_flash_device *)dev); - - while(block--) - { - w25qxx_page_write((pos + i)*spi_flash_device.geometry.bytes_per_sector, - ptr); - ptr += PAGE_SIZE; - i++; - } - - flash_unlock((struct spi_flash_device *)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; - - /* initialize mutex */ - if (rt_mutex_init(&spi_flash_device.lock, spi_device_name, RT_IPC_FLAG_FIFO) != RT_EOK) - { - rt_kprintf("init sd lock mutex failed\n"); - return -RT_ENOSYS; - } - - rt_spi_device = (struct rt_spi_device *)rt_device_find(spi_device_name); - if(rt_spi_device == RT_NULL) - { - FLASH_TRACE("spi device %s not found!\r\n", spi_device_name); - return -RT_ENOSYS; - } - spi_flash_device.rt_spi_device = rt_spi_device; - - /* config spi */ - { - struct rt_spi_configuration cfg; - cfg.data_width = 8; - cfg.mode = RT_SPI_MODE_0 | RT_SPI_MSB; /* SPI Compatible: Mode 0 and Mode 3 */ - cfg.max_hz = 50 * 1000 * 1000; /* 50M */ - rt_spi_configure(spi_flash_device.rt_spi_device, &cfg); - } - - /* init flash */ - { - rt_uint8_t cmd; - rt_uint8_t id_recv[3]; - uint16_t memory_type_capacity; - - flash_lock(&spi_flash_device); - - cmd = 0xFF; /* reset SPI FLASH, cancel all cmd in processing. */ - rt_spi_send(spi_flash_device.rt_spi_device, &cmd, 1); - - cmd = CMD_WRDI; - rt_spi_send(spi_flash_device.rt_spi_device, &cmd, 1); - - /* read flash id */ - cmd = CMD_JEDEC_ID; - rt_spi_send_then_recv(spi_flash_device.rt_spi_device, &cmd, 1, id_recv, 3); - - flash_unlock(&spi_flash_device); - - if(id_recv[0] != MF_ID) - { - FLASH_TRACE("Manufacturers ID error!\r\n"); - FLASH_TRACE("JEDEC Read-ID Data : %02X %02X %02X\r\n", id_recv[0], id_recv[1], id_recv[2]); - return -RT_ENOSYS; - } - - spi_flash_device.geometry.bytes_per_sector = 4096; - spi_flash_device.geometry.block_size = 4096; /* block erase: 4k */ - - /* get memory type and capacity */ - memory_type_capacity = id_recv[1]; - memory_type_capacity = (memory_type_capacity << 8) | id_recv[2]; - - if(memory_type_capacity == MTC_W25Q128_BV) - { - FLASH_TRACE("W25Q128BV detection\r\n"); - spi_flash_device.geometry.sector_count = 4096; - } - else if(memory_type_capacity == MTC_W25Q64_BV_CV) - { - FLASH_TRACE("W25Q64BV or W25Q64CV detection\r\n"); - spi_flash_device.geometry.sector_count = 2048; - } - else if(memory_type_capacity == MTC_W25Q64_DW) - { - FLASH_TRACE("W25Q64DW detection\r\n"); - spi_flash_device.geometry.sector_count = 2048; - } - else if(memory_type_capacity == MTC_W25Q32_BV) - { - FLASH_TRACE("W25Q32BV detection\r\n"); - spi_flash_device.geometry.sector_count = 1024; - } - else if(memory_type_capacity == MTC_W25Q32_DW) - { - FLASH_TRACE("W25Q32DW detection\r\n"); - spi_flash_device.geometry.sector_count = 1024; - } - else if(memory_type_capacity == MTC_W25Q16_BV_CL_CV) - { - FLASH_TRACE("W25Q16BV or W25Q16CL or W25Q16CV detection\r\n"); - spi_flash_device.geometry.sector_count = 512; - } - else if(memory_type_capacity == MTC_W25Q16_DW) - { - FLASH_TRACE("W25Q16DW detection\r\n"); - spi_flash_device.geometry.sector_count = 512; - } - else if(memory_type_capacity == MTC_W25Q80_BV) - { - FLASH_TRACE("W25Q80BV detection\r\n"); - spi_flash_device.geometry.sector_count = 256; - } - else - { - FLASH_TRACE("Memory Capacity error!\r\n"); - return -RT_ENOSYS; - } - } - - /* 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; - - rt_device_register(&spi_flash_device.flash_device, flash_device_name, - RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_STANDALONE); - - return RT_EOK; -} diff --git a/components/drivers/spi/spi_flash_w25qxx.h b/components/drivers/spi/spi_flash_w25qxx.h deleted file mode 100644 index 14837bc87c..0000000000 --- a/components/drivers/spi/spi_flash_w25qxx.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright (c) 2006-2018, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2011-12-16 aozima the first version - * 2012-08-23 aozima add flash lock. - */ - -#ifndef SPI_FLASH_W25QXX_H_INCLUDED -#define SPI_FLASH_W25QXX_H_INCLUDED - -#include <rtthread.h> - -extern rt_err_t w25qxx_init(const char * flash_device_name, - const char * spi_device_name); - -#endif // SPI_FLASH_W25QXX_H_INCLUDED diff --git a/components/drivers/spi/spi_flash_w25qxx_mtd.c b/components/drivers/spi/spi_flash_w25qxx_mtd.c deleted file mode 100644 index 9f1ef802f6..0000000000 --- a/components/drivers/spi/spi_flash_w25qxx_mtd.c +++ /dev/null @@ -1,336 +0,0 @@ -/* - * Copyright (c) 2006-2018, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - */ -#include <rtthread.h> -#include <rtdevice.h> - -#include "spi_flash.h" -#include "spi_flash_w25qxx_mtd.h" - -#include <stdint.h> -#include <stdio.h> -#include <string.h> -#include <stdlib.h> - -#define FLASH_DEBUG - -#ifdef FLASH_DEBUG -#define FLASH_TRACE printf -#else -#define FLASH_TRACE(...) -#endif /* #ifdef FLASH_DEBUG */ - -/* JEDEC Manufacturer’s ID */ -#define MF_ID (0xEF) -/* JEDEC Device ID: Memory type and Capacity */ -#define MTC_W25Q80_BV (0x4014) /* W25Q80BV */ -#define MTC_W25Q16_BV_CL_CV (0x4015) /* W25Q16BV W25Q16CL W25Q16CV */ -#define MTC_W25Q16_DW (0x6015) /* W25Q16DW */ -#define MTC_W25Q32_BV (0x4016) /* W25Q32BV */ -#define MTC_W25Q32_DW (0x6016) /* W25Q32DW */ -#define MTC_W25Q64_BV_CV (0x4017) /* W25Q64BV W25Q64CV */ -#define MTC_W25Q64_DW (0x4017) /* W25Q64DW */ -#define MTC_W25Q128_BV (0x4018) /* W25Q128BV */ -#define MTC_W25Q256_FV (TBD) /* W25Q256FV */ - -#define MTC_W25X80 (0x3014) - -/* command list */ -#define CMD_WRSR (0x01) /* Write Status Register */ -#define CMD_PP (0x02) /* Page Program */ -#define CMD_READ (0x03) /* Read Data */ -#define CMD_WRDI (0x04) /* Write Disable */ -#define CMD_RDSR1 (0x05) /* Read Status Register-1 */ -#define CMD_WREN (0x06) /* Write Enable */ -#define CMD_FAST_READ (0x0B) /* Fast Read */ -#define CMD_ERASE_4K (0x20) /* Sector Erase:4K */ -#define CMD_RDSR2 (0x35) /* Read Status Register-2 */ -#define CMD_ERASE_32K (0x52) /* 32KB Block Erase */ -#define CMD_JEDEC_ID (0x9F) /* Read JEDEC ID */ -#define CMD_ERASE_full (0xC7) /* Chip Erase */ -#define CMD_ERASE_64K (0xD8) /* 64KB Block Erase */ -#define CMD_MANU_ID (0x90) - -#define DUMMY (0xFF) - -#define FLASH_ERASE_CMD CMD_ERASE_4K -#define FLASH_BLOCK_SIZE 4096 -#define FLASH_PAGE_SIZE 256 - -static void w25qxx_lock(struct rt_mtd_nor_device *device) -{ - struct spi_flash_mtd *mtd = (struct spi_flash_mtd *)device; - rt_mutex_take(&mtd->lock, RT_WAITING_FOREVER); -} - -static void w25qxx_unlock(struct rt_mtd_nor_device *device) -{ - struct spi_flash_mtd *mtd = (struct spi_flash_mtd *)device; - rt_mutex_release(&mtd->lock); -} - -static rt_uint8_t w25qxx_read_status(struct rt_mtd_nor_device *device) -{ - struct spi_flash_mtd *mtd = (struct spi_flash_mtd *)device; - return rt_spi_sendrecv8(mtd->rt_spi_device, CMD_RDSR1); -} - -static void w25qxx_wait_busy(struct rt_mtd_nor_device *device) -{ - while( w25qxx_read_status(device) & (0x01)); -} - -static rt_err_t w25qxx_read_id(struct rt_mtd_nor_device *device) -{ - rt_uint8_t cmd; - rt_uint8_t id_recv[3]; - - struct spi_flash_mtd *mtd = (struct spi_flash_mtd *)device; - - w25qxx_lock(device); - - cmd = 0xFF; /* reset SPI FLASH, cancel all cmd in processing. */ - rt_spi_send(mtd->rt_spi_device, &cmd, 1); - - cmd = CMD_WRDI; - rt_spi_send(mtd->rt_spi_device, &cmd, 1); - - /* read flash id */ - cmd = CMD_JEDEC_ID; - rt_spi_send_then_recv(mtd->rt_spi_device, &cmd, 1, id_recv, 3); - - w25qxx_unlock(device); - - return (rt_uint32_t)(id_recv[0] << 16) | (id_recv[1] << 8) | id_recv[2]; -} - -static rt_size_t w25qxx_read(struct rt_mtd_nor_device *device, rt_off_t offset, rt_uint8_t *buffer, rt_size_t length) -{ - struct spi_flash_mtd *mtd = (struct spi_flash_mtd *)device; - rt_uint8_t send_buffer[4]; - - if((offset + length) > device->block_end * FLASH_BLOCK_SIZE) - return 0; - - - w25qxx_lock(device); - - send_buffer[0] = CMD_WRDI; - rt_spi_send(mtd->rt_spi_device, send_buffer, 1); - - send_buffer[0] = CMD_READ; - send_buffer[1] = (rt_uint8_t)(offset>>16); - send_buffer[2] = (rt_uint8_t)(offset>>8); - send_buffer[3] = (rt_uint8_t)(offset); - rt_spi_send_then_recv(mtd->rt_spi_device, - send_buffer, 4, - buffer, length); - - w25qxx_unlock(device); - return length; -} - -static rt_size_t w25qxx_write(struct rt_mtd_nor_device *device, rt_off_t offset, const rt_uint8_t *buffer, rt_size_t length) -{ - struct spi_flash_mtd *mtd = (struct spi_flash_mtd *)device; - rt_uint8_t send_buffer[4]; - rt_uint8_t *write_ptr ; - rt_size_t write_size,write_total; - - if((offset + length) > device->block_end * FLASH_BLOCK_SIZE) - return 0; - - w25qxx_lock(device); - - send_buffer[0] = CMD_WREN; - rt_spi_send(mtd->rt_spi_device, send_buffer, 1); - w25qxx_wait_busy(device); // wait erase done. - - write_size = 0; - write_total = 0; - write_ptr = (rt_uint8_t *)buffer; - while(write_total < length) - { - send_buffer[0] = CMD_WREN; - rt_spi_send(mtd->rt_spi_device, send_buffer, 1); - - //write first page... - send_buffer[0] = CMD_PP; - send_buffer[1] = (rt_uint8_t)(offset >> 16); - send_buffer[2] = (rt_uint8_t)(offset >> 8); - send_buffer[3] = (rt_uint8_t)(offset); - - //address % FLASH_PAGE_SIZE + length - if(((offset & (FLASH_PAGE_SIZE - 1)) + (length - write_total)) > FLASH_PAGE_SIZE) - { - write_size = FLASH_PAGE_SIZE - (offset & (FLASH_PAGE_SIZE - 1)); - } - else - { - write_size = (length - write_total); - } - - rt_spi_send_then_send(mtd->rt_spi_device, - send_buffer, 4, - write_ptr + write_total, write_size); - w25qxx_wait_busy(device); - - - offset += write_size; - write_total += write_size; - } - - send_buffer[0] = CMD_WRDI; - rt_spi_send(mtd->rt_spi_device, send_buffer, 1); - - w25qxx_unlock(device); - - return length; -} - -static rt_err_t w25qxx_erase_block(struct rt_mtd_nor_device *device, rt_off_t offset, rt_uint32_t length) -{ - struct spi_flash_mtd *mtd = (struct spi_flash_mtd *)device; - rt_uint8_t send_buffer[4]; - rt_uint32_t erase_size = 0; - - //offset must be ALIGN_DOWN to BLOCKSIZE - if(offset != RT_ALIGN_DOWN(offset,FLASH_BLOCK_SIZE)) - return 0; - - if((offset + length) > device->block_end * FLASH_BLOCK_SIZE) - return 0; - - /* check length must align to block size */ - if(length % device->block_size != 0) - { - rt_kprintf("param length = %d ,error\n",length); - return 0; - } - - w25qxx_lock(device); - - send_buffer[0] = CMD_WREN; - rt_spi_send(mtd->rt_spi_device, send_buffer, 1); - w25qxx_wait_busy(device); // wait erase done. - while (erase_size < length) - { - send_buffer[0] = CMD_ERASE_4K; - send_buffer[1] = (rt_uint8_t) (offset >> 16); - send_buffer[2] = (rt_uint8_t) (offset >> 8); - send_buffer[3] = (rt_uint8_t) (offset); - rt_spi_send(mtd->rt_spi_device, send_buffer, 4); - w25qxx_wait_busy(device); // wait erase done. - - erase_size += 4096; - offset += 4096; - } - send_buffer[0] = CMD_WRDI; - rt_spi_send(mtd->rt_spi_device, send_buffer, 1); - - w25qxx_unlock(device); - return RT_EOK; -} - -const static struct rt_mtd_nor_driver_ops w25qxx_mtd_ops = -{ - w25qxx_read_id, - w25qxx_read, - w25qxx_write, - w25qxx_erase_block, -}; - -rt_err_t w25qxx_mtd_init(const char *mtd_name,const char * spi_device_name) -{ - rt_err_t result = RT_EOK; - rt_uint32_t id; - rt_uint8_t send_buffer[3]; - - struct rt_spi_device* rt_spi_device; - struct spi_flash_mtd* mtd = (struct spi_flash_mtd *)rt_malloc(sizeof(struct spi_flash_mtd)); - - RT_ASSERT(mtd != RT_NULL); - - /* initialize mutex */ - if (rt_mutex_init(&mtd->lock, mtd_name, RT_IPC_FLAG_FIFO) != RT_EOK) - { - FLASH_TRACE("init mtd lock mutex failed\n"); - result = -RT_ENOSYS; - - goto _error_exit; - } - - rt_spi_device = (struct rt_spi_device *)rt_device_find(spi_device_name); - if(rt_spi_device == RT_NULL) - { - FLASH_TRACE("spi device %s not found!\r\n", spi_device_name); - result = -RT_ENOSYS; - - goto _error_exit; - } - mtd->rt_spi_device = rt_spi_device; - /* config spi */ - { - struct rt_spi_configuration cfg; - cfg.data_width = 8; - cfg.mode = RT_SPI_MODE_0 | RT_SPI_MSB; /* SPI Compatible: Mode 0 and Mode 3 */ - cfg.max_hz = 20 * 1000 * 1000; /* 20 */ - rt_spi_configure(rt_spi_device, &cfg); - } - - /* Init Flash device */ - { - w25qxx_lock(&mtd->mtd_device); - - send_buffer[0] = CMD_WREN; - rt_spi_send(mtd->rt_spi_device, send_buffer, 1); - w25qxx_wait_busy(&mtd->mtd_device); - - send_buffer[0] = CMD_WRSR; - send_buffer[1] = 0; - send_buffer[2] = 0; - rt_spi_send(mtd->rt_spi_device, send_buffer, 3); - w25qxx_wait_busy(&mtd->mtd_device); - - w25qxx_unlock(&mtd->mtd_device); - } - - id = w25qxx_read_id(&mtd->mtd_device); - - mtd->mtd_device.block_size = 4096; - mtd->mtd_device.block_start = 0; - switch(id & 0xFFFF) - { - case MTC_W25Q80_BV: /* W25Q80BV */ - mtd->mtd_device.block_end = 256; - break; - case MTC_W25Q16_BV_CL_CV: /* W25Q16BV W25Q16CL W25Q16CV */ - case MTC_W25Q16_DW: /* W25Q16DW */ - mtd->mtd_device.block_end = 512; - break; - case MTC_W25Q32_BV: /* W25Q32BV */ - case MTC_W25Q32_DW: /* W25Q32DW */ - mtd->mtd_device.block_end = 1024; - break; - case MTC_W25Q64_BV_CV: /* W25Q64BV W25Q64CV */ - mtd->mtd_device.block_end = 2048; - break; - case MTC_W25Q128_BV: /* W25Q128BV */ - mtd->mtd_device.block_end = 4086; - break; - } - mtd->mtd_device.ops = &w25qxx_mtd_ops; - rt_mtd_nor_register_device(mtd_name,&mtd->mtd_device); - - return RT_EOK; - -_error_exit: - if(mtd != RT_NULL) - rt_free(mtd); - return result; -} diff --git a/components/drivers/spi/spi_flash_w25qxx_mtd.h b/components/drivers/spi/spi_flash_w25qxx_mtd.h deleted file mode 100644 index 28f6828ffb..0000000000 --- a/components/drivers/spi/spi_flash_w25qxx_mtd.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright (c) 2006-2018, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2011-12-16 aozima the first version - * 2012-08-23 aozima add flash lock. - * 2017-02-11 urey add mtd fucntion - */ - -#ifndef SPI_FLASH_W25QXX_H_INCLUDED -#define SPI_FLASH_W25QXX_H_INCLUDED - -#include <rtthread.h> - -extern rt_err_t w25qxx_mtd_init(const char *mtd_name,const char * spi_device_name); - -#endif // SPI_FLASH_W25QXX_H_INCLUDED diff --git a/components/drivers/src/pipe.c b/components/drivers/src/pipe.c index 16fb82dbfb..b682c351ad 100644 --- a/components/drivers/src/pipe.c +++ b/components/drivers/src/pipe.c @@ -425,7 +425,7 @@ rt_pipe_t *rt_pipe_create(const char *name, int bufsz) rt_pipe_t *pipe; rt_device_t dev; - pipe = rt_malloc(sizeof(rt_pipe_t)); + pipe = (rt_pipe_t *)rt_malloc(sizeof(rt_pipe_t)); if (pipe == RT_NULL) return RT_NULL; rt_memset(pipe, 0, sizeof(rt_pipe_t)); diff --git a/components/drivers/src/ringblk_buf.c b/components/drivers/src/ringblk_buf.c index 74ced674fe..86e812cd4c 100644 --- a/components/drivers/src/ringblk_buf.c +++ b/components/drivers/src/ringblk_buf.c @@ -134,16 +134,16 @@ rt_rbb_blk_t rt_rbb_blk_alloc(rt_rbb_t rbb, rt_size_t blk_size) { rt_base_t level; rt_size_t empty1 = 0, empty2 = 0; - rt_rbb_blk_t head, tail, new = NULL; + rt_rbb_blk_t head, tail, new_rbb = NULL; RT_ASSERT(rbb); RT_ASSERT(blk_size < (1L << 24)); level = rt_hw_interrupt_disable(); - new = find_empty_blk_in_set(rbb); + new_rbb = find_empty_blk_in_set(rbb); - if (rt_slist_len(&rbb->blk_list) < rbb->blk_max_num && new) + if (rt_slist_len(&rbb->blk_list) < rbb->blk_max_num && new_rbb) { if (rt_slist_len(&rbb->blk_list) > 0) { @@ -163,22 +163,22 @@ rt_rbb_blk_t rt_rbb_blk_alloc(rt_rbb_t rbb, rt_size_t blk_size) if (empty1 >= blk_size) { - rt_slist_append(&rbb->blk_list, &new->list); - new->status = RT_RBB_BLK_INITED; - new->buf = tail->buf + tail->size; - new->size = blk_size; + rt_slist_append(&rbb->blk_list, &new_rbb->list); + new_rbb->status = RT_RBB_BLK_INITED; + new_rbb->buf = tail->buf + tail->size; + new_rbb->size = blk_size; } else if (empty2 >= blk_size) { - rt_slist_append(&rbb->blk_list, &new->list); - new->status = RT_RBB_BLK_INITED; - new->buf = rbb->buf; - new->size = blk_size; + rt_slist_append(&rbb->blk_list, &new_rbb->list); + new_rbb->status = RT_RBB_BLK_INITED; + new_rbb->buf = rbb->buf; + new_rbb->size = blk_size; } else { /* no space */ - new = NULL; + new_rbb = NULL; } } else @@ -194,35 +194,35 @@ rt_rbb_blk_t rt_rbb_blk_alloc(rt_rbb_t rbb, rt_size_t blk_size) if (empty1 >= blk_size) { - rt_slist_append(&rbb->blk_list, &new->list); - new->status = RT_RBB_BLK_INITED; - new->buf = tail->buf + tail->size; - new->size = blk_size; + rt_slist_append(&rbb->blk_list, &new_rbb->list); + new_rbb->status = RT_RBB_BLK_INITED; + new_rbb->buf = tail->buf + tail->size; + new_rbb->size = blk_size; } else { /* no space */ - new = NULL; + new_rbb = NULL; } } } else { /* the list is empty */ - rt_slist_append(&rbb->blk_list, &new->list); - new->status = RT_RBB_BLK_INITED; - new->buf = rbb->buf; - new->size = blk_size; + rt_slist_append(&rbb->blk_list, &new_rbb->list); + new_rbb->status = RT_RBB_BLK_INITED; + new_rbb->buf = rbb->buf; + new_rbb->size = blk_size; } } else { - new = NULL; + new_rbb = NULL; } rt_hw_interrupt_enable(level); - return new; + return new_rbb; } RTM_EXPORT(rt_rbb_blk_alloc); diff --git a/components/drivers/src/ringbuffer.c b/components/drivers/src/ringbuffer.c index 0acdbbd38c..c6a491a7cc 100644 --- a/components/drivers/src/ringbuffer.c +++ b/components/drivers/src/ringbuffer.c @@ -332,11 +332,11 @@ struct rt_ringbuffer* rt_ringbuffer_create(rt_uint16_t size) size = RT_ALIGN_DOWN(size, RT_ALIGN_SIZE); - rb = rt_malloc(sizeof(struct rt_ringbuffer)); + rb = (struct rt_ringbuffer *)rt_malloc(sizeof(struct rt_ringbuffer)); if (rb == RT_NULL) goto exit; - pool = rt_malloc(size); + pool = (rt_uint8_t *)rt_malloc(size); if (pool == RT_NULL) { rt_free(rb); diff --git a/components/drivers/src/workqueue.c b/components/drivers/src/workqueue.c index 7bf4bd81a7..2e0280df3a 100644 --- a/components/drivers/src/workqueue.c +++ b/components/drivers/src/workqueue.c @@ -71,6 +71,7 @@ static void _workqueue_thread_entry(void *parameter) rt_list_remove(&(work->list)); queue->work_current = work; work->flags &= ~RT_WORK_STATE_PENDING; + work->workqueue = RT_NULL; rt_hw_interrupt_enable(level); /* do work */ @@ -141,7 +142,7 @@ static rt_err_t _workqueue_cancel_work(struct rt_workqueue *queue, struct rt_wor return RT_EOK; } -static rt_err_t _workqueue_cancel_delayed_work(struct rt_delayed_work *work) +static rt_err_t _workqueue_cancel_delayed_work(struct rt_work *work) { rt_base_t level; int ret = RT_EOK; @@ -152,10 +153,10 @@ static rt_err_t _workqueue_cancel_delayed_work(struct rt_delayed_work *work) goto __exit; } - if (work->work.flags & RT_WORK_STATE_PENDING) + if (work->flags & RT_WORK_STATE_PENDING) { /* Remove from the queue if already submitted */ - ret = rt_workqueue_cancel_work(work->workqueue, &(work->work)); + ret = _workqueue_cancel_work(work->workqueue, work); if (ret) { goto __exit; @@ -163,12 +164,12 @@ static rt_err_t _workqueue_cancel_delayed_work(struct rt_delayed_work *work) } else { - if (work->work.flags & RT_WORK_STATE_SUBMITTING) + if (work->flags & RT_WORK_STATE_SUBMITTING) { level = rt_hw_interrupt_disable(); rt_timer_stop(&(work->timer)); rt_timer_detach(&(work->timer)); - work->work.flags &= ~RT_WORK_STATE_SUBMITTING; + work->flags &= ~RT_WORK_STATE_SUBMITTING; rt_hw_interrupt_enable(level); } } @@ -176,7 +177,7 @@ static rt_err_t _workqueue_cancel_delayed_work(struct rt_delayed_work *work) level = rt_hw_interrupt_disable(); /* Detach from workqueue */ work->workqueue = RT_NULL; - work->work.flags &= ~(RT_WORK_STATE_PENDING); + work->flags &= ~(RT_WORK_STATE_PENDING); rt_hw_interrupt_enable(level); __exit: @@ -184,11 +185,10 @@ __exit: } static rt_err_t _workqueue_submit_delayed_work(struct rt_workqueue *queue, - struct rt_delayed_work *work, rt_tick_t ticks) + struct rt_work *work, rt_tick_t ticks) { rt_base_t level; - int ret = RT_EOK; - + rt_err_t ret = RT_EOK; /* Work cannot be active in multiple queues */ if (work->workqueue && work->workqueue != queue) @@ -215,13 +215,13 @@ static rt_err_t _workqueue_submit_delayed_work(struct rt_workqueue *queue, if (!ticks) { /* Submit work if no ticks is 0 */ - _workqueue_submit_work(work->workqueue, &(work->work)); + ret = _workqueue_submit_work(work->workqueue, work); } else { level = rt_hw_interrupt_disable(); /* Add timeout */ - work->work.flags |= RT_WORK_STATE_SUBMITTING; + work->flags |= RT_WORK_STATE_SUBMITTING; rt_timer_init(&(work->timer), "work", _delayed_work_timeout_handler, work, ticks, RT_TIMER_FLAG_ONE_SHOT | RT_TIMER_FLAG_SOFT_TIMER); rt_hw_interrupt_enable(level); @@ -234,16 +234,17 @@ __exit: static void _delayed_work_timeout_handler(void *parameter) { - struct rt_delayed_work *delayed_work; + struct rt_work *delayed_work; rt_base_t level; - delayed_work = (struct rt_delayed_work *)parameter; + delayed_work = (struct rt_work *)parameter; level = rt_hw_interrupt_disable(); rt_timer_stop(&(delayed_work->timer)); rt_timer_detach(&(delayed_work->timer)); - delayed_work->work.flags &= ~RT_WORK_STATE_SUBMITTING; + delayed_work->flags &= ~RT_WORK_STATE_SUBMITTING; + delayed_work->type &= ~RT_WORK_TYPE_DELAYED; rt_hw_interrupt_enable(level); - _workqueue_submit_work(delayed_work->workqueue, &(delayed_work->work)); + _workqueue_submit_work(delayed_work->workqueue, delayed_work); } struct rt_workqueue *rt_workqueue_create(const char *name, rt_uint16_t stack_size, rt_uint8_t priority) @@ -295,9 +296,14 @@ rt_err_t rt_workqueue_submit_work(struct rt_workqueue *queue, struct rt_work *wo RT_ASSERT(queue != RT_NULL); RT_ASSERT(work != RT_NULL); + if (time > 0) + { + work->type |= RT_WORK_TYPE_DELAYED; + } + if (work->type & RT_WORK_TYPE_DELAYED) { - return _workqueue_submit_delayed_work(queue, (struct rt_delayed_work *)work, time); + return _workqueue_submit_delayed_work(queue, work, time); } else { @@ -341,7 +347,7 @@ rt_err_t rt_workqueue_cancel_work(struct rt_workqueue *queue, struct rt_work *wo if (work->type & RT_WORK_TYPE_DELAYED) { - return _workqueue_cancel_delayed_work((struct rt_delayed_work *)work); + return _workqueue_cancel_delayed_work(work); } else { @@ -391,8 +397,7 @@ rt_err_t rt_workqueue_cancel_all_work(struct rt_workqueue *queue) void rt_delayed_work_init(struct rt_delayed_work *work, void (*work_func)(struct rt_work *work, void *work_data), void *work_data) { - rt_work_init(&(work->work), work_func, work_data); - work->work.type = RT_WORK_TYPE_DELAYED; + rt_work_init(&work->work, work_func, work_data); } #ifdef RT_USING_SYSTEM_WORKQUEUE @@ -408,8 +413,11 @@ rt_err_t rt_work_cancel(struct rt_work *work) return rt_workqueue_cancel_work(sys_workq, work); } -static int rt_work_sys_workqueue_init(void) +int rt_work_sys_workqueue_init(void) { + if (sys_workq != RT_NULL) + return 0; + sys_workq = rt_workqueue_create("sys_work", RT_SYSTEM_WORKQUEUE_STACKSIZE, RT_SYSTEM_WORKQUEUE_PRIORITY); diff --git a/components/drivers/touch/SConscript b/components/drivers/touch/SConscript new file mode 100644 index 0000000000..f370b2aba6 --- /dev/null +++ b/components/drivers/touch/SConscript @@ -0,0 +1,11 @@ +# SConscript for touch framework + +from building import * + +cwd = GetCurrentDir() +src = ['touch.c'] +CPPPATH = [cwd, cwd + '/../include'] + +group = DefineGroup('Touch', src, depend = ['RT_USING_TOUCH', 'RT_USING_DEVICE'], CPPPATH = CPPPATH) + +Return('group') diff --git a/components/drivers/touch/touch.c b/components/drivers/touch/touch.c new file mode 100644 index 0000000000..80ba6378bb --- /dev/null +++ b/components/drivers/touch/touch.c @@ -0,0 +1,258 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-05-20 tyustli the first version + */ + +#include "touch.h" +#include <string.h> + +#define DBG_TAG "touch" +#define DBG_LVL DBG_INFO +#include <rtdbg.h> + +/* ISR for touch interrupt */ +static void irq_callback(void *args) +{ + rt_touch_t touch; + + touch = (rt_touch_t)args; + + if (touch->parent.rx_indicate == RT_NULL) + { + return; + } + + if (touch->irq_handle != RT_NULL) + { + touch->irq_handle(touch); + } + + touch->parent.rx_indicate(&touch->parent, 1); +} + +/* touch interrupt initialization function */ +static rt_err_t rt_touch_irq_init(rt_touch_t touch) +{ + if (touch->config.irq_pin.pin == RT_PIN_NONE) + { + return -RT_EINVAL; + } + + rt_pin_mode(touch->config.irq_pin.pin, touch->config.irq_pin.mode); + + if (touch->config.irq_pin.mode == PIN_MODE_INPUT_PULLDOWN) + { + rt_pin_attach_irq(touch->config.irq_pin.pin, PIN_IRQ_MODE_RISING, irq_callback, (void *)touch); + } + else if (touch->config.irq_pin.mode == PIN_MODE_INPUT_PULLUP) + { + rt_pin_attach_irq(touch->config.irq_pin.pin, PIN_IRQ_MODE_FALLING, irq_callback, (void *)touch); + } + else if (touch->config.irq_pin.mode == PIN_MODE_INPUT) + { + rt_pin_attach_irq(touch->config.irq_pin.pin, PIN_IRQ_MODE_RISING_FALLING, irq_callback, (void *)touch); + } + + rt_pin_irq_enable(touch->config.irq_pin.pin, PIN_IRQ_ENABLE); + + return RT_EOK; +} + +/* touch interrupt enable */ +static void rt_touch_irq_enable(rt_touch_t touch) +{ + if (touch->config.irq_pin.pin != RT_PIN_NONE) + { + rt_pin_irq_enable(touch->config.irq_pin.pin, RT_TRUE); + } +} + +/* touch interrupt disable */ +static void rt_touch_irq_disable(rt_touch_t touch) +{ + if (touch->config.irq_pin.pin != RT_PIN_NONE) + { + rt_pin_irq_enable(touch->config.irq_pin.pin, RT_FALSE); + } +} + +static rt_err_t rt_touch_open(rt_device_t dev, rt_uint16_t oflag) +{ + rt_touch_t touch; + RT_ASSERT(dev != RT_NULL); + touch = (rt_touch_t)dev; + + if (oflag & RT_DEVICE_FLAG_INT_RX && dev->flag & RT_DEVICE_FLAG_INT_RX) + { + /* Initialization touch interrupt */ + rt_touch_irq_init(touch); + } + + return RT_EOK; +} + +static rt_err_t rt_touch_close(rt_device_t dev) +{ + rt_touch_t touch; + RT_ASSERT(dev != RT_NULL); + touch = (rt_touch_t)dev; + + /* touch disable interrupt */ + rt_touch_irq_disable(touch); + + return RT_EOK; +} + +static rt_size_t rt_touch_read(rt_device_t dev, rt_off_t pos, void *buf, rt_size_t len) +{ + rt_touch_t touch; + rt_size_t result = 0; + RT_ASSERT(dev != RT_NULL); + touch = (rt_touch_t)dev; + + if (buf == NULL || len == 0) + { + return 0; + } + + result = touch->ops->touch_readpoint(touch, buf, len); + + return result; +} + +static rt_err_t rt_touch_control(rt_device_t dev, int cmd, void *args) +{ + rt_touch_t touch; + rt_err_t result = RT_EOK; + RT_ASSERT(dev != RT_NULL); + touch = (rt_touch_t)dev; + + switch (cmd) + { + case RT_TOUCH_CTRL_GET_ID: + if (args) + { + result = touch->ops->touch_control(touch, RT_TOUCH_CTRL_GET_ID, args); + } + else + { + result = -RT_ERROR; + } + + break; + case RT_TOUCH_CTRL_GET_INFO: + if (args) + { + result = touch->ops->touch_control(touch, RT_TOUCH_CTRL_GET_INFO, args); + } + else + { + result = -RT_ERROR; + } + + break; + case RT_TOUCH_CTRL_SET_MODE: + result = touch->ops->touch_control(touch, RT_TOUCH_CTRL_SET_MODE, args); + + if (result == RT_EOK) + { + rt_uint16_t mode; + mode = *(rt_uint16_t*)args; + if (mode == RT_DEVICE_FLAG_INT_RX) + { + rt_touch_irq_enable(touch); /* enable interrupt */ + } + } + + break; + case RT_TOUCH_CTRL_SET_X_RANGE: + result = touch->ops->touch_control(touch, RT_TOUCH_CTRL_SET_X_RANGE, args); + + if (result == RT_EOK) + { + touch->info.range_x = *(rt_int32_t *)args; + LOG_D("set x coordinate range :%d\n", touch->info.range_x); + } + + break; + case RT_TOUCH_CTRL_SET_Y_RANGE: + result = touch->ops->touch_control(touch, RT_TOUCH_CTRL_SET_Y_RANGE, args); + + if (result == RT_EOK) + { + touch->info.range_y = *(rt_uint32_t *)args; + LOG_D("set y coordinate range :%d \n", touch->info.range_x); + } + + break; + case RT_TOUCH_CTRL_DISABLE_INT: + rt_touch_irq_disable(touch); + break; + case RT_TOUCH_CTRL_ENABLE_INT: + rt_touch_irq_enable(touch); + break; + default: + return -RT_ERROR; + } + + return result; +} + +#ifdef RT_USING_DEVICE_OPS +const static struct rt_device_ops rt_touch_ops = +{ + RT_NULL, + rt_touch_open, + rt_touch_close, + rt_touch_read, + RT_NULL, + rt_touch_control +}; +#endif + +/* + * touch register + */ +int rt_hw_touch_register(rt_touch_t touch, + const char *name, + rt_uint32_t flag, + void *data) +{ + rt_int8_t result; + rt_device_t device; + RT_ASSERT(touch != RT_NULL); + + device = &touch->parent; + +#ifdef RT_USING_DEVICE_OPS + device->ops = &rt_touch_ops; +#else + device->init = RT_NULL; + device->open = rt_touch_open; + device->close = rt_touch_close; + device->read = rt_touch_read; + device->write = RT_NULL; + device->control = rt_touch_control; +#endif + device->type = RT_Device_Class_Touch; + device->rx_indicate = RT_NULL; + device->tx_complete = RT_NULL; + device->user_data = data; + + result = rt_device_register(device, name, flag | RT_DEVICE_FLAG_STANDALONE); + + if (result != RT_EOK) + { + LOG_E("rt_touch register err code: %d", result); + return result; + } + + LOG_I("rt_touch init success"); + + return RT_EOK; +} diff --git a/components/drivers/touch/touch.h b/components/drivers/touch/touch.h new file mode 100644 index 0000000000..6b7288a5a0 --- /dev/null +++ b/components/drivers/touch/touch.h @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-05-20 tyustli the first version + */ + +#ifndef __TOUCH_H__ +#define __TOUCH_H__ + +#include <rtthread.h> +#include <rtdevice.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef RT_USING_RTC +#define rt_touch_get_ts() time(RT_NULL) /* API for the touch to get the timestamp */ +#else +#define rt_touch_get_ts() rt_tick_get() /* API for the touch to get the timestamp */ +#endif + +#define RT_PIN_NONE 0xFFFF /* RT PIN NONE */ + +/* Touch vendor types */ +#define RT_TOUCH_VENDOR_UNKNOWN (0) /* unknown */ +#define RT_TOUCH_VENDOR_GT (1) /* GTxx series */ +#define RT_TOUCH_VENDOR_FT (2) /* FTxx series */ + +/* Touch ic type*/ +#define RT_TOUCH_TYPE_NONE (0) /* touch ic none */ +#define RT_TOUCH_TYPE_CAPACITANCE (1) /* capacitance ic */ +#define RT_TOUCH_TYPE_RESISTANCE (2) /* resistance ic */ + +/* Touch control cmd types */ +#define RT_TOUCH_CTRL_GET_ID (0) /* Get device id */ +#define RT_TOUCH_CTRL_GET_INFO (1) /* Get touch info */ +#define RT_TOUCH_CTRL_SET_MODE (2) /* Set touch's work mode. ex. RT_TOUCH_MODE_POLLING,RT_TOUCH_MODE_INT */ +#define RT_TOUCH_CTRL_SET_X_RANGE (3) /* Set x coordinate range */ +#define RT_TOUCH_CTRL_SET_Y_RANGE (4) /* Set y coordinate range */ +#define RT_TOUCH_CTRL_SET_X_TO_Y (5) /* Set X Y coordinate exchange */ +#define RT_TOUCH_CTRL_DISABLE_INT (6) /* Disable interrupt */ +#define RT_TOUCH_CTRL_ENABLE_INT (7) /* Enable interrupt */ + +/* Touch event */ +#define RT_TOUCH_EVENT_NONE (0) /* Touch none */ +#define RT_TOUCH_EVENT_UP (1) /* Touch up event */ +#define RT_TOUCH_EVENT_DOWN (2) /* Touch down event */ +#define RT_TOUCH_EVENT_MOVE (3) /* Touch move event */ + +struct rt_touch_info +{ + rt_uint8_t type; /* The touch type */ + rt_uint8_t vendor; /* Vendor of touchs */ + rt_uint8_t point_num; /* Support point num */ + rt_int32_t range_x; /* X coordinate range */ + rt_int32_t range_y; /* Y coordinate range */ +}; + +struct rt_touch_config +{ + struct rt_device_pin_mode irq_pin; /* Interrupt pin, The purpose of this pin is to notification read data */ + char *dev_name; /* The name of the communication device */ + void *user_data; +}; + +typedef struct rt_touch_device *rt_touch_t; +struct rt_touch_device +{ + struct rt_device parent; /* The standard device */ + struct rt_touch_info info; /* The touch info data */ + struct rt_touch_config config; /* The touch config data */ + + const struct rt_touch_ops *ops; /* The touch ops */ + rt_err_t (*irq_handle)(rt_touch_t touch); /* Called when an interrupt is generated, registered by the driver */ +}; + +struct rt_touch_data +{ + rt_uint8_t event; /* The touch event of the data */ + rt_uint8_t track_id; /* Track id of point */ + rt_uint8_t width; /* Point of width */ + rt_uint16_t x_coordinate; /* Point of x coordinate */ + rt_uint16_t y_coordinate; /* Point of y coordinate */ + rt_tick_t timestamp; /* The timestamp when the data was received */ +}; + +struct rt_touch_ops +{ + rt_size_t (*touch_readpoint)(struct rt_touch_device *touch, void *buf, rt_size_t touch_num); + rt_err_t (*touch_control)(struct rt_touch_device *touch, int cmd, void *arg); +}; + +int rt_hw_touch_register(rt_touch_t touch, + const char *name, + rt_uint32_t flag, + void *data); + +#ifdef __cplusplus +} +#endif + +#endif /* __TOUCH_H__ */ diff --git a/components/drivers/usb/usbdevice/SConscript b/components/drivers/usb/usbdevice/SConscript index be0b0c7b50..010b9837a4 100644 --- a/components/drivers/usb/usbdevice/SConscript +++ b/components/drivers/usb/usbdevice/SConscript @@ -24,6 +24,12 @@ if GetDepend('RT_USB_DEVICE_RNDIS'): if GetDepend('RT_USB_DEVICE_WINUSB'): src += Glob('class/winusb.c') + +if GetDepend('RT_USB_DEVICE_AUDIO_MIC'): + src += Glob('class/audio_mic.c') + +if GetDepend('RT_USB_DEVICE_AUDIO_SPEAKER'): + src += Glob('class/audio_speaker.c') CPPPATH = [cwd] diff --git a/components/drivers/usb/usbdevice/class/audio.h b/components/drivers/usb/usbdevice/class/audio.h new file mode 100644 index 0000000000..4bb8994b47 --- /dev/null +++ b/components/drivers/usb/usbdevice/class/audio.h @@ -0,0 +1,676 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +/* + * <linux/usb/audio.h> -- USB Audio definitions. + * + * Copyright (C) 2006 Thumtronics Pty Ltd. + * Developed for Thumtronics by Grey Innovation + * Ben Williamson <[email protected]> + * + * This software is distributed under the terms of the GNU General Public + * License ("GPL") version 2, as published by the Free Software Foundation. + * + * This file holds USB constants and structures defined + * by the USB Device Class Definition for Audio Devices. + * Comments below reference relevant sections of that document: + * + * http://www.usb.org/developers/devclass_docs/audio10.pdf + * + * Types and defines in this file are either specific to version 1.0 of + * this standard or common for newer versions. + */ + +#ifndef _UAPI__LINUX_USB_AUDIO_H +#define _UAPI__LINUX_USB_AUDIO_H + +//#include <linux/types.h> +#include <rtthread.h> + +typedef int8_t __s8; +typedef uint8_t __u8; +typedef int16_t __s16; +typedef uint16_t __u16; +typedef int32_t __s32; +typedef uint32_t __u32; +typedef int64_t __s64; +typedef uint64_t __u64; + +#define UAC_USE_FEATURE_UNIT 0 /* Feature unit does not support */ + +/* + * Below are truly Linux-specific types that should never collide with + * any application/library that wants linux/types.h. + */ + +#ifdef __CHECKER__ +#define __bitwise__ __attribute__((bitwise)) +#else +#define __bitwise__ +#endif +#ifdef __CHECK_ENDIAN__ +#define __bitwise __bitwise__ +#else +#define __bitwise +#endif + +typedef __u16 __bitwise __le16; +typedef __u16 __bitwise __be16; +typedef __u32 __bitwise __le32; +typedef __u32 __bitwise __be32; +typedef __u64 __bitwise __le64; +typedef __u64 __bitwise __be64; + +typedef __u16 __bitwise __sum16; +typedef __u32 __bitwise __wsum; + +/* bInterfaceProtocol values to denote the version of the standard used */ +#define UAC_VERSION_1 0x00 +#define UAC_VERSION_2 0x20 +#define UAC_VERSION_3 0x30 + +/* A.2 Audio Interface Subclass Codes */ +#define USB_SUBCLASS_AUDIOCONTROL 0x01 +#define USB_SUBCLASS_AUDIOSTREAMING 0x02 +#define USB_SUBCLASS_MIDISTREAMING 0x03 + +/* A.5 Audio Class-Specific AC Interface Descriptor Subtypes */ +#define UAC_HEADER 0x01 +#define UAC_INPUT_TERMINAL 0x02 +#define UAC_OUTPUT_TERMINAL 0x03 +#define UAC_MIXER_UNIT 0x04 +#define UAC_SELECTOR_UNIT 0x05 +#define UAC_FEATURE_UNIT 0x06 +#define UAC1_PROCESSING_UNIT 0x07 +#define UAC1_EXTENSION_UNIT 0x08 + +/* A.6 Audio Class-Specific AS Interface Descriptor Subtypes */ +#define UAC_AS_GENERAL 0x01 +#define UAC_FORMAT_TYPE 0x02 +#define UAC_FORMAT_SPECIFIC 0x03 + +/* A.7 Processing Unit Process Types */ +#define UAC_PROCESS_UNDEFINED 0x00 +#define UAC_PROCESS_UP_DOWNMIX 0x01 +#define UAC_PROCESS_DOLBY_PROLOGIC 0x02 +#define UAC_PROCESS_STEREO_EXTENDER 0x03 +#define UAC_PROCESS_REVERB 0x04 +#define UAC_PROCESS_CHORUS 0x05 +#define UAC_PROCESS_DYN_RANGE_COMP 0x06 + +/* A.8 Audio Class-Specific Endpoint Descriptor Subtypes */ +#define UAC_EP_GENERAL 0x01 + +/* A.9 Audio Class-Specific Request Codes */ +#define UAC_SET_ 0x00 +#define UAC_GET_ 0x80 + +#define UAC__CUR 0x1 +#define UAC__MIN 0x2 +#define UAC__MAX 0x3 +#define UAC__RES 0x4 +#define UAC__MEM 0x5 + +#define UAC_SET_CUR (UAC_SET_ | UAC__CUR) +#define UAC_GET_CUR (UAC_GET_ | UAC__CUR) +#define UAC_SET_MIN (UAC_SET_ | UAC__MIN) +#define UAC_GET_MIN (UAC_GET_ | UAC__MIN) +#define UAC_SET_MAX (UAC_SET_ | UAC__MAX) +#define UAC_GET_MAX (UAC_GET_ | UAC__MAX) +#define UAC_SET_RES (UAC_SET_ | UAC__RES) +#define UAC_GET_RES (UAC_GET_ | UAC__RES) +#define UAC_SET_MEM (UAC_SET_ | UAC__MEM) +#define UAC_GET_MEM (UAC_GET_ | UAC__MEM) + +#define UAC_GET_STAT 0xff + +/* A.10 Control Selector Codes */ + +/* A.10.1 Terminal Control Selectors */ +#define UAC_TERM_COPY_PROTECT 0x01 + +/* A.10.2 Feature Unit Control Selectors */ +#define UAC_FU_MUTE 0x01 +#define UAC_FU_VOLUME 0x02 +#define UAC_FU_BASS 0x03 +#define UAC_FU_MID 0x04 +#define UAC_FU_TREBLE 0x05 +#define UAC_FU_GRAPHIC_EQUALIZER 0x06 +#define UAC_FU_AUTOMATIC_GAIN 0x07 +#define UAC_FU_DELAY 0x08 +#define UAC_FU_BASS_BOOST 0x09 +#define UAC_FU_LOUDNESS 0x0a + +#define UAC_CONTROL_BIT(CS) (1 << ((CS) - 1)) + +/* A.10.3.1 Up/Down-mix Processing Unit Controls Selectors */ +#define UAC_UD_ENABLE 0x01 +#define UAC_UD_MODE_SELECT 0x02 + +/* A.10.3.2 Dolby Prologic (tm) Processing Unit Controls Selectors */ +#define UAC_DP_ENABLE 0x01 +#define UAC_DP_MODE_SELECT 0x02 + +/* A.10.3.3 3D Stereo Extender Processing Unit Control Selectors */ +#define UAC_3D_ENABLE 0x01 +#define UAC_3D_SPACE 0x02 + +/* A.10.3.4 Reverberation Processing Unit Control Selectors */ +#define UAC_REVERB_ENABLE 0x01 +#define UAC_REVERB_LEVEL 0x02 +#define UAC_REVERB_TIME 0x03 +#define UAC_REVERB_FEEDBACK 0x04 + +/* A.10.3.5 Chorus Processing Unit Control Selectors */ +#define UAC_CHORUS_ENABLE 0x01 +#define UAC_CHORUS_LEVEL 0x02 +#define UAC_CHORUS_RATE 0x03 +#define UAC_CHORUS_DEPTH 0x04 + +/* A.10.3.6 Dynamic Range Compressor Unit Control Selectors */ +#define UAC_DCR_ENABLE 0x01 +#define UAC_DCR_RATE 0x02 +#define UAC_DCR_MAXAMPL 0x03 +#define UAC_DCR_THRESHOLD 0x04 +#define UAC_DCR_ATTACK_TIME 0x05 +#define UAC_DCR_RELEASE_TIME 0x06 + +/* A.10.4 Extension Unit Control Selectors */ +#define UAC_XU_ENABLE 0x01 + +/* MIDI - A.1 MS Class-Specific Interface Descriptor Subtypes */ +#define UAC_MS_HEADER 0x01 +#define UAC_MIDI_IN_JACK 0x02 +#define UAC_MIDI_OUT_JACK 0x03 + +/* MIDI - A.1 MS Class-Specific Endpoint Descriptor Subtypes */ +#define UAC_MS_GENERAL 0x01 + +/* Terminals - 2.1 USB Terminal Types */ +#define UAC_TERMINAL_UNDEFINED 0x100 +#define UAC_TERMINAL_STREAMING 0x101 +#define UAC_TERMINAL_VENDOR_SPEC 0x1FF + +/* Terminal Control Selectors */ +/* 4.3.2 Class-Specific AC Interface Descriptor */ +struct uac1_ac_header_descriptor { + __u8 bLength; /* 8 + n */ + __u8 bDescriptorType; /* USB_DT_CS_INTERFACE */ + __u8 bDescriptorSubtype; /* UAC_MS_HEADER */ + __le16 bcdADC; /* 0x0100 */ + __le16 wTotalLength; /* includes Unit and Terminal desc. */ + __u8 bInCollection; /* n */ + __u8 baInterfaceNr[]; /* [n] */ +} __attribute__ ((packed)); + +#define UAC_DT_AC_HEADER_SIZE(n) (8 + (n)) + +/* As above, but more useful for defining your own descriptors: */ +#define DECLARE_UAC_AC_HEADER_DESCRIPTOR(n) \ +struct uac1_ac_header_descriptor_##n { \ + __u8 bLength; \ + __u8 bDescriptorType; \ + __u8 bDescriptorSubtype; \ + __le16 bcdADC; \ + __le16 wTotalLength; \ + __u8 bInCollection; \ + __u8 baInterfaceNr[n]; \ +} __attribute__ ((packed)) + +/* 4.3.2.1 Input Terminal Descriptor */ +struct uac_input_terminal_descriptor { + __u8 bLength; /* in bytes: 12 */ + __u8 bDescriptorType; /* CS_INTERFACE descriptor type */ + __u8 bDescriptorSubtype; /* INPUT_TERMINAL descriptor subtype */ + __u8 bTerminalID; /* Constant uniquely terminal ID */ + __le16 wTerminalType; /* USB Audio Terminal Types */ + __u8 bAssocTerminal; /* ID of the Output Terminal associated */ + __u8 bNrChannels; /* Number of logical output channels */ + __le16 wChannelConfig; + __u8 iChannelNames; + __u8 iTerminal; +} __attribute__ ((packed)); + +#define UAC_DT_INPUT_TERMINAL_SIZE 12 + +/* Terminals - 2.2 Input Terminal Types */ +#define UAC_INPUT_TERMINAL_UNDEFINED 0x200 +#define UAC_INPUT_TERMINAL_MICROPHONE 0x201 +#define UAC_INPUT_TERMINAL_DESKTOP_MICROPHONE 0x202 +#define UAC_INPUT_TERMINAL_PERSONAL_MICROPHONE 0x203 +#define UAC_INPUT_TERMINAL_OMNI_DIR_MICROPHONE 0x204 +#define UAC_INPUT_TERMINAL_MICROPHONE_ARRAY 0x205 +#define UAC_INPUT_TERMINAL_PROC_MICROPHONE_ARRAY 0x206 + +/* Terminals - control selectors */ + +#define UAC_TERMINAL_CS_COPY_PROTECT_CONTROL 0x01 + +/* 4.3.2.2 Output Terminal Descriptor */ +struct uac1_output_terminal_descriptor { + __u8 bLength; /* in bytes: 9 */ + __u8 bDescriptorType; /* CS_INTERFACE descriptor type */ + __u8 bDescriptorSubtype; /* OUTPUT_TERMINAL descriptor subtype */ + __u8 bTerminalID; /* Constant uniquely terminal ID */ + __le16 wTerminalType; /* USB Audio Terminal Types */ + __u8 bAssocTerminal; /* ID of the Input Terminal associated */ + __u8 bSourceID; /* ID of the connected Unit or Terminal*/ + __u8 iTerminal; +} __attribute__ ((packed)); + +#define UAC_DT_OUTPUT_TERMINAL_SIZE 9 + +/* Terminals - 2.3 Output Terminal Types */ +#define UAC_OUTPUT_TERMINAL_UNDEFINED 0x300 +#define UAC_OUTPUT_TERMINAL_SPEAKER 0x301 +#define UAC_OUTPUT_TERMINAL_HEADPHONES 0x302 +#define UAC_OUTPUT_TERMINAL_HEAD_MOUNTED_DISPLAY_AUDIO 0x303 +#define UAC_OUTPUT_TERMINAL_DESKTOP_SPEAKER 0x304 +#define UAC_OUTPUT_TERMINAL_ROOM_SPEAKER 0x305 +#define UAC_OUTPUT_TERMINAL_COMMUNICATION_SPEAKER 0x306 +#define UAC_OUTPUT_TERMINAL_LOW_FREQ_EFFECTS_SPEAKER 0x307 + +/* Terminals - 2.4 Bi-directional Terminal Types */ +#define UAC_BIDIR_TERMINAL_UNDEFINED 0x400 +#define UAC_BIDIR_TERMINAL_HANDSET 0x401 +#define UAC_BIDIR_TERMINAL_HEADSET 0x402 +#define UAC_BIDIR_TERMINAL_SPEAKER_PHONE 0x403 +#define UAC_BIDIR_TERMINAL_ECHO_SUPPRESSING 0x404 +#define UAC_BIDIR_TERMINAL_ECHO_CANCELING 0x405 + +/* Set bControlSize = 2 as default setting */ +#define UAC_DT_FEATURE_UNIT_SIZE(ch) (7 + ((ch) + 1) * 2) + +/* As above, but more useful for defining your own descriptors: */ +#define DECLARE_UAC_FEATURE_UNIT_DESCRIPTOR(ch) \ +struct uac_feature_unit_descriptor_##ch { \ + __u8 bLength; \ + __u8 bDescriptorType; \ + __u8 bDescriptorSubtype; \ + __u8 bUnitID; \ + __u8 bSourceID; \ + __u8 bControlSize; \ + __le16 bmaControls[ch + 1]; \ + __u8 iFeature; \ +} __attribute__ ((packed)) + +/* 4.3.2.3 Mixer Unit Descriptor */ +struct uac_mixer_unit_descriptor { + __u8 bLength; + __u8 bDescriptorType; + __u8 bDescriptorSubtype; + __u8 bUnitID; + __u8 bNrInPins; + __u8 baSourceID[]; +} __attribute__ ((packed)); + +static inline __u8 uac_mixer_unit_bNrChannels(struct uac_mixer_unit_descriptor *desc) +{ + return desc->baSourceID[desc->bNrInPins]; +} + +static inline __u32 uac_mixer_unit_wChannelConfig(struct uac_mixer_unit_descriptor *desc, + int protocol) +{ + if (protocol == UAC_VERSION_1) + return (desc->baSourceID[desc->bNrInPins + 2] << 8) | + desc->baSourceID[desc->bNrInPins + 1]; + else + return (desc->baSourceID[desc->bNrInPins + 4] << 24) | + (desc->baSourceID[desc->bNrInPins + 3] << 16) | + (desc->baSourceID[desc->bNrInPins + 2] << 8) | + (desc->baSourceID[desc->bNrInPins + 1]); +} + +static inline __u8 uac_mixer_unit_iChannelNames(struct uac_mixer_unit_descriptor *desc, + int protocol) +{ + return (protocol == UAC_VERSION_1) ? + desc->baSourceID[desc->bNrInPins + 3] : + desc->baSourceID[desc->bNrInPins + 5]; +} + +static inline __u8 *uac_mixer_unit_bmControls(struct uac_mixer_unit_descriptor *desc, + int protocol) +{ + switch (protocol) { + case UAC_VERSION_1: + return &desc->baSourceID[desc->bNrInPins + 4]; + case UAC_VERSION_2: + return &desc->baSourceID[desc->bNrInPins + 6]; + case UAC_VERSION_3: + return &desc->baSourceID[desc->bNrInPins + 2]; + default: + return NULL; + } +} + +static inline __u16 uac3_mixer_unit_wClusterDescrID(struct uac_mixer_unit_descriptor *desc) +{ + return (desc->baSourceID[desc->bNrInPins + 1] << 8) | + desc->baSourceID[desc->bNrInPins]; +} + +static inline __u8 uac_mixer_unit_iMixer(struct uac_mixer_unit_descriptor *desc) +{ + __u8 *raw = (__u8 *) desc; + return raw[desc->bLength - 1]; +} + +/* 4.3.2.4 Selector Unit Descriptor */ +struct uac_selector_unit_descriptor { + __u8 bLength; + __u8 bDescriptorType; + __u8 bDescriptorSubtype; + __u8 bUintID; + __u8 bNrInPins; + __u8 baSourceID[]; +} __attribute__ ((packed)); + +static inline __u8 uac_selector_unit_iSelector(struct uac_selector_unit_descriptor *desc) +{ + __u8 *raw = (__u8 *) desc; + return raw[desc->bLength - 1]; +} +#if UAC_USE_FEATURE_UNIT +/* 4.3.2.5 Feature Unit Descriptor */ +struct uac_feature_unit_descriptor { + __u8 bLength; + __u8 bDescriptorType; + __u8 bDescriptorSubtype; + __u8 bUnitID; + __u8 bSourceID; + __u8 bControlSize; + __u8 bmaControls[0]; /* variable length */ +} __attribute__((packed)); + +static inline __u8 uac_feature_unit_iFeature(struct uac_feature_unit_descriptor *desc) +{ + __u8 *raw = (__u8 *) desc; + return raw[desc->bLength - 1]; +} +#endif +/* 4.3.2.6 Processing Unit Descriptors */ +struct uac_processing_unit_descriptor { + __u8 bLength; + __u8 bDescriptorType; + __u8 bDescriptorSubtype; + __u8 bUnitID; + __le16 wProcessType; + __u8 bNrInPins; + __u8 baSourceID[]; +} __attribute__ ((packed)); + +static inline __u8 uac_processing_unit_bNrChannels(struct uac_processing_unit_descriptor *desc) +{ + return desc->baSourceID[desc->bNrInPins]; +} + +static inline __u32 uac_processing_unit_wChannelConfig(struct uac_processing_unit_descriptor *desc, + int protocol) +{ + if (protocol == UAC_VERSION_1) + return (desc->baSourceID[desc->bNrInPins + 2] << 8) | + desc->baSourceID[desc->bNrInPins + 1]; + else + return (desc->baSourceID[desc->bNrInPins + 4] << 24) | + (desc->baSourceID[desc->bNrInPins + 3] << 16) | + (desc->baSourceID[desc->bNrInPins + 2] << 8) | + (desc->baSourceID[desc->bNrInPins + 1]); +} + +static inline __u8 uac_processing_unit_iChannelNames(struct uac_processing_unit_descriptor *desc, + int protocol) +{ + return (protocol == UAC_VERSION_1) ? + desc->baSourceID[desc->bNrInPins + 3] : + desc->baSourceID[desc->bNrInPins + 5]; +} + +static inline __u8 uac_processing_unit_bControlSize(struct uac_processing_unit_descriptor *desc, + int protocol) +{ + switch (protocol) { + case UAC_VERSION_1: + return desc->baSourceID[desc->bNrInPins + 4]; + case UAC_VERSION_2: + return 2; /* in UAC2, this value is constant */ + case UAC_VERSION_3: + return 4; /* in UAC3, this value is constant */ + default: + return 1; + } +} + +static inline __u8 *uac_processing_unit_bmControls(struct uac_processing_unit_descriptor *desc, + int protocol) +{ + switch (protocol) { + case UAC_VERSION_1: + return &desc->baSourceID[desc->bNrInPins + 5]; + case UAC_VERSION_2: + return &desc->baSourceID[desc->bNrInPins + 6]; + case UAC_VERSION_3: + return &desc->baSourceID[desc->bNrInPins + 2]; + default: + return NULL; + } +} + +static inline __u8 uac_processing_unit_iProcessing(struct uac_processing_unit_descriptor *desc, + int protocol) +{ + __u8 control_size = uac_processing_unit_bControlSize(desc, protocol); + + switch (protocol) { + case UAC_VERSION_1: + case UAC_VERSION_2: + default: + return *(uac_processing_unit_bmControls(desc, protocol) + + control_size); + case UAC_VERSION_3: + return 0; /* UAC3 does not have this field */ + } +} + +static inline __u8 *uac_processing_unit_specific(struct uac_processing_unit_descriptor *desc, + int protocol) +{ + __u8 control_size = uac_processing_unit_bControlSize(desc, protocol); + + switch (protocol) { + case UAC_VERSION_1: + case UAC_VERSION_2: + default: + return uac_processing_unit_bmControls(desc, protocol) + + control_size + 1; + case UAC_VERSION_3: + return uac_processing_unit_bmControls(desc, protocol) + + control_size; + } +} + +/* + * Extension Unit (XU) has almost compatible layout with Processing Unit, but + * on UAC2, it has a different bmControls size (bControlSize); it's 1 byte for + * XU while 2 bytes for PU. The last iExtension field is a one-byte index as + * well as iProcessing field of PU. + */ +static inline __u8 uac_extension_unit_bControlSize(struct uac_processing_unit_descriptor *desc, + int protocol) +{ + switch (protocol) { + case UAC_VERSION_1: + return desc->baSourceID[desc->bNrInPins + 4]; + case UAC_VERSION_2: + return 1; /* in UAC2, this value is constant */ + case UAC_VERSION_3: + return 4; /* in UAC3, this value is constant */ + default: + return 1; + } +} + +static inline __u8 uac_extension_unit_iExtension(struct uac_processing_unit_descriptor *desc, + int protocol) +{ + __u8 control_size = uac_extension_unit_bControlSize(desc, protocol); + + switch (protocol) { + case UAC_VERSION_1: + case UAC_VERSION_2: + default: + return *(uac_processing_unit_bmControls(desc, protocol) + + control_size); + case UAC_VERSION_3: + return 0; /* UAC3 does not have this field */ + } +} + +/* 4.5.2 Class-Specific AS Interface Descriptor */ +struct uac1_as_header_descriptor { + __u8 bLength; /* in bytes: 7 */ + __u8 bDescriptorType; /* USB_DT_CS_INTERFACE */ + __u8 bDescriptorSubtype; /* AS_GENERAL */ + __u8 bTerminalLink; /* Terminal ID of connected Terminal */ + __u8 bDelay; /* Delay introduced by the data path */ + __le16 wFormatTag; /* The Audio Data Format */ +} __attribute__ ((packed)); + +#define UAC_DT_AS_HEADER_SIZE 7 + +/* Formats - A.1.1 Audio Data Format Type I Codes */ +#define UAC_FORMAT_TYPE_I_UNDEFINED 0x0 +#define UAC_FORMAT_TYPE_I_PCM 0x1 +#define UAC_FORMAT_TYPE_I_PCM8 0x2 +#define UAC_FORMAT_TYPE_I_IEEE_FLOAT 0x3 +#define UAC_FORMAT_TYPE_I_ALAW 0x4 +#define UAC_FORMAT_TYPE_I_MULAW 0x5 + +struct uac_format_type_i_continuous_descriptor { + __u8 bLength; /* in bytes: 8 + (ns * 3) */ + __u8 bDescriptorType; /* USB_DT_CS_INTERFACE */ + __u8 bDescriptorSubtype; /* FORMAT_TYPE */ + __u8 bFormatType; /* FORMAT_TYPE_1 */ + __u8 bNrChannels; /* physical channels in the stream */ + __u8 bSubframeSize; /* */ + __u8 bBitResolution; + __u8 bSamFreqType; + __u8 tLowerSamFreq[3]; + __u8 tUpperSamFreq[3]; +} __attribute__ ((packed)); + +#define UAC_FORMAT_TYPE_I_CONTINUOUS_DESC_SIZE 14 + +struct uac_format_type_i_discrete_descriptor { + __u8 bLength; /* in bytes: 8 + (ns * 3) */ + __u8 bDescriptorType; /* USB_DT_CS_INTERFACE */ + __u8 bDescriptorSubtype; /* FORMAT_TYPE */ + __u8 bFormatType; /* FORMAT_TYPE_1 */ + __u8 bNrChannels; /* physical channels in the stream */ + __u8 bSubframeSize; /* */ + __u8 bBitResolution; + __u8 bSamFreqType; + __u8 tSamFreq[][3]; +} __attribute__ ((packed)); + +#define DECLARE_UAC_FORMAT_TYPE_I_DISCRETE_DESC(n) \ +struct uac_format_type_i_discrete_descriptor_##n { \ + __u8 bLength; \ + __u8 bDescriptorType; \ + __u8 bDescriptorSubtype; \ + __u8 bFormatType; \ + __u8 bNrChannels; \ + __u8 bSubframeSize; \ + __u8 bBitResolution; \ + __u8 bSamFreqType; \ + __u8 tSamFreq[n][3]; \ +} __attribute__ ((packed)) + +#define UAC_FORMAT_TYPE_I_DISCRETE_DESC_SIZE(n) (8 + (n * 3)) + +struct uac_format_type_i_ext_descriptor { + __u8 bLength; + __u8 bDescriptorType; + __u8 bDescriptorSubtype; + __u8 bFormatType; + __u8 bSubslotSize; + __u8 bBitResolution; + __u8 bHeaderLength; + __u8 bControlSize; + __u8 bSideBandProtocol; +} __attribute__((packed)); + +/* Formats - Audio Data Format Type I Codes */ + +#define UAC_FORMAT_TYPE_II_MPEG 0x1001 +#define UAC_FORMAT_TYPE_II_AC3 0x1002 + +struct uac_format_type_ii_discrete_descriptor { + __u8 bLength; + __u8 bDescriptorType; + __u8 bDescriptorSubtype; + __u8 bFormatType; + __le16 wMaxBitRate; + __le16 wSamplesPerFrame; + __u8 bSamFreqType; + __u8 tSamFreq[][3]; +} __attribute__((packed)); + +struct uac_format_type_ii_ext_descriptor { + __u8 bLength; + __u8 bDescriptorType; + __u8 bDescriptorSubtype; + __u8 bFormatType; + __le16 wMaxBitRate; + __le16 wSamplesPerFrame; + __u8 bHeaderLength; + __u8 bSideBandProtocol; +} __attribute__((packed)); + +/* type III */ +#define UAC_FORMAT_TYPE_III_IEC1937_AC3 0x2001 +#define UAC_FORMAT_TYPE_III_IEC1937_MPEG1_LAYER1 0x2002 +#define UAC_FORMAT_TYPE_III_IEC1937_MPEG2_NOEXT 0x2003 +#define UAC_FORMAT_TYPE_III_IEC1937_MPEG2_EXT 0x2004 +#define UAC_FORMAT_TYPE_III_IEC1937_MPEG2_LAYER1_LS 0x2005 +#define UAC_FORMAT_TYPE_III_IEC1937_MPEG2_LAYER23_LS 0x2006 + +/* Formats - A.2 Format Type Codes */ +#define UAC_FORMAT_TYPE_UNDEFINED 0x0 +#define UAC_FORMAT_TYPE_I 0x1 +#define UAC_FORMAT_TYPE_II 0x2 +#define UAC_FORMAT_TYPE_III 0x3 +#define UAC_EXT_FORMAT_TYPE_I 0x81 +#define UAC_EXT_FORMAT_TYPE_II 0x82 +#define UAC_EXT_FORMAT_TYPE_III 0x83 + +struct uac_iso_endpoint_descriptor { + __u8 bLength; /* in bytes: 7 */ + __u8 bDescriptorType; /* USB_DT_CS_ENDPOINT */ + __u8 bDescriptorSubtype; /* EP_GENERAL */ + __u8 bmAttributes; + __u8 bLockDelayUnits; + __le16 wLockDelay; +} __attribute__((packed)); +#define UAC_ISO_ENDPOINT_DESC_SIZE 7 + +#define UAC_EP_CS_ATTR_SAMPLE_RATE 0x01 +#define UAC_EP_CS_ATTR_PITCH_CONTROL 0x02 +#define UAC_EP_CS_ATTR_FILL_MAX 0x80 + +/* status word format (3.7.1.1) */ + +#define UAC1_STATUS_TYPE_ORIG_MASK 0x0f +#define UAC1_STATUS_TYPE_ORIG_AUDIO_CONTROL_IF 0x0 +#define UAC1_STATUS_TYPE_ORIG_AUDIO_STREAM_IF 0x1 +#define UAC1_STATUS_TYPE_ORIG_AUDIO_STREAM_EP 0x2 + +#define UAC1_STATUS_TYPE_IRQ_PENDING (1 << 7) +#define UAC1_STATUS_TYPE_MEM_CHANGED (1 << 6) + +struct uac1_status_word { + __u8 bStatusType; + __u8 bOriginator; +} __attribute__((packed)); + + +#endif /* _UAPI__LINUX_USB_AUDIO_H */ diff --git a/components/drivers/usb/usbdevice/class/audio_mic.c b/components/drivers/usb/usbdevice/class/audio_mic.c new file mode 100644 index 0000000000..4ac85711ad --- /dev/null +++ b/components/drivers/usb/usbdevice/class/audio_mic.c @@ -0,0 +1,577 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-09-07 flybreak the first version + */ + +#include <rthw.h> +#include <rtthread.h> +#include <rtservice.h> +#include <rtdevice.h> + +#include "drivers/usb_device.h" +#include "audio.h" + +#define DBG_TAG "usbd.audio.mic" +#define DBG_LVL DBG_INFO +#include <rtdbg.h> + +#define RECORD_SAMPLERATE 16000 +#define RECORD_CHANNEL 1 +#define RESOLUTION_BITS 16 + +#define RESOLUTION_BYTE (RESOLUTION_BITS / 8) +#define RECORD_PER_MS_SZ ((RECORD_SAMPLERATE * RECORD_CHANNEL * RESOLUTION_BYTE) / 1000) +#define RECORD_BUFFER_SZ (RECORD_PER_MS_SZ * 20) /* 20ms */ + +#if defined(RT_USBD_MIC_DEVICE_NAME) + #define MIC_DEVICE_NAME RT_USBD_MIC_DEVICE_NAME +#else + #define MIC_DEVICE_NAME "mic0" +#endif + +#define EVENT_RECORD_START (1 << 0) +#define EVENT_RECORD_STOP (1 << 1) +#define EVENT_RECORD_DATA (1 << 2) + +/* + * uac mic descriptor define + */ + +#define UAC_CS_INTERFACE 0x24 +#define UAC_CS_ENDPOINT 0x25 + +#define UAC_MAX_PACKET_SIZE 64 +#define UAC_EP_MAX_PACKET_SIZE 32 +#define UAC_CHANNEL_NUM RECORD_CHANNEL +#define UAC_INTR_NUM 1 +#define UAC_CH_NUM 1 +#define UAC_FORMAT_NUM 1 + +struct uac_ac_descriptor +{ +#ifdef RT_USB_DEVICE_COMPOSITE + struct uiad_descriptor iad_desc; +#endif + struct uinterface_descriptor intf_desc; + DECLARE_UAC_AC_HEADER_DESCRIPTOR(UAC_INTR_NUM) hdr_desc; + struct uac_input_terminal_descriptor it_desc; + struct uac1_output_terminal_descriptor ot_desc; +#if UAC_USE_FEATURE_UNIT + DECLARE_UAC_FEATURE_UNIT_DESCRIPTOR(UAC_CH_NUM) feature_unit_desc; +#endif +}; + +struct uac_as_descriptor +{ + struct uinterface_descriptor intf_desc; + struct uac1_as_header_descriptor hdr_desc; + DECLARE_UAC_FORMAT_TYPE_I_DISCRETE_DESC(UAC_FORMAT_NUM) format_type_desc; + struct uendpoint_descriptor ep_desc; + struct uac_iso_endpoint_descriptor as_ep_desc; +}; + +/* + * uac mic device type + */ + +struct uac_audio_mic +{ + rt_device_t dev; + rt_event_t event; + rt_uint8_t open_count; + + rt_uint8_t *buffer; + rt_uint32_t buffer_index; + + uep_t ep; +}; +static struct uac_audio_mic mic; + +ALIGN(4) +static struct udevice_descriptor dev_desc = +{ + USB_DESC_LENGTH_DEVICE, //bLength; + USB_DESC_TYPE_DEVICE, //type; + USB_BCD_VERSION, //bcdUSB; + USB_CLASS_DEVICE, //bDeviceClass; + 0x00, //bDeviceSubClass; + 0x00, //bDeviceProtocol; + UAC_MAX_PACKET_SIZE, //bMaxPacketSize0; + _VENDOR_ID, //idVendor; + _PRODUCT_ID, //idProduct; + USB_BCD_DEVICE, //bcdDevice; + USB_STRING_MANU_INDEX, //iManufacturer; + USB_STRING_PRODUCT_INDEX, //iProduct; + USB_STRING_SERIAL_INDEX, //iSerialNumber;Unused. + USB_DYNAMIC, //bNumConfigurations; +}; + +//FS and HS needed +ALIGN(4) +static struct usb_qualifier_descriptor dev_qualifier = +{ + sizeof(dev_qualifier), //bLength + USB_DESC_TYPE_DEVICEQUALIFIER, //bDescriptorType + 0x0200, //bcdUSB + USB_CLASS_AUDIO, //bDeviceClass + 0x00, //bDeviceSubClass + 0x00, //bDeviceProtocol + 64, //bMaxPacketSize0 + 0x01, //bNumConfigurations + 0, +}; + +ALIGN(4) +const static char *_ustring[] = +{ + "Language", + "RT-Thread Team.", + "Microphone", + "32021919830108", + "Configuration", + "Interface", +}; + +ALIGN(4) +static struct uac_ac_descriptor ac_desc = +{ +#ifdef RT_USB_DEVICE_COMPOSITE + /* Interface Association Descriptor */ + { + USB_DESC_LENGTH_IAD, + USB_DESC_TYPE_IAD, + USB_DYNAMIC, + 0x02, + USB_CLASS_AUDIO, + USB_SUBCLASS_AUDIOSTREAMING, + 0x00, + 0x00, + }, +#endif + /* Interface Descriptor */ + { + USB_DESC_LENGTH_INTERFACE, + USB_DESC_TYPE_INTERFACE, + USB_DYNAMIC, + 0x00, + 0x00, + USB_CLASS_AUDIO, + USB_SUBCLASS_AUDIOCONTROL, + 0x00, + 0x00, + }, + /* Header Descriptor */ + { + UAC_DT_AC_HEADER_SIZE(UAC_INTR_NUM), + UAC_CS_INTERFACE, + UAC_HEADER, + 0x0100, /* Version: 1.00 */ + 0x001E, /* Total length: 30 */ + 0x01, /* Total number of interfaces: 1 */ + {0x01}, /* Interface number: 1 */ + }, + /* Input Terminal Descriptor */ + { + UAC_DT_INPUT_TERMINAL_SIZE, + UAC_CS_INTERFACE, + UAC_INPUT_TERMINAL, + 0x01, /* Terminal ID: 1 */ + 0x0201, /* Terminal Type: Microphone (0x0201) */ + 0x00, /* Assoc Terminal: 0 */ + 0x01, /* Number Channels: 1 */ + 0x0000, /* Channel Config: 0x0000 */ + 0x00, /* Channel Names: 0 */ + 0x00, /* Terminal: 0 */ + }, + /* Output Terminal Descriptor */ + { + UAC_DT_OUTPUT_TERMINAL_SIZE, + UAC_CS_INTERFACE, + UAC_OUTPUT_TERMINAL, + 0x02, /* Terminal ID: 2 */ + 0x0101, /* Terminal Type: USB Streaming (0x0101) */ + 0x00, /* Assoc Terminal: 0 */ + 0x01, /* Source ID: 1 */ + 0x00, /* Terminal: 0 */ + }, +#if UAC_USE_FEATURE_UNIT + /* Feature unit Descriptor */ + { + UAC_DT_FEATURE_UNIT_SIZE(UAC_CH_NUM), + UAC_CS_INTERFACE, + UAC_FEATURE_UNIT, + 0x02, + 0x0101, + 0x00, + 0x01, + }, +#endif +}; + +ALIGN(4) +static struct uinterface_descriptor as_desc0 = +{ + USB_DESC_LENGTH_INTERFACE, + USB_DESC_TYPE_INTERFACE, + USB_DYNAMIC, + 0x00, + 0x00, + USB_CLASS_AUDIO, + USB_SUBCLASS_AUDIOSTREAMING, + 0x00, + 0x00, +}; + +ALIGN(4) +static struct uac_as_descriptor as_desc = +{ + /* Interface Descriptor */ + { + USB_DESC_LENGTH_INTERFACE, + USB_DESC_TYPE_INTERFACE, + USB_DYNAMIC, + 0x01, + 0x01, + USB_CLASS_AUDIO, + USB_SUBCLASS_AUDIOSTREAMING, + 0x00, + 0x00, + }, + /* General AS Descriptor */ + { + UAC_DT_AS_HEADER_SIZE, + UAC_CS_INTERFACE, + UAC_AS_GENERAL, + 0x02, /* Terminal ID: 2 */ + 0x01, /* Interface delay in frames: 1 */ + UAC_FORMAT_TYPE_I_PCM, + }, + /* Format type i Descriptor */ + { + UAC_FORMAT_TYPE_I_DISCRETE_DESC_SIZE(UAC_FORMAT_NUM), + UAC_CS_INTERFACE, + UAC_FORMAT_TYPE, + UAC_FORMAT_TYPE_I, + UAC_CHANNEL_NUM, + 2, /* Subframe Size: 2 */ + RESOLUTION_BITS, + 0x01, /* Samples Frequence Type: 1 */ + {0}, /* Samples Frequence */ + }, + /* Endpoint Descriptor */ + { + USB_DESC_LENGTH_ENDPOINT, + USB_DESC_TYPE_ENDPOINT, + USB_DYNAMIC | USB_DIR_IN, + USB_EP_ATTR_ISOC, + UAC_EP_MAX_PACKET_SIZE, + 0x01, + }, + /* AS Endpoint Descriptor */ + { + UAC_ISO_ENDPOINT_DESC_SIZE, + UAC_CS_ENDPOINT, + UAC_MS_GENERAL, + }, +}; + +void mic_entry(void *parameter) +{ + struct rt_audio_caps caps = {0}; + rt_uint32_t e, index; + + mic.buffer = rt_malloc(RECORD_BUFFER_SZ); + if (mic.buffer == RT_NULL) + { + LOG_E("malloc failed"); + goto __exit; + } + + mic.dev = rt_device_find(MIC_DEVICE_NAME); + if (mic.dev == RT_NULL) + { + LOG_E("can't find device:%s", MIC_DEVICE_NAME); + goto __exit; + } + + while (1) + { + if (rt_event_recv(mic.event, EVENT_RECORD_START | EVENT_RECORD_STOP, + RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, + 1000, &e) != RT_EOK) + { + continue; + } + if (mic.open_count == 0) + { + continue; + } + LOG_D("record start"); + + rt_device_open(mic.dev, RT_DEVICE_OFLAG_RDONLY); + + caps.main_type = AUDIO_TYPE_INPUT; + caps.sub_type = AUDIO_DSP_PARAM; + caps.udata.config.samplerate = RECORD_SAMPLERATE; + caps.udata.config.channels = RECORD_CHANNEL; + caps.udata.config.samplebits = RESOLUTION_BITS; + rt_device_control(mic.dev, AUDIO_CTL_CONFIGURE, &caps); + + while (1) + { + if (rt_event_recv(mic.event, EVENT_RECORD_DATA | EVENT_RECORD_STOP, + RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, + 1000, &e) != RT_EOK) + { + if (mic.open_count > 0) + continue; + else + break; + } + if (e & EVENT_RECORD_DATA) + { + index = (mic.buffer_index >= RECORD_BUFFER_SZ / 2) ? 0 : (RECORD_BUFFER_SZ / 2); + rt_device_read(mic.dev, 0, mic.buffer + index, RECORD_BUFFER_SZ / 2); + } + else if (e & EVENT_RECORD_STOP) + { + break; + } + } + LOG_D("record stop"); + rt_device_close(mic.dev); + } + +__exit: + if (mic.buffer) + rt_free(mic.buffer); +} + +static rt_err_t _record_start(ufunction_t func) +{ + mic.ep->request.buffer = RT_NULL; + mic.ep->request.size = UAC_EP_MAX_PACKET_SIZE; + mic.ep->request.req_type = UIO_REQUEST_WRITE; + rt_usbd_io_request(func->device, mic.ep, &mic.ep->request); + + mic.open_count ++; + rt_event_send(mic.event, EVENT_RECORD_START); + return 0; +} + +static rt_err_t _record_stop(ufunction_t func) +{ + mic.open_count --; + rt_event_send(mic.event, EVENT_RECORD_STOP); + return 0; +} + +static rt_err_t _ep_data_in_handler(ufunction_t func, rt_size_t size) +{ + RT_ASSERT(func != RT_NULL); + LOG_D("_ep_data_in_handler"); + + mic.ep->request.buffer = mic.buffer + mic.buffer_index; + mic.ep->request.size = UAC_EP_MAX_PACKET_SIZE; + mic.ep->request.req_type = UIO_REQUEST_WRITE; + rt_usbd_io_request(func->device, mic.ep, &mic.ep->request); + + mic.buffer_index += UAC_EP_MAX_PACKET_SIZE; + if (mic.buffer_index >= RECORD_BUFFER_SZ) + { + mic.buffer_index = 0; + rt_event_send(mic.event, EVENT_RECORD_DATA); + } + else if (mic.buffer_index == RECORD_BUFFER_SZ / 2) + { + rt_event_send(mic.event, EVENT_RECORD_DATA); + } + + return RT_EOK; +} + +static rt_err_t _interface_as_handler(ufunction_t func, ureq_t setup) +{ + RT_ASSERT(func != RT_NULL); + RT_ASSERT(func->device != RT_NULL); + RT_ASSERT(setup != RT_NULL); + + LOG_D("_interface_as_handler"); + + if ((setup->request_type & USB_REQ_TYPE_MASK) == USB_REQ_TYPE_STANDARD) + { + switch (setup->bRequest) + { + case USB_REQ_GET_INTERFACE: + break; + case USB_REQ_SET_INTERFACE: + LOG_D("set interface handler"); + if (setup->wValue == 1) + { + _record_start(func); + } + else if (setup->wValue == 0) + { + _record_stop(func); + } + break; + default: + LOG_D("unknown uac request 0x%x", setup->bRequest); + return -RT_ERROR; + } + } + + return RT_EOK; +} + +static rt_err_t _function_enable(ufunction_t func) +{ + RT_ASSERT(func != RT_NULL); + + LOG_D("uac function enable"); + + return RT_EOK; +} + +static rt_err_t _function_disable(ufunction_t func) +{ + RT_ASSERT(func != RT_NULL); + + LOG_D("uac function disable"); + _record_stop(func); + return RT_EOK; +} + +static struct ufunction_ops ops = +{ + _function_enable, + _function_disable, + RT_NULL, +}; +/** + * This function will configure uac descriptor. + * + * @param comm the communication interface number. + * @param data the data interface number. + * + * @return RT_EOK on successful. + */ +static rt_err_t _uac_descriptor_config(struct uac_ac_descriptor *ac, + rt_uint8_t cintf_nr, struct uac_as_descriptor *as, rt_uint8_t sintf_nr) +{ + ac->hdr_desc.baInterfaceNr[0] = sintf_nr; +#ifdef RT_USB_DEVICE_COMPOSITE + ac->iad_desc.bFirstInterface = cintf_nr; +#endif + + return RT_EOK; +} + +static rt_err_t _uac_samplerate_config(struct uac_as_descriptor *as, rt_uint32_t samplerate) +{ + as->format_type_desc.tSamFreq[0][2] = samplerate >> 16 & 0xff; + as->format_type_desc.tSamFreq[0][1] = samplerate >> 8 & 0xff; + as->format_type_desc.tSamFreq[0][0] = samplerate & 0xff; + return RT_EOK; +} + +/** + * This function will create a uac function instance. + * + * @param device the usb device object. + * + * @return RT_EOK on successful. + */ +ufunction_t rt_usbd_function_uac_mic_create(udevice_t device) +{ + ufunction_t func; + uintf_t intf_ac, intf_as; + ualtsetting_t setting_as0; + ualtsetting_t setting_ac, setting_as; + struct uac_as_descriptor *as_desc_t; + + /* parameter check */ + RT_ASSERT(device != RT_NULL); + + /* set usb device string description */ + rt_usbd_device_set_string(device, _ustring); + + /* create a uac function */ + func = rt_usbd_function_new(device, &dev_desc, &ops); + //not support HS + //rt_usbd_device_set_qualifier(device, &dev_qualifier); + + /* create interface */ + intf_ac = rt_usbd_interface_new(device, RT_NULL); + intf_as = rt_usbd_interface_new(device, _interface_as_handler); + + /* create alternate setting */ + setting_ac = rt_usbd_altsetting_new(sizeof(struct uac_ac_descriptor)); + setting_as0 = rt_usbd_altsetting_new(sizeof(struct uinterface_descriptor)); + setting_as = rt_usbd_altsetting_new(sizeof(struct uac_as_descriptor)); + /* config desc in alternate setting */ + rt_usbd_altsetting_config_descriptor(setting_ac, &ac_desc, + (rt_off_t) & ((struct uac_ac_descriptor *)0)->intf_desc); + rt_usbd_altsetting_config_descriptor(setting_as0, &as_desc0, 0); + rt_usbd_altsetting_config_descriptor(setting_as, &as_desc, + (rt_off_t) & ((struct uac_as_descriptor *)0)->intf_desc); + /* configure the uac interface descriptor */ + _uac_descriptor_config(setting_ac->desc, intf_ac->intf_num, setting_as->desc, intf_as->intf_num); + _uac_samplerate_config(setting_as->desc, RECORD_SAMPLERATE); + + /* create endpoint */ + as_desc_t = (struct uac_as_descriptor *)setting_as->desc; + mic.ep = rt_usbd_endpoint_new(&as_desc_t->ep_desc, _ep_data_in_handler); + + /* add the endpoint to the alternate setting */ + rt_usbd_altsetting_add_endpoint(setting_as, mic.ep); + + /* add the alternate setting to the interface, then set default setting of the interface */ + rt_usbd_interface_add_altsetting(intf_ac, setting_ac); + rt_usbd_set_altsetting(intf_ac, 0); + rt_usbd_interface_add_altsetting(intf_as, setting_as0); + rt_usbd_interface_add_altsetting(intf_as, setting_as); + rt_usbd_set_altsetting(intf_as, 0); + + /* add the interface to the uac function */ + rt_usbd_function_add_interface(func, intf_ac); + rt_usbd_function_add_interface(func, intf_as); + + return func; +} + +int audio_mic_init(void) +{ + rt_thread_t mic_tid; + mic.event = rt_event_create("mic_event", RT_IPC_FLAG_FIFO); + + mic_tid = rt_thread_create("mic_thread", + mic_entry, RT_NULL, + 1024, + 5, 10); + + if (mic_tid != RT_NULL) + rt_thread_startup(mic_tid); + return RT_EOK; +} +INIT_COMPONENT_EXPORT(audio_mic_init); + +/* + * register uac class + */ +struct udclass uac_class = +{ + .rt_usbd_function_create = rt_usbd_function_uac_mic_create +}; + +int rt_usbd_uac_mic_class_register(void) +{ + rt_usbd_class_register(&uac_class); + return 0; +} +INIT_PREV_EXPORT(rt_usbd_uac_mic_class_register); diff --git a/components/drivers/usb/usbdevice/class/audio_speaker.c b/components/drivers/usb/usbdevice/class/audio_speaker.c new file mode 100644 index 0000000000..84c36d2053 --- /dev/null +++ b/components/drivers/usb/usbdevice/class/audio_speaker.c @@ -0,0 +1,578 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-09-19 flybreak the first version + */ + +#include <rthw.h> +#include <rtthread.h> +#include <rtservice.h> +#include <rtdevice.h> + +#include "drivers/usb_device.h" +#include "audio.h" + +#define DBG_TAG "usbd.audio.speaker" +#define DBG_LVL DBG_INFO +#include <rtdbg.h> + +#define AUDIO_SAMPLERATE 16000 +#define AUDIO_CHANNEL 1 +#define RESOLUTION_BITS 16 + +#define RESOLUTION_BYTE (RESOLUTION_BITS / 8) +#define AUDIO_PER_MS_SZ ((AUDIO_SAMPLERATE * AUDIO_CHANNEL * RESOLUTION_BYTE) / 1000) +#define AUDIO_BUFFER_SZ (AUDIO_PER_MS_SZ * 20) /* 20ms */ + +#if defined(RT_USBD_SPEAKER_DEVICE_NAME) + #define SPEAKER_DEVICE_NAME RT_USBD_SPEAKER_DEVICE_NAME +#else + #define SPEAKER_DEVICE_NAME "sound0" +#endif + +#define EVENT_AUDIO_START (1 << 0) +#define EVENT_AUDIO_STOP (1 << 1) +#define EVENT_AUDIO_DATA (1 << 2) + +/* + * uac speaker descriptor define + */ + +#define UAC_CS_INTERFACE 0x24 +#define UAC_CS_ENDPOINT 0x25 + +#define UAC_MAX_PACKET_SIZE 64 +#define UAC_EP_MAX_PACKET_SIZE 32 +#define UAC_CHANNEL_NUM AUDIO_CHANNEL +#define UAC_INTR_NUM 1 +#define UAC_CH_NUM 1 +#define UAC_FORMAT_NUM 1 + +struct uac_ac_descriptor +{ +#ifdef RT_USB_DEVICE_COMPOSITE + struct uiad_descriptor iad_desc; +#endif + struct uinterface_descriptor intf_desc; + DECLARE_UAC_AC_HEADER_DESCRIPTOR(UAC_INTR_NUM) hdr_desc; + struct uac_input_terminal_descriptor it_desc; + struct uac1_output_terminal_descriptor ot_desc; +#if UAC_USE_FEATURE_UNIT + DECLARE_UAC_FEATURE_UNIT_DESCRIPTOR(UAC_CH_NUM) feature_unit_desc; +#endif +}; + +struct uac_as_descriptor +{ + struct uinterface_descriptor intf_desc; + struct uac1_as_header_descriptor hdr_desc; + DECLARE_UAC_FORMAT_TYPE_I_DISCRETE_DESC(UAC_FORMAT_NUM) format_type_desc; + struct uendpoint_descriptor ep_desc; + struct uac_iso_endpoint_descriptor as_ep_desc; +}; + +/* + * uac speaker device type + */ + +struct uac_audio_speaker +{ + rt_device_t dev; + rt_event_t event; + rt_uint8_t open_count; + + rt_uint8_t *buffer; + rt_uint32_t buffer_index; + + uep_t ep; +}; +static struct uac_audio_speaker speaker; + +ALIGN(4) +static struct udevice_descriptor dev_desc = +{ + USB_DESC_LENGTH_DEVICE, //bLength; + USB_DESC_TYPE_DEVICE, //type; + USB_BCD_VERSION, //bcdUSB; + USB_CLASS_DEVICE, //bDeviceClass; + 0x00, //bDeviceSubClass; + 0x00, //bDeviceProtocol; + UAC_MAX_PACKET_SIZE, //bMaxPacketSize0; + _VENDOR_ID, //idVendor; + _PRODUCT_ID, //idProduct; + USB_BCD_DEVICE, //bcdDevice; + USB_STRING_MANU_INDEX, //iManufacturer; + USB_STRING_PRODUCT_INDEX, //iProduct; + USB_STRING_SERIAL_INDEX, //iSerialNumber;Unused. + USB_DYNAMIC, //bNumConfigurations; +}; + +//FS and HS needed +ALIGN(4) +static struct usb_qualifier_descriptor dev_qualifier = +{ + sizeof(dev_qualifier), //bLength + USB_DESC_TYPE_DEVICEQUALIFIER, //bDescriptorType + 0x0200, //bcdUSB + USB_CLASS_AUDIO, //bDeviceClass + 0x00, //bDeviceSubClass + 0x00, //bDeviceProtocol + 64, //bMaxPacketSize0 + 0x01, //bNumConfigurations + 0, +}; + +ALIGN(4) +const static char *_ustring[] = +{ + "Language", + "RT-Thread Team.", + "RT-Thread Speaker", + "32021919830108", + "Configuration", + "Interface", +}; + +ALIGN(4) +static struct uac_ac_descriptor ac_desc = +{ +#ifdef RT_USB_DEVICE_COMPOSITE + /* Interface Association Descriptor */ + { + USB_DESC_LENGTH_IAD, + USB_DESC_TYPE_IAD, + USB_DYNAMIC, + 0x02, + USB_CLASS_AUDIO, + USB_SUBCLASS_AUDIOSTREAMING, + 0x00, + 0x00, + }, +#endif + /* Interface Descriptor */ + { + USB_DESC_LENGTH_INTERFACE, + USB_DESC_TYPE_INTERFACE, + USB_DYNAMIC, + 0x00, + 0x00, + USB_CLASS_AUDIO, + USB_SUBCLASS_AUDIOCONTROL, + 0x00, + 0x00, + }, + /* Header Descriptor */ + { + UAC_DT_AC_HEADER_SIZE(UAC_INTR_NUM), + UAC_CS_INTERFACE, + UAC_HEADER, + 0x0100, /* Version: 1.00 */ + 0x0027, /* Total length: 39 */ + 0x01, /* Total number of interfaces: 1 */ + {0x01}, /* Interface number: 1 */ + }, + /* Input Terminal Descriptor */ + { + UAC_DT_INPUT_TERMINAL_SIZE, + UAC_CS_INTERFACE, + UAC_INPUT_TERMINAL, + 0x01, /* Terminal ID: 1 */ + 0x0101, /* Terminal Type: USB Streaming (0x0101) */ + 0x00, /* Assoc Terminal: 0 */ + 0x01, /* Number Channels: 1 */ + 0x0000, /* Channel Config: 0x0000 */ + 0x00, /* Channel Names: 0 */ + 0x00, /* Terminal: 0 */ + }, + /* Output Terminal Descriptor */ + { + UAC_DT_OUTPUT_TERMINAL_SIZE, + UAC_CS_INTERFACE, + UAC_OUTPUT_TERMINAL, + 0x02, /* Terminal ID: 2 */ + 0x0302, /* Terminal Type: Headphones (0x0302) */ + 0x00, /* Assoc Terminal: 0 */ + 0x01, /* Source ID: 1 */ + 0x00, /* Terminal: 0 */ + }, +#if UAC_USE_FEATURE_UNIT + /* Feature unit Descriptor */ + { + UAC_DT_FEATURE_UNIT_SIZE(UAC_CH_NUM), + UAC_CS_INTERFACE, + UAC_FEATURE_UNIT, + 0x02, + 0x0101, + 0x00, + 0x01, + }, +#endif +}; + +ALIGN(4) +static struct uinterface_descriptor as_desc0 = +{ + USB_DESC_LENGTH_INTERFACE, + USB_DESC_TYPE_INTERFACE, + USB_DYNAMIC, + 0x00, + 0x00, + USB_CLASS_AUDIO, + USB_SUBCLASS_AUDIOSTREAMING, + 0x00, + 0x00, +}; + +ALIGN(4) +static struct uac_as_descriptor as_desc = +{ + /* Interface Descriptor */ + { + USB_DESC_LENGTH_INTERFACE, + USB_DESC_TYPE_INTERFACE, + USB_DYNAMIC, + 0x01, + 0x01, + USB_CLASS_AUDIO, + USB_SUBCLASS_AUDIOSTREAMING, + 0x00, + 0x00, + }, + /* General AS Descriptor */ + { + UAC_DT_AS_HEADER_SIZE, + UAC_CS_INTERFACE, + UAC_AS_GENERAL, + 0x01, /* Terminal ID: 1 */ + 0x01, /* Interface delay in frames: 1 */ + UAC_FORMAT_TYPE_I_PCM, + }, + /* Format type i Descriptor */ + { + UAC_FORMAT_TYPE_I_DISCRETE_DESC_SIZE(UAC_FORMAT_NUM), + UAC_CS_INTERFACE, + UAC_FORMAT_TYPE, + UAC_FORMAT_TYPE_I, + UAC_CHANNEL_NUM, + 2, /* Subframe Size: 2 */ + RESOLUTION_BITS, + 0x01, /* Samples Frequence Type: 1 */ + {0}, /* Samples Frequence */ + }, + /* Endpoint Descriptor */ + { + USB_DESC_LENGTH_ENDPOINT, + USB_DESC_TYPE_ENDPOINT, + USB_DYNAMIC | USB_DIR_OUT, + USB_EP_ATTR_ISOC, + UAC_EP_MAX_PACKET_SIZE, + 0x01, + }, + /* AS Endpoint Descriptor */ + { + UAC_ISO_ENDPOINT_DESC_SIZE, + UAC_CS_ENDPOINT, + UAC_MS_GENERAL, + }, +}; + +void speaker_entry(void *parameter) +{ + struct rt_audio_caps caps = {0}; + rt_uint32_t e, index; + + speaker.buffer = rt_malloc(AUDIO_BUFFER_SZ); + if (speaker.buffer == RT_NULL) + { + LOG_E("malloc failed"); + goto __exit; + } + + speaker.dev = rt_device_find(SPEAKER_DEVICE_NAME); + if (speaker.dev == RT_NULL) + { + LOG_E("can't find device:%s", SPEAKER_DEVICE_NAME); + goto __exit; + } + + while (1) + { + if (rt_event_recv(speaker.event, EVENT_AUDIO_START | EVENT_AUDIO_STOP, + RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, + 1000, &e) != RT_EOK) + { + continue; + } + if (speaker.open_count == 0) + { + continue; + } + LOG_D("play start"); + + rt_device_open(speaker.dev, RT_DEVICE_OFLAG_WRONLY); + + caps.main_type = AUDIO_TYPE_OUTPUT; + caps.sub_type = AUDIO_DSP_PARAM; + caps.udata.config.samplerate = AUDIO_SAMPLERATE; + caps.udata.config.channels = AUDIO_CHANNEL; + caps.udata.config.samplebits = RESOLUTION_BITS; + rt_device_control(speaker.dev, AUDIO_CTL_CONFIGURE, &caps); + + while (1) + { + if (rt_event_recv(speaker.event, EVENT_AUDIO_DATA | EVENT_AUDIO_STOP, + RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, + 1000, &e) != RT_EOK) + { + if (speaker.open_count > 0) + continue; + else + break; + } + if (e & EVENT_AUDIO_DATA) + { + index = (speaker.buffer_index >= AUDIO_BUFFER_SZ / 2) ? 0 : (AUDIO_BUFFER_SZ / 2); + rt_device_write(speaker.dev, 0, speaker.buffer + index, AUDIO_BUFFER_SZ / 2); + } + else if (e & EVENT_AUDIO_STOP) + { + break; + } + } + LOG_D("play stop"); + rt_device_close(speaker.dev); + } + +__exit: + if (speaker.buffer) + rt_free(speaker.buffer); +} + +static rt_err_t _audio_start(ufunction_t func) +{ + speaker.ep->request.buffer = speaker.buffer; + speaker.ep->request.size = UAC_EP_MAX_PACKET_SIZE; + speaker.ep->request.req_type = UIO_REQUEST_READ_FULL; + rt_usbd_io_request(func->device, speaker.ep, &speaker.ep->request); + + speaker.open_count ++; + rt_event_send(speaker.event, EVENT_AUDIO_START); + + return 0; +} + +static rt_err_t _audio_stop(ufunction_t func) +{ + speaker.open_count --; + rt_event_send(speaker.event, EVENT_AUDIO_STOP); + return 0; +} + +static rt_err_t _ep_data_handler(ufunction_t func, rt_size_t size) +{ + RT_ASSERT(func != RT_NULL); + LOG_D("_ep_data_handler"); + + speaker.ep->request.buffer = speaker.buffer + speaker.buffer_index; + speaker.ep->request.size = UAC_EP_MAX_PACKET_SIZE; + speaker.ep->request.req_type = UIO_REQUEST_READ_FULL; + rt_usbd_io_request(func->device, speaker.ep, &speaker.ep->request); + + speaker.buffer_index += UAC_EP_MAX_PACKET_SIZE; + if (speaker.buffer_index >= AUDIO_BUFFER_SZ) + { + speaker.buffer_index = 0; + rt_event_send(speaker.event, EVENT_AUDIO_DATA); + } + else if (speaker.buffer_index == AUDIO_BUFFER_SZ / 2) + { + rt_event_send(speaker.event, EVENT_AUDIO_DATA); + } + + return RT_EOK; +} + +static rt_err_t _interface_as_handler(ufunction_t func, ureq_t setup) +{ + RT_ASSERT(func != RT_NULL); + RT_ASSERT(func->device != RT_NULL); + RT_ASSERT(setup != RT_NULL); + + LOG_D("_interface_as_handler"); + + if ((setup->request_type & USB_REQ_TYPE_MASK) == USB_REQ_TYPE_STANDARD) + { + switch (setup->bRequest) + { + case USB_REQ_GET_INTERFACE: + break; + case USB_REQ_SET_INTERFACE: + LOG_D("set interface handler"); + if (setup->wValue == 1) + { + _audio_start(func); + } + else if (setup->wValue == 0) + { + _audio_stop(func); + } + break; + default: + LOG_D("unknown uac request 0x%x", setup->bRequest); + return -RT_ERROR; + } + } + + return RT_EOK; +} + +static rt_err_t _function_enable(ufunction_t func) +{ + RT_ASSERT(func != RT_NULL); + + LOG_D("uac function enable"); + + return RT_EOK; +} + +static rt_err_t _function_disable(ufunction_t func) +{ + RT_ASSERT(func != RT_NULL); + + LOG_D("uac function disable"); + _audio_stop(func); + return RT_EOK; +} + +static struct ufunction_ops ops = +{ + _function_enable, + _function_disable, + RT_NULL, +}; +/** + * This function will configure uac descriptor. + * + * @param comm the communication interface number. + * @param data the data interface number. + * + * @return RT_EOK on successful. + */ +static rt_err_t _uac_descriptor_config(struct uac_ac_descriptor *ac, + rt_uint8_t cintf_nr, struct uac_as_descriptor *as, rt_uint8_t sintf_nr) +{ + ac->hdr_desc.baInterfaceNr[0] = sintf_nr; +#ifdef RT_USB_DEVICE_COMPOSITE + ac->iad_desc.bFirstInterface = cintf_nr; +#endif + + return RT_EOK; +} + +static rt_err_t _uac_samplerate_config(struct uac_as_descriptor *as, rt_uint32_t samplerate) +{ + as->format_type_desc.tSamFreq[0][2] = samplerate >> 16 & 0xff; + as->format_type_desc.tSamFreq[0][1] = samplerate >> 8 & 0xff; + as->format_type_desc.tSamFreq[0][0] = samplerate & 0xff; + return RT_EOK; +} + +/** + * This function will create a uac function instance. + * + * @param device the usb device object. + * + * @return RT_EOK on successful. + */ +ufunction_t rt_usbd_function_uac_speaker_create(udevice_t device) +{ + ufunction_t func; + uintf_t intf_ac, intf_as; + ualtsetting_t setting_as0; + ualtsetting_t setting_ac, setting_as; + struct uac_as_descriptor *as_desc_t; + + /* parameter check */ + RT_ASSERT(device != RT_NULL); + + /* set usb device string description */ + rt_usbd_device_set_string(device, _ustring); + + /* create a uac function */ + func = rt_usbd_function_new(device, &dev_desc, &ops); + //not support HS + //rt_usbd_device_set_qualifier(device, &dev_qualifier); + + /* create interface */ + intf_ac = rt_usbd_interface_new(device, RT_NULL); + intf_as = rt_usbd_interface_new(device, _interface_as_handler); + + /* create alternate setting */ + setting_ac = rt_usbd_altsetting_new(sizeof(struct uac_ac_descriptor)); + setting_as0 = rt_usbd_altsetting_new(sizeof(struct uinterface_descriptor)); + setting_as = rt_usbd_altsetting_new(sizeof(struct uac_as_descriptor)); + /* config desc in alternate setting */ + rt_usbd_altsetting_config_descriptor(setting_ac, &ac_desc, + (rt_off_t) & ((struct uac_ac_descriptor *)0)->intf_desc); + rt_usbd_altsetting_config_descriptor(setting_as0, &as_desc0, 0); + rt_usbd_altsetting_config_descriptor(setting_as, &as_desc, + (rt_off_t) & ((struct uac_as_descriptor *)0)->intf_desc); + /* configure the uac interface descriptor */ + _uac_descriptor_config(setting_ac->desc, intf_ac->intf_num, setting_as->desc, intf_as->intf_num); + _uac_samplerate_config(setting_as->desc, AUDIO_SAMPLERATE); + + /* create endpoint */ + as_desc_t = (struct uac_as_descriptor *)setting_as->desc; + speaker.ep = rt_usbd_endpoint_new(&as_desc_t->ep_desc, _ep_data_handler); + + /* add the endpoint to the alternate setting */ + rt_usbd_altsetting_add_endpoint(setting_as, speaker.ep); + + /* add the alternate setting to the interface, then set default setting of the interface */ + rt_usbd_interface_add_altsetting(intf_ac, setting_ac); + rt_usbd_set_altsetting(intf_ac, 0); + rt_usbd_interface_add_altsetting(intf_as, setting_as0); + rt_usbd_interface_add_altsetting(intf_as, setting_as); + rt_usbd_set_altsetting(intf_as, 0); + + /* add the interface to the uac function */ + rt_usbd_function_add_interface(func, intf_ac); + rt_usbd_function_add_interface(func, intf_as); + + return func; +} + +int audio_speaker_init(void) +{ + rt_thread_t speaker_tid; + speaker.event = rt_event_create("speaker_event", RT_IPC_FLAG_FIFO); + + speaker_tid = rt_thread_create("speaker_thread", + speaker_entry, RT_NULL, + 1024, + 5, 10); + + if (speaker_tid != RT_NULL) + rt_thread_startup(speaker_tid); + return RT_EOK; +} +INIT_COMPONENT_EXPORT(audio_speaker_init); + +/* + * register uac class + */ +static struct udclass uac_speaker_class = +{ + .rt_usbd_function_create = rt_usbd_function_uac_speaker_create +}; + +int rt_usbd_uac_speaker_class_register(void) +{ + rt_usbd_class_register(&uac_speaker_class); + return 0; +} +INIT_PREV_EXPORT(rt_usbd_uac_speaker_class_register); diff --git a/components/drivers/usb/usbdevice/class/ecm.c b/components/drivers/usb/usbdevice/class/ecm.c index cda1a8bf1b..b98b5007f4 100644 --- a/components/drivers/usb/usbdevice/class/ecm.c +++ b/components/drivers/usb/usbdevice/class/ecm.c @@ -6,17 +6,16 @@ * Change Logs: * Date Author Notes * 2017-11-19 ZYH first version + * 2019-06-10 ZYH fix hotplug */ #include <rtdevice.h> +#ifdef RT_USB_DEVICE_ECM #include "cdc.h" - -#ifdef ECM_DEBUG -#define ECM_PRINTF rt_kprintf("[ECM] "); rt_kprintf -#else -#define ECM_PRINTF(...) -#endif /* ECM_DEBUG */ +#define DBG_LEVEL DBG_WARNING +#define DBG_SECTION_NAME "ECM" +#include <rtdbg.h> /* RT-Thread LWIP ethernet interface */ #include <netif/ethernetif.h> @@ -216,15 +215,21 @@ static rt_err_t _cdc_send_notifi(ufunction_t func,ucdc_notification_code_t notif return RT_EOK; } + static rt_err_t _ecm_set_eth_packet_filter(ufunction_t func, ureq_t setup) { rt_ecm_eth_t _ecm_eth = (rt_ecm_eth_t)func->user_data; dcd_ep0_send_status(func->device->dcd); - /* send link up. */ eth_device_linkchange(&_ecm_eth->parent, RT_TRUE); - _cdc_send_notifi(func,UCDC_NOTIFI_NETWORK_CONNECTION,1,0); + _cdc_send_notifi(func, UCDC_NOTIFI_NETWORK_CONNECTION, 1, 0); + +#ifdef LWIP_USING_DHCPD + extern void dhcpd_start(const char *netif_name); + dhcpd_start("u0"); +#endif + return RT_EOK; } /** @@ -243,10 +248,11 @@ static rt_err_t _interface_handler(ufunction_t func, ureq_t setup) switch(setup->bRequest) { case CDC_SET_ETH_PACKET_FILTER: + LOG_D("CDC_SET_ETH_PACKET_FILTER"); _ecm_set_eth_packet_filter(func, setup); break; default: - rt_kprintf("setup->bRequest:0x%02X",setup->bRequest); + LOG_E("Unknow setup->bRequest: 0x%02X", setup->bRequest); break; } return RT_EOK; @@ -402,22 +408,26 @@ rt_err_t rt_ecm_eth_tx(rt_device_t dev, struct pbuf* p) if(!ecm_eth_dev->parent.link_status) { - ECM_PRINTF("linkdown, drop pkg\r\n"); + LOG_D("linkdown, drop pkg"); return RT_EOK; } - // RT_ASSERT(p->tot_len < USB_ETH_MTU); if(p->tot_len > USB_ETH_MTU) { - ECM_PRINTF("RNDIS MTU is:%d, but the send packet size is %d\r\n", + LOG_W("ECM MTU is:%d, but the send packet size is %d", USB_ETH_MTU, p->tot_len); p->tot_len = USB_ETH_MTU; } - result = rt_sem_take(&ecm_eth_dev->tx_buffer_free, RT_WAITING_FOREVER); + + result = rt_sem_take(&device->tx_buffer_free, rt_tick_from_millisecond(1000)); if(result != RT_EOK) { + LOG_W("wait for buffer free timeout"); + /* if cost 1s to wait send done it said that connection is close . drop it */ + rt_sem_release(&device->tx_buffer_free); return result; } + pbuffer = (char *)&ecm_eth_dev->tx_buffer; for (q = p; q != NULL; q = q->next) { @@ -461,8 +471,13 @@ static rt_err_t _function_enable(ufunction_t func) { cdc_eps_t eps; rt_ecm_eth_t ecm_device = (rt_ecm_eth_t)func->user_data; + + LOG_D("plugged in"); + eps = (cdc_eps_t)&ecm_device->eps; eps->ep_out->buffer = ecm_device->rx_pool; + + /* reset eth rx tx */ ecm_device->rx_size = 0; ecm_device->rx_offset = 0; @@ -482,7 +497,14 @@ static rt_err_t _function_enable(ufunction_t func) */ static rt_err_t _function_disable(ufunction_t func) { + LOG_D("plugged out"); + eth_device_linkchange(&((rt_ecm_eth_t)func->user_data)->parent, RT_FALSE); + + /* reset eth rx tx */ + ((rt_ecm_eth_t)func->user_data)->rx_size = 0; + ((rt_ecm_eth_t)func->user_data)->rx_offset = 0; + return RT_EOK; } @@ -643,3 +665,5 @@ int rt_usbd_ecm_class_register(void) return 0; } INIT_PREV_EXPORT(rt_usbd_ecm_class_register); + +#endif /* RT_USB_DEVICE_ECM */ diff --git a/components/drivers/usb/usbdevice/class/hid.c b/components/drivers/usb/usbdevice/class/hid.c index aea6d802d1..a9b2e62d70 100644 --- a/components/drivers/usb/usbdevice/class/hid.c +++ b/components/drivers/usb/usbdevice/class/hid.c @@ -372,7 +372,7 @@ const static char* _ustring[] = "Interface", }; -static void dump_data(uint8_t *data, rt_size_t size) +static void dump_data(rt_uint8_t *data, rt_size_t size) { rt_size_t i; for (i = 0; i < size; i++) diff --git a/components/drivers/usb/usbdevice/class/rndis.c b/components/drivers/usb/usbdevice/class/rndis.c index 8996b728e6..93e0ba6ae2 100644 --- a/components/drivers/usb/usbdevice/class/rndis.c +++ b/components/drivers/usb/usbdevice/class/rndis.c @@ -13,21 +13,21 @@ * 2013-07-09 aozima support respone chain list. * 2013-07-18 aozima re-initial respone chain list when RNDIS restart. * 2017-11-25 ZYH fix it and add OS descriptor + * 2019-06-10 ZYH fix hot plug and delay linkup */ #include <rtdevice.h> +#ifdef RT_USB_DEVICE_RNDIS #include "cdc.h" #include "rndis.h" #include "ndis.h" -//#define RNDIS_DEBUG -//#define RNDIS_DELAY_LINK_UP +/* define RNDIS_DELAY_LINK_UP by menuconfig for delay linkup */ + +#define DBG_LEVEL DBG_WARNING +#define DBG_SECTION_NAME "RNDIS" +#include <rtdbg.h> -#ifdef RNDIS_DEBUG -#define RNDIS_PRINTF rt_kprintf("[RNDIS] "); rt_kprintf -#else -#define RNDIS_PRINTF(...) -#endif /* RNDIS_DEBUG */ /* RT-Thread LWIP ethernet interface */ #include <netif/ethernetif.h> @@ -314,7 +314,7 @@ static rt_err_t _rndis_init_response(ufunction_t func, rndis_init_msg_t msg) if( (response == RT_NULL) || (resp == RT_NULL) ) { - RNDIS_PRINTF("%d: no memory!\r\n", __LINE__); + LOG_E("%s,%d: no memory!", __func__, __LINE__); if(response != RT_NULL) rt_free(response); @@ -360,7 +360,7 @@ static rndis_query_cmplt_t _create_resp(rt_size_t size) if(resp == RT_NULL) { - RNDIS_PRINTF("%d: no memory!\r\n", __LINE__); + LOG_E("%s,%d: no memory!", __func__, __LINE__); return RT_NULL; } @@ -421,7 +421,7 @@ static rt_err_t _rndis_query_response(ufunction_t func,rndis_query_msg_t msg) case OID_GEN_LINK_SPEED: resp = _create_resp(4); if(resp == RT_NULL) break; - _set_resp(resp, func->device->dcd->device_is_hs ? (480UL * 1000 *1000) : (12UL * 1000 * 1000) / 100); + _set_resp(resp, (func->device->dcd->device_is_hs ? (480UL * 1000 *1000) : (12UL * 1000 * 1000)) / 100); break; case OID_GEN_MEDIA_CONNECT_STATUS: @@ -510,7 +510,7 @@ static rt_err_t _rndis_query_response(ufunction_t func,rndis_query_msg_t msg) break; default: - RNDIS_PRINTF("OID %X\n", msg->Oid); + LOG_W("Not support OID %X", msg->Oid); ret = -RT_ERROR; break; } @@ -518,7 +518,7 @@ static rt_err_t _rndis_query_response(ufunction_t func,rndis_query_msg_t msg) response = rt_malloc(sizeof(struct rt_rndis_response)); if( (response == RT_NULL) || (resp == RT_NULL) ) { - RNDIS_PRINTF("%d: no memory!\r\n", __LINE__); + LOG_E("%s,%d: no memory!", __func__, __LINE__); if(response != RT_NULL) rt_free(response); @@ -557,7 +557,7 @@ static rt_err_t _rndis_set_response(ufunction_t func,rndis_set_msg_t msg) if( (response == RT_NULL) || (resp == RT_NULL) ) { - RNDIS_PRINTF("%d: no memory!\r\n", __LINE__); + LOG_E("%s,%d: no memory!", __func__, __LINE__); if(response != RT_NULL) rt_free(response); @@ -577,8 +577,10 @@ static rt_err_t _rndis_set_response(ufunction_t func,rndis_set_msg_t msg) case OID_GEN_CURRENT_PACKET_FILTER: oid_packet_filter = *((rt_uint32_t *)((rt_uint8_t *)&(msg->RequestId) + \ msg->InformationBufferOffset)); + /* TODO: make complier happy */ oid_packet_filter = oid_packet_filter; - RNDIS_PRINTF("OID_GEN_CURRENT_PACKET_FILTER\r\n"); + + LOG_D("OID_GEN_CURRENT_PACKET_FILTER"); #ifdef RNDIS_DELAY_LINK_UP /* link up. */ @@ -592,6 +594,7 @@ static rt_err_t _rndis_set_response(ufunction_t func,rndis_set_msg_t msg) break; default: + LOG_W("Unknow rndis set 0x%02X", msg->Oid); resp->Status = RNDIS_STATUS_FAILURE; return RT_EOK; } @@ -609,6 +612,56 @@ static rt_err_t _rndis_set_response(ufunction_t func,rndis_set_msg_t msg) return RT_EOK; } +static rt_err_t _rndis_reset_response(ufunction_t func,rndis_set_msg_t msg) +{ + struct rndis_reset_cmplt * resp; + struct rt_rndis_response * response; + + response = rt_malloc(sizeof(struct rt_rndis_response)); + resp = rt_malloc(sizeof(struct rndis_reset_cmplt)); + + if( (response == RT_NULL) || (resp == RT_NULL) ) + { + LOG_E("%s,%d: no memory!", __func__, __LINE__); + + if(response != RT_NULL) + rt_free(response); + + if(resp != RT_NULL) + rt_free(resp); + + return -RT_ENOMEM; + } + + /* reset packet filter */ + + oid_packet_filter = 0x0000000; + + /* link down eth */ + + eth_device_linkchange(&((rt_rndis_eth_t)func->user_data)->parent, RT_FALSE); + + /* reset eth rx tx */ + ((rt_rndis_eth_t)func->user_data)->rx_frist = RT_TRUE; + ((rt_rndis_eth_t)func->user_data)->rx_flag = RT_FALSE; + + + resp->MessageType = REMOTE_NDIS_RESET_CMPLT; + resp->MessageLength = sizeof(struct rndis_reset_cmplt); + resp->Status = RNDIS_STATUS_SUCCESS; + resp->AddressingReset = 1; + + response->buffer = resp; + + { + rt_base_t level = rt_hw_interrupt_disable(); + rt_list_insert_before(&((rt_rndis_eth_t)func->user_data)->response_list, &response->list); + rt_hw_interrupt_enable(level); + } + + return RT_EOK; +} + static rt_err_t _rndis_keepalive_response(ufunction_t func,rndis_keepalive_msg_t msg) { rndis_keepalive_cmplt_t resp; @@ -619,7 +672,7 @@ static rt_err_t _rndis_keepalive_response(ufunction_t func,rndis_keepalive_msg_t if( (response == RT_NULL) || (resp == RT_NULL) ) { - RNDIS_PRINTF("%d: no memory!\r\n", __LINE__); + LOG_E("%s,%d: no memory!", __func__, __LINE__); if(response != RT_NULL) rt_free(response); @@ -652,34 +705,42 @@ static rt_err_t _rndis_msg_parser(ufunction_t func, rt_uint8_t *msg) switch (((rndis_gen_msg_t) msg)->MessageType) { case REMOTE_NDIS_INITIALIZE_MSG: + LOG_D("REMOTE_NDIS_INITIALIZE_MSG"); ret = _rndis_init_response(func, (rndis_init_msg_t) msg); break; case REMOTE_NDIS_HALT_MSG: - RNDIS_PRINTF("halt\n"); + LOG_D("REMOTE_NDIS_HALT_MSG"); /* link down. */ eth_device_linkchange(&((rt_rndis_eth_t)func->user_data)->parent, RT_FALSE); + + /* reset eth rx tx */ + ((rt_rndis_eth_t)func->user_data)->rx_frist = RT_TRUE; + ((rt_rndis_eth_t)func->user_data)->rx_flag = RT_FALSE; break; case REMOTE_NDIS_QUERY_MSG: + LOG_D("REMOTE_NDIS_QUERY_MSG"); ret = _rndis_query_response(func,(rndis_query_msg_t) msg); break; case REMOTE_NDIS_SET_MSG: + LOG_D("REMOTE_NDIS_SET_MSG"); ret = _rndis_set_response(func,(rndis_set_msg_t) msg); - RNDIS_PRINTF("set\n"); break; case REMOTE_NDIS_RESET_MSG: - RNDIS_PRINTF("reset\n"); + LOG_D("REMOTE_NDIS_RESET_MSG"); + ret = _rndis_reset_response(func,(rndis_set_msg_t) msg); break; case REMOTE_NDIS_KEEPALIVE_MSG: + LOG_D("REMOTE_NDIS_KEEPALIVE_MSG"); ret = _rndis_keepalive_response(func,(rndis_keepalive_msg_t) msg); break; default: - RNDIS_PRINTF("msg %X\n", ((rndis_gen_msg_t) msg)->MessageType); + LOG_W("not support RNDIS msg %X", ((rndis_gen_msg_t) msg)->MessageType); ret = -RT_ERROR; break; } @@ -718,7 +779,7 @@ static rt_err_t _rndis_get_encapsulated_response(ufunction_t func, ureq_t setup) if(rt_list_isempty(&((rt_rndis_eth_t)func->user_data)->response_list)) { - RNDIS_PRINTF("response_list is empty!\r\n"); + LOG_D("response_list is empty!"); ((rt_rndis_eth_t)func->user_data)->need_notify = RT_TRUE; return RT_EOK; } @@ -741,7 +802,7 @@ static rt_err_t _rndis_get_encapsulated_response(ufunction_t func, ureq_t setup) { rt_uint32_t * data; - RNDIS_PRINTF("auto append next response!\r\n"); + LOG_I("auto append next response!"); data = (rt_uint32_t *)((rt_rndis_eth_t)func->user_data)->eps.ep_cmd->buffer; data[0] = RESPONSE_AVAILABLE; data[1] = 0; @@ -758,55 +819,6 @@ static rt_err_t _rndis_get_encapsulated_response(ufunction_t func, ureq_t setup) return RT_EOK; } -#ifdef RNDIS_DELAY_LINK_UP -/** - * This function will set rndis connect status. - * - * @param device the usb device object. - * @param status the connect status. - * - * @return RT_EOK on successful. - */ -static rt_err_t _rndis_indicate_status_msg(ufunction_t func, rt_uint32_t status) -{ - rndis_indicate_status_msg_t resp; - struct rt_rndis_response * response; - - response = rt_malloc(sizeof(struct rt_rndis_response)); - resp = rt_malloc(sizeof(struct rndis_indicate_status_msg)); - - if( (response == RT_NULL) || (resp == RT_NULL) ) - { - RNDIS_PRINTF("%d: no memory!\r\n", __LINE__); - - if(response != RT_NULL) - rt_free(response); - - if(resp != RT_NULL) - rt_free(resp); - - return -RT_ENOMEM; - } - - resp->MessageType = REMOTE_NDIS_INDICATE_STATUS_MSG; - resp->MessageLength = 20; /* sizeof(struct rndis_indicate_status_msg) */ - resp->Status = status; - resp->StatusBufferLength = 0; - resp->StatusBufferOffset = 0; - - response->buffer = resp; - { - rt_base_t level = rt_hw_interrupt_disable(); - rt_list_insert_before(&((rt_rndis_eth_t)func->user_data)->response_list, &response->list); - rt_hw_interrupt_enable(level); - } - - _rndis_response_available(func); - - return RT_EOK; -} -#endif /* RNDIS_DELAY_LINK_UP */ - /** * This function will handle rndis interface request. * @@ -831,7 +843,7 @@ static rt_err_t _interface_handler(ufunction_t func, ureq_t setup) break; default: - RNDIS_PRINTF("unkown setup->request!\r\n"); + LOG_W("unkown setup->request 0x%02X !", setup->bRequest); break; } @@ -933,6 +945,8 @@ static rt_err_t _function_enable(ufunction_t func) { cdc_eps_t eps; + LOG_I("plugged in"); + eps = (cdc_eps_t)&((rt_rndis_eth_t)func->user_data)->eps; eps->ep_in->buffer = ((rt_rndis_eth_t)func->user_data)->tx_pool; eps->ep_out->buffer = ((rt_rndis_eth_t)func->user_data)->rx_pool; @@ -945,6 +959,7 @@ static rt_err_t _function_enable(ufunction_t func) ((rt_rndis_eth_t)func->user_data)->rx_flag = RT_FALSE; ((rt_rndis_eth_t)func->user_data)->rx_frist = RT_TRUE; + // eth_device_ready(&(((rt_rndis_eth_t)func->user_data)->parent)); #ifdef RNDIS_DELAY_LINK_UP /* stop link up timer. */ @@ -981,7 +996,7 @@ static rt_err_t _function_enable(ufunction_t func) */ static rt_err_t _function_disable(ufunction_t func) { - RNDIS_PRINTF("plugged out\n"); + LOG_I("plugged out"); #ifdef RNDIS_DELAY_LINK_UP /* stop link up timer. */ @@ -996,7 +1011,7 @@ static rt_err_t _function_disable(ufunction_t func) while(!rt_list_isempty(&((rt_rndis_eth_t)func->user_data)->response_list)) { response = (struct rt_rndis_response *)((rt_rndis_eth_t)func->user_data)->response_list.next; - RNDIS_PRINTF("remove resp chain list!\r\n"); + LOG_D("remove resp chain list!"); rt_list_remove(&response->list); rt_free((void *)response->buffer); @@ -1007,8 +1022,14 @@ static rt_err_t _function_disable(ufunction_t func) rt_hw_interrupt_enable(level); } + /* link down. */ eth_device_linkchange(&((rt_rndis_eth_t)func->user_data)->parent, RT_FALSE); + + /* reset eth rx tx */ + ((rt_rndis_eth_t)func->user_data)->rx_frist = RT_TRUE; + ((rt_rndis_eth_t)func->user_data)->rx_flag = RT_FALSE; + return RT_EOK; } @@ -1141,22 +1162,25 @@ rt_err_t rt_rndis_eth_tx(rt_device_t dev, struct pbuf* p) if(!device->parent.link_status) { - RNDIS_PRINTF("linkdown, drop pkg\r\n"); + LOG_I("linkdown, drop pkg"); return RT_EOK; } - RT_ASSERT(p->tot_len < sizeof(device->tx_buffer)); + //RT_ASSERT(p->tot_len < sizeof(device->tx_buffer)); if(p->tot_len > sizeof(device->tx_buffer)) { - RNDIS_PRINTF("RNDIS MTU is:%d, but the send packet size is %d\r\n", + LOG_W("RNDIS MTU is:%d, but the send packet size is %d", sizeof(device->tx_buffer), p->tot_len); p->tot_len = sizeof(device->tx_buffer); } /* wait for buffer free. */ - result = rt_sem_take(&device->tx_buffer_free, RT_WAITING_FOREVER); + result = rt_sem_take(&device->tx_buffer_free, rt_tick_from_millisecond(1000)); if(result != RT_EOK) { + LOG_W("wait for buffer free timeout"); + /* if cost 1s to wait send done it said that connection is close . drop it */ + rt_sem_release(&device->tx_buffer_free); return result; } @@ -1215,11 +1239,59 @@ const static struct rt_device_ops rndis_device_ops = #endif /* RT_USING_LWIP */ #ifdef RNDIS_DELAY_LINK_UP + +/** + * This function will set rndis connect status. + * + * @param device the usb device object. + * @param status the connect status. + * + * @return RT_EOK on successful. + */ +static rt_err_t _rndis_indicate_status_msg(ufunction_t func, rt_uint32_t status) +{ + rndis_indicate_status_msg_t resp; + struct rt_rndis_response * response; + + response = rt_malloc(sizeof(struct rt_rndis_response)); + resp = rt_malloc(sizeof(struct rndis_indicate_status_msg)); + + if( (response == RT_NULL) || (resp == RT_NULL) ) + { + LOG_E("%s,%d: no memory!", __func__, __LINE__); + + if(response != RT_NULL) + rt_free(response); + + if(resp != RT_NULL) + rt_free(resp); + + return -RT_ENOMEM; + } + + resp->MessageType = REMOTE_NDIS_INDICATE_STATUS_MSG; + resp->MessageLength = 20; /* sizeof(struct rndis_indicate_status_msg) */ + resp->Status = status; + resp->StatusBufferLength = 0; + resp->StatusBufferOffset = 0; + + response->buffer = resp; + { + rt_base_t level = rt_hw_interrupt_disable(); + rt_list_insert_before(&((rt_rndis_eth_t)func->user_data)->response_list, &response->list); + rt_hw_interrupt_enable(level); + } + + _rndis_response_available(func); + + return RT_EOK; +} + /* the delay linkup timer handler. */ static void timer_timeout(void* parameter) { - RNDIS_PRINTF("delay link up!\r\n"); - _rndis_indicate_status_msg(((rt_rndis_eth_t)parameter)->parent.parent.user_data, + LOG_I("delay link up!"); + _rndis_indicate_status_msg(((rt_rndis_eth_t)parameter)->func, RNDIS_STATUS_MEDIA_CONNECT); eth_device_linkchange(&((rt_rndis_eth_t)parameter)->parent, RT_TRUE); } @@ -1319,7 +1391,7 @@ ufunction_t rt_usbd_function_rndis_create(udevice_t device) timer_timeout, _rndis, RT_TICK_PER_SECOND * 2, - RT_TIMER_FLAG_ONE_SHOT); + RT_TIMER_FLAG_ONE_SHOT | RT_TIMER_FLAG_SOFT_TIMER); #endif /* RNDIS_DELAY_LINK_UP */ /* OUI 00-00-00, only for test. */ @@ -1372,4 +1444,6 @@ int rt_usbd_rndis_class_register(void) rt_usbd_class_register(&rndis_class); return 0; } -INIT_PREV_EXPORT(rt_usbd_rndis_class_register);
\ No newline at end of file +INIT_PREV_EXPORT(rt_usbd_rndis_class_register); + +#endif /* RT_USB_DEVICE_RNDIS */ diff --git a/components/drivers/usb/usbdevice/class/rndis.h b/components/drivers/usb/usbdevice/class/rndis.h index 000ea62baf..fcdd249984 100644 --- a/components/drivers/usb/usbdevice/class/rndis.h +++ b/components/drivers/usb/usbdevice/class/rndis.h @@ -180,6 +180,15 @@ struct rndis_reset_msg rt_uint32_t Reserved; }; +/* Remote NDIS Soft Reset Response */ +struct rndis_reset_cmplt +{ + rt_uint32_t MessageType; + rt_uint32_t MessageLength; + rt_uint32_t Status; + rt_uint32_t AddressingReset; +}; + /* Remote NDIS Indicate Status Message */ struct rndis_indicate_status_msg { diff --git a/components/drivers/usb/usbdevice/core/core.c b/components/drivers/usb/usbdevice/core/core.c index 4e3a3e9280..584556303f 100644 --- a/components/drivers/usb/usbdevice/core/core.c +++ b/components/drivers/usb/usbdevice/core/core.c @@ -237,7 +237,8 @@ static rt_err_t _get_interface(struct udevice* device, ureq_t setup) { rt_uint8_t value; uintf_t intf; - + ufunction_t func; + /* parameter check */ RT_ASSERT(device != RT_NULL); RT_ASSERT(setup != RT_NULL); @@ -251,12 +252,17 @@ static rt_err_t _get_interface(struct udevice* device, ureq_t setup) } /* find the specified interface and its alternate setting */ - intf = rt_usbd_find_interface(device, setup->wIndex & 0xFF, RT_NULL); + intf = rt_usbd_find_interface(device, setup->wIndex & 0xFF, &func); value = intf->curr_setting->intf_desc->bAlternateSetting; /* send the interface alternate setting to endpoint 0*/ rt_usbd_ep0_write(device, &value, 1); + if (intf->handler) + { + intf->handler(func, setup); + } + return RT_EOK; } @@ -270,6 +276,7 @@ static rt_err_t _get_interface(struct udevice* device, ureq_t setup) */ static rt_err_t _set_interface(struct udevice* device, ureq_t setup) { + ufunction_t func; uintf_t intf; uep_t ep; struct rt_list_node* i; @@ -288,7 +295,7 @@ static rt_err_t _set_interface(struct udevice* device, ureq_t setup) } /* find the specified interface */ - intf = rt_usbd_find_interface(device, setup->wIndex & 0xFF, RT_NULL); + intf = rt_usbd_find_interface(device, setup->wIndex & 0xFF, &func); /* set alternate setting to the interface */ rt_usbd_set_altsetting(intf, setup->wValue & 0xFF); @@ -303,6 +310,11 @@ static rt_err_t _set_interface(struct udevice* device, ureq_t setup) } dcd_ep0_send_status(device->dcd); + if (intf->handler) + { + intf->handler(func, setup); + } + return RT_EOK; } @@ -995,7 +1007,7 @@ udevice_t rt_usbd_device_new(void) RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_device_new\n")); /* allocate memory for the object */ - udevice = rt_malloc(sizeof(struct udevice)); + udevice = (udevice_t)rt_malloc(sizeof(struct udevice)); if(udevice == RT_NULL) { rt_kprintf("alloc memery failed\n"); @@ -1109,7 +1121,7 @@ uconfig_t rt_usbd_config_new(void) RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_config_new\n")); /* allocate memory for the object */ - cfg = rt_malloc(sizeof(struct uconfig)); + cfg = (uconfig_t)rt_malloc(sizeof(struct uconfig)); if(cfg == RT_NULL) { rt_kprintf("alloc memery failed\n"); @@ -1488,9 +1500,10 @@ uep_t rt_usbd_find_endpoint(udevice_t device, ufunction_t* pfunc, rt_uint8_t ep_ */ rt_err_t rt_usbd_device_add_config(udevice_t device, uconfig_t cfg) { - struct rt_list_node *i, *j, *k; + struct rt_list_node *i, *j, *k, *m; ufunction_t func; uintf_t intf; + ualtsetting_t altsetting; uep_t ep; RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_device_add_config\n")); @@ -1512,22 +1525,26 @@ rt_err_t rt_usbd_device_add_config(udevice_t device, uconfig_t cfg) intf = (uintf_t)rt_list_entry(j, struct uinterface, list); cfg->cfg_desc.bNumInterfaces++; - /* allocate address for every endpoint in the interface alternate setting */ - for(k=intf->curr_setting->ep_list.next; - k!=&intf->curr_setting->ep_list; k=k->next) + for(k=intf->setting_list.next; k!=&intf->setting_list;k=k->next) { - ep = (uep_t)rt_list_entry(k, struct uendpoint, list); - if(rt_usbd_ep_assign(device, ep) != RT_EOK) + altsetting = (ualtsetting_t)rt_list_entry(k, struct ualtsetting, list); + + /* allocate address for every endpoint in the interface alternate setting */ + for(m=altsetting->ep_list.next; m!=&altsetting->ep_list; m=m->next) { - rt_kprintf("endpoint assign error\n"); + ep = (uep_t)rt_list_entry(m, struct uendpoint, list); + if(rt_usbd_ep_assign(device, ep) != RT_EOK) + { + rt_kprintf("endpoint assign error\n"); + } } - } - /* construct complete configuration descriptor */ - rt_memcpy((void*)&cfg->cfg_desc.data[cfg->cfg_desc.wTotalLength - USB_DESC_LENGTH_CONFIG], - (void*)intf->curr_setting->desc, - intf->curr_setting->desc_size); - cfg->cfg_desc.wTotalLength += intf->curr_setting->desc_size; + /* construct complete configuration descriptor */ + rt_memcpy((void*)&cfg->cfg_desc.data[cfg->cfg_desc.wTotalLength - USB_DESC_LENGTH_CONFIG], + (void*)altsetting->desc, + altsetting->desc_size); + cfg->cfg_desc.wTotalLength += altsetting->desc_size; + } } } @@ -2053,7 +2070,7 @@ rt_size_t rt_usbd_ep0_write(udevice_t device, void *buffer, rt_size_t size) ep0 = &device->dcd->ep0; ep0->request.size = size; - ep0->request.buffer = buffer; + ep0->request.buffer = (rt_uint8_t *)buffer; ep0->request.remain_size = size; if(size >= ep0->id->maxpacket) { @@ -2079,7 +2096,7 @@ rt_size_t rt_usbd_ep0_read(udevice_t device, void *buffer, rt_size_t size, RT_ASSERT(buffer != RT_NULL); ep0 = &device->dcd->ep0; - ep0->request.buffer = buffer; + ep0->request.buffer = (rt_uint8_t *)buffer; ep0->request.remain_size = size; ep0->rx_indicate = rx_ind; if(size >= ep0->id->maxpacket) diff --git a/components/drivers/wlan/SConscript b/components/drivers/wlan/SConscript index 271ca66a80..f2a6bbdc82 100644 --- a/components/drivers/wlan/SConscript +++ b/components/drivers/wlan/SConscript @@ -1,8 +1,30 @@ from building import * cwd = GetCurrentDir() -src = Glob('*.c') CPPPATH = [cwd] + +src = Split(''' + wlan_dev.c + ''') + +if GetDepend(['RT_WLAN_MANAGE_ENABLE']): + src += ['wlan_mgnt.c'] + +if GetDepend(['RT_WLAN_MSH_CMD_ENABLE']): + src += ['wlan_cmd.c'] + +if GetDepend(['RT_WLAN_PROT_ENABLE']): + src += ['wlan_prot.c'] + +if GetDepend(['RT_WLAN_PROT_LWIP_ENABLE']): + src += ['wlan_lwip.c'] + +if GetDepend(['RT_WLAN_CFG_ENABLE']): + src += ['wlan_cfg.c'] + +if GetDepend(['RT_WLAN_WORK_THREAD_ENABLE']): + src += ['wlan_workqueue.c'] + group = DefineGroup('DeviceDrivers', src, depend = ['RT_USING_WIFI'], CPPPATH = CPPPATH) Return('group') diff --git a/components/drivers/wlan/wlan_cfg.c b/components/drivers/wlan/wlan_cfg.c index 126cee40f5..7fa9ecb2da 100644 --- a/components/drivers/wlan/wlan_cfg.c +++ b/components/drivers/wlan/wlan_cfg.c @@ -19,6 +19,8 @@ #endif /* RT_WLAN_CFG_DEBUG */ #include <rtdbg.h> +#ifdef RT_WLAN_CFG_ENABLE + #define WLAN_CFG_LOCK() (rt_mutex_take(&cfg_mutex, RT_WAITING_FOREVER)) #define WLAN_CFG_UNLOCK() (rt_mutex_release(&cfg_mutex)) @@ -462,3 +464,5 @@ void rt_wlan_cfg_dump(void) rt_kprintf("%3d \n", info->channel); } } + +#endif diff --git a/components/drivers/wlan/wlan_cmd.c b/components/drivers/wlan/wlan_cmd.c index b962b63947..fead6a8bf2 100644 --- a/components/drivers/wlan/wlan_cmd.c +++ b/components/drivers/wlan/wlan_cmd.c @@ -13,6 +13,8 @@ #include <wlan_cfg.h> #include <wlan_prot.h> +#if defined(RT_WLAN_MANAGE_ENABLE) && defined(RT_WLAN_MSH_CMD_ENABLE) + struct wifi_cmd_des { const char *cmd; @@ -75,7 +77,7 @@ static int wifi_help(int argc, char *argv[]) { rt_kprintf("wifi\n"); rt_kprintf("wifi help\n"); - rt_kprintf("wifi scan\n"); + rt_kprintf("wifi scan [SSID]\n"); rt_kprintf("wifi join [SSID] [PASSWORD]\n"); rt_kprintf("wifi ap SSID [PASSWORD]\n"); rt_kprintf("wifi disc\n"); @@ -143,12 +145,23 @@ static int wifi_status(int argc, char *argv[]) static int wifi_scan(int argc, char *argv[]) { struct rt_wlan_scan_result *scan_result = RT_NULL; + struct rt_wlan_info *info = RT_NULL; + struct rt_wlan_info filter; - if (argc > 2) + if (argc > 3) return -1; + if (argc == 3) + { + INVALID_INFO(&filter); + SSID_SET(&filter, argv[2]); + info = &filter; + } + + /* clean scan result */ + rt_wlan_scan_result_clean(); /* scan ap info */ - scan_result = rt_wlan_scan_sync(); + scan_result = rt_wlan_scan_with_info(info); if (scan_result) { int index, num; @@ -224,8 +237,10 @@ static int wifi_join(int argc, char *argv[]) const char *key = RT_NULL; struct rt_wlan_cfg_info cfg_info; + rt_memset(&cfg_info, 0, sizeof(cfg_info)); if (argc == 2) { +#ifdef RT_WLAN_CFG_ENABLE /* get info to connect */ if (rt_wlan_cfg_read_index(&cfg_info, 0) == 1) { @@ -234,8 +249,9 @@ static int wifi_join(int argc, char *argv[]) key = (char *)(&cfg_info.key.val[0]); } else +#endif { - rt_kprintf("not find info\n"); + rt_kprintf("not find connect info\n"); } } else if (argc == 3) @@ -387,8 +403,9 @@ static int wifi_debug_save_cfg(int argc, char *argv[]) rt_memcpy(&cfg_info.key.val[0], password, len); cfg_info.key.len = len; } - +#ifdef RT_WLAN_CFG_ENABLE rt_wlan_cfg_save(&cfg_info); +#endif return 0; } @@ -396,7 +413,9 @@ static int wifi_debug_dump_cfg(int argc, char *argv[]) { if (argc == 1) { +#ifdef RT_WLAN_CFG_ENABLE rt_wlan_cfg_dump(); +#endif } else { @@ -409,8 +428,10 @@ static int wifi_debug_clear_cfg(int argc, char *argv[]) { if (argc == 1) { +#ifdef RT_WLAN_CFG_ENABLE rt_wlan_cfg_delete_all(); rt_wlan_cfg_cache_save(); +#endif } else { @@ -447,6 +468,10 @@ static int wifi_debug_set_mode(int argc, char *argv[]) { mode = RT_WLAN_AP; } + else if (rt_strcmp("none", argv[1]) == 0) + { + mode = RT_WLAN_NONE; + } else return -1; @@ -564,3 +589,5 @@ static int wifi_msh(int argc, char *argv[]) #if defined(RT_USING_FINSH) && defined(FINSH_USING_MSH) FINSH_FUNCTION_EXPORT_ALIAS(wifi_msh, __cmd_wifi, wifi command.); #endif + +#endif diff --git a/components/drivers/wlan/wlan_dev.c b/components/drivers/wlan/wlan_dev.c index 82fa4e73e7..cbfd50a6c3 100644 --- a/components/drivers/wlan/wlan_dev.c +++ b/components/drivers/wlan/wlan_dev.c @@ -21,6 +21,8 @@ #endif /* RT_WLAN_DEV_DEBUG */ #include <rtdbg.h> +#if defined(RT_USING_WIFI) || defined(RT_USING_WLAN) + #ifndef RT_DEVICE #define RT_DEVICE(__device) ((rt_device_t)__device) #endif @@ -56,6 +58,17 @@ rt_err_t rt_wlan_dev_init(struct rt_wlan_device *device, rt_wlan_mode_t mode) return -RT_ERROR; } + if (mode == RT_WLAN_AP && device->flags & RT_WLAN_FLAG_STA_ONLY) + { + LOG_E("F:%s L:%d This wlan device can only be set to sta mode!", __FUNCTION__, __LINE__); + return -RT_ERROR; + } + else if (mode == RT_WLAN_STATION && device->flags & RT_WLAN_FLAG_AP_ONLY) + { + LOG_E("F:%s L:%d This wlan device can only be set to ap mode!", __FUNCTION__, __LINE__); + return -RT_ERROR; + } + result = rt_device_init(RT_DEVICE(device)); if (result != RT_EOK) { @@ -134,8 +147,8 @@ rt_err_t rt_wlan_dev_ap_start(struct rt_wlan_device *device, struct rt_wlan_info return -RT_ERROR; } - if ((password_len >= RT_WLAN_PASSWORD_MAX_LENGTH) || - (info->ssid.len >= RT_WLAN_SSID_MAX_LENGTH)) + if ((password_len > RT_WLAN_PASSWORD_MAX_LENGTH) || + (info->ssid.len > RT_WLAN_SSID_MAX_LENGTH)) { LOG_E("L:%d password or ssid is to long", __LINE__); return -RT_ERROR; @@ -515,15 +528,24 @@ rt_err_t rt_wlan_dev_scan(struct rt_wlan_device *device, struct rt_wlan_info *in if (info != RT_NULL) { - if (info->ssid.len >= RT_WLAN_SSID_MAX_LENGTH) + if (info->ssid.len > RT_WLAN_SSID_MAX_LENGTH) { LOG_E("L:%d ssid is to long", __LINE__); return -RT_EINVAL; } rt_memcpy(&scan_info.ssid, &info->ssid, sizeof(rt_wlan_ssid_t)); rt_memcpy(scan_info.bssid, info->bssid, RT_WLAN_BSSID_MAX_LENGTH); - scan_info.channel_min = -1; - scan_info.channel_max = -1; + if (info->channel > 0) + { + scan_info.channel_min = info->channel; + scan_info.channel_max = info->channel; + } + else + { + scan_info.channel_min = -1; + scan_info.channel_max = -1; + } + scan_info.passive = info->hidden ? RT_TRUE : RT_FALSE; p_scan_info = &scan_info; } result = rt_device_control(RT_DEVICE(device), RT_WLAN_CMD_SCAN, p_scan_info); @@ -545,7 +567,11 @@ rt_err_t rt_wlan_dev_scan_stop(struct rt_wlan_device *device) rt_err_t rt_wlan_dev_report_data(struct rt_wlan_device *device, void *buff, int len) { +#ifdef RT_WLAN_PROT_ENABLE return rt_wlan_dev_transfer_prot(device, buff, len); +#else + return -RT_ERROR; +#endif } static rt_err_t _rt_wlan_dev_init(rt_device_t dev) @@ -768,14 +794,15 @@ rt_err_t rt_wlan_dev_register(struct rt_wlan_device *wlan, const char *name, con { rt_err_t err = RT_EOK; - if ((wlan == RT_NULL) || (name == RT_NULL) || (ops == RT_NULL)) + if ((wlan == RT_NULL) || (name == RT_NULL) || (ops == RT_NULL) || + (flag & RT_WLAN_FLAG_STA_ONLY && flag & RT_WLAN_FLAG_AP_ONLY)) { LOG_E("F:%s L:%d parameter Wrongful", __FUNCTION__, __LINE__); return RT_NULL; } rt_memset(wlan, 0, sizeof(struct rt_wlan_device)); - + #ifdef RT_USING_DEVICE_OPS wlan->device.ops = &wlan_ops; #else @@ -801,3 +828,5 @@ rt_err_t rt_wlan_dev_register(struct rt_wlan_device *wlan, const char *name, con return err; } + +#endif diff --git a/components/drivers/wlan/wlan_dev.h b/components/drivers/wlan/wlan_dev.h index a9300be9d7..43d6506d6f 100644 --- a/components/drivers/wlan/wlan_dev.h +++ b/components/drivers/wlan/wlan_dev.h @@ -381,6 +381,11 @@ typedef struct rt_wlan_key rt_wlan_key_t; (_info)->channel = -1; \ } while(0) +#define SSID_SET(_info, _ssid) do { \ + rt_strncpy((char *)(_info)->ssid.val, (_ssid), RT_WLAN_SSID_MAX_LENGTH); \ + (_info)->ssid.len = rt_strlen((char *)(_info)->ssid.val); \ + } while(0) + struct rt_wlan_info { /* security type */ @@ -442,6 +447,7 @@ struct rt_wlan_device rt_wlan_pormisc_callback_t pormisc_callback; const struct rt_wlan_dev_ops *ops; rt_uint32_t flags; + struct netdev *netdev; void *prot; void *user_data; }; @@ -470,6 +476,7 @@ struct rt_scan_info rt_uint8_t bssid[6]; rt_int16_t channel_min; rt_int16_t channel_max; + rt_bool_t passive; }; struct rt_wlan_dev_ops diff --git a/components/drivers/wlan/wlan_lwip.c b/components/drivers/wlan/wlan_lwip.c index 84b448c68f..3c4e4dd598 100644 --- a/components/drivers/wlan/wlan_lwip.c +++ b/components/drivers/wlan/wlan_lwip.c @@ -14,12 +14,17 @@ #include <wlan_prot.h> #include <wlan_workqueue.h> +#if defined(RT_WLAN_PROT_ENABLE) && defined(RT_WLAN_PROT_LWIP_ENABLE) + #ifdef RT_USING_LWIP #include <netif/ethernetif.h> #include <lwip/netifapi.h> #ifdef LWIP_USING_DHCPD #include <dhcp_server.h> #endif +#ifdef RT_USING_NETDEV +#include <netdev.h> +#endif #define DBG_TAG "WLAN.lwip" #ifdef RT_WLAN_LWIP_DEBUG @@ -33,6 +38,10 @@ #define IPADDR_STRLEN_MAX (32) #endif +#ifndef RT_WLAN_PROT_LWIP_NAME +#define RT_WLAN_PROT_LWIP_NAME ("lwip") +#endif + struct lwip_prot_des { struct rt_wlan_prot prot; @@ -47,12 +56,16 @@ static void netif_is_ready(struct rt_work *work, void *parameter) ip_addr_t ip_addr_zero = { 0 }; struct rt_wlan_device *wlan = parameter; struct lwip_prot_des *lwip_prot = (struct lwip_prot_des *)wlan->prot; - struct eth_device *eth_dev = &lwip_prot->eth; + struct eth_device *eth_dev; rt_base_t level; struct rt_wlan_buff buff; rt_uint32_t ip_addr[4]; char str[IPADDR_STRLEN_MAX]; + if (lwip_prot == RT_NULL) + return; + + eth_dev = &lwip_prot->eth; rt_timer_stop(&lwip_prot->timer); if (ip_addr_cmp(&(eth_dev->netif->ip_addr), &ip_addr_zero) != 0) { @@ -100,18 +113,26 @@ static void netif_is_ready(struct rt_work *work, void *parameter) LOG_I("Got IP address : %s", str); exit: level = rt_hw_interrupt_disable(); - rt_memset(work, 0, sizeof(struct rt_work)); + if (work) + { + rt_memset(work, 0, sizeof(struct rt_work)); + } rt_hw_interrupt_enable(level); } static void timer_callback(void *parameter) { +#ifdef RT_WLAN_WORK_THREAD_ENABLE struct rt_workqueue *workqueue; struct rt_wlan_device *wlan = parameter; struct lwip_prot_des *lwip_prot = (struct lwip_prot_des *)wlan->prot; - struct rt_work *work = &lwip_prot->work; + struct rt_work *work; rt_base_t level; + if (lwip_prot == RT_NULL) + return; + + work = &lwip_prot->work; workqueue = rt_wlan_get_workqueue(); if (workqueue != RT_NULL) { @@ -125,13 +146,22 @@ static void timer_callback(void *parameter) rt_hw_interrupt_enable(level); } } +#else + netif_is_ready(RT_NULL, parameter); +#endif + } static void netif_set_connected(void *parameter) { struct rt_wlan_device *wlan = parameter; struct lwip_prot_des *lwip_prot = wlan->prot; - struct eth_device *eth_dev = &lwip_prot->eth; + struct eth_device *eth_dev; + + if (lwip_prot == RT_NULL) + return; + + eth_dev = &lwip_prot->eth; if (lwip_prot->connected_flag) { @@ -151,14 +181,10 @@ static void netif_set_connected(void *parameter) netifapi_netif_common(eth_dev->netif, netif_set_link_up, NULL); #ifdef LWIP_USING_DHCPD { - char netif_name[8]; - int i; + char netif_name[RT_NAME_MAX]; rt_memset(netif_name, 0, sizeof(netif_name)); - for (i = 0; i < sizeof(eth_dev->netif->name); i++) - { - netif_name[i] = eth_dev->netif->name[i]; - } + rt_memcpy(netif_name, eth_dev->netif->name, sizeof(eth_dev->netif->name)); dhcpd_start(netif_name); } #endif @@ -166,24 +192,24 @@ static void netif_set_connected(void *parameter) } else { - if (wlan->mode == RT_WLAN_STATION) - { - LOG_D("F:%s L:%d dhcp stop run", __FUNCTION__, __LINE__); - netifapi_netif_common(eth_dev->netif, netif_set_link_down, NULL); + LOG_D("F:%s L:%d set linkdown", __FUNCTION__, __LINE__); + netifapi_netif_common(eth_dev->netif, netif_set_link_down, NULL); + rt_timer_stop(&lwip_prot->timer); #ifdef RT_LWIP_DHCP - { - ip_addr_t ip_addr = { 0 }; - dhcp_stop(eth_dev->netif); - netif_set_addr(eth_dev->netif, &ip_addr, &ip_addr, &ip_addr); - } -#endif - rt_timer_stop(&lwip_prot->timer); + { + ip_addr_t ip_addr = { 0 }; + dhcp_stop(eth_dev->netif); + netif_set_addr(eth_dev->netif, &ip_addr, &ip_addr, &ip_addr); } - else if (wlan->mode == RT_WLAN_AP) +#endif +#ifdef LWIP_USING_DHCPD { - LOG_D("F:%s L:%d dhcpd stop run", __FUNCTION__, __LINE__); - netifapi_netif_common(eth_dev->netif, netif_set_link_down, NULL); + char netif_name[RT_NAME_MAX]; + rt_memset(netif_name, 0, sizeof(netif_name)); + rt_memcpy(netif_name, lwip_prot->eth.netif->name, sizeof(lwip_prot->eth.netif->name)); + dhcpd_stop(netif_name); } +#endif } } @@ -192,6 +218,9 @@ static void rt_wlan_lwip_event_handle(struct rt_wlan_prot *port, struct rt_wlan_ struct lwip_prot_des *lwip_prot = (struct lwip_prot_des *)wlan->prot; rt_bool_t flag_old; + if (lwip_prot == RT_NULL) + return; + flag_old = lwip_prot->connected_flag; switch (event) @@ -238,8 +267,11 @@ static void rt_wlan_lwip_event_handle(struct rt_wlan_prot *port, struct rt_wlan_ } if (flag_old != lwip_prot->connected_flag) { +#ifdef RT_WLAN_WORK_THREAD_ENABLE rt_wlan_workqueue_dowork(netif_set_connected, wlan); - // netif_set_connected(wlan); +#else + netif_set_connected(wlan); +#endif } } @@ -385,7 +417,7 @@ const static struct rt_device_ops wlan_lwip_ops = static struct rt_wlan_prot *rt_wlan_lwip_protocol_register(struct rt_wlan_prot *prot, struct rt_wlan_device *wlan) { struct eth_device *eth = RT_NULL; - static rt_uint8_t id = 0; + rt_uint8_t id = 0; char eth_name[4], timer_name[16]; rt_device_t device = RT_NULL; struct lwip_prot_des *lwip_prot; @@ -452,22 +484,43 @@ static struct rt_wlan_prot *rt_wlan_lwip_protocol_register(struct rt_wlan_prot * return RT_NULL; } rt_memcpy(&lwip_prot->prot, prot, sizeof(struct rt_wlan_prot)); - if (wlan->mode == RT_WLAN_STATION) - { - rt_sprintf(timer_name, "timer_%s", eth_name); - rt_timer_init(&lwip_prot->timer, timer_name, timer_callback, wlan, rt_tick_from_millisecond(1000), - RT_TIMER_FLAG_SOFT_TIMER | RT_TIMER_FLAG_ONE_SHOT); - } + rt_sprintf(timer_name, "timer_%s", eth_name); + rt_timer_init(&lwip_prot->timer, timer_name, timer_callback, wlan, rt_tick_from_millisecond(1000), + RT_TIMER_FLAG_SOFT_TIMER | RT_TIMER_FLAG_ONE_SHOT); netif_set_up(eth->netif); LOG_I("eth device init ok name:%s", eth_name); - +#ifdef RT_USING_NETDEV + wlan->netdev = netdev_get_by_name(eth_name); +#endif return &lwip_prot->prot; } static void rt_wlan_lwip_protocol_unregister(struct rt_wlan_prot *prot, struct rt_wlan_device *wlan) { - /*TODO*/ + struct lwip_prot_des *lwip_prot = (struct lwip_prot_des *)prot; + LOG_D("F:%s L:%d is run wlan:0x%08x", __FUNCTION__, __LINE__, wlan); +#if !defined(RT_USING_LWIP141) + wlan->prot = RT_NULL; + if (lwip_prot == RT_NULL) + { + return; + } + +#ifdef LWIP_USING_DHCPD + { + char netif_name[RT_NAME_MAX]; + rt_memset(netif_name, 0, sizeof(netif_name)); + rt_memcpy(netif_name, lwip_prot->eth.netif->name, sizeof(lwip_prot->eth.netif->name)); + dhcpd_stop(netif_name); + } +#endif + eth_device_deinit(&lwip_prot->eth); + rt_device_close((rt_device_t)wlan); + rt_timer_detach(&lwip_prot->timer); + wlan->netdev = RT_NULL; + rt_free(lwip_prot); +#endif } static struct rt_wlan_prot_ops ops = @@ -483,7 +536,7 @@ int rt_wlan_lwip_init(void) rt_wlan_prot_event_t event; rt_memset(&prot, 0, sizeof(prot)); - rt_strncpy(&prot.name[0], RT_WLAN_PROT_LWIP, RT_WLAN_PROT_NAME_LEN); + rt_strncpy(&prot.name[0], RT_WLAN_PROT_LWIP_NAME, RT_WLAN_PROT_NAME_LEN); prot.ops = &ops; if (rt_wlan_prot_regisetr(&prot) != RT_EOK) @@ -502,3 +555,4 @@ int rt_wlan_lwip_init(void) INIT_PREV_EXPORT(rt_wlan_lwip_init); #endif +#endif diff --git a/components/drivers/wlan/wlan_mgnt.c b/components/drivers/wlan/wlan_mgnt.c index 91a77e43d0..cf2204c6b3 100644 --- a/components/drivers/wlan/wlan_mgnt.c +++ b/components/drivers/wlan/wlan_mgnt.c @@ -24,6 +24,8 @@ #endif /* RT_WLAN_MGNT_DEBUG */ #include <rtdbg.h> +#ifdef RT_WLAN_MANAGE_ENABLE + #ifndef RT_WLAN_DEVICE #define RT_WLAN_DEVICE(__device) ((struct rt_wlan_device *)__device) #endif @@ -48,13 +50,16 @@ #define COMPLETE_LOCK() (rt_mutex_take(&complete_mutex, RT_WAITING_FOREVER)) #define COMPLETE_UNLOCK() (rt_mutex_release(&complete_mutex)) +#ifdef RT_WLAN_AUTO_CONNECT_ENABLE #define TIME_STOP() (rt_timer_stop(&reconnect_time)) #define TIME_START() (rt_timer_start(&reconnect_time)) - -#define DISCONNECT_RESPONSE_TICK (2000) +#else +#define TIME_STOP() +#define TIME_START() +#endif #if RT_WLAN_EBOX_NUM < 1 -#error "event box num Too little" +#error "event box num Too few" #endif struct rt_wlan_mgnt_des @@ -113,8 +118,11 @@ static struct rt_wlan_event_desc event_tab[RT_WLAN_EVT_MAX]; static struct rt_wlan_complete_des *complete_tab[5]; static struct rt_mutex complete_mutex; +static struct rt_wlan_info *scan_filter; +#ifdef RT_WLAN_AUTO_CONNECT_ENABLE static struct rt_timer reconnect_time; +#endif rt_inline int _sta_is_null(void) { @@ -145,9 +153,97 @@ rt_inline rt_bool_t _is_do_connect(void) return RT_TRUE; } -static void rt_wlan_mgnt_work(void *parameter); +#ifdef RT_WLAN_WORK_THREAD_ENABLE + +static rt_bool_t rt_wlan_info_isequ(struct rt_wlan_info *info1, struct rt_wlan_info *info2) +{ + rt_bool_t is_equ = 1; + rt_uint8_t bssid_zero[RT_WLAN_BSSID_MAX_LENGTH] = { 0 }; + + if (is_equ && (info1->security != SECURITY_UNKNOWN) && (info2->security != SECURITY_UNKNOWN)) + { + is_equ &= info2->security == info1->security; + } + if (is_equ && ((info1->ssid.len > 0) && (info2->ssid.len > 0))) + { + is_equ &= info1->ssid.len == info2->ssid.len; + is_equ &= rt_memcmp(&info2->ssid.val[0], &info1->ssid.val[0], info1->ssid.len) == 0; + } + if (is_equ && (rt_memcmp(&info1->bssid[0], bssid_zero, RT_WLAN_BSSID_MAX_LENGTH)) && + (rt_memcmp(&info2->bssid[0], bssid_zero, RT_WLAN_BSSID_MAX_LENGTH))) + { + is_equ &= rt_memcmp(&info1->bssid[0], &info2->bssid[0], RT_WLAN_BSSID_MAX_LENGTH) == 0; + } + if (is_equ && info1->datarate && info2->datarate) + { + is_equ &= info1->datarate == info2->datarate; + } + if (is_equ && (info1->channel >= 0) && (info2->channel >= 0)) + { + is_equ &= info1->channel == info2->channel; + } + if (is_equ && (info1->rssi < 0) && (info2->rssi < 0)) + { + is_equ &= info1->rssi == info2->rssi; + } + return is_equ; +} + +static void rt_wlan_mgnt_work(void *parameter) +{ + struct rt_wlan_msg *msg = parameter; + void *user_parameter; + rt_wlan_event_handler handler = RT_NULL; + struct rt_wlan_buff user_buff = { 0 }; + rt_base_t level; + + /* Get user callback */ + if (msg->event < RT_WLAN_EVT_MAX) + { + level = rt_hw_interrupt_disable(); + handler = event_tab[msg->event].handler; + user_parameter = event_tab[msg->event].parameter; + rt_hw_interrupt_enable(level); + } + + /* run user callback fun */ + if (handler) + { + user_buff.data = msg->buff; + user_buff.len = msg->len; + RT_WLAN_LOG_D("wlan work thread run user callback, event:%d", msg->event); + handler(msg->event, &user_buff, user_parameter); + } + + switch (msg->event) + { + case RT_WLAN_EVT_STA_CONNECTED: + { + struct rt_wlan_cfg_info cfg_info; + + rt_memset(&cfg_info, 0, sizeof(cfg_info)); + /* save config */ + if (rt_wlan_is_connected() == RT_TRUE) + { + rt_enter_critical(); + cfg_info.info = _sta_mgnt.info; + cfg_info.key = _sta_mgnt.key; + rt_exit_critical(); + RT_WLAN_LOG_D("run save config! ssid:%s len%d", _sta_mgnt.info.ssid.val, _sta_mgnt.info.ssid.len); +#ifdef RT_WLAN_CFG_ENABLE + rt_wlan_cfg_save(&cfg_info); +#endif + } + break; + } + default : + break; + } + + rt_free(msg); +} -static rt_err_t rt_wlan_send_msg(rt_wlan_dev_event_t event, void *buff, int len) +static rt_err_t rt_wlan_send_to_thread(rt_wlan_event_t event, void *buff, int len) { struct rt_wlan_msg *msg; @@ -164,7 +260,8 @@ static rt_err_t rt_wlan_send_msg(rt_wlan_dev_event_t event, void *buff, int len) msg->event = event; if (len != 0) { - msg->buff = ((char *)msg) + sizeof(struct rt_wlan_msg); + msg->buff = (void *)&msg[1]; + rt_memcpy(msg->buff, buff, len); msg->len = len; } @@ -177,14 +274,16 @@ static rt_err_t rt_wlan_send_msg(rt_wlan_dev_event_t event, void *buff, int len) } return RT_EOK; } +#endif static rt_err_t rt_wlan_scan_result_cache(struct rt_wlan_info *info, int timeout) { struct rt_wlan_info *ptable; rt_err_t err = RT_EOK; int i, insert = -1; + rt_base_t level; - if (_sta_is_null() || (info == RT_NULL)) return RT_EOK; + if (_sta_is_null() || (info == RT_NULL) || (info->ssid.len == 0)) return RT_EOK; RT_WLAN_LOG_D("ssid:%s len:%d mac:%02x:%02x:%02x:%02x:%02x:%02x", info->ssid.val, info->ssid.len, info->bssid[0], info->bssid[1], info->bssid[2], info->bssid[3], info->bssid[4], info->bssid[5]); @@ -193,6 +292,23 @@ static rt_err_t rt_wlan_scan_result_cache(struct rt_wlan_info *info, int timeout if (err != RT_EOK) return err; + /* scanning result filtering */ + level = rt_hw_interrupt_disable(); + if (scan_filter) + { + struct rt_wlan_info _tmp_info = *scan_filter; + rt_hw_interrupt_enable(level); + if (rt_wlan_info_isequ(&_tmp_info, info) != RT_TRUE) + { + rt_mutex_release(&scan_result_mutex); + return RT_EOK; + } + } + else + { + rt_hw_interrupt_enable(level); + } + /* de-duplicatio */ for (i = 0; i < scan_result.num; i++) { @@ -381,7 +497,7 @@ static rt_err_t rt_wlan_sta_info_del_all(int timeout) sta_info.node = RT_NULL; return err; } - +#ifdef RT_WLAN_AUTO_CONNECT_ENABLE static void rt_wlan_auto_connect_run(struct rt_work *work, void *parameter) { static rt_uint32_t id = 0; @@ -413,12 +529,12 @@ static void rt_wlan_auto_connect_run(struct rt_work *work, void *parameter) if (id >= rt_wlan_cfg_get_num()) id = 0; - if ((cfg_info.key.len > 0) && (cfg_info.key.len < RT_WLAN_PASSWORD_MAX_LENGTH)) + if ((cfg_info.key.len > 0) && (cfg_info.key.len <= RT_WLAN_PASSWORD_MAX_LENGTH)) { cfg_info.key.val[cfg_info.key.len] = '\0'; password = (char *)(&cfg_info.key.val[0]); } - rt_wlan_connect_adv(&cfg_info.info, password); + rt_wlan_connect((char *)cfg_info.info.ssid.val, password); exit: rt_mutex_release(&mgnt_mutex); level = rt_hw_interrupt_disable(); @@ -449,41 +565,10 @@ static void rt_wlan_cyclic_check(void *parameter) } } } - -static void rt_wlan_mgnt_work(void *parameter) -{ - struct rt_wlan_msg *msg = parameter; - - switch (msg->event) - { - case RT_WLAN_DEV_EVT_CONNECT: - { - struct rt_wlan_cfg_info cfg_info; - - /* save config */ - if (rt_wlan_is_connected() == RT_TRUE) - { - rt_enter_critical(); - cfg_info.info = _sta_mgnt.info; - cfg_info.key = _sta_mgnt.key; - rt_exit_critical(); - RT_WLAN_LOG_D("run save config! ssid:%s len%d", _sta_mgnt.info.ssid.val, _sta_mgnt.info.ssid.len); - rt_wlan_cfg_save(&cfg_info); - } - break; - } - default : - break; - } - - rt_free(msg); -} +#endif static void rt_wlan_event_dispatch(struct rt_wlan_device *device, rt_wlan_dev_event_t event, struct rt_wlan_buff *buff, void *parameter) { - rt_base_t level; - void *user_parameter; - rt_wlan_event_handler handler = RT_NULL; rt_err_t err = RT_NULL; rt_wlan_event_t user_event = RT_WLAN_EVT_MAX; int i; @@ -503,7 +588,6 @@ static void rt_wlan_event_dispatch(struct rt_wlan_device *device, rt_wlan_dev_ev _sta_mgnt.state &= ~RT_WLAN_STATE_CONNECTING; user_event = RT_WLAN_EVT_STA_CONNECTED; TIME_STOP(); - rt_wlan_send_msg(event, RT_NULL, 0); user_buff.data = &_sta_mgnt.info; user_buff.len = sizeof(struct rt_wlan_info); RT_WLAN_LOG_I("wifi connect success ssid:%s", &_sta_mgnt.info.ssid.val[0]); @@ -518,7 +602,10 @@ static void rt_wlan_event_dispatch(struct rt_wlan_device *device, rt_wlan_dev_ev user_event = RT_WLAN_EVT_STA_CONNECTED_FAIL; user_buff.data = &_sta_mgnt.info; user_buff.len = sizeof(struct rt_wlan_info); - TIME_START(); + if (rt_wlan_get_autoreconnect_mode()) + { + TIME_START(); + } break; } case RT_WLAN_DEV_EVT_DISCONNECT: @@ -529,7 +616,10 @@ static void rt_wlan_event_dispatch(struct rt_wlan_device *device, rt_wlan_dev_ev user_event = RT_WLAN_EVT_STA_DISCONNECTED; user_buff.data = &_sta_mgnt.info; user_buff.len = sizeof(struct rt_wlan_info); - TIME_START(); + if (rt_wlan_get_autoreconnect_mode()) + { + TIME_START(); + } break; } case RT_WLAN_DEV_EVT_AP_START: @@ -622,20 +712,30 @@ static void rt_wlan_event_dispatch(struct rt_wlan_device *device, rt_wlan_dev_ev } } COMPLETE_UNLOCK(); - /* Get user callback */ - if (user_event < RT_WLAN_EVT_MAX) +#ifdef RT_WLAN_WORK_THREAD_ENABLE + rt_wlan_send_to_thread(user_event, RT_NULL, 0); +#else { - level = rt_hw_interrupt_disable(); - handler = event_tab[user_event].handler; - user_parameter = event_tab[user_event].parameter; - rt_hw_interrupt_enable(level); - } + void *user_parameter; + rt_wlan_event_handler handler = RT_NULL; + rt_base_t level; + /* Get user callback */ + if (user_event < RT_WLAN_EVT_MAX) + { + level = rt_hw_interrupt_disable(); + handler = event_tab[user_event].handler; + user_parameter = event_tab[user_event].parameter; + rt_hw_interrupt_enable(level); + } - /* run user callback fun */ - if (handler) - { - handler(user_event, &user_buff, user_parameter); + /* run user callback fun */ + if (handler) + { + RT_WLAN_LOG_D("unknown thread run user callback, event:%d", user_event); + handler(user_event, &user_buff, user_parameter); + } } +#endif } static struct rt_wlan_complete_des *rt_wlan_complete_create(const char *name) @@ -820,14 +920,30 @@ rt_err_t rt_wlan_set_mode(const char *dev_name, rt_wlan_mode_t mode) /* update dev event handle */ if (up_event_flag == 1) { - rt_wlan_dev_event_t event; - for (event = RT_WLAN_DEV_EVT_INIT_DONE; event < RT_WLAN_DEV_EVT_MAX; event++) + if (handler) { - if (handler) + if (mode == RT_WLAN_STATION) + { + rt_wlan_dev_register_event_handler(RT_WLAN_DEVICE(device), RT_WLAN_DEV_EVT_CONNECT, handler, RT_NULL); + rt_wlan_dev_register_event_handler(RT_WLAN_DEVICE(device), RT_WLAN_DEV_EVT_CONNECT_FAIL, handler, RT_NULL); + rt_wlan_dev_register_event_handler(RT_WLAN_DEVICE(device), RT_WLAN_DEV_EVT_DISCONNECT, handler, RT_NULL); + rt_wlan_dev_register_event_handler(RT_WLAN_DEVICE(device), RT_WLAN_DEV_EVT_SCAN_REPORT, handler, RT_NULL); + rt_wlan_dev_register_event_handler(RT_WLAN_DEVICE(device), RT_WLAN_DEV_EVT_SCAN_DONE, handler, RT_NULL); + } + else if (mode == RT_WLAN_AP) { - rt_wlan_dev_register_event_handler(RT_WLAN_DEVICE(device), event, handler, RT_NULL); + rt_wlan_dev_register_event_handler(RT_WLAN_DEVICE(device), RT_WLAN_DEV_EVT_AP_START, handler, RT_NULL); + rt_wlan_dev_register_event_handler(RT_WLAN_DEVICE(device), RT_WLAN_DEV_EVT_AP_STOP, handler, RT_NULL); + rt_wlan_dev_register_event_handler(RT_WLAN_DEVICE(device), RT_WLAN_DEV_EVT_AP_ASSOCIATED, handler, RT_NULL); + rt_wlan_dev_register_event_handler(RT_WLAN_DEVICE(device), RT_WLAN_DEV_EVT_AP_DISASSOCIATED, handler, RT_NULL); + rt_wlan_dev_register_event_handler(RT_WLAN_DEVICE(device), RT_WLAN_DEV_EVT_AP_ASSOCIATE_FAILED, handler, RT_NULL); } - else + } + else + { + rt_wlan_dev_event_t event; + handler = rt_wlan_event_dispatch; + for (event = RT_WLAN_DEV_EVT_INIT_DONE; event < RT_WLAN_DEV_EVT_MAX; event++) { rt_wlan_dev_unregister_event_handler(RT_WLAN_DEVICE(device), event, handler); } @@ -836,8 +952,11 @@ rt_err_t rt_wlan_set_mode(const char *dev_name, rt_wlan_mode_t mode) MGNT_UNLOCK(); /* Mount protocol */ -#ifdef RT_WLAN_DEFAULT_PROT - rt_wlan_prot_attach(dev_name, RT_WLAN_DEFAULT_PROT); +#if defined(RT_WLAN_PROT_ENABLE) && defined(RT_WLAN_DEFAULT_PROT) + if (err == RT_EOK) + { + rt_wlan_prot_attach(dev_name, RT_WLAN_DEFAULT_PROT); + } #endif return err; } @@ -932,6 +1051,7 @@ rt_err_t rt_wlan_connect(const char *ssid, const char *password) struct rt_wlan_info info; struct rt_wlan_complete_des *complete; rt_uint32_t set = 0, recved = 0; + rt_uint32_t scan_retry = RT_WLAN_SCAN_RETRY_CNT; /* sta dev Can't be NULL */ if (_sta_is_null()) @@ -960,12 +1080,11 @@ rt_err_t rt_wlan_connect(const char *ssid, const char *password) /* get info from cache */ INVALID_INFO(&info); MGNT_LOCK(); - if (rt_wlan_find_best_by_cache(ssid, &info) != RT_TRUE) + while (scan_retry-- && rt_wlan_find_best_by_cache(ssid, &info) != RT_TRUE) { rt_wlan_scan_sync(); - rt_wlan_find_best_by_cache(ssid, &info); - rt_wlan_scan_result_clean(); } + rt_wlan_scan_result_clean(); if (info.ssid.len <= 0) { @@ -1216,10 +1335,13 @@ rt_err_t rt_wlan_get_info(struct rt_wlan_info *info) } RT_WLAN_LOG_D("%s is run", __FUNCTION__); - rt_enter_critical(); - *info = _sta_mgnt.info; - rt_exit_critical(); - return RT_EOK; + if (rt_wlan_is_connected() == RT_TRUE) + { + *info = _sta_mgnt.info; + info->rssi = rt_wlan_get_rssi(); + return RT_EOK; + } + return -RT_ERROR; } int rt_wlan_get_rssi(void) @@ -1268,6 +1390,7 @@ rt_err_t rt_wlan_start_ap(const char *ssid, const char *password) rt_memcpy(&info.ssid.val, ssid, ssid_len); info.ssid.len = ssid_len; info.channel = 6; + info.band = RT_802_11_BAND_2_4GHZ; /* Initializing events that need to wait */ MGNT_LOCK(); @@ -1427,8 +1550,12 @@ rt_err_t rt_wlan_ap_get_info(struct rt_wlan_info *info) } RT_WLAN_LOG_D("%s is run", __FUNCTION__); - *info = _ap_mgnt.info; - return RT_EOK; + if (rt_wlan_ap_is_active() == RT_TRUE) + { + *info = _ap_mgnt.info; + return RT_EOK; + } + return -RT_ERROR; } /* get sta number */ @@ -1555,27 +1682,35 @@ rt_country_code_t rt_wlan_ap_get_country(void) void rt_wlan_config_autoreconnect(rt_bool_t enable) { +#ifdef RT_WLAN_AUTO_CONNECT_ENABLE RT_WLAN_LOG_D("%s is run enable:%d", __FUNCTION__, enable); MGNT_LOCK(); if (enable) { + TIME_START(); _sta_mgnt.flags |= RT_WLAN_STATE_AUTOEN; } else { + TIME_STOP(); _sta_mgnt.flags &= ~RT_WLAN_STATE_AUTOEN; } MGNT_UNLOCK(); +#endif } rt_bool_t rt_wlan_get_autoreconnect_mode(void) { +#ifdef RT_WLAN_AUTO_CONNECT_ENABLE rt_bool_t enable = 0; enable = _sta_mgnt.flags & RT_WLAN_STATE_AUTOEN ? 1 : 0; RT_WLAN_LOG_D("%s is run enable:%d", __FUNCTION__, enable); return enable; +#else + return RT_FALSE; +#endif } /* Call the underlying scan function, which is asynchronous. @@ -1612,6 +1747,9 @@ struct rt_wlan_scan_result *rt_wlan_scan_with_info(struct rt_wlan_info *info) rt_err_t err = RT_EOK; struct rt_wlan_complete_des *complete; rt_uint32_t set = 0, recved = 0; + static struct rt_wlan_info scan_filter_info; + rt_base_t level; + struct rt_wlan_scan_result *result; if (_sta_is_null()) { @@ -1633,14 +1771,23 @@ struct rt_wlan_scan_result *rt_wlan_scan_with_info(struct rt_wlan_info *info) return &scan_result; } + /* add scan info filter */ + if (info) + { + scan_filter_info = *info; + level = rt_hw_interrupt_disable(); + scan_filter = &scan_filter_info; + rt_hw_interrupt_enable(level); + } + /* run scan */ err = rt_wlan_dev_scan(STA_DEVICE(), info); if (err != RT_EOK) { rt_wlan_complete_delete(complete); RT_WLAN_LOG_E("scan sync fail"); - MGNT_UNLOCK(); - return RT_NULL; + result = RT_NULL; + goto scan_exit; } /* Initializing events that need to wait */ @@ -1653,12 +1800,17 @@ struct rt_wlan_scan_result *rt_wlan_scan_with_info(struct rt_wlan_info *info) if (!(recved & set)) { RT_WLAN_LOG_E("scan wait timeout!"); - MGNT_UNLOCK(); - return &scan_result; + result = &scan_result; + goto scan_exit; } +scan_exit: MGNT_UNLOCK(); - return &scan_result; + level = rt_hw_interrupt_disable(); + scan_filter = RT_NULL; + rt_hw_interrupt_enable(level); + result = &scan_result; + return result; } int rt_wlan_scan_get_info_num(void) @@ -1709,8 +1861,7 @@ int rt_wlan_scan_find_cache(struct rt_wlan_info *info, struct rt_wlan_info *out_ { int i = 0, count = 0; struct rt_wlan_info *scan_info; - rt_bool_t is_equ = 1; - rt_uint8_t bssid_zero[RT_WLAN_BSSID_MAX_LENGTH] = { 0 }; + rt_bool_t is_equ; if ((out_info == RT_NULL) || (info == RT_NULL) || (num <= 0)) { @@ -1721,31 +1872,7 @@ int rt_wlan_scan_find_cache(struct rt_wlan_info *info, struct rt_wlan_info *out_ for (i = 0; (i < scan_result.num) && (count < num); i++) { scan_info = &scan_result.info[i]; - - if (is_equ && (info->security != SECURITY_UNKNOWN)) - { - is_equ &= info->security == scan_info->security; - } - if (is_equ && ((info->ssid.len > 0) && (info->ssid.len == scan_info->ssid.len))) - { - is_equ &= rt_memcmp(&info->ssid.val[0], &scan_info->ssid.val[0], scan_info->ssid.len) == 0; - } - if (is_equ && (rt_memcmp(&info->bssid[0], bssid_zero, RT_WLAN_BSSID_MAX_LENGTH))) - { - is_equ &= rt_memcmp(&info->bssid[0], &scan_info->bssid[0], RT_WLAN_BSSID_MAX_LENGTH) == 0; - } - if (is_equ && info->datarate) - { - is_equ &= info->datarate == scan_info->datarate; - } - if (is_equ && (info->channel >= 0)) - { - is_equ &= info->channel == scan_info->channel; - } - if (is_equ && (info->rssi < 0)) - { - is_equ &= info->rssi == scan_info->rssi; - } + is_equ = rt_wlan_info_isequ(scan_info, info); /* Determine whether to find */ if (is_equ) { @@ -1840,8 +1967,6 @@ void rt_wlan_mgnt_unlock(void) int rt_wlan_prot_ready_event(struct rt_wlan_device *wlan, struct rt_wlan_buff *buff) { rt_base_t level; - void *user_parameter; - rt_wlan_event_handler handler = RT_NULL; if ((wlan == RT_NULL) || (_sta_mgnt.device != wlan) || (!(_sta_mgnt.state & RT_WLAN_STATE_CONNECT))) @@ -1854,13 +1979,24 @@ int rt_wlan_prot_ready_event(struct rt_wlan_device *wlan, struct rt_wlan_buff *b } level = rt_hw_interrupt_disable(); _sta_mgnt.state |= RT_WLAN_STATE_READY; - handler = event_tab[RT_WLAN_EVT_READY].handler; - user_parameter = event_tab[RT_WLAN_EVT_READY].parameter; rt_hw_interrupt_enable(level); - if (handler) +#ifdef RT_WLAN_WORK_THREAD_ENABLE + rt_wlan_send_to_thread(RT_WLAN_EVT_READY, buff->data, buff->len); +#else { - handler(RT_WLAN_EVT_READY, buff, user_parameter); + void *user_parameter; + rt_wlan_event_handler handler = RT_NULL; + + level = rt_hw_interrupt_disable(); + handler = event_tab[RT_WLAN_EVT_READY].handler; + user_parameter = event_tab[RT_WLAN_EVT_READY].parameter; + rt_hw_interrupt_enable(level); + if (handler) + { + handler(RT_WLAN_EVT_READY, buff, user_parameter); + } } +#endif return 0; } @@ -1879,10 +2015,15 @@ int rt_wlan_init(void) rt_mutex_init(&scan_result_mutex, "scan", RT_IPC_FLAG_FIFO); rt_mutex_init(&sta_info_mutex, "sta", RT_IPC_FLAG_FIFO); rt_mutex_init(&complete_mutex, "complete", RT_IPC_FLAG_FIFO); - rt_timer_init(&reconnect_time, "wifi_tim", rt_wlan_cyclic_check, RT_NULL, DISCONNECT_RESPONSE_TICK, RT_TIMER_FLAG_PERIODIC | RT_TIMER_FLAG_SOFT_TIMER); - rt_timer_start(&reconnect_time); +#ifdef RT_WLAN_AUTO_CONNECT_ENABLE + rt_timer_init(&reconnect_time, "wifi_tim", rt_wlan_cyclic_check, RT_NULL, + rt_tick_from_millisecond(AUTO_CONNECTION_PERIOD_MS), + RT_TIMER_FLAG_PERIODIC | RT_TIMER_FLAG_SOFT_TIMER); +#endif _init_flag = 1; } return 0; } INIT_PREV_EXPORT(rt_wlan_init); + +#endif diff --git a/components/drivers/wlan/wlan_mgnt.h b/components/drivers/wlan/wlan_mgnt.h index f4d9e0cff9..df0827bb7b 100644 --- a/components/drivers/wlan/wlan_mgnt.h +++ b/components/drivers/wlan/wlan_mgnt.h @@ -37,6 +37,14 @@ extern "C" { #define RT_WLAN_EBOX_NUM (10) #endif +#ifndef RT_WLAN_SCAN_RETRY_CNT +#define RT_WLAN_SCAN_RETRY_CNT (3) +#endif + +#ifndef AUTO_CONNECTION_PERIOD_MS +#define AUTO_CONNECTION_PERIOD_MS (2000) +#endif + /*state fot station*/ #define RT_WLAN_STATE_CONNECT (1UL << 0) #define RT_WLAN_STATE_CONNECTING (1UL << 1) diff --git a/components/drivers/wlan/wlan_prot.c b/components/drivers/wlan/wlan_prot.c index 0402962e01..b1a1b5de99 100644 --- a/components/drivers/wlan/wlan_prot.c +++ b/components/drivers/wlan/wlan_prot.c @@ -21,6 +21,8 @@ #endif /* RT_WLAN_PROT_DEBUG */ #include <rtdbg.h> +#ifdef RT_WLAN_PROT_ENABLE + #if RT_WLAN_PROT_NAME_LEN < 4 #error "The name is too short" #endif @@ -160,7 +162,7 @@ rt_err_t rt_wlan_prot_attach_dev(struct rt_wlan_device *wlan, const char *prot_n { int i = 0; struct rt_wlan_prot *prot = wlan->prot; - rt_wlan_dev_event_t event; + rt_wlan_dev_event_handler handler = rt_wlan_prot_event_handle; if (wlan == RT_NULL) { @@ -180,7 +182,7 @@ rt_err_t rt_wlan_prot_attach_dev(struct rt_wlan_device *wlan, const char *prot_n rt_wlan_prot_detach_dev(wlan); #ifdef RT_WLAN_PROT_LWIP_PBUF_FORCE - if (rt_strcmp(RT_WLAN_PROT_LWIP, prot_name) != 0) + if (rt_strcmp(RT_WLAN_PROT_LWIP_NAME, prot_name) != 0) { return -RT_ERROR; } @@ -202,13 +204,12 @@ rt_err_t rt_wlan_prot_attach_dev(struct rt_wlan_device *wlan, const char *prot_n return -RT_ERROR; } - for (event = RT_WLAN_DEV_EVT_INIT_DONE; event < RT_WLAN_DEV_EVT_MAX; event ++) - { - if (rt_wlan_dev_register_event_handler(wlan, event, rt_wlan_prot_event_handle, RT_NULL) != RT_EOK) - { - LOG_E("prot register event filed:%d", event); - } - } + rt_wlan_dev_register_event_handler(wlan, RT_WLAN_DEV_EVT_CONNECT, handler, RT_NULL); + rt_wlan_dev_register_event_handler(wlan, RT_WLAN_DEV_EVT_DISCONNECT, handler, RT_NULL); + rt_wlan_dev_register_event_handler(wlan, RT_WLAN_DEV_EVT_AP_START, handler, RT_NULL); + rt_wlan_dev_register_event_handler(wlan, RT_WLAN_DEV_EVT_AP_STOP, handler, RT_NULL); + rt_wlan_dev_register_event_handler(wlan, RT_WLAN_DEV_EVT_AP_ASSOCIATED, handler, RT_NULL); + rt_wlan_dev_register_event_handler(wlan, RT_WLAN_DEV_EVT_AP_DISASSOCIATED, handler, RT_NULL); return RT_EOK; } @@ -360,3 +361,4 @@ void rt_wlan_prot_dump(void) } } } +#endif diff --git a/components/drivers/wlan/wlan_prot.h b/components/drivers/wlan/wlan_prot.h index 34c5bae7fd..2df979270f 100644 --- a/components/drivers/wlan/wlan_prot.h +++ b/components/drivers/wlan/wlan_prot.h @@ -25,8 +25,6 @@ extern "C" { #define RT_LWAN_ID_PREFIX (0x5054) -#define RT_WLAN_PROT_LWIP ("lwip") - typedef enum { RT_WLAN_PROT_EVT_INIT_DONE = 0, diff --git a/components/drivers/wlan/wlan_workqueue.c b/components/drivers/wlan/wlan_workqueue.c index ec21243d60..4cd98346d2 100644 --- a/components/drivers/wlan/wlan_workqueue.c +++ b/components/drivers/wlan/wlan_workqueue.c @@ -17,6 +17,8 @@ #define DBG_LVL DBG_INFO #include <rtdbg.h> +#ifdef RT_WLAN_WORK_THREAD_ENABLE + struct rt_wlan_work { struct rt_work work; @@ -95,3 +97,5 @@ int rt_wlan_workqueue_init(void) return 0; } INIT_PREV_EXPORT(rt_wlan_workqueue_init); + +#endif diff --git a/components/finsh/SConscript b/components/finsh/SConscript index e1e2b3bbdb..be04c56616 100644 --- a/components/finsh/SConscript +++ b/components/finsh/SConscript @@ -4,7 +4,6 @@ from building import * cwd = GetCurrentDir() src = Split(''' shell.c -symbol.c cmd.c ''') @@ -21,19 +20,20 @@ finsh_vm.c finsh_token.c ''') -msh_src = Split(''' -msh.c -msh_cmd.c -msh_file.c -''') +msh_src = Glob('msh.c') -CPPPATH = [cwd] +if GetDepend('RT_USING_DFS'): + msh_src += ['msh_file.c'] +if not GetDepend('FINSH_USING_SYMTAB'): + src += ['symbol.c'] if GetDepend('FINSH_USING_MSH'): src = src + msh_src if not GetDepend('FINSH_USING_MSH_ONLY'): src = src + fsh_src +CPPPATH = [cwd] + group = DefineGroup('finsh', src, depend = ['RT_USING_FINSH'], CPPPATH = CPPPATH) Return('group') diff --git a/components/finsh/cmd.c b/components/finsh/cmd.c index ba0292d81a..ebef0eac1c 100644 --- a/components/finsh/cmd.c +++ b/components/finsh/cmd.c @@ -440,8 +440,16 @@ static long _list_mempool(struct rt_list_node *list) rt_kprintf( " ---- ---- ---- --------------\n"); for (node = list->next; node != list; node = node->next) { + int suspend_thread_count; + rt_list_t *temp_node; mp = (struct rt_mempool *)rt_list_entry(node, struct rt_object, list); - if (mp->suspend_thread_count > 0) + suspend_thread_count = 0; + rt_list_for_each(temp_node, &mp->suspend_thread) + { + suspend_thread_count++; + } + + if (suspend_thread_count > 0) { rt_kprintf("%-*.*s %04d %04d %04d %d:", maxlen, RT_NAME_MAX, @@ -449,7 +457,7 @@ static long _list_mempool(struct rt_list_node *list) mp->block_size, mp->block_total_count, mp->block_free_count, - mp->suspend_thread_count); + suspend_thread_count); show_wait_queue(&(mp->suspend_thread)); rt_kprintf("\n"); } @@ -461,7 +469,7 @@ static long _list_mempool(struct rt_list_node *list) mp->block_size, mp->block_total_count, mp->block_free_count, - mp->suspend_thread_count); + suspend_thread_count); } } @@ -547,6 +555,7 @@ static long _list_device(struct rt_list_node *list) "Timer Device", "Miscellaneous Device", "Sensor Device", + "Touch Device", "Unknown" }; const char *item_title = "device"; @@ -598,7 +607,7 @@ long list(void) /* skip the internal command */ if (strncmp((char *)index->name, "__", 2) == 0) continue; -#ifdef FINSH_USING_DESCRIPTION +#if defined(FINSH_USING_DESCRIPTION) && defined(FINSH_USING_SYMTAB) rt_kprintf("%-16s -- %s\n", index->name, index->desc); #else rt_kprintf("%s\n", index->name); diff --git a/components/finsh/finsh_vm.c b/components/finsh/finsh_vm.c index fcd58494a9..7c56407084 100644 --- a/components/finsh/finsh_vm.c +++ b/components/finsh/finsh_vm.c @@ -78,28 +78,6 @@ void finsh_syscall_append(const char* name, syscall_func func) } #endif -#if defined(_MSC_VER) || (defined(__GNUC__) && defined(__x86_64__)) -struct finsh_syscall* finsh_syscall_next(struct finsh_syscall* call) -{ - unsigned int *ptr; - ptr = (unsigned int*) (call + 1); - while ((*ptr == 0) && ((unsigned int*)ptr < (unsigned int*) _syscall_table_end)) - ptr ++; - - return (struct finsh_syscall*)ptr; -} - -struct finsh_sysvar* finsh_sysvar_next(struct finsh_sysvar* call) -{ - unsigned int *ptr; - ptr = (unsigned int*) (call + 1); - while ((*ptr == 0) && ((unsigned int*)ptr < (unsigned int*) _sysvar_table_end)) - ptr ++; - - return (struct finsh_sysvar*)ptr; -} -#endif - struct finsh_syscall* finsh_syscall_lookup(const char* name) { struct finsh_syscall* index; diff --git a/components/finsh/msh.c b/components/finsh/msh.c index fd1ee1198d..79f1e3c87f 100644 --- a/components/finsh/msh.c +++ b/components/finsh/msh.c @@ -89,6 +89,37 @@ int msh_help(int argc, char **argv) } FINSH_FUNCTION_EXPORT_ALIAS(msh_help, __cmd_help, RT-Thread shell help.); +int cmd_ps(int argc, char **argv) +{ + extern long list_thread(void); + extern int list_module(void); + +#ifdef RT_USING_MODULE + if ((argc == 2) && (strcmp(argv[1], "-m") == 0)) + list_module(); + else +#endif + list_thread(); + return 0; +} +FINSH_FUNCTION_EXPORT_ALIAS(cmd_ps, __cmd_ps, List threads in the system.); + +#ifdef RT_USING_HEAP +int cmd_free(int argc, char **argv) +{ + extern void list_mem(void); + extern void list_memheap(void); + +#ifdef RT_USING_MEMHEAP_AS_HEAP + list_memheap(); +#else + list_mem(); +#endif + return 0; +} +FINSH_FUNCTION_EXPORT_ALIAS(cmd_free, __cmd_free, Show the memory usage in the system.); +#endif + static int msh_split(char *cmd, rt_size_t length, char *argv[FINSH_ARG_MAX]) { char *ptr; diff --git a/components/finsh/msh_cmd.c b/components/finsh/msh_cmd.c deleted file mode 100644 index 4a9c67fa75..0000000000 --- a/components/finsh/msh_cmd.c +++ /dev/null @@ -1,331 +0,0 @@ -/* - * Copyright (c) 2006-2018, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2013-03-30 Bernard the first verion for FinSH - * 2015-08-28 Bernard Add mkfs command. - */ - -#include <rtthread.h> - -#ifdef FINSH_USING_MSH - -#include <finsh.h> -#include "msh.h" - -#ifdef RT_USING_DFS -#include <dfs_posix.h> - -#ifdef DFS_USING_WORKDIR -extern char working_directory[]; -#endif - -int cmd_ls(int argc, char **argv) -{ - extern void ls(const char *pathname); - - if (argc == 1) - { -#ifdef DFS_USING_WORKDIR - ls(working_directory); -#else - ls("/"); -#endif - } - else - { - ls(argv[1]); - } - - return 0; -} -FINSH_FUNCTION_EXPORT_ALIAS(cmd_ls, __cmd_ls, List information about the FILEs.); - -int cmd_cp(int argc, char **argv) -{ - void copy(const char *src, const char *dst); - - if (argc != 3) - { - rt_kprintf("Usage: cp SOURCE DEST\n"); - rt_kprintf("Copy SOURCE to DEST.\n"); - } - else - { - copy(argv[1], argv[2]); - } - - return 0; -} -FINSH_FUNCTION_EXPORT_ALIAS(cmd_cp, __cmd_cp, Copy SOURCE to DEST.); - -int cmd_mv(int argc, char **argv) -{ - if (argc != 3) - { - rt_kprintf("Usage: mv SOURCE DEST\n"); - rt_kprintf("Rename SOURCE to DEST, or move SOURCE(s) to DIRECTORY.\n"); - } - else - { - int fd; - char *dest = RT_NULL; - - rt_kprintf("%s => %s\n", argv[1], argv[2]); - - fd = open(argv[2], O_DIRECTORY, 0); - if (fd >= 0) - { - char *src; - - close(fd); - - /* it's a directory */ - dest = (char *)rt_malloc(DFS_PATH_MAX); - if (dest == RT_NULL) - { - rt_kprintf("out of memory\n"); - return -RT_ENOMEM; - } - - src = argv[1] + rt_strlen(argv[1]); - while (src != argv[1]) - { - if (*src == '/') break; - src --; - } - - rt_snprintf(dest, DFS_PATH_MAX - 1, "%s/%s", argv[2], src); - } - else - { - fd = open(argv[2], O_RDONLY, 0); - if (fd >= 0) - { - close(fd); - - unlink(argv[2]); - } - - dest = argv[2]; - } - - rename(argv[1], dest); - if (dest != RT_NULL && dest != argv[2]) rt_free(dest); - } - - return 0; -} -FINSH_FUNCTION_EXPORT_ALIAS(cmd_mv, __cmd_mv, Rename SOURCE to DEST.); - -int cmd_cat(int argc, char **argv) -{ - int index; - extern void cat(const char *filename); - - if (argc == 1) - { - rt_kprintf("Usage: cat [FILE]...\n"); - rt_kprintf("Concatenate FILE(s)\n"); - return 0; - } - - for (index = 1; index < argc; index ++) - { - cat(argv[index]); - } - - return 0; -} -FINSH_FUNCTION_EXPORT_ALIAS(cmd_cat, __cmd_cat, Concatenate FILE(s)); - -int cmd_rm(int argc, char **argv) -{ - int index; - - if (argc == 1) - { - rt_kprintf("Usage: rm FILE...\n"); - rt_kprintf("Remove (unlink) the FILE(s).\n"); - return 0; - } - - for (index = 1; index < argc; index ++) - { - unlink(argv[index]); - } - - return 0; -} -FINSH_FUNCTION_EXPORT_ALIAS(cmd_rm, __cmd_rm, Remove(unlink) the FILE(s).); - -#ifdef DFS_USING_WORKDIR -int cmd_cd(int argc, char **argv) -{ - if (argc == 1) - { - rt_kprintf("%s\n", working_directory); - } - else if (argc == 2) - { - if (chdir(argv[1]) != 0) - { - rt_kprintf("No such directory: %s\n", argv[1]); - } - } - - return 0; -} -FINSH_FUNCTION_EXPORT_ALIAS(cmd_cd, __cmd_cd, Change the shell working directory.); - -int cmd_pwd(int argc, char **argv) -{ - rt_kprintf("%s\n", working_directory); - return 0; -} -FINSH_FUNCTION_EXPORT_ALIAS(cmd_pwd, __cmd_pwd, Print the name of the current working directory.); -#endif - -int cmd_mkdir(int argc, char **argv) -{ - if (argc == 1) - { - rt_kprintf("Usage: mkdir [OPTION] DIRECTORY\n"); - rt_kprintf("Create the DIRECTORY, if they do not already exist.\n"); - } - else - { - mkdir(argv[1], 0); - } - - return 0; -} -FINSH_FUNCTION_EXPORT_ALIAS(cmd_mkdir, __cmd_mkdir, Create the DIRECTORY.); - -int cmd_mkfs(int argc, char **argv) -{ - int result = 0; - char *type = "elm"; /* use the default file system type as 'fatfs' */ - - if (argc == 2) - { - result = dfs_mkfs(type, argv[1]); - } - else if (argc == 4) - { - if (strcmp(argv[1], "-t") == 0) - { - type = argv[2]; - result = dfs_mkfs(type, argv[3]); - } - } - else - { - rt_kprintf("Usage: mkfs [-t type] device\n"); - return 0; - } - - if (result != RT_EOK) - { - rt_kprintf("mkfs failed, result=%d\n", result); - } - - return 0; -} -FINSH_FUNCTION_EXPORT_ALIAS(cmd_mkfs, __cmd_mkfs, format disk with file system); - -extern int df(const char *path); -int cmd_df(int argc, char** argv) -{ - if (argc != 2) - { - df("/"); - } - else - { - if ((strcmp(argv[1], "--help") == 0) || (strcmp(argv[1], "-h") == 0)) - { - rt_kprintf("df [path]\n"); - } - else - { - df(argv[1]); - } - } - - return 0; -} -FINSH_FUNCTION_EXPORT_ALIAS(cmd_df, __cmd_df, disk free); - -int cmd_echo(int argc, char** argv) -{ - if (argc == 2) - { - rt_kprintf("%s\n", argv[1]); - } - else if (argc == 3) - { - int fd; - - fd = open(argv[2], O_RDWR | O_APPEND | O_CREAT, 0); - if (fd >= 0) - { - write (fd, argv[1], strlen(argv[1])); - close(fd); - } - else - { - rt_kprintf("open file:%s failed!\n", argv[2]); - } - } - else - { - rt_kprintf("Usage: echo \"string\" [filename]\n"); - } - - return 0; -} -FINSH_FUNCTION_EXPORT_ALIAS(cmd_echo, __cmd_echo, echo string to file); -#endif - -int cmd_ps(int argc, char **argv) -{ - extern long list_thread(void); - extern int list_module(void); - -#ifdef RT_USING_MODULE - if ((argc == 2) && (strcmp(argv[1], "-m") == 0)) - list_module(); - else -#endif - list_thread(); - return 0; -} -FINSH_FUNCTION_EXPORT_ALIAS(cmd_ps, __cmd_ps, List threads in the system.); - -int cmd_time(int argc, char **argv) -{ - return 0; -} -FINSH_FUNCTION_EXPORT_ALIAS(cmd_time, __cmd_time, Execute command with time.); - -#ifdef RT_USING_HEAP -int cmd_free(int argc, char **argv) -{ - extern void list_mem(void); - extern void list_memheap(void); - -#ifdef RT_USING_MEMHEAP_AS_HEAP - list_memheap(); -#else - list_mem(); -#endif - return 0; -} -FINSH_FUNCTION_EXPORT_ALIAS(cmd_free, __cmd_free, Show the memory usage in the system.); -#endif - -#endif /* FINSH_USING_MSH */ diff --git a/components/finsh/msh_file.c b/components/finsh/msh_file.c index d8eec0a71a..10251b4cb5 100644 --- a/components/finsh/msh_file.c +++ b/components/finsh/msh_file.c @@ -137,5 +137,276 @@ int msh_exec_script(const char *cmd_line, int size) return ret; } +#ifdef DFS_USING_WORKDIR +extern char working_directory[]; +#endif + +int cmd_ls(int argc, char **argv) +{ + extern void ls(const char *pathname); + + if (argc == 1) + { +#ifdef DFS_USING_WORKDIR + ls(working_directory); +#else + ls("/"); +#endif + } + else + { + ls(argv[1]); + } + + return 0; +} +FINSH_FUNCTION_EXPORT_ALIAS(cmd_ls, __cmd_ls, List information about the FILEs.); + +int cmd_cp(int argc, char **argv) +{ + void copy(const char *src, const char *dst); + + if (argc != 3) + { + rt_kprintf("Usage: cp SOURCE DEST\n"); + rt_kprintf("Copy SOURCE to DEST.\n"); + } + else + { + copy(argv[1], argv[2]); + } + + return 0; +} +FINSH_FUNCTION_EXPORT_ALIAS(cmd_cp, __cmd_cp, Copy SOURCE to DEST.); + +int cmd_mv(int argc, char **argv) +{ + if (argc != 3) + { + rt_kprintf("Usage: mv SOURCE DEST\n"); + rt_kprintf("Rename SOURCE to DEST, or move SOURCE(s) to DIRECTORY.\n"); + } + else + { + int fd; + char *dest = RT_NULL; + + rt_kprintf("%s => %s\n", argv[1], argv[2]); + + fd = open(argv[2], O_DIRECTORY, 0); + if (fd >= 0) + { + char *src; + + close(fd); + + /* it's a directory */ + dest = (char *)rt_malloc(DFS_PATH_MAX); + if (dest == RT_NULL) + { + rt_kprintf("out of memory\n"); + return -RT_ENOMEM; + } + + src = argv[1] + rt_strlen(argv[1]); + while (src != argv[1]) + { + if (*src == '/') break; + src --; + } + + rt_snprintf(dest, DFS_PATH_MAX - 1, "%s/%s", argv[2], src); + } + else + { + fd = open(argv[2], O_RDONLY, 0); + if (fd >= 0) + { + close(fd); + + unlink(argv[2]); + } + + dest = argv[2]; + } + + rename(argv[1], dest); + if (dest != RT_NULL && dest != argv[2]) rt_free(dest); + } + + return 0; +} +FINSH_FUNCTION_EXPORT_ALIAS(cmd_mv, __cmd_mv, Rename SOURCE to DEST.); + +int cmd_cat(int argc, char **argv) +{ + int index; + extern void cat(const char *filename); + + if (argc == 1) + { + rt_kprintf("Usage: cat [FILE]...\n"); + rt_kprintf("Concatenate FILE(s)\n"); + return 0; + } + + for (index = 1; index < argc; index ++) + { + cat(argv[index]); + } + + return 0; +} +FINSH_FUNCTION_EXPORT_ALIAS(cmd_cat, __cmd_cat, Concatenate FILE(s)); + +int cmd_rm(int argc, char **argv) +{ + int index; + + if (argc == 1) + { + rt_kprintf("Usage: rm FILE...\n"); + rt_kprintf("Remove (unlink) the FILE(s).\n"); + return 0; + } + + for (index = 1; index < argc; index ++) + { + unlink(argv[index]); + } + + return 0; +} +FINSH_FUNCTION_EXPORT_ALIAS(cmd_rm, __cmd_rm, Remove(unlink) the FILE(s).); + +#ifdef DFS_USING_WORKDIR +int cmd_cd(int argc, char **argv) +{ + if (argc == 1) + { + rt_kprintf("%s\n", working_directory); + } + else if (argc == 2) + { + if (chdir(argv[1]) != 0) + { + rt_kprintf("No such directory: %s\n", argv[1]); + } + } + + return 0; +} +FINSH_FUNCTION_EXPORT_ALIAS(cmd_cd, __cmd_cd, Change the shell working directory.); + +int cmd_pwd(int argc, char **argv) +{ + rt_kprintf("%s\n", working_directory); + return 0; +} +FINSH_FUNCTION_EXPORT_ALIAS(cmd_pwd, __cmd_pwd, Print the name of the current working directory.); +#endif + +int cmd_mkdir(int argc, char **argv) +{ + if (argc == 1) + { + rt_kprintf("Usage: mkdir [OPTION] DIRECTORY\n"); + rt_kprintf("Create the DIRECTORY, if they do not already exist.\n"); + } + else + { + mkdir(argv[1], 0); + } + + return 0; +} +FINSH_FUNCTION_EXPORT_ALIAS(cmd_mkdir, __cmd_mkdir, Create the DIRECTORY.); + +int cmd_mkfs(int argc, char **argv) +{ + int result = 0; + char *type = "elm"; /* use the default file system type as 'fatfs' */ + + if (argc == 2) + { + result = dfs_mkfs(type, argv[1]); + } + else if (argc == 4) + { + if (strcmp(argv[1], "-t") == 0) + { + type = argv[2]; + result = dfs_mkfs(type, argv[3]); + } + } + else + { + rt_kprintf("Usage: mkfs [-t type] device\n"); + return 0; + } + + if (result != RT_EOK) + { + rt_kprintf("mkfs failed, result=%d\n", result); + } + + return 0; +} +FINSH_FUNCTION_EXPORT_ALIAS(cmd_mkfs, __cmd_mkfs, format disk with file system); + +extern int df(const char *path); +int cmd_df(int argc, char** argv) +{ + if (argc != 2) + { + df("/"); + } + else + { + if ((strcmp(argv[1], "--help") == 0) || (strcmp(argv[1], "-h") == 0)) + { + rt_kprintf("df [path]\n"); + } + else + { + df(argv[1]); + } + } + + return 0; +} +FINSH_FUNCTION_EXPORT_ALIAS(cmd_df, __cmd_df, disk free); + +int cmd_echo(int argc, char** argv) +{ + if (argc == 2) + { + rt_kprintf("%s\n", argv[1]); + } + else if (argc == 3) + { + int fd; + + fd = open(argv[2], O_RDWR | O_APPEND | O_CREAT, 0); + if (fd >= 0) + { + write (fd, argv[1], strlen(argv[1])); + close(fd); + } + else + { + rt_kprintf("open file:%s failed!\n", argv[2]); + } + } + else + { + rt_kprintf("Usage: echo \"string\" [filename]\n"); + } + + return 0; +} +FINSH_FUNCTION_EXPORT_ALIAS(cmd_echo, __cmd_echo, echo string to file); + #endif /* defined(FINSH_USING_MSH) && defined(RT_USING_DFS) */ diff --git a/components/finsh/shell.c b/components/finsh/shell.c index 53dcd11c66..852d3e7ac7 100644 --- a/components/finsh/shell.c +++ b/components/finsh/shell.c @@ -15,7 +15,7 @@ * 2011-02-23 Bernard fix variable section end issue of finsh shell * initialization when use GNU GCC compiler. * 2016-11-26 armink add password authentication - * 2018-07-02 aozima add custome prompt support. + * 2018-07-02 aozima add custom prompt support. */ #include <rthw.h> @@ -41,9 +41,39 @@ static char finsh_thread_stack[FINSH_THREAD_STACK_SIZE]; struct finsh_shell _shell; #endif +/* finsh symtab */ +#ifdef FINSH_USING_SYMTAB +struct finsh_syscall *_syscall_table_begin = NULL; +struct finsh_syscall *_syscall_table_end = NULL; +struct finsh_sysvar *_sysvar_table_begin = NULL; +struct finsh_sysvar *_sysvar_table_end = NULL; +#endif + struct finsh_shell *shell; static char *finsh_prompt_custom = RT_NULL; +#if defined(_MSC_VER) || (defined(__GNUC__) && defined(__x86_64__)) +struct finsh_syscall* finsh_syscall_next(struct finsh_syscall* call) +{ + unsigned int *ptr; + ptr = (unsigned int*) (call + 1); + while ((*ptr == 0) && ((unsigned int*)ptr < (unsigned int*) _syscall_table_end)) + ptr ++; + + return (struct finsh_syscall*)ptr; +} + +struct finsh_sysvar* finsh_sysvar_next(struct finsh_sysvar* call) +{ + unsigned int *ptr; + ptr = (unsigned int*) (call + 1); + while ((*ptr == 0) && ((unsigned int*)ptr < (unsigned int*) _sysvar_table_end)) + ptr ++; + + return (struct finsh_sysvar*)ptr; +} +#endif /* defined(_MSC_VER) || (defined(__GNUC__) && defined(__x86_64__)) */ + #ifdef RT_USING_HEAP int finsh_set_prompt(const char * prompt) { @@ -56,7 +86,7 @@ int finsh_set_prompt(const char * prompt) /* strdup */ if(prompt) { - finsh_prompt_custom = rt_malloc(strlen(prompt)+1); + finsh_prompt_custom = (char *)rt_malloc(strlen(prompt)+1); if(finsh_prompt_custom) { strcpy(finsh_prompt_custom, prompt); @@ -136,6 +166,7 @@ void finsh_set_prompt_mode(rt_uint32_t prompt_mode) static int finsh_getchar(void) { +#ifdef RT_USING_DEVICE #ifdef RT_USING_POSIX return getchar(); #else @@ -147,9 +178,13 @@ static int finsh_getchar(void) return (int)ch; #endif +#else + extern char rt_hw_console_getchar(void); + return rt_hw_console_getchar(); +#endif } -#ifndef RT_USING_POSIX +#if !defined(RT_USING_POSIX) && defined(RT_USING_DEVICE) static rt_err_t finsh_rx_ind(rt_device_t dev, rt_size_t size) { RT_ASSERT(shell != RT_NULL); @@ -309,8 +344,8 @@ static void finsh_wait_auth(void) else if (ch == '\b' && cur_pos > 0) { /* backspace */ - password[cur_pos] = '\0'; cur_pos--; + password[cur_pos] = '\0'; rt_kprintf("\b \b"); } else if (ch == '\r' || ch == '\n') @@ -477,7 +512,7 @@ void finsh_thread_entry(void *parameter) finsh_init(&shell->parser); #endif -#ifndef RT_USING_POSIX +#if !defined(RT_USING_POSIX) && defined(RT_USING_DEVICE) /* set console device as shell device */ if (shell->device == RT_NULL) { diff --git a/components/finsh/shell.h b/components/finsh/shell.h index 2cf2c9b833..8741759ed4 100644 --- a/components/finsh/shell.h +++ b/components/finsh/shell.h @@ -79,10 +79,10 @@ struct finsh_shell #endif char line[FINSH_CMD_SIZE]; - rt_uint8_t line_position; - rt_uint8_t line_curpos; + rt_uint16_t line_position; + rt_uint16_t line_curpos; -#ifndef RT_USING_POSIX +#if !defined(RT_USING_POSIX) && defined(RT_USING_DEVICE) rt_device_t device; #endif diff --git a/components/finsh/symbol.c b/components/finsh/symbol.c index e500637bdd..78df9fac5c 100644 --- a/components/finsh/symbol.c +++ b/components/finsh/symbol.c @@ -10,7 +10,7 @@ #include <rtthread.h> -#ifdef RT_USING_FINSH +#if defined(RT_USING_FINSH) && !defined(FINSH_USING_SYMTAB) #include "finsh.h" @@ -27,12 +27,6 @@ long list_msgqueue(void); long list_mempool(void); long list_timer(void); -#ifdef FINSH_USING_SYMTAB -struct finsh_syscall *_syscall_table_begin = NULL; -struct finsh_syscall *_syscall_table_end = NULL; -struct finsh_sysvar *_sysvar_table_begin = NULL; -struct finsh_sysvar *_sysvar_table_end = NULL; -#else struct finsh_syscall _syscall_table[] = { {"hello", hello}, @@ -67,7 +61,6 @@ struct finsh_syscall *_syscall_table_end = &_syscall_table[sizeof(_syscall_tab struct finsh_sysvar *_sysvar_table_begin = NULL; struct finsh_sysvar *_sysvar_table_end = NULL; -#endif -#endif /* RT_USING_FINSH */ +#endif /* RT_USING_FINSH && !FINSH_USING_SYMTAB */ diff --git a/components/libc/Kconfig b/components/libc/Kconfig index 43d9330102..2d1e9315f1 100644 --- a/components/libc/Kconfig +++ b/components/libc/Kconfig @@ -39,4 +39,10 @@ if RT_USING_LIBC && RT_USING_DFS default n endif +if RT_USING_LIBC != y + config RT_LIBC_USING_TIME + bool "Enable TIME FUNCTIONS WITHOUT COMPILER'S LIBC" + default y +endif + endmenu diff --git a/components/libc/compilers/armlibc/libc.h b/components/libc/compilers/armlibc/libc.h index 158fe06c3e..b9b1b6212d 100644 --- a/components/libc/compilers/armlibc/libc.h +++ b/components/libc/compilers/armlibc/libc.h @@ -12,11 +12,17 @@ #include <stddef.h> +#ifdef __cplusplus +extern "C" { +#endif int libc_system_init(void); int libc_stdio_set_console(const char* device_name, int mode); int libc_stdio_get_console(void); -int libc_stdio_read (void *buffer, size_t size); -int libc_stdio_write(const void *buffer, size_t size); +int libc_stdio_read(void* buffer, size_t size); +int libc_stdio_write(const void* buffer, size_t size); +#ifdef __cplusplus +} +#endif #endif diff --git a/components/libc/compilers/armlibc/sys/time.h b/components/libc/compilers/armlibc/sys/time.h deleted file mode 100644 index bac122e183..0000000000 --- a/components/libc/compilers/armlibc/sys/time.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2006-2018, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - */ -#ifndef _SYS_TIME_H_ -#define _SYS_TIME_H_ - -#include <time.h> -#include <sys/types.h> - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef _TIMEVAL_DEFINED -#define _TIMEVAL_DEFINED -/* - * Structure returned by gettimeofday(2) system call, - * and used in other calls. - */ -struct timeval { - long tv_sec; /* seconds */ - long tv_usec; /* and microseconds */ -}; -#endif /* _TIMEVAL_DEFINED */ - -#ifndef _TIMESPEC_DEFINED -#define _TIMESPEC_DEFINED -/* - * Structure defined by POSIX.1b to be like a timeval. - */ -struct timespec { - time_t tv_sec; /* seconds */ - long tv_nsec; /* and nanoseconds */ -}; -#endif /* _TIMESPEC_DEFINED */ - -struct timezone { - int tz_minuteswest; /* minutes west of Greenwich */ - int tz_dsttime; /* type of dst correction */ -}; - -int gettimeofday(struct timeval *tp, void *ignore); -struct tm *gmtime_r(const time_t *timep, struct tm *r); - -#ifdef __cplusplus -} -#endif - -#endif /* _SYS_TIME_H_ */ diff --git a/components/libc/compilers/armlibc/sys/types.h b/components/libc/compilers/armlibc/sys/types.h index 4c76dfc429..001ace4dd2 100644 --- a/components/libc/compilers/armlibc/sys/types.h +++ b/components/libc/compilers/armlibc/sys/types.h @@ -15,6 +15,10 @@ typedef rt_int32_t clockid_t; typedef rt_int32_t key_t; /* Used for interprocess communication. */ typedef rt_int32_t pid_t; /* Used for process IDs and process group IDs. */ -typedef signed long ssize_t; /* Used for a count of bytes or an error indication. */ +#ifndef ARCH_CPU_64BIT +typedef signed int ssize_t; /* Used for a count of bytes or an error indication. */ +#else +typedef long signed int ssize_t; /* Used for a count of bytes or an error indication. */ +#endif #endif diff --git a/components/libc/compilers/armlibc/time.c b/components/libc/compilers/armlibc/time.c deleted file mode 100644 index f099d51330..0000000000 --- a/components/libc/compilers/armlibc/time.c +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (c) 2006-2018, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - */ -#include <sys/time.h> -#include <rtthread.h> - -#ifdef RT_USING_DEVICE -int gettimeofday(struct timeval *tp, void *ignore) -{ - time_t time; - rt_device_t device; - - device = rt_device_find("rtc"); - RT_ASSERT(device != RT_NULL); - - rt_device_control(device, RT_DEVICE_CTRL_RTC_GET_TIME, &time); - if (tp != RT_NULL) - { - tp->tv_sec = time; - tp->tv_usec = 0; - } - - return time; -} -#endif - -/** - * Returns the current time. - * - * @param time_t * t the timestamp pointer, if not used, keep NULL. - * - * @return time_t return timestamp current. - * - */ -/* for IAR 6.2 later Compiler */ -#if defined (__IAR_SYSTEMS_ICC__) && (__VER__) >= 6020000 -#pragma module_name = "?time" -time_t (__time32)(time_t *t) /* Only supports 32-bit timestamp */ -#else -time_t time(time_t *t) -#endif -{ - time_t time_now = 0; - -#ifdef RT_USING_RTC - static rt_device_t device = RT_NULL; - - /* optimization: find rtc device only first. */ - if (device == RT_NULL) - { - device = rt_device_find("rtc"); - } - - /* read timestamp from RTC device. */ - if (device != RT_NULL) - { - if (rt_device_open(device, 0) == RT_EOK) - { - rt_device_control(device, RT_DEVICE_CTRL_RTC_GET_TIME, &time_now); - rt_device_close(device); - } - } -#endif /* RT_USING_RTC */ - - /* if t is not NULL, write timestamp to *t */ - if (t != RT_NULL) - { - *t = time_now; - } - - return time_now; -} - -RT_WEAK clock_t clock(void) -{ - return rt_tick_get(); -} diff --git a/components/libc/compilers/common/SConscript b/components/libc/compilers/common/SConscript index 02bf49941d..a8d2606820 100644 --- a/components/libc/compilers/common/SConscript +++ b/components/libc/compilers/common/SConscript @@ -2,11 +2,18 @@ from building import * Import('rtconfig') -src = Glob('*.c') +src = [] cwd = GetCurrentDir() group = [] CPPPATH = [cwd] -group = DefineGroup('libc', src, depend = ['RT_USING_LIBC'], CPPPATH = CPPPATH) +if GetDepend('RT_USING_LIBC'): + src += Glob('*.c') +else: + if GetDepend('RT_LIBC_USING_TIME'): + src += ['time.c'] + +if (rtconfig.PLATFORM == 'armcc' or rtconfig.PLATFORM == 'iar') and rtconfig.ARCH != 'sim' : + group = DefineGroup('libc', src, depend = [''], CPPPATH = CPPPATH) Return('group') diff --git a/components/libc/compilers/common/gmtime_r.c b/components/libc/compilers/common/gmtime_r.c deleted file mode 100644 index dff251ab6c..0000000000 --- a/components/libc/compilers/common/gmtime_r.c +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (c) 2006-2018, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2018-10-26 zylx first version - */ - -#if defined(__CC_ARM) || defined(__CLANG_ARM) || defined (__IAR_SYSTEMS_ICC__) -#include <sys/time.h> - -/* seconds per day */ -#define SPD 24*60*60 - -/* days per month -- nonleap! */ -const short __spm[13] = -{ - 0, - (31), - (31 + 28), - (31 + 28 + 31), - (31 + 28 + 31 + 30), - (31 + 28 + 31 + 30 + 31), - (31 + 28 + 31 + 30 + 31 + 30), - (31 + 28 + 31 + 30 + 31 + 30 + 31), - (31 + 28 + 31 + 30 + 31 + 30 + 31 + 31), - (31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30), - (31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31), - (31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30), - (31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + 31), -}; - -int __isleap(int year) -{ - /* every fourth year is a leap year except for century years that are - * not divisible by 400. */ - /* return (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)); */ - return (!(year % 4) && ((year % 100) || !(year % 400))); -} - -/** - * This function will convert Time (Restartable) - * - * @param timep the timestamp - * @param the structure to stores information - * - * @return the structure to stores information - * - */ -struct tm *gmtime_r(const time_t *timep, struct tm *r) -{ - time_t i; - register time_t work = *timep % (SPD); - r->tm_sec = work % 60; - work /= 60; - r->tm_min = work % 60; - r->tm_hour = work / 60; - work = *timep / (SPD); - r->tm_wday = (4 + work) % 7; - for (i = 1970;; ++i) - { - register time_t k = __isleap(i) ? 366 : 365; - if (work >= k) - work -= k; - else - break; - } - r->tm_year = i - 1900; - r->tm_yday = work; - - r->tm_mday = 1; - if (__isleap(i) && (work > 58)) - { - if (work == 59) - r->tm_mday = 2; /* 29.2. */ - work -= 1; - } - - for (i = 11; i && (__spm[i] > work); --i) - ; - r->tm_mon = i; - r->tm_mday += work - __spm[i]; - return r; -} -#endif /* end of __CC_ARM or __CLANG_ARM or __IAR_SYSTEMS_ICC__ */ - diff --git a/components/libc/compilers/dlib/sys/time.h b/components/libc/compilers/common/sys/time.h index baf566936b..1d68eeafa3 100644 --- a/components/libc/compilers/dlib/sys/time.h +++ b/components/libc/compilers/common/sys/time.h @@ -10,7 +10,6 @@ #define _SYS_TIME_H_ #include <time.h> -#include <sys/types.h> #ifdef __cplusplus extern "C" { diff --git a/components/libc/compilers/common/time.c b/components/libc/compilers/common/time.c new file mode 100644 index 0000000000..50a800b259 --- /dev/null +++ b/components/libc/compilers/common/time.c @@ -0,0 +1,291 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-08-21 zhangjun copy from minilibc + */ + +#include <sys/time.h> +#include <rtthread.h> + +#if !defined (__IAR_SYSTEMS_ICC__) + +/* days per month -- nonleap! */ +const short __spm[13] = +{ + 0, + (31), + (31 + 28), + (31 + 28 + 31), + (31 + 28 + 31 + 30), + (31 + 28 + 31 + 30 + 31), + (31 + 28 + 31 + 30 + 31 + 30), + (31 + 28 + 31 + 30 + 31 + 30 + 31), + (31 + 28 + 31 + 30 + 31 + 30 + 31 + 31), + (31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30), + (31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31), + (31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30), + (31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + 31), +}; +static const char days[] = "Sun Mon Tue Wed Thu Fri Sat "; +static const char months[] = "Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec "; + +/* seconds per day */ +#define SPD 24*60*60 + +int __isleap(int year) +{ + /* every fourth year is a leap year except for century years that are + * not divisible by 400. */ + /* return (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)); */ + return (!(year % 4) && ((year % 100) || !(year % 400))); +} + +struct tm *gmtime_r(const time_t *timep, struct tm *r) +{ + time_t i; + register time_t work = *timep % (SPD); + r->tm_sec = work % 60; + work /= 60; + r->tm_min = work % 60; + r->tm_hour = work / 60; + work = *timep / (SPD); + r->tm_wday = (4 + work) % 7; + for (i = 1970;; ++i) + { + register time_t k = __isleap(i) ? 366 : 365; + if (work >= k) + work -= k; + else + break; + } + r->tm_year = i - 1900; + r->tm_yday = work; + + r->tm_mday = 1; + if (__isleap(i) && (work > 58)) + { + if (work == 59) + r->tm_mday = 2; /* 29.2. */ + work -= 1; + } + + for (i = 11; i && (__spm[i] > work); --i) + ; + r->tm_mon = i; + r->tm_mday += work - __spm[i]; + return r; +} + +struct tm* gmtime(const time_t* t) +{ + static struct tm tmp; + return gmtime_r(t, &tmp); +} + +/*TODO timezone is not supprt now */ +struct tm* localtime_r(const time_t* t, struct tm* r) +{ + return gmtime_r(t, r); +} + +struct tm* localtime(const time_t* t) +{ + static struct tm tmp; + return localtime_r(t, &tmp); +} + +time_t mktime(struct tm * const t) +{ + register time_t day; + register time_t i; + register time_t years = t->tm_year - 70; + + if (t->tm_sec > 60) + { + t->tm_min += t->tm_sec / 60; + t->tm_sec %= 60; + } + if (t->tm_min > 60) + { + t->tm_hour += t->tm_min / 60; + t->tm_min %= 60; + } + if (t->tm_hour > 24) + { + t->tm_mday += t->tm_hour / 24; + t->tm_hour %= 24; + } + if (t->tm_mon > 12) + { + t->tm_year += t->tm_mon / 12; + t->tm_mon %= 12; + } + while (t->tm_mday > __spm[1 + t->tm_mon]) + { + if (t->tm_mon == 1 && __isleap(t->tm_year + 1900)) + { + --t->tm_mday; + } + t->tm_mday -= __spm[t->tm_mon]; + ++t->tm_mon; + if (t->tm_mon > 11) + { + t->tm_mon = 0; + ++t->tm_year; + } + } + + if (t->tm_year < 70) + return (time_t) - 1; + + /* Days since 1970 is 365 * number of years + number of leap years since 1970 */ + day = years * 365 + (years + 1) / 4; + + /* After 2100 we have to substract 3 leap years for every 400 years + This is not intuitive. Most mktime implementations do not support + dates after 2059, anyway, so we might leave this out for it's + bloat. */ + if (years >= 131) + { + years -= 131; + years /= 100; + day -= (years >> 2) * 3 + 1; + if ((years &= 3) == 3) + years--; + day -= years; + } + + day += t->tm_yday = __spm[t->tm_mon] + t->tm_mday - 1 + + (__isleap(t->tm_year + 1900) & (t->tm_mon > 1)); + + /* day is now the number of days since 'Jan 1 1970' */ + i = 7; + t->tm_wday = (day + 4) % i; /* Sunday=0, Monday=1, ..., Saturday=6 */ + + i = 24; + day *= i; + i = 60; + return ((day + t->tm_hour) * i + t->tm_min) * i + t->tm_sec; +} + +static void num2str(char *c, int i) +{ + c[0] = i / 10 + '0'; + c[1] = i % 10 + '0'; +} + +char* asctime_r(const struct tm *t, char *buf) +{ + /* "Wed Jun 30 21:49:08 1993\n" */ + *(int*) buf = *(int*) (days + (t->tm_wday << 2)); + *(int*) (buf + 4) = *(int*) (months + (t->tm_mon << 2)); + num2str(buf + 8, t->tm_mday); + if (buf[8] == '0') + buf[8] = ' '; + buf[10] = ' '; + num2str(buf + 11, t->tm_hour); + buf[13] = ':'; + num2str(buf + 14, t->tm_min); + buf[16] = ':'; + num2str(buf + 17, t->tm_sec); + buf[19] = ' '; + num2str(buf + 20, (t->tm_year + 1900) / 100); + num2str(buf + 22, (t->tm_year + 1900) % 100); + buf[24] = '\n'; + return buf; +} + +char* asctime(const struct tm *timeptr) +{ + static char buf[25]; + return asctime_r(timeptr, buf); +} + +char* ctime(const time_t *timep) +{ + return asctime(localtime(timep)); +} + +#endif /* __IAR_SYSTEMS_ICC__ */ + +int gettimeofday(struct timeval *tp, void *ignore) +{ + time_t time = 0; +#ifdef RT_USING_DEVICE + rt_device_t device; + device = rt_device_find("rtc"); + RT_ASSERT(device != RT_NULL); + rt_device_control(device, RT_DEVICE_CTRL_RTC_GET_TIME, &time); + if (tp != RT_NULL) + { + tp->tv_sec = time; + tp->tv_usec = 0; + } +#else + tv->tv_sec = 0; + tv->tv_usec = 0; +#endif + + return time; +} + + +/** + * Returns the current time. + * + * @param time_t * t the timestamp pointer, if not used, keep NULL. + * + * @return time_t return timestamp current. + * + */ +/* for IAR 6.2 later Compiler */ +#if defined (__IAR_SYSTEMS_ICC__) && (__VER__) >= 6020000 +#pragma module_name = "?time" +#if _DLIB_TIME_USES_64 +time_t __time64(time_t *t) +#else +time_t __time32(time_t *t) +#endif +#else +time_t time(time_t *t) +#endif +{ + time_t time_now = 0; + +#ifdef RT_USING_RTC + static rt_device_t device = RT_NULL; + + /* optimization: find rtc device only first. */ + if (device == RT_NULL) + { + device = rt_device_find("rtc"); + } + + /* read timestamp from RTC device. */ + if (device != RT_NULL) + { + if (rt_device_open(device, 0) == RT_EOK) + { + rt_device_control(device, RT_DEVICE_CTRL_RTC_GET_TIME, &time_now); + rt_device_close(device); + } + } +#endif /* RT_USING_RTC */ + + /* if t is not NULL, write timestamp to *t */ + if (t != RT_NULL) + { + *t = time_now; + } + + return time_now; +} + +RT_WEAK clock_t clock(void) +{ + return rt_tick_get(); +} diff --git a/components/libc/compilers/dlib/libc.h b/components/libc/compilers/dlib/libc.h index 7b2665c32b..5b46bee0c8 100644 --- a/components/libc/compilers/dlib/libc.h +++ b/components/libc/compilers/dlib/libc.h @@ -13,11 +13,17 @@ #include <stddef.h> +#ifdef __cplusplus +extern "C" { +#endif int libc_system_init(void); int libc_stdio_set_console(const char* device_name, int mode); int libc_stdio_get_console(void); -int libc_stdio_read (void *buffer, size_t size); -int libc_stdio_write(const void *buffer, size_t size); +int libc_stdio_read(void* buffer, size_t size); +int libc_stdio_write(const void* buffer, size_t size); +#ifdef __cplusplus +} +#endif #endif diff --git a/components/libc/compilers/dlib/sys/errno.h b/components/libc/compilers/dlib/sys/errno.h new file mode 100644 index 0000000000..1ad4c8acc0 --- /dev/null +++ b/components/libc/compilers/dlib/sys/errno.h @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-07-08 Bernard The first version + */ + +#ifndef SYS_ERRNO_H__ +#define SYS_ERRNO_H__ + +#include <errno.h> + +#endif diff --git a/components/libc/compilers/dlib/sys/signal.h b/components/libc/compilers/dlib/sys/signal.h new file mode 100644 index 0000000000..22adb1228b --- /dev/null +++ b/components/libc/compilers/dlib/sys/signal.h @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-07-08 Bernard The first version + */ + +#ifndef SYS_SIGNAL_H__ +#define SYS_SIGNAL_H__ + +#include <libc/libc_signal.h> + +#endif diff --git a/components/libc/compilers/dlib/sys/types.h b/components/libc/compilers/dlib/sys/types.h index 4c76dfc429..001ace4dd2 100644 --- a/components/libc/compilers/dlib/sys/types.h +++ b/components/libc/compilers/dlib/sys/types.h @@ -15,6 +15,10 @@ typedef rt_int32_t clockid_t; typedef rt_int32_t key_t; /* Used for interprocess communication. */ typedef rt_int32_t pid_t; /* Used for process IDs and process group IDs. */ -typedef signed long ssize_t; /* Used for a count of bytes or an error indication. */ +#ifndef ARCH_CPU_64BIT +typedef signed int ssize_t; /* Used for a count of bytes or an error indication. */ +#else +typedef long signed int ssize_t; /* Used for a count of bytes or an error indication. */ +#endif #endif diff --git a/components/libc/compilers/dlib/sys/unistd.h b/components/libc/compilers/dlib/sys/unistd.h index 5985a42996..29f68f24f8 100644 --- a/components/libc/compilers/dlib/sys/unistd.h +++ b/components/libc/compilers/dlib/sys/unistd.h @@ -34,14 +34,6 @@ #define _FNDELAY _FNONBLOCK /* non blocking I/O (4.2 style) */ #define _FNOCTTY 0x8000 /* don't assign a ctty on this open */ -#define O_RDONLY 0 /* +1 == FREAD */ -#define O_WRONLY 1 /* +1 == FWRITE */ -#define O_RDWR 2 /* +1 == FREAD|FWRITE */ -#define O_APPEND _FAPPEND -#define O_CREAT _FCREAT -#define O_TRUNC _FTRUNC -#define O_EXCL _FEXCL -#define O_SYNC _FSYNC #endif #endif /* _SYS_UNISTD_H */ diff --git a/components/libc/compilers/dlib/time.c b/components/libc/compilers/dlib/time.c deleted file mode 100644 index df35313b0e..0000000000 --- a/components/libc/compilers/dlib/time.c +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (c) 2006-2018, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - */ -#include <sys/time.h> -#include <rtthread.h> - -#ifdef RT_USING_DEVICE -int gettimeofday(struct timeval *tp, void *ignore) -{ - time_t time; - rt_device_t device; - - device = rt_device_find("rtc"); - RT_ASSERT(device != RT_NULL); - - rt_device_control(device, RT_DEVICE_CTRL_RTC_GET_TIME, &time); - if (tp != RT_NULL) - { - tp->tv_sec = time; - tp->tv_usec = 0; - } - - return time; -} -#endif - -/** - * Returns the current time. - * - * @param time_t * t the timestamp pointer, if not used, keep NULL. - * - * @return time_t return timestamp current. - * - */ -#pragma module_name = "?time" -#if _DLIB_TIME_USES_64 -time_t __time64(time_t *t) -#else -/* for IAR 6.2 later Compiler */ -#if defined (__IAR_SYSTEMS_ICC__) && (__VER__) >= 6020000 -time_t __time32(time_t *t) -#else -time_t time(time_t *t) -#endif -#endif -{ - time_t time_now = 0; - -#ifdef RT_USING_RTC - static rt_device_t device = RT_NULL; - - /* optimization: find rtc device only first. */ - if (device == RT_NULL) - { - device = rt_device_find("rtc"); - } - - /* read timestamp from RTC device. */ - if (device != RT_NULL) - { - if (rt_device_open(device, 0) == RT_EOK) - { - rt_device_control(device, RT_DEVICE_CTRL_RTC_GET_TIME, &time_now); - rt_device_close(device); - } - } -#endif /* RT_USING_RTC */ - - /* if t is not NULL, write timestamp to *t */ - if (t != RT_NULL) - { - *t = time_now; - } - - return time_now; -} - -RT_WEAK clock_t clock(void) -{ - return rt_tick_get(); -} diff --git a/components/libc/compilers/minilibc/math.h b/components/libc/compilers/minilibc/math.h index 9ddb9c859b..49b80d8219 100644 --- a/components/libc/compilers/minilibc/math.h +++ b/components/libc/compilers/minilibc/math.h @@ -14,4 +14,7 @@ double sin(double x); double cos(double x); +typedef float float_t; +typedef double double_t; + #endif diff --git a/components/libc/compilers/minilibc/sys/types.h b/components/libc/compilers/minilibc/sys/types.h index 460baab623..d3abc6bb38 100644 --- a/components/libc/compilers/minilibc/sys/types.h +++ b/components/libc/compilers/minilibc/sys/types.h @@ -11,8 +11,14 @@ #include <rtconfig.h> typedef long off_t; -typedef unsigned long size_t; -typedef signed long ssize_t; /* Used for a count of bytes or an error indication. */ + +#ifndef ARCH_CPU_64BIT +typedef unsigned int size_t; +typedef signed int ssize_t; /* Used for a count of bytes or an error indication. */ +#else +typedef long unsigned int size_t; +typedef long signed int ssize_t; /* Used for a count of bytes or an error indication. */ +#endif typedef unsigned char u_char; typedef unsigned short u_short; diff --git a/components/libc/compilers/newlib/libc.h b/components/libc/compilers/newlib/libc.h index ab9334fe26..fdf2ab4f60 100644 --- a/components/libc/compilers/newlib/libc.h +++ b/components/libc/compilers/newlib/libc.h @@ -27,13 +27,19 @@ #define MICROSECOND_PER_TICK (MICROSECOND_PER_SECOND / RT_TICK_PER_SECOND) #define NANOSECOND_PER_TICK (NANOSECOND_PER_SECOND / RT_TICK_PER_SECOND) +#ifdef __cplusplus +extern "C" { +#endif int libc_system_init(void); int libc_stdio_set_console(const char* device_name, int mode); int libc_stdio_get_console(void); /* some time related function */ -int libc_set_time(const struct timespec *time); -int libc_get_time(struct timespec *time); -int libc_time_to_tick(const struct timespec *time); +int libc_set_time(const struct timespec* time); +int libc_get_time(struct timespec* time); +int libc_time_to_tick(const struct timespec* time); +#ifdef __cplusplus +} +#endif #endif diff --git a/components/libc/compilers/newlib/syscalls.c b/components/libc/compilers/newlib/syscalls.c index 9919e11727..59c1881ad1 100644 --- a/components/libc/compilers/newlib/syscalls.c +++ b/components/libc/compilers/newlib/syscalls.c @@ -442,3 +442,18 @@ void abort(void) while (1); } + +uid_t getuid(void) +{ + return 0; +} + +mode_t umask(mode_t mask) +{ + return 022; +} + +int flock(int fd, int operation) +{ + return 0; +} diff --git a/components/libc/pthreads/pthread.c b/components/libc/pthreads/pthread.c index 7ecf304038..5d3bc0796a 100644 --- a/components/libc/pthreads/pthread.c +++ b/components/libc/pthreads/pthread.c @@ -102,7 +102,7 @@ void _pthread_data_destroy(pthread_t pth) rt_sem_delete(ptd->joinable_sem); /* release thread resource */ - if (ptd->attr.stackaddr == RT_NULL) + if (ptd->attr.stackaddr == RT_NULL && ptd->tid->stack_addr != RT_NULL) { /* release thread allocated stack */ rt_free(ptd->tid->stack_addr); @@ -219,20 +219,6 @@ int pthread_create(pthread_t *pid, } rt_snprintf(name, sizeof(name), "pth%02d", pthread_number ++); - if (ptd->attr.stackaddr == 0) - { - stack = (void *)rt_malloc(ptd->attr.stacksize); - } - else - { - stack = (void *)(ptd->attr.stackaddr); - } - - if (stack == RT_NULL) - { - ret = ENOMEM; - goto __exit; - } /* pthread is a static thread object */ ptd->tid = (rt_thread_t) rt_malloc(sizeof(struct rt_thread)); @@ -241,6 +227,7 @@ int pthread_create(pthread_t *pid, ret = ENOMEM; goto __exit; } + memset(ptd->tid, 0, sizeof(struct rt_thread)); if (ptd->attr.detachstate == PTHREAD_CREATE_JOINABLE) { @@ -260,6 +247,22 @@ int pthread_create(pthread_t *pid, ptd->thread_entry = start; ptd->thread_parameter = parameter; + /* stack */ + if (ptd->attr.stackaddr == 0) + { + stack = (void *)rt_malloc(ptd->attr.stacksize); + } + else + { + stack = (void *)(ptd->attr.stackaddr); + } + + if (stack == RT_NULL) + { + ret = ENOMEM; + goto __exit; + } + /* initial this pthread to system */ if (rt_thread_init(ptd->tid, name, pthread_entry_stub, ptd, stack, ptd->attr.stacksize, diff --git a/components/net/Kconfig b/components/net/Kconfig index 68737176ed..4436934f09 100644 --- a/components/net/Kconfig +++ b/components/net/Kconfig @@ -1,18 +1,17 @@ menu "Network" menu "Socket abstraction layer" - + config RT_USING_SAL bool "Enable socket abstraction layer" select RT_USING_NETDEV - select RT_USING_LIBC select RT_USING_SYSTEM_WORKQUEUE default n if RT_USING_SAL if RT_USING_LWIP || AT_USING_SOCKET - + menu "protocol stack implement" config SAL_USING_LWIP @@ -24,29 +23,30 @@ config RT_USING_SAL bool "Support AT Commands stack" default y depends on AT_USING_SOCKET - + config SAL_USING_TLS bool "Support MbedTLS protocol" default y depends on PKG_USING_MBEDTLS endmenu - + endif config SAL_USING_POSIX bool "Enable BSD socket operated by file system API" default n select RT_USING_DFS + select RT_USING_LIBC select RT_USING_POSIX help Let BSD socket operated by file system API, such as read/write and involveed in select/poll POSIX APIs. - + if !SAL_USING_POSIX - + config SAL_SOCKETS_NUM int "the maximum number of sockets" default 16 - + endif endif @@ -68,7 +68,7 @@ config RT_USING_NETDEV config NETDEV_USING_PING bool "Enable ping features" default y - + config NETDEV_USING_NETSTAT bool "Enable netstat features" default y @@ -76,6 +76,25 @@ config RT_USING_NETDEV config NETDEV_USING_AUTO_DEFAULT bool "Enable default netdev automatic change features" default y + + config NETDEV_USING_IPV6 + bool "Enable IPV6 protocol support" + default n + + config NETDEV_IPV4 + int + default 1 + + config NETDEV_IPV6 + int + default 1 if NETDEV_USING_IPV6 + default 0 if !NETDEV_USING_IPV6 + + config NETDEV_IPV6_SCOPES + bool + help + Defined to synchronize the ip6_addr structure state + default n endif endmenu @@ -104,11 +123,11 @@ config RT_USING_LWIP endchoice if (RT_USING_LWIP210 || RT_USING_LWIP202) - if (!RT_USING_NETDEV || (RT_USING_NETDEV && NETDEV_IPV6)) - config RT_USING_LWIP_IPV6 - bool "IPV6 protocol" - default n - endif + config RT_USING_LWIP_IPV6 + bool "IPV6 protocol" + default n + select NETDEV_USING_IPV6 + select NETDEV_IPV6_SCOPES if RT_USING_LWIP210 endif config RT_LWIP_IGMP @@ -258,7 +277,7 @@ config RT_USING_LWIP config LWIP_NETIF_STATUS_CALLBACK int "Enable netif status callback" default 1 - + config LWIP_NETIF_LINK_CALLBACK int "Enable netif link status callback" default 1 @@ -295,7 +314,7 @@ config RT_USING_LWIP config RT_LWIP_USING_HW_CHECKSUM bool "Enable hardware checksum" default n - + config RT_LWIP_USING_PING bool "Enable ping features" default y @@ -427,8 +446,6 @@ config RT_USING_LWIP endmenu -source "$RTT_DIR/components/net/freemodbus/Kconfig" - source "$RTT_DIR/components/net/at/Kconfig" if RT_USING_LWIP diff --git a/components/net/at/Kconfig b/components/net/at/Kconfig index 5a4a644761..50de005545 100644 --- a/components/net/at/Kconfig +++ b/components/net/at/Kconfig @@ -9,11 +9,11 @@ if RT_USING_AT config AT_DEBUG bool "Enable debug log output" default n - + config AT_USING_SERVER bool "Enable AT commands server" default n - + if AT_USING_SERVER config AT_SERVER_DEVICE @@ -44,33 +44,32 @@ if RT_USING_AT endchoice endif - + config AT_USING_CLIENT bool "Enable AT commands client" default n - + if AT_USING_CLIENT config AT_CLIENT_NUM_MAX int "The maximum number of supported clients" default 1 range 1 65535 - + config AT_USING_SOCKET bool "Enable BSD Socket API support by AT commnads" - select RT_USING_LIBC select RT_USING_SAL default n - + endif if AT_USING_SERVER || AT_USING_CLIENT - + config AT_USING_CLI bool "Enable CLI(Command-Line Interface) for AT commands" default y depends on FINSH_USING_MSH - + config AT_PRINT_RAW_CMD bool "Enable print RAW format AT command communication data" default n @@ -78,7 +77,7 @@ if RT_USING_AT config AT_CMD_MAX_LEN int "The maximum lenght of AT Commonds buffer" default 128 - + endif config AT_SW_VERSION_NUM diff --git a/components/net/at/at_socket/at_socket.c b/components/net/at/at_socket/at_socket.c index 993ec33506..11be4e23c0 100644 --- a/components/net/at/at_socket/at_socket.c +++ b/components/net/at/at_socket/at_socket.c @@ -54,7 +54,6 @@ static rt_slist_t _socket_list = RT_SLIST_OBJECT_INIT(_socket_list); struct at_socket *at_get_socket(int socket) { rt_base_t level; - size_t list_num = 0; rt_slist_t *node = RT_NULL; struct at_socket *at_sock = RT_NULL; @@ -62,9 +61,9 @@ struct at_socket *at_get_socket(int socket) rt_slist_for_each(node, &_socket_list) { - if (socket == (list_num++)) + at_sock = rt_slist_entry(node, struct at_socket, list); + if (socket == at_sock->socket) { - at_sock = rt_slist_entry(node, struct at_socket, list); if (at_sock && at_sock->magic == AT_SOCKET_MAGIC) { rt_hw_interrupt_enable(level); @@ -275,6 +274,34 @@ static void at_do_event_clean(struct at_socket *sock, at_event_t event) } } +static int alloc_empty_socket(rt_slist_t *l) +{ + rt_base_t level; + rt_slist_t *node = RT_NULL; + rt_slist_t *pre_node = &_socket_list; + struct at_socket *at_sock = RT_NULL; + int idx = 0; + + level = rt_hw_interrupt_disable(); + + rt_slist_init(l); + + rt_slist_for_each(node, &_socket_list) + { + at_sock = rt_slist_entry(node, struct at_socket, list); + if(at_sock->socket != idx) + break; + idx++; + pre_node = node; + } + + rt_slist_insert(pre_node, l); + + rt_hw_interrupt_enable(level); + + return idx; +} + static struct at_socket *alloc_socket_by_device(struct at_device *device) { static rt_mutex_t at_slock = RT_NULL; @@ -304,21 +331,9 @@ static struct at_socket *alloc_socket_by_device(struct at_device *device) goto __err; } - /* add device socket to global socket list */ - { - rt_base_t level; - - level = rt_hw_interrupt_disable(); - - rt_slist_init(&(device->sockets[idx].list)); - rt_slist_append(&_socket_list, &(device->sockets[idx].list)); - - rt_hw_interrupt_enable(level); - } - sock = &(device->sockets[idx]); /* the socket descriptor is the number of sockte lists */ - sock->socket = rt_slist_len(&_socket_list) - 1; + sock->socket = alloc_empty_socket(&(sock->list)); /* the socket operations is the specify operations of the device */ sock->ops = device->class->socket_ops; /* the user-data is the at device socket descriptor */ @@ -446,7 +461,6 @@ static int free_socket(struct at_socket *sock) /* delect socket from socket list */ { rt_base_t level; - int list_num = 0; rt_slist_t *node = RT_NULL; struct at_socket *at_sock = RT_NULL; @@ -454,10 +468,10 @@ static int free_socket(struct at_socket *sock) rt_slist_for_each(node, &_socket_list) { - if (sock->socket == (list_num++)) + at_sock = rt_slist_entry(node, struct at_socket, list); + if (sock->socket == at_sock->socket) { - at_sock = rt_slist_entry(node, struct at_socket, list); - if (at_sock) + if (at_sock && at_sock->magic == AT_SOCKET_MAGIC) { rt_slist_remove(&_socket_list, &at_sock->list); break; @@ -540,11 +554,12 @@ static int socketaddr_to_ipaddr_port(const struct sockaddr *sockaddr, ip_addr_t const struct sockaddr_in* sin = (const struct sockaddr_in*) (const void *) sockaddr; #if NETDEV_IPV4 && NETDEV_IPV6 - (*addr).u_addr.ip4.addr = sin->sin_addr.s_addr; + addr->u_addr.ip4.addr = sin->sin_addr.s_addr; + addr->type = IPADDR_TYPE_V4; #elif NETDEV_IPV4 - (*addr).addr = sin->sin_addr.s_addr; + addr->addr = sin->sin_addr.s_addr; #elif NETDEV_IPV6 - LOG_E("not support IPV6."); +#error "not support IPV6." #endif /* NETDEV_IPV4 && NETDEV_IPV6 */ *port = (uint16_t) HTONS_PORT(sin->sin_port); @@ -855,7 +870,7 @@ int at_recv(int s, void *mem, size_t len, int flags) int at_sendto(int socket, const void *data, size_t size, int flags, const struct sockaddr *to, socklen_t tolen) { struct at_socket *sock = RT_NULL; - int len, result = 0; + int len = 0, result = 0; if (data == RT_NULL || size == 0) { @@ -1126,10 +1141,11 @@ struct hostent *at_gethostbyname(const char *name) #if NETDEV_IPV4 && NETDEV_IPV6 addr.u_addr.ip4.addr = ipstr_to_u32(ipstr); + addr.type = IPADDR_TYPE_V4; #elif NETDEV_IPV4 addr.addr = ipstr_to_u32(ipstr); #elif NETDEV_IPV6 - LOG_E("not support IPV6."); +#error "not support IPV6." #endif /* NETDEV_IPV4 && NETDEV_IPV6 */ /* fill hostent structure */ @@ -1202,7 +1218,7 @@ int at_getaddrinfo(const char *nodename, const char *servname, if ((hints != RT_NULL) && (hints->ai_flags & AI_NUMERICHOST)) { /* no DNS lookup, just parse for an address string */ - if (!inet_aton(nodename, (ip4_addr_t * )&addr)) + if (!inet_aton(nodename, &addr)) { return EAI_NONAME; } @@ -1240,7 +1256,7 @@ int at_getaddrinfo(const char *nodename, const char *servname, #elif NETDEV_IPV4 addr.addr = ipstr_to_u32(ip_str); #elif NETDEV_IPV6 - LOG_E("not support IPV6."); + #error "not support IPV6." #endif /* NETDEV_IPV4 && NETDEV_IPV6 */ } } @@ -1275,10 +1291,11 @@ int at_getaddrinfo(const char *nodename, const char *servname, /* set up sockaddr */ #if NETDEV_IPV4 && NETDEV_IPV6 sa4->sin_addr.s_addr = addr.u_addr.ip4.addr; + sa4->type = IPADDR_TYPE_V4; #elif NETDEV_IPV4 sa4->sin_addr.s_addr = addr.addr; #elif NETDEV_IPV6 - LOG_E("not support IPV6."); +#error "not support IPV6." #endif /* NETDEV_IPV4 && NETDEV_IPV6 */ sa4->sin_family = AF_INET; sa4->sin_len = sizeof(struct sockaddr_in); diff --git a/components/net/at/include/at.h b/components/net/at/include/at.h index dc2abef353..a7a6aeca7a 100644 --- a/components/net/at/include/at.h +++ b/components/net/at/include/at.h @@ -96,7 +96,7 @@ struct at_server rt_device_t device; at_status_t status; - char (*get_char)(void); + rt_err_t (*get_char)(struct at_server *server, char *ch, rt_int32_t timeout); rt_bool_t echo_mode; char recv_buffer[AT_SERVER_RECV_BUFF_LEN]; @@ -194,6 +194,8 @@ int at_server_init(void); void at_server_printf(const char *format, ...); void at_server_printfln(const char *format, ...); void at_server_print_result(at_result_t result); +rt_size_t at_server_send(at_server_t server, const char *buf, rt_size_t size); +rt_size_t at_server_recv(at_server_t server, char *buf, rt_size_t size, rt_int32_t timeout); /* AT server request arguments parse */ int at_req_parse_args(const char *req_args, const char *req_expr, ...); diff --git a/components/net/at/src/at_cli.c b/components/net/at/src/at_cli.c index 80af613fa6..e39a913357 100644 --- a/components/net/at/src/at_cli.c +++ b/components/net/at/src/at_cli.c @@ -100,6 +100,12 @@ void at_cli_deinit(void) } #ifdef AT_USING_SERVER +static rt_err_t at_server_console_getchar(struct at_server *server, char *ch, rt_int32_t timeout) +{ + *ch = console_getchar(); + return RT_EOK; +} + static void server_cli_parser(void) { extern at_server_t at_get_server(void); @@ -107,7 +113,7 @@ static void server_cli_parser(void) at_server_t server = at_get_server(); rt_base_t int_lvl; static rt_device_t device_bak; - static char (*getchar_bak)(void); + static rt_err_t (*getchar_bak)(struct at_server *server, char *ch, rt_int32_t timeout); static char endmark_back[AT_END_MARK_LEN]; /* backup server device and getchar function */ @@ -122,7 +128,7 @@ static void server_cli_parser(void) /* setup server device as console device */ server->device = rt_console_get_device(); - server->get_char = console_getchar; + server->get_char = at_server_console_getchar; memset(server->end_mark, 0x00, AT_END_MARK_LEN); server->end_mark[0] = '\r'; diff --git a/components/net/at/src/at_server.c b/components/net/at/src/at_server.c index 31f1bec96f..81d00951f5 100644 --- a/components/net/at/src/at_server.c +++ b/components/net/at/src/at_server.c @@ -167,6 +167,79 @@ void rt_at_server_print_all_cmd(void) } } +/** + * Send data to AT Client by uart device. + * + * @param server current AT server object + * @param buf send data buffer + * @param size send fixed data size + * + * @return >0: send data size + * =0: send failed + */ +rt_size_t at_server_send(at_server_t server, const char *buf, rt_size_t size) +{ + RT_ASSERT(buf); + + if (server == RT_NULL) + { + LOG_E("input AT Server object is NULL, please create or get AT Server object!"); + return 0; + } + + return rt_device_write(server->device, 0, buf, size); +} + +/** + * AT Server receive fixed-length data. + * + * @param client current AT Server object + * @param buf receive data buffer + * @param size receive fixed data size + * @param timeout receive data timeout (ms) + * + * @note this function can only be used in execution function of AT commands + * + * @return >0: receive data size + * =0: receive failed + */ +rt_size_t at_server_recv(at_server_t server, char *buf, rt_size_t size, rt_int32_t timeout) +{ + rt_size_t read_idx = 0; + rt_err_t result = RT_EOK; + char ch = 0; + + RT_ASSERT(buf); + + if (server == RT_NULL) + { + LOG_E("input AT Server object is NULL, please create or get AT Server object!"); + return 0; + } + + while (1) + { + if (read_idx < size) + { + /* check get data value */ + result = server->get_char(server, &ch, timeout); + if (result != RT_EOK) + { + LOG_E("AT Server receive failed, uart device get data error."); + return 0; + } + + buf[read_idx++] = ch; + } + else + { + break; + } + } + + return read_idx; +} + at_server_t at_get_server(void) { RT_ASSERT(at_server_local); @@ -339,17 +412,21 @@ static rt_err_t at_cmd_get_name(const char *cmd_buffer, char *cmd_name) return -RT_ERROR; } -static char at_server_gerchar(void) +static rt_err_t at_server_gerchar(at_server_t server, char *ch, rt_int32_t timeout) { - char ch; + rt_err_t result = RT_EOK; - while (rt_device_read(at_server_local->device, 0, &ch, 1) == 0) + while (rt_device_read(at_server_local->device, 0, ch, 1) == 0) { rt_sem_control(at_server_local->rx_notice, RT_IPC_CMD_RESET, RT_NULL); - rt_sem_take(at_server_local->rx_notice, RT_WAITING_FOREVER); + result = rt_sem_take(at_server_local->rx_notice, rt_tick_from_millisecond(timeout)); + if (result != RT_EOK) + { + return result; + } } - return ch; + return result; } static void server_parser(at_server_t server) @@ -365,14 +442,24 @@ static void server_parser(at_server_t server) RT_ASSERT(server); RT_ASSERT(server->status != AT_STATUS_UNINITIALIZED); - while (ESC_KEY != (ch = server->get_char())) + while (1) { + server->get_char(server, &ch, RT_WAITING_FOREVER); + if (ESC_KEY == ch) + { + break; + } + if (server->echo_mode) { if (ch == AT_CMD_CR || (ch == AT_CMD_LF && last_ch != AT_CMD_CR)) { at_server_printf("%c%c", AT_CMD_CR, AT_CMD_LF); } + else if (ch == AT_CMD_LF) + { + // skip the end sign check + } else if (ch == BACKSPACE_KEY || ch == DELECT_KEY) { if (server->cur_recv_len) diff --git a/components/net/freemodbus/Changelog.txt b/components/net/freemodbus/Changelog.txt deleted file mode 100644 index 2816ea30f3..0000000000 --- a/components/net/freemodbus/Changelog.txt +++ /dev/null @@ -1,329 +0,0 @@ -2013-10-17 (REL_1_6_0) Armink <[email protected]> - Notes: Added modbus master. - -2010-05-06 (REL_1_5_0) Christian Walter <[email protected]> - Notes: Added support for Atmel AT91SAM3S (Cortex M3) for IAR. - - Detailed notes: - - FEATURES (ATSAM3S) : Added new port. - -2007-08-28 (REL_1_4_0) Christian Walter <[email protected]>: - Notes: Added support for HCS08. Fixed some small bugs in the documentation - for the porting layer. - - Detailed notes: - - FEATURES (HCS08) : Added new port. - - BUGS (ALL) : Fixed some small bugs in the porting guide. - -2007-07-17 (REL_1_3_0) Christian Walter <[email protected]>: - Notes: Added ARM7/AT91SAM7X port. Added Linux/TCP port from Steven Guo. - - Detailed notes: - - FEATURES (ARM7): Added ARM7/AT91SAM7x port. - - FEATURES (LINUX): Added Linux/TCP port from Steven Guo. - - BUGS (ALL): Fixed bug in <eMBFuncReadInputRegister> where the high - byte of the register count was ignored. This does not have a - practical impact because the actual number of registers is always - lower. - -2007-07-17 (REL_1_3_0) Christian Walter <[email protected]>: - Notes: Added Linux/TCP port. Fixed bug in MSP430 port. - Detailted notes: - - FEATURE (LINUX): Added Linux/TCP port. - - BUGS (MSP430): Fixed bug with calculating the timer value. - -2007-04-25 (REL_1_2_0) Christian Walter <[email protected]>: - Notes: Added LPC214X ARM port with Keil compiler. Added Z8Encore port for - Z8F6422 microcontroller. - - Detailed notes: - - FEATURE (ARM): Added LPC214X ARM port for Keil ARM 2.41. - - FEATURE (Z8ENCORE): Added Z8F6422 for Z8Encore using the ZDS II - Z8 - Encore! development tools. - -2007-02-18 (REL_1_1_2) Christian Walter <[email protected]>: - Notes: Fixed typo with the defined defining the supported Modbus - functions. Fixed bug when illegal slave address was passed to eMBInit - where the error was not detected. Fixed typo in the holding registers - where the frame for write multiple registers was parsed with the wrong - constants. The fix is not critical because the values matched. Fixed bug - in discrete input registers implementation where the frame was not parsed - correctly. Added new support for a CodeWarrior Coldfire port. - - Detailed notes: - - BUG (ALL): Modbus functions are compiled into the stack conditionally - by changing the MB_FUNC_XXX defines to either true(1) or false(0). - The defines for MB_FUNC_READ_HOLDING and MB_FUNC_WRITE_HOLDING - were wrong. - - BUG (ALL): eMBInit did not correctly check for addresses. Therefore - is was possible to start the Modbus stack with an address of 0 - or one > 247. - - BUG (ALL): eMBFuncWriteHoldingRegister should use - MB_PDU_FUNC_WRITE_MUL_ADDR_OFF and not MB_PDU_FUNC_READ_ADDR_OFF. - - BUG (ALL): eMBFuncReadDiscreteInputs calculated the number of discrete - registers to read wrong. - - FEATURE (ALL): Fixed some warnings in the code. - -2006-11-19 (REL_1_1_1) Christian Walter <[email protected]>: - Notes: Fixed bug in Read/Write Multiple Registers function where - the registers addresses where calculated wrong. - Fixed bug in RTU and ASCII with the resource allocation in case of - an error. - Changed license to BSD style licsense. - - Detailed notes: - - OTHER (ALL): License is now BSD for protocol stack. - - BUG (ALL): The registers address received in a Modbus frame - must be converted to application addresses. The code for this - conversion was missing and therefore has lead to error when - this function was used (Registers of by one, Start at > 1). - - BUG (ALL): If the serial initialization within the porting fails - a timer is still allocated in eMBRTUInit and eMBASCIIInit. This - can lead to a memory leak depending upon the implementation of the - porting layer. - - FEATURE (MCF5235): Added sample shell scripts for testing. - - FEATURE (MSP430): Added sample shell script for testing and - changed default values to match the other ports. - -2006-10-30 (REL_1_1_0) Christian Walter <[email protected]>: - Notes: Added support for Read/Write Multiple Registers function - (0x17). Added some tips to reduce memory requirements. - Added MSP430 Port for GCC and Rowley Crossworks. - - Detailed notes: - - FEATURE (MSP430): Added new MSP430 port. - - FEATURE (ALL): Added support for Read/Write Multiple Registers - function (0x17). The implementation simply makes two callbacks - to the eMBRegHoldingCB function where first the values are - written and then the other register values are read. - - FEATURE (ALL): Added some tips on reducing memory requirements - with the protocol stack. - -2006-10-30 (REL_1_0_5) Christian Walter <[email protected]>: - Notes: eMBDisable and eMBClose can now be called multiple times - which makes shutdown of the protocol stack easier. - Fixed bug in RTU state machine where we switched from the - error state immediately to the idle state. Correct behaviour - would be to wait till the end of frame. - Added new STR71X GCC port which uses only freely available tools - like GNU ARM, OpenOCD (Wiggler) and GDB. - - Detailed notes: - - FEATURE (STR71X): Added GCC standalone port which does not - depend on the Rowley Crosswork tools. - - FEATURE (ALL): eMBDisable can now be called multiple times - and returns MB_ENOERR in case is was already disabled. - eMBClose also supports beeing called multiple times in - which pvMBFrameCloseCur( ) is called when the protocol stack - is in state STATE_DISABLED. - - BUG (RTU): Fixed bug in xMBRTUReceiveFSM where the error - state is immediately left because of a missing break. Instead - we should wait till the damaged frame is finished. - -2006-10-11 (REL_1_0_4) Christian Walter <[email protected]>: - Notes: Fixed bug when more than 255 coils are requested. Fixed bug in - Linux/Cygwin port when not all bytes could be written by the first - call to write. Added support for removing previously registered - function handlers. - - Detailed notes: - - BUG (ALL): mbfunccoils contained a bug which limited the amount - of coils to read to 255. - - BUG (LINUX): prvbMBPortSerialWrite contained a bug in the loop - which writes the RTU/ASCII frame to the serial file descriptor. - If not all bytes where written in the first call or write was - interrupted the sent frame is corrupted. - - FEATURE (ALL): eMBRegisterCB now supports NULL as handler - argument in which case a previously registered function - handler is deregistered from the protocol stack. - -2006-09-27 (REL_1_0_3) Christian Walter <[email protected]>: - Notes: Added new functions to support registering of custom callback - handlers. This makes it possible to implement new Modbus function - codes without touching the protocol stack. - New port for ATMega128 added. Thanks to Richard C Sandoz Jr. for - the patches. - - Detailed notes: - - FEATURE (ALL): Added support for registering new functions handlers - with eMBRegisterCB. - - FEATURE (AVR): Added patches from Richard C Sandoz Jr. for ATMega128 - -2006-09-06 (REL_1_0_2) Christian Walter <[email protected]>: - Notes: Fixed bug in FreeRTOS porting layer for STR71X/lwIP target where - memory is not freed in the sys_arch_thread_remove function. - Synched MCF5235TCP port with the FreeRTOS/lwIP port for the STR71X. - - Detailed notes: - - BUG (STR71XTCP): Sys_arch_thread_remove did not free the memory from - the TCB. - - BUG (STR71XTCP): Unnecessary call to vTaskSuspendAll removed. - - BUG (STR71XTCP): Bug with counting variable. The first to lwIP tasks - got the same name (lwIP0). - - FEATURE (MCF5235TCP): Enhanced functions from the STR71X/lwIP port - merged into the Coldfire port. - -2006-09-04 (REL_1_0_1) Christian Walter <[email protected]>: - Notes: Fixed bug in serial driver for STR71x target when the ring buffer - overflows. - - Detailed notes: - - BUG (STR71XTCP): Under high load the ring buffer in the serial driver - functions might overflow. There was an error with counting the number - of received characters which corrupted received frames. - Now receiver correctly recovers in case of dropped bytes. - -2006-09-04 (REL_1_0) Christian Walter <[email protected]>: - Notes: Added support for ATmega8, ATmega16, ATmega32, ATmega169 and - RS485 drivers in the AVR support. Special thanks to Tran Minh Hoang - for his contribution. - Added a new lwIP port for the STR71X target which uses one serial - interface for a PPP connection. This can be used for remote Modbus/TCP - devices in combination with a Modem (E.g. GPRS or Analog). - - Detailed notes: - - FEATURES (AVR): Integrated patches from Tran Minh Hoang to support the - ATmega8, ATmega16, ATmega32, ATmega169 controllers. - - FEATURES (AVR): Added support for RS485 drivers in the AVR code. The - example supports the DS76176. - - FEATURES (STR71XTCP): implemented function in STR71X/lwIP porting layer - to remove running tasks. - - FEATURES (STR71XTCP): added new thread creation function in STR71X/lwIP - porting layer which allows specifing the stack size. - - BUGS (STR71XTCP): pppOpen defined in ppp.c does not check the return - value of sys_thread_new. If task creation fails the system crashes. - - BUGS (STR71XTCP): pppMain must not return - Instead it should remove - its task from the scheduler. - -2006-08-30 (REL_9) Christian Walter <[email protected]>: - Notes: Added lwIP port for the MCF5235 target. The lwIP part is - generic and therefore FreeModbus now works on any target with - lwIP support. - - Detailed notes: - - FEATURES: Incoperated MCF5235 FreeRTOS/lwIP port done by the - author in this project. - - FEATURES: Added lwIP port for FreeModbus - - FEATURES: Added demo application for FreeModbus and lwIP. - -2006-08-22 (REL_0_82) Christian Walter <[email protected]> - Notes: Fixed bug with Modbus ASCII support - - Detailed notes: - - BUG: During the last upgrade an error was introduced in the - initialization code of Modbus ASCII and therefore ASCII - support was broken. The bug is fixed now and was tested with - the Win32 port. - -2006-08-22 (REL_0_81) Christian Walter <[email protected]> - Notes: Added porting guide - - Detailed notes: - - OTHER: Added a new porting guide to the documentation. - - OTHER: Added a empty example for new ports to the project as a - starting point. - -2006-08-01 (REL_0_8) Christian Walter <[email protected]> - Notes: Added Linux RTU/ASCII port. - - Detailed notes: - - FEATURES: Added a new Linux RTU/ASCII port. The port should work - on any Linux distribution and it should be possible to run it - on uCLinux. - -2006-06-26 (REL_0_7) Christian Walter <[email protected]> - Notes: Changed the WIN32 serial port to better fit into the design. - - Detailed notes: - - OTHER: Design of the WIN32 serial port changed. The polling function - for the serial device are now called from the event loop. - - OTHER: Debugging uses the same interface as the WIN32/TCP port. - -2006-06-25 Christian Walter <[email protected]> - - Notes: Initial work on a Modbus/TCP port is available. The port includes - an example for a Win32 port which uses the Winsock API. - - Detailed notes: - - FEATURES: added required functions to core protocol stack to support - a Modbus/TCP implementation. - - FEATURES: added a Win32 port for the Modbus/TCP core. The port is - currently limited to one concurrent client. - - OTHER: The implementation of eMBClose to shutdown the protocol stack - was changed to unify it with the new Modbus/TCP code. - - - -2006-06-18 Christian Walter <[email protected]> - - Detailed notes: - - OTHER: while working on the Win32 port some line feeds got - wrong. Also some source files used tabs instead of spaces. - - OTHER: prototypes for xMBUtilSetBits and xMBUtilGetBits fixed. - usNBits should be ucNBits by convention. - -2006-06-17 Christian Walter <[email protected]> - - Notes: Fixed various bugs with the Win32 port - - Detailed notes: - - FEATURES: implement shutdown functionality for protocol stack. - - FEATURES: protocol stack can be enabled and disabled during runtime. - - FEATURES: interface functions now do more error checking. For - example if eMBPool is called in an uninitialized state. - - FEATURES: extended Win32 demo application to use the new features. - - BUG: fixed bug in Win32 demo for ASCII mode. - -2006-06-16 Christian Walter <[email protected]> - Notes: The new version includes a new port for the - Win32 platform - - Detailed notes: - - FEATURES: added Win32 platform - -2006-05-14 Christian Walter <[email protected]> - Notes: The new version includes a new port for the - Freescale MCF5235 processor. - - Detailed notes: - - FEATURES: added new MCF5235 port. - - OTHER: fixed some missing code headers. - -2006-05-01 Christian Walter <[email protected]> - Notes: This version removes the t1.5 timers from the Modbus RTU - implementation because no one actually uses it and the CPU - load is very high. T - In addition some documentation cleanups has been done and the - ARM demo has been updated. - - Detailed notes: - - - FEATURES: the t1.5 timeout has been removed. Therefore only - one timer is required. - - BUG: the ARM demo project missed some files in the project - workspace and did not compile cleanly - -2006-02-28 Christian Walter <[email protected]> - Notes: This version includes support for two new command - (write multiple coils, read discrete input) - - Detailed notes: - - BUG: some function used the wrong data types - - FEATURES: added support for write multiple coils function. - - FEATURES: added support for read discrete input. - - OTHER: some code cleanups with lint tool. - -2006-02-28 Christian Walter <[email protected]> - - Notes: The new version 0.31 adds support for reading and writing the - coil registers and add some bug fixes. - - Detailed notes: - - BUG: fixed bug with to small modbus requests being ignored. - - FEATURES: added support for write single coil function. - - FEATURES: added support for working with byte packed bit fields - to support coils and discrete inputs better. - - API: API for set slave id functions changed. - -2006-02-26 Christian Walter <[email protected]> - - Notes: First public release which includes an ARM and AVR port. diff --git a/components/net/freemodbus/Kconfig b/components/net/freemodbus/Kconfig deleted file mode 100644 index 9a84efa0c5..0000000000 --- a/components/net/freemodbus/Kconfig +++ /dev/null @@ -1,27 +0,0 @@ -menu "Modbus master and slave stack" - -config RT_USING_MODBUS - bool "Enable Modbus stack" - default n - - if RT_USING_MODBUS - config RT_MODBUS_MASTER_RTU - bool "RTU master mode" - default n - - config RT_MODBUS_SLAVE_RTU - bool "RTU slave mode" - default n - if RT_MODBUS_SLAVE_RTU - config RT_MODBUS_SLAVE_USE_CONTROL_PIN - bool "Use Contorl Pin" - default n - if RT_MODBUS_SLAVE_USE_CONTROL_PIN - config MODBUS_SLAVE_RT_CONTROL_PIN_INDEX - int "pin index for RS485 TX/RX select" - default 10 - endif - endif - endif - -endmenu diff --git a/components/net/freemodbus/SConscript b/components/net/freemodbus/SConscript deleted file mode 100644 index d613a9f398..0000000000 --- a/components/net/freemodbus/SConscript +++ /dev/null @@ -1,77 +0,0 @@ -Import('RTT_ROOT') -from building import * - -src = Split(""" -modbus/functions/mbfuncdiag.c -modbus/functions/mbutils.c -modbus/functions/mbfuncother.c -modbus/rtu/mbcrc.c -port/port.c -""") - -master_rtu_src = Split(""" -modbus/functions/mbfunccoils_m.c -modbus/functions/mbfuncdisc_m.c -modbus/functions/mbfuncholding_m.c -modbus/functions/mbfuncinput_m.c -modbus/rtu/mbrtu_m.c -modbus/mb_m.c -port/portevent_m.c -port/portserial_m.c -port/porttimer_m.c -port/user_mb_app_m.c -""") - -slave_rtu_src = Split(""" -modbus/functions/mbfunccoils.c -modbus/functions/mbfuncdisc.c -modbus/functions/mbfuncholding.c -modbus/functions/mbfuncinput.c -modbus/rtu/mbrtu.c -modbus/mb.c -port/portevent.c -port/portserial.c -port/porttimer.c -port/user_mb_app.c -""") - -master_slave_rtu_src = Split(""" -modbus/functions/mbfunccoils.c -modbus/functions/mbfunccoils_m.c -modbus/functions/mbfuncdisc.c -modbus/functions/mbfuncdisc_m.c -modbus/functions/mbfuncholding.c -modbus/functions/mbfuncholding_m.c -modbus/functions/mbfuncinput.c -modbus/functions/mbfuncinput_m.c -modbus/rtu/mbrtu.c -modbus/rtu/mbrtu_m.c -modbus/mb.c -modbus/mb_m.c -port/portevent.c -port/portevent_m.c -port/portserial.c -port/portserial_m.c -port/porttimer.c -port/porttimer_m.c -port/user_mb_app.c -port/user_mb_app_m.c -""") - -# The set of source files associated with this SConscript file. -path = [GetCurrentDir() + '/modbus/include', - GetCurrentDir() + '/modbus/rtu', - GetCurrentDir() + '/port'] - -if GetDepend(['RT_MODBUS_MASTER_RTU']): - src += master_rtu_src - -if GetDepend(['RT_MODBUS_SLAVE_RTU']): - src += slave_rtu_src - -if GetDepend(['RT_MODBUS_MASTER_SLAVE_RTU']): - src += master_slave_rtu_src - -group = DefineGroup('FreeModbus', src, depend = ['RT_USING_MODBUS'], CPPPATH = path) - -Return('group') diff --git a/components/net/freemodbus/bsd.txt b/components/net/freemodbus/bsd.txt deleted file mode 100644 index 362d3e37c8..0000000000 --- a/components/net/freemodbus/bsd.txt +++ /dev/null @@ -1,25 +0,0 @@ -Copyright (c) 2006 Christian Walter <[email protected]> -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: -1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. -3. The name of the author may not be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - diff --git a/components/net/freemodbus/gpl.txt b/components/net/freemodbus/gpl.txt deleted file mode 100644 index 3912109b5c..0000000000 --- a/components/net/freemodbus/gpl.txt +++ /dev/null @@ -1,340 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Library General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - <one line to give the program's name and a brief idea of what it does.> - Copyright (C) <year> <name of author> - - 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 St, Fifth Floor, Boston, MA 02110-1301 USA - - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - <signature of Ty Coon>, 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Library General -Public License instead of this License. diff --git a/components/net/freemodbus/lgpl.txt b/components/net/freemodbus/lgpl.txt deleted file mode 100644 index 8add30ad59..0000000000 --- a/components/net/freemodbus/lgpl.txt +++ /dev/null @@ -1,504 +0,0 @@ - GNU LESSER GENERAL PUBLIC LICENSE - Version 2.1, February 1999 - - Copyright (C) 1991, 1999 Free Software Foundation, Inc. - 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - -[This is the first released version of the Lesser GPL. It also counts - as the successor of the GNU Library Public License, version 2, hence - the version number 2.1.] - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -Licenses are intended to guarantee your freedom to share and change -free software--to make sure the software is free for all its users. - - This license, the Lesser General Public License, applies to some -specially designated software packages--typically libraries--of the -Free Software Foundation and other authors who decide to use it. You -can use it too, but we suggest you first think carefully about whether -this license or the ordinary General Public License is the better -strategy to use in any particular case, based on the explanations below. - - When we speak of free software, we are referring to freedom of use, -not price. Our General Public Licenses are designed to make sure that -you have the freedom to distribute copies of free software (and charge -for this service if you wish); that you receive source code or can get -it if you want it; that you can change the software and use pieces of -it in new free programs; and that you are informed that you can do -these things. - - To protect your rights, we need to make restrictions that forbid -distributors to deny you these rights or to ask you to surrender these -rights. These restrictions translate to certain responsibilities for -you if you distribute copies of the library or if you modify it. - - For example, if you distribute copies of the library, whether gratis -or for a fee, you must give the recipients all the rights that we gave -you. You must make sure that they, too, receive or can get the source -code. If you link other code with the library, you must provide -complete object files to the recipients, so that they can relink them -with the library after making changes to the library and recompiling -it. And you must show them these terms so they know their rights. - - We protect your rights with a two-step method: (1) we copyright the -library, and (2) we offer you this license, which gives you legal -permission to copy, distribute and/or modify the library. - - To protect each distributor, we want to make it very clear that -there is no warranty for the free library. Also, if the library is -modified by someone else and passed on, the recipients should know -that what they have is not the original version, so that the original -author's reputation will not be affected by problems that might be -introduced by others. - - Finally, software patents pose a constant threat to the existence of -any free program. We wish to make sure that a company cannot -effectively restrict the users of a free program by obtaining a -restrictive license from a patent holder. Therefore, we insist that -any patent license obtained for a version of the library must be -consistent with the full freedom of use specified in this license. - - Most GNU software, including some libraries, is covered by the -ordinary GNU General Public License. This license, the GNU Lesser -General Public License, applies to certain designated libraries, and -is quite different from the ordinary General Public License. We use -this license for certain libraries in order to permit linking those -libraries into non-free programs. - - When a program is linked with a library, whether statically or using -a shared library, the combination of the two is legally speaking a -combined work, a derivative of the original library. The ordinary -General Public License therefore permits such linking only if the -entire combination fits its criteria of freedom. The Lesser General -Public License permits more lax criteria for linking other code with -the library. - - We call this license the "Lesser" General Public License because it -does Less to protect the user's freedom than the ordinary General -Public License. It also provides other free software developers Less -of an advantage over competing non-free programs. These disadvantages -are the reason we use the ordinary General Public License for many -libraries. However, the Lesser license provides advantages in certain -special circumstances. - - For example, on rare occasions, there may be a special need to -encourage the widest possible use of a certain library, so that it becomes -a de-facto standard. To achieve this, non-free programs must be -allowed to use the library. A more frequent case is that a free -library does the same job as widely used non-free libraries. In this -case, there is little to gain by limiting the free library to free -software only, so we use the Lesser General Public License. - - In other cases, permission to use a particular library in non-free -programs enables a greater number of people to use a large body of -free software. For example, permission to use the GNU C Library in -non-free programs enables many more people to use the whole GNU -operating system, as well as its variant, the GNU/Linux operating -system. - - Although the Lesser General Public License is Less protective of the -users' freedom, it does ensure that the user of a program that is -linked with the Library has the freedom and the wherewithal to run -that program using a modified version of the Library. - - The precise terms and conditions for copying, distribution and -modification follow. Pay close attention to the difference between a -"work based on the library" and a "work that uses the library". The -former contains code derived from the library, whereas the latter must -be combined with the library in order to run. - - GNU LESSER GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License Agreement applies to any software library or other -program which contains a notice placed by the copyright holder or -other authorized party saying it may be distributed under the terms of -this Lesser General Public License (also called "this License"). -Each licensee is addressed as "you". - - A "library" means a collection of software functions and/or data -prepared so as to be conveniently linked with application programs -(which use some of those functions and data) to form executables. - - The "Library", below, refers to any such software library or work -which has been distributed under these terms. A "work based on the -Library" means either the Library or any derivative work under -copyright law: that is to say, a work containing the Library or a -portion of it, either verbatim or with modifications and/or translated -straightforwardly into another language. (Hereinafter, translation is -included without limitation in the term "modification".) - - "Source code" for a work means the preferred form of the work for -making modifications to it. For a library, complete source code means -all the source code for all modules it contains, plus any associated -interface definition files, plus the scripts used to control compilation -and installation of the library. - - Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running a program using the Library is not restricted, and output from -such a program is covered only if its contents constitute a work based -on the Library (independent of the use of the Library in a tool for -writing it). Whether that is true depends on what the Library does -and what the program that uses the Library does. - - 1. You may copy and distribute verbatim copies of the Library's -complete source code as you receive it, in any medium, provided that -you conspicuously and appropriately publish on each copy an -appropriate copyright notice and disclaimer of warranty; keep intact -all the notices that refer to this License and to the absence of any -warranty; and distribute a copy of this License along with the -Library. - - You may charge a fee for the physical act of transferring a copy, -and you may at your option offer warranty protection in exchange for a -fee. - - 2. You may modify your copy or copies of the Library or any portion -of it, thus forming a work based on the Library, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) The modified work must itself be a software library. - - b) You must cause the files modified to carry prominent notices - stating that you changed the files and the date of any change. - - c) You must cause the whole of the work to be licensed at no - charge to all third parties under the terms of this License. - - d) If a facility in the modified Library refers to a function or a - table of data to be supplied by an application program that uses - the facility, other than as an argument passed when the facility - is invoked, then you must make a good faith effort to ensure that, - in the event an application does not supply such function or - table, the facility still operates, and performs whatever part of - its purpose remains meaningful. - - (For example, a function in a library to compute square roots has - a purpose that is entirely well-defined independent of the - application. Therefore, Subsection 2d requires that any - application-supplied function or table used by this function must - be optional: if the application does not supply it, the square - root function must still compute square roots.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Library, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Library, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote -it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Library. - -In addition, mere aggregation of another work not based on the Library -with the Library (or with a work based on the Library) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may opt to apply the terms of the ordinary GNU General Public -License instead of this License to a given copy of the Library. To do -this, you must alter all the notices that refer to this License, so -that they refer to the ordinary GNU General Public License, version 2, -instead of to this License. (If a newer version than version 2 of the -ordinary GNU General Public License has appeared, then you can specify -that version instead if you wish.) Do not make any other change in -these notices. - - Once this change is made in a given copy, it is irreversible for -that copy, so the ordinary GNU General Public License applies to all -subsequent copies and derivative works made from that copy. - - This option is useful when you wish to copy part of the code of -the Library into a program that is not a library. - - 4. You may copy and distribute the Library (or a portion or -derivative of it, under Section 2) in object code or executable form -under the terms of Sections 1 and 2 above provided that you accompany -it with the complete corresponding machine-readable source code, which -must be distributed under the terms of Sections 1 and 2 above on a -medium customarily used for software interchange. - - If distribution of object code is made by offering access to copy -from a designated place, then offering equivalent access to copy the -source code from the same place satisfies the requirement to -distribute the source code, even though third parties are not -compelled to copy the source along with the object code. - - 5. A program that contains no derivative of any portion of the -Library, but is designed to work with the Library by being compiled or -linked with it, is called a "work that uses the Library". Such a -work, in isolation, is not a derivative work of the Library, and -therefore falls outside the scope of this License. - - However, linking a "work that uses the Library" with the Library -creates an executable that is a derivative of the Library (because it -contains portions of the Library), rather than a "work that uses the -library". The executable is therefore covered by this License. -Section 6 states terms for distribution of such executables. - - When a "work that uses the Library" uses material from a header file -that is part of the Library, the object code for the work may be a -derivative work of the Library even though the source code is not. -Whether this is true is especially significant if the work can be -linked without the Library, or if the work is itself a library. The -threshold for this to be true is not precisely defined by law. - - If such an object file uses only numerical parameters, data -structure layouts and accessors, and small macros and small inline -functions (ten lines or less in length), then the use of the object -file is unrestricted, regardless of whether it is legally a derivative -work. (Executables containing this object code plus portions of the -Library will still fall under Section 6.) - - Otherwise, if the work is a derivative of the Library, you may -distribute the object code for the work under the terms of Section 6. -Any executables containing that work also fall under Section 6, -whether or not they are linked directly with the Library itself. - - 6. As an exception to the Sections above, you may also combine or -link a "work that uses the Library" with the Library to produce a -work containing portions of the Library, and distribute that work -under terms of your choice, provided that the terms permit -modification of the work for the customer's own use and reverse -engineering for debugging such modifications. - - You must give prominent notice with each copy of the work that the -Library is used in it and that the Library and its use are covered by -this License. You must supply a copy of this License. If the work -during execution displays copyright notices, you must include the -copyright notice for the Library among them, as well as a reference -directing the user to the copy of this License. Also, you must do one -of these things: - - a) Accompany the work with the complete corresponding - machine-readable source code for the Library including whatever - changes were used in the work (which must be distributed under - Sections 1 and 2 above); and, if the work is an executable linked - with the Library, with the complete machine-readable "work that - uses the Library", as object code and/or source code, so that the - user can modify the Library and then relink to produce a modified - executable containing the modified Library. (It is understood - that the user who changes the contents of definitions files in the - Library will not necessarily be able to recompile the application - to use the modified definitions.) - - b) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (1) uses at run time a - copy of the library already present on the user's computer system, - rather than copying library functions into the executable, and (2) - will operate properly with a modified version of the library, if - the user installs one, as long as the modified version is - interface-compatible with the version that the work was made with. - - c) Accompany the work with a written offer, valid for at - least three years, to give the same user the materials - specified in Subsection 6a, above, for a charge no more - than the cost of performing this distribution. - - d) If distribution of the work is made by offering access to copy - from a designated place, offer equivalent access to copy the above - specified materials from the same place. - - e) Verify that the user has already received a copy of these - materials or that you have already sent this user a copy. - - For an executable, the required form of the "work that uses the -Library" must include any data and utility programs needed for -reproducing the executable from it. However, as a special exception, -the materials to be distributed need not include anything that is -normally distributed (in either source or binary form) with the major -components (compiler, kernel, and so on) of the operating system on -which the executable runs, unless that component itself accompanies -the executable. - - It may happen that this requirement contradicts the license -restrictions of other proprietary libraries that do not normally -accompany the operating system. Such a contradiction means you cannot -use both them and the Library together in an executable that you -distribute. - - 7. You may place library facilities that are a work based on the -Library side-by-side in a single library together with other library -facilities not covered by this License, and distribute such a combined -library, provided that the separate distribution of the work based on -the Library and of the other library facilities is otherwise -permitted, and provided that you do these two things: - - a) Accompany the combined library with a copy of the same work - based on the Library, uncombined with any other library - facilities. This must be distributed under the terms of the - Sections above. - - b) Give prominent notice with the combined library of the fact - that part of it is a work based on the Library, and explaining - where to find the accompanying uncombined form of the same work. - - 8. You may not copy, modify, sublicense, link with, or distribute -the Library except as expressly provided under this License. Any -attempt otherwise to copy, modify, sublicense, link with, or -distribute the Library is void, and will automatically terminate your -rights under this License. However, parties who have received copies, -or rights, from you under this License will not have their licenses -terminated so long as such parties remain in full compliance. - - 9. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Library or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Library (or any work based on the -Library), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Library or works based on it. - - 10. Each time you redistribute the Library (or any work based on the -Library), the recipient automatically receives a license from the -original licensor to copy, distribute, link with or modify the Library -subject to these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties with -this License. - - 11. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Library at all. For example, if a patent -license would not permit royalty-free redistribution of the Library by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Library. - -If any portion of this section is held invalid or unenforceable under any -particular circumstance, the balance of the section is intended to apply, -and the section as a whole is intended to apply in other circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 12. If the distribution and/or use of the Library is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Library under this License may add -an explicit geographical distribution limitation excluding those countries, -so that distribution is permitted only in or among countries not thus -excluded. In such case, this License incorporates the limitation as if -written in the body of this License. - - 13. The Free Software Foundation may publish revised and/or new -versions of the Lesser General Public License from time to time. -Such new versions will be similar in spirit to the present version, -but may differ in detail to address new problems or concerns. - -Each version is given a distinguishing version number. If the Library -specifies a version number of this License which applies to it and -"any later version", you have the option of following the terms and -conditions either of that version or of any later version published by -the Free Software Foundation. If the Library does not specify a -license version number, you may choose any version ever published by -the Free Software Foundation. - - 14. If you wish to incorporate parts of the Library into other free -programs whose distribution conditions are incompatible with these, -write to the author to ask for permission. For software which is -copyrighted by the Free Software Foundation, write to the Free -Software Foundation; we sometimes make exceptions for this. Our -decision will be guided by the two goals of preserving the free status -of all derivatives of our free software and of promoting the sharing -and reuse of software generally. - - NO WARRANTY - - 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO -WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. -EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR -OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY -KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE -LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME -THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN -WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY -AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU -FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR -CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE -LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING -RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A -FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF -SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Libraries - - If you develop a new library, and you want it to be of the greatest -possible use to the public, we recommend making it free software that -everyone can redistribute and change. You can do so by permitting -redistribution under these terms (or, alternatively, under the terms of the -ordinary General Public License). - - To apply these terms, attach the following notices to the library. It is -safest to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least the -"copyright" line and a pointer to where the full notice is found. - - <one line to give the library's name and a brief idea of what it does.> - Copyright (C) <year> <name of author> - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -Also add information on how to contact you by electronic and paper mail. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the library, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the - library `Frob' (a library for tweaking knobs) written by James Random Hacker. - - <signature of Ty Coon>, 1 April 1990 - Ty Coon, President of Vice - -That's all there is to it! - - diff --git a/components/net/freemodbus/modbus/ascii/mbascii.c b/components/net/freemodbus/modbus/ascii/mbascii.c deleted file mode 100644 index b0f3bc05d2..0000000000 --- a/components/net/freemodbus/modbus/ascii/mbascii.c +++ /dev/null @@ -1,485 +0,0 @@ -/* - * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. - * Copyright (c) 2006 Christian Walter <[email protected]> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * File: $Id: mbascii.c,v 1.15 2007/02/18 23:46:48 wolti Exp $ - */ - -/* ----------------------- System includes ----------------------------------*/ -#include "stdlib.h" -#include "string.h" - -/* ----------------------- Platform includes --------------------------------*/ -#include "port.h" - -/* ----------------------- Modbus includes ----------------------------------*/ -#include "mb.h" -#include "mbconfig.h" -#include "mbascii.h" -#include "mbframe.h" - -#include "mbcrc.h" -#include "mbport.h" - -#if MB_SLAVE_ASCII_ENABLED > 0 - -/* ----------------------- Defines ------------------------------------------*/ -#define MB_ASCII_DEFAULT_CR '\r' /*!< Default CR character for Modbus ASCII. */ -#define MB_ASCII_DEFAULT_LF '\n' /*!< Default LF character for Modbus ASCII. */ -#define MB_SER_PDU_SIZE_MIN 3 /*!< Minimum size of a Modbus ASCII frame. */ -#define MB_SER_PDU_SIZE_MAX 256 /*!< Maximum size of a Modbus ASCII frame. */ -#define MB_SER_PDU_SIZE_LRC 1 /*!< Size of LRC field in PDU. */ -#define MB_SER_PDU_ADDR_OFF 0 /*!< Offset of slave address in Ser-PDU. */ -#define MB_SER_PDU_PDU_OFF 1 /*!< Offset of Modbus-PDU in Ser-PDU. */ - -/* ----------------------- Type definitions ---------------------------------*/ -typedef enum -{ - STATE_RX_IDLE, /*!< Receiver is in idle state. */ - STATE_RX_RCV, /*!< Frame is beeing received. */ - STATE_RX_WAIT_EOF /*!< Wait for End of Frame. */ -} eMBRcvState; - -typedef enum -{ - STATE_TX_IDLE, /*!< Transmitter is in idle state. */ - STATE_TX_START, /*!< Starting transmission (':' sent). */ - STATE_TX_DATA, /*!< Sending of data (Address, Data, LRC). */ - STATE_TX_END, /*!< End of transmission. */ - STATE_TX_NOTIFY /*!< Notify sender that the frame has been sent. */ -} eMBSndState; - -typedef enum -{ - BYTE_HIGH_NIBBLE, /*!< Character for high nibble of byte. */ - BYTE_LOW_NIBBLE /*!< Character for low nibble of byte. */ -} eMBBytePos; - -/* ----------------------- Static functions ---------------------------------*/ -static UCHAR prvucMBCHAR2BIN( UCHAR ucCharacter ); - -static UCHAR prvucMBBIN2CHAR( UCHAR ucByte ); - -static UCHAR prvucMBLRC( UCHAR * pucFrame, USHORT usLen ); - -/* ----------------------- Static variables ---------------------------------*/ -static volatile eMBSndState eSndState; -static volatile eMBRcvState eRcvState; - -/* We reuse the Modbus RTU buffer because only one buffer is needed and the - * RTU buffer is bigger. */ -extern volatile UCHAR ucRTUBuf[]; -static volatile UCHAR *ucASCIIBuf = ucRTUBuf; - -static volatile USHORT usRcvBufferPos; -static volatile eMBBytePos eBytePos; - -static volatile UCHAR *pucSndBufferCur; -static volatile USHORT usSndBufferCount; - -static volatile UCHAR ucLRC; -static volatile UCHAR ucMBLFCharacter; - -/* ----------------------- Start implementation -----------------------------*/ -eMBErrorCode -eMBASCIIInit( UCHAR ucSlaveAddress, UCHAR ucPort, ULONG ulBaudRate, eMBParity eParity ) -{ - eMBErrorCode eStatus = MB_ENOERR; - ( void )ucSlaveAddress; - - ENTER_CRITICAL_SECTION( ); - ucMBLFCharacter = MB_ASCII_DEFAULT_LF; - - if( xMBPortSerialInit( ucPort, ulBaudRate, 7, eParity ) != TRUE ) - { - eStatus = MB_EPORTERR; - } - else if( xMBPortTimersInit( MB_ASCII_TIMEOUT_SEC * 20000UL ) != TRUE ) - { - eStatus = MB_EPORTERR; - } - - EXIT_CRITICAL_SECTION( ); - - return eStatus; -} - -void -eMBASCIIStart( void ) -{ - ENTER_CRITICAL_SECTION( ); - vMBPortSerialEnable( TRUE, FALSE ); - eRcvState = STATE_RX_IDLE; - EXIT_CRITICAL_SECTION( ); - - /* No special startup required for ASCII. */ - ( void )xMBPortEventPost( EV_READY ); -} - -void -eMBASCIIStop( void ) -{ - ENTER_CRITICAL_SECTION( ); - vMBPortSerialEnable( FALSE, FALSE ); - vMBPortTimersDisable( ); - EXIT_CRITICAL_SECTION( ); -} - -eMBErrorCode -eMBASCIIReceive( UCHAR * pucRcvAddress, UCHAR ** pucFrame, USHORT * pusLength ) -{ - eMBErrorCode eStatus = MB_ENOERR; - - ENTER_CRITICAL_SECTION( ); - assert( usRcvBufferPos < MB_SER_PDU_SIZE_MAX ); - - /* Length and CRC check */ - if( ( usRcvBufferPos >= MB_SER_PDU_SIZE_MIN ) - && ( prvucMBLRC( ( UCHAR * ) ucASCIIBuf, usRcvBufferPos ) == 0 ) ) - { - /* Save the address field. All frames are passed to the upper layed - * and the decision if a frame is used is done there. - */ - *pucRcvAddress = ucASCIIBuf[MB_SER_PDU_ADDR_OFF]; - - /* Total length of Modbus-PDU is Modbus-Serial-Line-PDU minus - * size of address field and CRC checksum. - */ - *pusLength = ( USHORT )( usRcvBufferPos - MB_SER_PDU_PDU_OFF - MB_SER_PDU_SIZE_LRC ); - - /* Return the start of the Modbus PDU to the caller. */ - *pucFrame = ( UCHAR * ) & ucASCIIBuf[MB_SER_PDU_PDU_OFF]; - } - else - { - eStatus = MB_EIO; - } - EXIT_CRITICAL_SECTION( ); - return eStatus; -} - -eMBErrorCode -eMBASCIISend( UCHAR ucSlaveAddress, const UCHAR * pucFrame, USHORT usLength ) -{ - eMBErrorCode eStatus = MB_ENOERR; - UCHAR usLRC; - - ENTER_CRITICAL_SECTION( ); - /* Check if the receiver is still in idle state. If not we where to - * slow with processing the received frame and the master sent another - * frame on the network. We have to abort sending the frame. - */ - if( eRcvState == STATE_RX_IDLE ) - { - /* First byte before the Modbus-PDU is the slave address. */ - pucSndBufferCur = ( UCHAR * ) pucFrame - 1; - usSndBufferCount = 1; - - /* Now copy the Modbus-PDU into the Modbus-Serial-Line-PDU. */ - pucSndBufferCur[MB_SER_PDU_ADDR_OFF] = ucSlaveAddress; - usSndBufferCount += usLength; - - /* Calculate LRC checksum for Modbus-Serial-Line-PDU. */ - usLRC = prvucMBLRC( ( UCHAR * ) pucSndBufferCur, usSndBufferCount ); - ucASCIIBuf[usSndBufferCount++] = usLRC; - - /* Activate the transmitter. */ - eSndState = STATE_TX_START; - vMBPortSerialEnable( FALSE, TRUE ); - } - else - { - eStatus = MB_EIO; - } - EXIT_CRITICAL_SECTION( ); - return eStatus; -} - -BOOL -xMBASCIIReceiveFSM( void ) -{ - BOOL xNeedPoll = FALSE; - UCHAR ucByte; - UCHAR ucResult; - - assert( eSndState == STATE_TX_IDLE ); - - ( void )xMBPortSerialGetByte( ( CHAR * ) & ucByte ); - switch ( eRcvState ) - { - /* A new character is received. If the character is a ':' the input - * buffer is cleared. A CR-character signals the end of the data - * block. Other characters are part of the data block and their - * ASCII value is converted back to a binary representation. - */ - case STATE_RX_RCV: - /* Enable timer for character timeout. */ - vMBPortTimersEnable( ); - if( ucByte == ':' ) - { - /* Empty receive buffer. */ - eBytePos = BYTE_HIGH_NIBBLE; - usRcvBufferPos = 0; - } - else if( ucByte == MB_ASCII_DEFAULT_CR ) - { - eRcvState = STATE_RX_WAIT_EOF; - } - else - { - ucResult = prvucMBCHAR2BIN( ucByte ); - switch ( eBytePos ) - { - /* High nibble of the byte comes first. We check for - * a buffer overflow here. */ - case BYTE_HIGH_NIBBLE: - if( usRcvBufferPos < MB_SER_PDU_SIZE_MAX ) - { - ucASCIIBuf[usRcvBufferPos] = ( UCHAR )( ucResult << 4 ); - eBytePos = BYTE_LOW_NIBBLE; - break; - } - else - { - /* not handled in Modbus specification but seems - * a resonable implementation. */ - eRcvState = STATE_RX_IDLE; - /* Disable previously activated timer because of error state. */ - vMBPortTimersDisable( ); - } - break; - - case BYTE_LOW_NIBBLE: - ucASCIIBuf[usRcvBufferPos++] |= ucResult; - eBytePos = BYTE_HIGH_NIBBLE; - break; - } - } - break; - - case STATE_RX_WAIT_EOF: - if( ucByte == ucMBLFCharacter ) - { - /* Disable character timeout timer because all characters are - * received. */ - vMBPortTimersDisable( ); - /* Receiver is again in idle state. */ - eRcvState = STATE_RX_IDLE; - - /* Notify the caller of eMBASCIIReceive that a new frame - * was received. */ - xNeedPoll = xMBPortEventPost( EV_FRAME_RECEIVED ); - } - else if( ucByte == ':' ) - { - /* Empty receive buffer and back to receive state. */ - eBytePos = BYTE_HIGH_NIBBLE; - usRcvBufferPos = 0; - eRcvState = STATE_RX_RCV; - - /* Enable timer for character timeout. */ - vMBPortTimersEnable( ); - } - else - { - /* Frame is not okay. Delete entire frame. */ - eRcvState = STATE_RX_IDLE; - } - break; - - case STATE_RX_IDLE: - if( ucByte == ':' ) - { - /* Enable timer for character timeout. */ - vMBPortTimersEnable( ); - /* Reset the input buffers to store the frame. */ - usRcvBufferPos = 0;; - eBytePos = BYTE_HIGH_NIBBLE; - eRcvState = STATE_RX_RCV; - } - break; - } - - return xNeedPoll; -} - -BOOL -xMBASCIITransmitFSM( void ) -{ - BOOL xNeedPoll = FALSE; - UCHAR ucByte; - - assert( eRcvState == STATE_RX_IDLE ); - switch ( eSndState ) - { - /* Start of transmission. The start of a frame is defined by sending - * the character ':'. */ - case STATE_TX_START: - ucByte = ':'; - xMBPortSerialPutByte( ( CHAR )ucByte ); - eSndState = STATE_TX_DATA; - eBytePos = BYTE_HIGH_NIBBLE; - break; - - /* Send the data block. Each data byte is encoded as a character hex - * stream with the high nibble sent first and the low nibble sent - * last. If all data bytes are exhausted we send a '\r' character - * to end the transmission. */ - case STATE_TX_DATA: - if( usSndBufferCount > 0 ) - { - switch ( eBytePos ) - { - case BYTE_HIGH_NIBBLE: - ucByte = prvucMBBIN2CHAR( ( UCHAR )( *pucSndBufferCur >> 4 ) ); - xMBPortSerialPutByte( ( CHAR ) ucByte ); - eBytePos = BYTE_LOW_NIBBLE; - break; - - case BYTE_LOW_NIBBLE: - ucByte = prvucMBBIN2CHAR( ( UCHAR )( *pucSndBufferCur & 0x0F ) ); - xMBPortSerialPutByte( ( CHAR )ucByte ); - pucSndBufferCur++; - eBytePos = BYTE_HIGH_NIBBLE; - usSndBufferCount--; - break; - } - } - else - { - xMBPortSerialPutByte( MB_ASCII_DEFAULT_CR ); - eSndState = STATE_TX_END; - } - break; - - /* Finish the frame by sending a LF character. */ - case STATE_TX_END: - xMBPortSerialPutByte( ( CHAR )ucMBLFCharacter ); - /* We need another state to make sure that the CR character has - * been sent. */ - eSndState = STATE_TX_NOTIFY; - break; - - /* Notify the task which called eMBASCIISend that the frame has - * been sent. */ - case STATE_TX_NOTIFY: - eSndState = STATE_TX_IDLE; - xNeedPoll = xMBPortEventPost( EV_FRAME_SENT ); - - /* Disable transmitter. This prevents another transmit buffer - * empty interrupt. */ - vMBPortSerialEnable( TRUE, FALSE ); - eSndState = STATE_TX_IDLE; - break; - - /* We should not get a transmitter event if the transmitter is in - * idle state. */ - case STATE_TX_IDLE: - /* enable receiver/disable transmitter. */ - vMBPortSerialEnable( TRUE, FALSE ); - break; - } - - return xNeedPoll; -} - -BOOL -xMBASCIITimerT1SExpired( void ) -{ - switch ( eRcvState ) - { - /* If we have a timeout we go back to the idle state and wait for - * the next frame. - */ - case STATE_RX_RCV: - case STATE_RX_WAIT_EOF: - eRcvState = STATE_RX_IDLE; - break; - - default: - assert( ( eRcvState == STATE_RX_RCV ) || ( eRcvState == STATE_RX_WAIT_EOF ) ); - break; - } - vMBPortTimersDisable( ); - - /* no context switch required. */ - return FALSE; -} - - -static UCHAR -prvucMBCHAR2BIN( UCHAR ucCharacter ) -{ - if( ( ucCharacter >= '0' ) && ( ucCharacter <= '9' ) ) - { - return ( UCHAR )( ucCharacter - '0' ); - } - else if( ( ucCharacter >= 'A' ) && ( ucCharacter <= 'F' ) ) - { - return ( UCHAR )( ucCharacter - 'A' + 0x0A ); - } - else - { - return 0xFF; - } -} - -static UCHAR -prvucMBBIN2CHAR( UCHAR ucByte ) -{ - if( ucByte <= 0x09 ) - { - return ( UCHAR )( '0' + ucByte ); - } - else if( ( ucByte >= 0x0A ) && ( ucByte <= 0x0F ) ) - { - return ( UCHAR )( ucByte - 0x0A + 'A' ); - } - else - { - /* Programming error. */ - assert( 0 ); - } - return '0'; -} - - -static UCHAR -prvucMBLRC( UCHAR * pucFrame, USHORT usLen ) -{ - UCHAR ucLRC = 0; /* LRC char initialized */ - - while( usLen-- ) - { - ucLRC += *pucFrame++; /* Add buffer byte without carry */ - } - - /* Return twos complement */ - ucLRC = ( UCHAR ) ( -( ( CHAR ) ucLRC ) ); - return ucLRC; -} - -#endif diff --git a/components/net/freemodbus/modbus/ascii/mbascii.h b/components/net/freemodbus/modbus/ascii/mbascii.h deleted file mode 100644 index cdec83ff00..0000000000 --- a/components/net/freemodbus/modbus/ascii/mbascii.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. - * Copyright (c) 2006 Christian Walter <[email protected]> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * File: $Id: mbascii.h,v 1.8 2006/12/07 22:10:34 wolti Exp $ - */ - -#ifndef _MB_ASCII_H -#define _MB_ASCII_H - -#ifdef __cplusplus -PR_BEGIN_EXTERN_C -#endif - -#if MB_SLAVE_ASCII_ENABLED > 0 -eMBErrorCode eMBASCIIInit( UCHAR slaveAddress, UCHAR ucPort, - ULONG ulBaudRate, eMBParity eParity ); -void eMBASCIIStart( void ); -void eMBASCIIStop( void ); - -eMBErrorCode eMBASCIIReceive( UCHAR * pucRcvAddress, UCHAR ** pucFrame, - USHORT * pusLength ); -eMBErrorCode eMBASCIISend( UCHAR slaveAddress, const UCHAR * pucFrame, - USHORT usLength ); -BOOL xMBASCIIReceiveFSM( void ); -BOOL xMBASCIITransmitFSM( void ); -BOOL xMBASCIITimerT1SExpired( void ); -#endif - -#ifdef __cplusplus -PR_END_EXTERN_C -#endif -#endif diff --git a/components/net/freemodbus/modbus/functions/mbfunccoils.c b/components/net/freemodbus/modbus/functions/mbfunccoils.c deleted file mode 100644 index 681bd50656..0000000000 --- a/components/net/freemodbus/modbus/functions/mbfunccoils.c +++ /dev/null @@ -1,269 +0,0 @@ -/* - * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. - * Copyright (c) 2006 Christian Walter <[email protected]> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * File: $Id: mbfunccoils.c,v 1.8 2007/02/18 23:47:16 wolti Exp $ - */ - -/* ----------------------- System includes ----------------------------------*/ -#include "stdlib.h" -#include "string.h" - -/* ----------------------- Platform includes --------------------------------*/ -#include "port.h" - -/* ----------------------- Modbus includes ----------------------------------*/ -#include "mb.h" -#include "mbframe.h" -#include "mbproto.h" -#include "mbconfig.h" - -/* ----------------------- Defines ------------------------------------------*/ -#define MB_PDU_FUNC_READ_ADDR_OFF ( MB_PDU_DATA_OFF ) -#define MB_PDU_FUNC_READ_COILCNT_OFF ( MB_PDU_DATA_OFF + 2 ) -#define MB_PDU_FUNC_READ_SIZE ( 4 ) -#define MB_PDU_FUNC_READ_COILCNT_MAX ( 0x07D0 ) - -#define MB_PDU_FUNC_WRITE_ADDR_OFF ( MB_PDU_DATA_OFF ) -#define MB_PDU_FUNC_WRITE_VALUE_OFF ( MB_PDU_DATA_OFF + 2 ) -#define MB_PDU_FUNC_WRITE_SIZE ( 4 ) - -#define MB_PDU_FUNC_WRITE_MUL_ADDR_OFF ( MB_PDU_DATA_OFF ) -#define MB_PDU_FUNC_WRITE_MUL_COILCNT_OFF ( MB_PDU_DATA_OFF + 2 ) -#define MB_PDU_FUNC_WRITE_MUL_BYTECNT_OFF ( MB_PDU_DATA_OFF + 4 ) -#define MB_PDU_FUNC_WRITE_MUL_VALUES_OFF ( MB_PDU_DATA_OFF + 5 ) -#define MB_PDU_FUNC_WRITE_MUL_SIZE_MIN ( 5 ) -#define MB_PDU_FUNC_WRITE_MUL_COILCNT_MAX ( 0x07B0 ) - -/* ----------------------- Static functions ---------------------------------*/ -eMBException prveMBError2Exception( eMBErrorCode eErrorCode ); - -/* ----------------------- Start implementation -----------------------------*/ - -#if MB_FUNC_READ_COILS_ENABLED > 0 - -eMBException -eMBFuncReadCoils( UCHAR * pucFrame, USHORT * usLen ) -{ - USHORT usRegAddress; - USHORT usCoilCount; - UCHAR ucNBytes; - UCHAR *pucFrameCur; - - eMBException eStatus = MB_EX_NONE; - eMBErrorCode eRegStatus; - - if( *usLen == ( MB_PDU_FUNC_READ_SIZE + MB_PDU_SIZE_MIN ) ) - { - usRegAddress = ( USHORT )( pucFrame[MB_PDU_FUNC_READ_ADDR_OFF] << 8 ); - usRegAddress |= ( USHORT )( pucFrame[MB_PDU_FUNC_READ_ADDR_OFF + 1] ); - usRegAddress++; - - usCoilCount = ( USHORT )( pucFrame[MB_PDU_FUNC_READ_COILCNT_OFF] << 8 ); - usCoilCount |= ( USHORT )( pucFrame[MB_PDU_FUNC_READ_COILCNT_OFF + 1] ); - - /* Check if the number of registers to read is valid. If not - * return Modbus illegal data value exception. - */ - if( ( usCoilCount >= 1 ) && - ( usCoilCount < MB_PDU_FUNC_READ_COILCNT_MAX ) ) - { - /* Set the current PDU data pointer to the beginning. */ - pucFrameCur = &pucFrame[MB_PDU_FUNC_OFF]; - *usLen = MB_PDU_FUNC_OFF; - - /* First byte contains the function code. */ - *pucFrameCur++ = MB_FUNC_READ_COILS; - *usLen += 1; - - /* Test if the quantity of coils is a multiple of 8. If not last - * byte is only partially field with unused coils set to zero. */ - if( ( usCoilCount & 0x0007 ) != 0 ) - { - ucNBytes = ( UCHAR )( usCoilCount / 8 + 1 ); - } - else - { - ucNBytes = ( UCHAR )( usCoilCount / 8 ); - } - *pucFrameCur++ = ucNBytes; - *usLen += 1; - - eRegStatus = - eMBRegCoilsCB( pucFrameCur, usRegAddress, usCoilCount, - MB_REG_READ ); - - /* If an error occured convert it into a Modbus exception. */ - if( eRegStatus != MB_ENOERR ) - { - eStatus = prveMBError2Exception( eRegStatus ); - } - else - { - /* The response contains the function code, the starting address - * and the quantity of registers. We reuse the old values in the - * buffer because they are still valid. */ - *usLen += ucNBytes;; - } - } - else - { - eStatus = MB_EX_ILLEGAL_DATA_VALUE; - } - } - else - { - /* Can't be a valid read coil register request because the length - * is incorrect. */ - eStatus = MB_EX_ILLEGAL_DATA_VALUE; - } - return eStatus; -} -#endif - -#if MB_FUNC_WRITE_COIL_ENABLED > 0 -eMBException -eMBFuncWriteCoil( UCHAR * pucFrame, USHORT * usLen ) -{ - USHORT usRegAddress; - UCHAR ucBuf[2]; - - eMBException eStatus = MB_EX_NONE; - eMBErrorCode eRegStatus; - - if( *usLen == ( MB_PDU_FUNC_WRITE_SIZE + MB_PDU_SIZE_MIN ) ) - { - usRegAddress = ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_ADDR_OFF] << 8 ); - usRegAddress |= ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_ADDR_OFF + 1] ); - usRegAddress++; - - if( ( pucFrame[MB_PDU_FUNC_WRITE_VALUE_OFF + 1] == 0x00 ) && - ( ( pucFrame[MB_PDU_FUNC_WRITE_VALUE_OFF] == 0xFF ) || - ( pucFrame[MB_PDU_FUNC_WRITE_VALUE_OFF] == 0x00 ) ) ) - { - ucBuf[1] = 0; - if( pucFrame[MB_PDU_FUNC_WRITE_VALUE_OFF] == 0xFF ) - { - ucBuf[0] = 1; - } - else - { - ucBuf[0] = 0; - } - eRegStatus = - eMBRegCoilsCB( &ucBuf[0], usRegAddress, 1, MB_REG_WRITE ); - - /* If an error occured convert it into a Modbus exception. */ - if( eRegStatus != MB_ENOERR ) - { - eStatus = prveMBError2Exception( eRegStatus ); - } - } - else - { - eStatus = MB_EX_ILLEGAL_DATA_VALUE; - } - } - else - { - /* Can't be a valid write coil register request because the length - * is incorrect. */ - eStatus = MB_EX_ILLEGAL_DATA_VALUE; - } - return eStatus; -} - -#endif - -#if MB_FUNC_WRITE_MULTIPLE_COILS_ENABLED > 0 -eMBException -eMBFuncWriteMultipleCoils( UCHAR * pucFrame, USHORT * usLen ) -{ - USHORT usRegAddress; - USHORT usCoilCnt; - UCHAR ucByteCount; - UCHAR ucByteCountVerify; - - eMBException eStatus = MB_EX_NONE; - eMBErrorCode eRegStatus; - - if( *usLen > ( MB_PDU_FUNC_WRITE_SIZE + MB_PDU_SIZE_MIN ) ) - { - usRegAddress = ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_MUL_ADDR_OFF] << 8 ); - usRegAddress |= ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_MUL_ADDR_OFF + 1] ); - usRegAddress++; - - usCoilCnt = ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_MUL_COILCNT_OFF] << 8 ); - usCoilCnt |= ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_MUL_COILCNT_OFF + 1] ); - - ucByteCount = pucFrame[MB_PDU_FUNC_WRITE_MUL_BYTECNT_OFF]; - - /* Compute the number of expected bytes in the request. */ - if( ( usCoilCnt & 0x0007 ) != 0 ) - { - ucByteCountVerify = ( UCHAR )( usCoilCnt / 8 + 1 ); - } - else - { - ucByteCountVerify = ( UCHAR )( usCoilCnt / 8 ); - } - - if( ( usCoilCnt >= 1 ) && - ( usCoilCnt <= MB_PDU_FUNC_WRITE_MUL_COILCNT_MAX ) && - ( ucByteCountVerify == ucByteCount ) ) - { - eRegStatus = - eMBRegCoilsCB( &pucFrame[MB_PDU_FUNC_WRITE_MUL_VALUES_OFF], - usRegAddress, usCoilCnt, MB_REG_WRITE ); - - /* If an error occured convert it into a Modbus exception. */ - if( eRegStatus != MB_ENOERR ) - { - eStatus = prveMBError2Exception( eRegStatus ); - } - else - { - /* The response contains the function code, the starting address - * and the quantity of registers. We reuse the old values in the - * buffer because they are still valid. */ - *usLen = MB_PDU_FUNC_WRITE_MUL_BYTECNT_OFF; - } - } - else - { - eStatus = MB_EX_ILLEGAL_DATA_VALUE; - } - } - else - { - /* Can't be a valid write coil register request because the length - * is incorrect. */ - eStatus = MB_EX_ILLEGAL_DATA_VALUE; - } - return eStatus; -} - -#endif diff --git a/components/net/freemodbus/modbus/functions/mbfunccoils_m.c b/components/net/freemodbus/modbus/functions/mbfunccoils_m.c deleted file mode 100644 index 93801de06f..0000000000 --- a/components/net/freemodbus/modbus/functions/mbfunccoils_m.c +++ /dev/null @@ -1,390 +0,0 @@ -/* - * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. - * Copyright (C) 2013 Armink <[email protected]> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * File: $Id: mbfunccoils_m.c,v 1.60 2013/10/12 15:10:12 Armink Add Master Functions - */ - -/* ----------------------- System includes ----------------------------------*/ -#include "stdlib.h" -#include "string.h" - -/* ----------------------- Platform includes --------------------------------*/ -#include "port.h" - -/* ----------------------- Modbus includes ----------------------------------*/ -#include "mb.h" -#include "mb_m.h" -#include "mbframe.h" -#include "mbproto.h" -#include "mbconfig.h" - -/* ----------------------- Defines ------------------------------------------*/ -#define MB_PDU_REQ_READ_ADDR_OFF ( MB_PDU_DATA_OFF + 0 ) -#define MB_PDU_REQ_READ_COILCNT_OFF ( MB_PDU_DATA_OFF + 2 ) -#define MB_PDU_REQ_READ_SIZE ( 4 ) -#define MB_PDU_FUNC_READ_COILCNT_OFF ( MB_PDU_DATA_OFF + 0 ) -#define MB_PDU_FUNC_READ_VALUES_OFF ( MB_PDU_DATA_OFF + 1 ) -#define MB_PDU_FUNC_READ_SIZE_MIN ( 1 ) - -#define MB_PDU_REQ_WRITE_ADDR_OFF ( MB_PDU_DATA_OFF ) -#define MB_PDU_REQ_WRITE_VALUE_OFF ( MB_PDU_DATA_OFF + 2 ) -#define MB_PDU_REQ_WRITE_SIZE ( 4 ) -#define MB_PDU_FUNC_WRITE_ADDR_OFF ( MB_PDU_DATA_OFF ) -#define MB_PDU_FUNC_WRITE_VALUE_OFF ( MB_PDU_DATA_OFF + 2 ) -#define MB_PDU_FUNC_WRITE_SIZE ( 4 ) - -#define MB_PDU_REQ_WRITE_MUL_ADDR_OFF ( MB_PDU_DATA_OFF ) -#define MB_PDU_REQ_WRITE_MUL_COILCNT_OFF ( MB_PDU_DATA_OFF + 2 ) -#define MB_PDU_REQ_WRITE_MUL_BYTECNT_OFF ( MB_PDU_DATA_OFF + 4 ) -#define MB_PDU_REQ_WRITE_MUL_VALUES_OFF ( MB_PDU_DATA_OFF + 5 ) -#define MB_PDU_REQ_WRITE_MUL_SIZE_MIN ( 5 ) -#define MB_PDU_REQ_WRITE_MUL_COILCNT_MAX ( 0x07B0 ) -#define MB_PDU_FUNC_WRITE_MUL_ADDR_OFF ( MB_PDU_DATA_OFF ) -#define MB_PDU_FUNC_WRITE_MUL_COILCNT_OFF ( MB_PDU_DATA_OFF + 2 ) -#define MB_PDU_FUNC_WRITE_MUL_SIZE ( 5 ) - -/* ----------------------- Static functions ---------------------------------*/ -eMBException prveMBError2Exception( eMBErrorCode eErrorCode ); - -/* ----------------------- Start implementation -----------------------------*/ -#if MB_MASTER_RTU_ENABLED > 0 || MB_MASTER_ASCII_ENABLED > 0 -#if MB_FUNC_READ_COILS_ENABLED > 0 - -/** - * This function will request read coil. - * - * @param ucSndAddr salve address - * @param usCoilAddr coil start address - * @param usNCoils coil total number - * @param lTimeOut timeout (-1 will waiting forever) - * - * @return error code - */ -eMBMasterReqErrCode -eMBMasterReqReadCoils( UCHAR ucSndAddr, USHORT usCoilAddr, USHORT usNCoils ,LONG lTimeOut ) -{ - UCHAR *ucMBFrame; - eMBMasterReqErrCode eErrStatus = MB_MRE_NO_ERR; - - if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG; - else if ( xMBMasterRunResTake( lTimeOut ) == FALSE ) eErrStatus = MB_MRE_MASTER_BUSY; - else - { - vMBMasterGetPDUSndBuf(&ucMBFrame); - vMBMasterSetDestAddress(ucSndAddr); - ucMBFrame[MB_PDU_FUNC_OFF] = MB_FUNC_READ_COILS; - ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF] = usCoilAddr >> 8; - ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF + 1] = usCoilAddr; - ucMBFrame[MB_PDU_REQ_READ_COILCNT_OFF ] = usNCoils >> 8; - ucMBFrame[MB_PDU_REQ_READ_COILCNT_OFF + 1] = usNCoils; - vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_READ_SIZE ); - ( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_SENT ); - eErrStatus = eMBMasterWaitRequestFinish( ); - - } - return eErrStatus; -} - -eMBException -eMBMasterFuncReadCoils( UCHAR * pucFrame, USHORT * usLen ) -{ - UCHAR *ucMBFrame; - USHORT usRegAddress; - USHORT usCoilCount; - UCHAR ucByteCount; - - eMBException eStatus = MB_EX_NONE; - eMBErrorCode eRegStatus; - - /* If this request is broadcast, and it's read mode. This request don't need execute. */ - if ( xMBMasterRequestIsBroadcast() ) - { - eStatus = MB_EX_NONE; - } - else if ( *usLen >= MB_PDU_SIZE_MIN + MB_PDU_FUNC_READ_SIZE_MIN ) - { - vMBMasterGetPDUSndBuf(&ucMBFrame); - usRegAddress = ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF] << 8 ); - usRegAddress |= ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF + 1] ); - usRegAddress++; - - usCoilCount = ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_COILCNT_OFF] << 8 ); - usCoilCount |= ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_COILCNT_OFF + 1] ); - - /* Test if the quantity of coils is a multiple of 8. If not last - * byte is only partially field with unused coils set to zero. */ - if( ( usCoilCount & 0x0007 ) != 0 ) - { - ucByteCount = ( UCHAR )( usCoilCount / 8 + 1 ); - } - else - { - ucByteCount = ( UCHAR )( usCoilCount / 8 ); - } - - /* Check if the number of registers to read is valid. If not - * return Modbus illegal data value exception. - */ - if( ( usCoilCount >= 1 ) && - ( ucByteCount == pucFrame[MB_PDU_FUNC_READ_COILCNT_OFF] ) ) - { - /* Make callback to fill the buffer. */ - eRegStatus = eMBMasterRegCoilsCB( &pucFrame[MB_PDU_FUNC_READ_VALUES_OFF], usRegAddress, usCoilCount, MB_REG_READ ); - - /* If an error occured convert it into a Modbus exception. */ - if( eRegStatus != MB_ENOERR ) - { - eStatus = prveMBError2Exception( eRegStatus ); - } - } - else - { - eStatus = MB_EX_ILLEGAL_DATA_VALUE; - } - } - else - { - /* Can't be a valid read coil register request because the length - * is incorrect. */ - eStatus = MB_EX_ILLEGAL_DATA_VALUE; - } - return eStatus; -} -#endif - -#if MB_FUNC_WRITE_COIL_ENABLED > 0 - -/** - * This function will request write one coil. - * - * @param ucSndAddr salve address - * @param usCoilAddr coil start address - * @param usCoilData data to be written - * @param lTimeOut timeout (-1 will waiting forever) - * - * @return error code - * - * @see eMBMasterReqWriteMultipleCoils - */ -eMBMasterReqErrCode -eMBMasterReqWriteCoil( UCHAR ucSndAddr, USHORT usCoilAddr, USHORT usCoilData, LONG lTimeOut ) -{ - UCHAR *ucMBFrame; - eMBMasterReqErrCode eErrStatus = MB_MRE_NO_ERR; - - if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG; - else if ( ( usCoilData != 0xFF00 ) && ( usCoilData != 0x0000 ) ) eErrStatus = MB_MRE_ILL_ARG; - else if ( xMBMasterRunResTake( lTimeOut ) == FALSE ) eErrStatus = MB_MRE_MASTER_BUSY; - else - { - vMBMasterGetPDUSndBuf(&ucMBFrame); - vMBMasterSetDestAddress(ucSndAddr); - ucMBFrame[MB_PDU_FUNC_OFF] = MB_FUNC_WRITE_SINGLE_COIL; - ucMBFrame[MB_PDU_REQ_WRITE_ADDR_OFF] = usCoilAddr >> 8; - ucMBFrame[MB_PDU_REQ_WRITE_ADDR_OFF + 1] = usCoilAddr; - ucMBFrame[MB_PDU_REQ_WRITE_VALUE_OFF ] = usCoilData >> 8; - ucMBFrame[MB_PDU_REQ_WRITE_VALUE_OFF + 1] = usCoilData; - vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_WRITE_SIZE ); - ( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_SENT ); - eErrStatus = eMBMasterWaitRequestFinish( ); - } - return eErrStatus; -} - -eMBException -eMBMasterFuncWriteCoil( UCHAR * pucFrame, USHORT * usLen ) -{ - USHORT usRegAddress; - UCHAR ucBuf[2]; - - eMBException eStatus = MB_EX_NONE; - eMBErrorCode eRegStatus; - - if( *usLen == ( MB_PDU_FUNC_WRITE_SIZE + MB_PDU_SIZE_MIN ) ) - { - usRegAddress = ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_ADDR_OFF] << 8 ); - usRegAddress |= ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_ADDR_OFF + 1] ); - usRegAddress++; - - if( ( pucFrame[MB_PDU_FUNC_WRITE_VALUE_OFF + 1] == 0x00 ) && - ( ( pucFrame[MB_PDU_FUNC_WRITE_VALUE_OFF] == 0xFF ) || - ( pucFrame[MB_PDU_FUNC_WRITE_VALUE_OFF] == 0x00 ) ) ) - { - ucBuf[1] = 0; - if( pucFrame[MB_PDU_FUNC_WRITE_VALUE_OFF] == 0xFF ) - { - ucBuf[0] = 1; - } - else - { - ucBuf[0] = 0; - } - eRegStatus = - eMBMasterRegCoilsCB( &ucBuf[0], usRegAddress, 1, MB_REG_WRITE ); - - /* If an error occured convert it into a Modbus exception. */ - if( eRegStatus != MB_ENOERR ) - { - eStatus = prveMBError2Exception( eRegStatus ); - } - } - else - { - eStatus = MB_EX_ILLEGAL_DATA_VALUE; - } - } - else - { - /* Can't be a valid write coil register request because the length - * is incorrect. */ - eStatus = MB_EX_ILLEGAL_DATA_VALUE; - } - return eStatus; -} - -#endif - -#if MB_FUNC_WRITE_MULTIPLE_COILS_ENABLED > 0 - -/** - * This function will request write multiple coils. - * - * @param ucSndAddr salve address - * @param usCoilAddr coil start address - * @param usNCoils coil total number - * @param usCoilData data to be written - * @param lTimeOut timeout (-1 will waiting forever) - * - * @return error code - * - * @see eMBMasterReqWriteCoil - */ -eMBMasterReqErrCode -eMBMasterReqWriteMultipleCoils( UCHAR ucSndAddr, - USHORT usCoilAddr, USHORT usNCoils, UCHAR * pucDataBuffer, LONG lTimeOut) -{ - UCHAR *ucMBFrame; - USHORT usRegIndex = 0; - UCHAR ucByteCount; - eMBMasterReqErrCode eErrStatus = MB_MRE_NO_ERR; - - if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG; - else if ( usNCoils > MB_PDU_REQ_WRITE_MUL_COILCNT_MAX ) eErrStatus = MB_MRE_ILL_ARG; - else if ( xMBMasterRunResTake( lTimeOut ) == FALSE ) eErrStatus = MB_MRE_MASTER_BUSY; - else - { - vMBMasterGetPDUSndBuf(&ucMBFrame); - vMBMasterSetDestAddress(ucSndAddr); - ucMBFrame[MB_PDU_FUNC_OFF] = MB_FUNC_WRITE_MULTIPLE_COILS; - ucMBFrame[MB_PDU_REQ_WRITE_MUL_ADDR_OFF] = usCoilAddr >> 8; - ucMBFrame[MB_PDU_REQ_WRITE_MUL_ADDR_OFF + 1] = usCoilAddr; - ucMBFrame[MB_PDU_REQ_WRITE_MUL_COILCNT_OFF] = usNCoils >> 8; - ucMBFrame[MB_PDU_REQ_WRITE_MUL_COILCNT_OFF + 1] = usNCoils ; - if( ( usNCoils & 0x0007 ) != 0 ) - { - ucByteCount = ( UCHAR )( usNCoils / 8 + 1 ); - } - else - { - ucByteCount = ( UCHAR )( usNCoils / 8 ); - } - ucMBFrame[MB_PDU_REQ_WRITE_MUL_BYTECNT_OFF] = ucByteCount; - ucMBFrame += MB_PDU_REQ_WRITE_MUL_VALUES_OFF; - while( ucByteCount > usRegIndex) - { - *ucMBFrame++ = pucDataBuffer[usRegIndex++]; - } - vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_WRITE_MUL_SIZE_MIN + ucByteCount ); - ( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_SENT ); - eErrStatus = eMBMasterWaitRequestFinish( ); - } - return eErrStatus; -} - -eMBException -eMBMasterFuncWriteMultipleCoils( UCHAR * pucFrame, USHORT * usLen ) -{ - USHORT usRegAddress; - USHORT usCoilCnt; - UCHAR ucByteCount; - UCHAR ucByteCountVerify; - UCHAR *ucMBFrame; - - eMBException eStatus = MB_EX_NONE; - eMBErrorCode eRegStatus; - - /* If this request is broadcast, the *usLen is not need check. */ - if( ( *usLen == MB_PDU_FUNC_WRITE_MUL_SIZE ) || xMBMasterRequestIsBroadcast() ) - { - vMBMasterGetPDUSndBuf(&ucMBFrame); - usRegAddress = ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_MUL_ADDR_OFF] << 8 ); - usRegAddress |= ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_MUL_ADDR_OFF + 1] ); - usRegAddress++; - - usCoilCnt = ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_MUL_COILCNT_OFF] << 8 ); - usCoilCnt |= ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_MUL_COILCNT_OFF + 1] ); - - ucByteCount = ucMBFrame[MB_PDU_REQ_WRITE_MUL_BYTECNT_OFF]; - - /* Compute the number of expected bytes in the request. */ - if( ( usCoilCnt & 0x0007 ) != 0 ) - { - ucByteCountVerify = ( UCHAR )( usCoilCnt / 8 + 1 ); - } - else - { - ucByteCountVerify = ( UCHAR )( usCoilCnt / 8 ); - } - - if( ( usCoilCnt >= 1 ) && ( ucByteCountVerify == ucByteCount ) ) - { - eRegStatus = - eMBMasterRegCoilsCB( &ucMBFrame[MB_PDU_REQ_WRITE_MUL_VALUES_OFF], - usRegAddress, usCoilCnt, MB_REG_WRITE ); - - /* If an error occured convert it into a Modbus exception. */ - if( eRegStatus != MB_ENOERR ) - { - eStatus = prveMBError2Exception( eRegStatus ); - } - } - else - { - eStatus = MB_EX_ILLEGAL_DATA_VALUE; - } - } - else - { - /* Can't be a valid write coil register request because the length - * is incorrect. */ - eStatus = MB_EX_ILLEGAL_DATA_VALUE; - } - return eStatus; -} - -#endif -#endif diff --git a/components/net/freemodbus/modbus/functions/mbfuncdiag.c b/components/net/freemodbus/modbus/functions/mbfuncdiag.c deleted file mode 100644 index d75ffc0f72..0000000000 --- a/components/net/freemodbus/modbus/functions/mbfuncdiag.c +++ /dev/null @@ -1,29 +0,0 @@ -/* - * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. - * Copyright (c) 2006 Christian Walter <[email protected]> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * File: $Id: mbfuncdiag.c,v 1.3 2006/12/07 22:10:34 wolti Exp $ - */ diff --git a/components/net/freemodbus/modbus/functions/mbfuncdisc.c b/components/net/freemodbus/modbus/functions/mbfuncdisc.c deleted file mode 100644 index fb378441b9..0000000000 --- a/components/net/freemodbus/modbus/functions/mbfuncdisc.c +++ /dev/null @@ -1,125 +0,0 @@ - /* - * FreeRTOS Modbus Libary: A Modbus serial implementation for FreeRTOS - * Copyright (C) 2006 Christian Walter <[email protected]> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - - - -/* ----------------------- System includes ----------------------------------*/ -#include "stdlib.h" -#include "string.h" - -/* ----------------------- Platform includes --------------------------------*/ -#include "port.h" - -/* ----------------------- Modbus includes ----------------------------------*/ -#include "mb.h" -#include "mbframe.h" -#include "mbproto.h" -#include "mbconfig.h" - -/* ----------------------- Defines ------------------------------------------*/ -#define MB_PDU_FUNC_READ_ADDR_OFF ( MB_PDU_DATA_OFF ) -#define MB_PDU_FUNC_READ_DISCCNT_OFF ( MB_PDU_DATA_OFF + 2 ) -#define MB_PDU_FUNC_READ_SIZE ( 4 ) -#define MB_PDU_FUNC_READ_DISCCNT_MAX ( 0x07D0 ) - -/* ----------------------- Static functions ---------------------------------*/ -eMBException prveMBError2Exception( eMBErrorCode eErrorCode ); - -/* ----------------------- Start implementation -----------------------------*/ - -#if MB_FUNC_READ_COILS_ENABLED > 0 - -eMBException -eMBFuncReadDiscreteInputs( UCHAR * pucFrame, USHORT * usLen ) -{ - USHORT usRegAddress; - USHORT usDiscreteCnt; - UCHAR ucNBytes; - UCHAR *pucFrameCur; - - eMBException eStatus = MB_EX_NONE; - eMBErrorCode eRegStatus; - - if( *usLen == ( MB_PDU_FUNC_READ_SIZE + MB_PDU_SIZE_MIN ) ) - { - usRegAddress = ( USHORT )( pucFrame[MB_PDU_FUNC_READ_ADDR_OFF] << 8 ); - usRegAddress |= ( USHORT )( pucFrame[MB_PDU_FUNC_READ_ADDR_OFF + 1] ); - usRegAddress++; - - usDiscreteCnt = ( USHORT )( pucFrame[MB_PDU_FUNC_READ_DISCCNT_OFF] << 8 ); - usDiscreteCnt |= ( USHORT )( pucFrame[MB_PDU_FUNC_READ_DISCCNT_OFF + 1] ); - - /* Check if the number of registers to read is valid. If not - * return Modbus illegal data value exception. - */ - if( ( usDiscreteCnt >= 1 ) && - ( usDiscreteCnt < MB_PDU_FUNC_READ_DISCCNT_MAX ) ) - { - /* Set the current PDU data pointer to the beginning. */ - pucFrameCur = &pucFrame[MB_PDU_FUNC_OFF]; - *usLen = MB_PDU_FUNC_OFF; - - /* First byte contains the function code. */ - *pucFrameCur++ = MB_FUNC_READ_DISCRETE_INPUTS; - *usLen += 1; - - /* Test if the quantity of coils is a multiple of 8. If not last - * byte is only partially field with unused coils set to zero. */ - if( ( usDiscreteCnt & 0x0007 ) != 0 ) - { - ucNBytes = ( UCHAR ) ( usDiscreteCnt / 8 + 1 ); - } - else - { - ucNBytes = ( UCHAR ) ( usDiscreteCnt / 8 ); - } - *pucFrameCur++ = ucNBytes; - *usLen += 1; - - eRegStatus = - eMBRegDiscreteCB( pucFrameCur, usRegAddress, usDiscreteCnt ); - - /* If an error occured convert it into a Modbus exception. */ - if( eRegStatus != MB_ENOERR ) - { - eStatus = prveMBError2Exception( eRegStatus ); - } - else - { - /* The response contains the function code, the starting address - * and the quantity of registers. We reuse the old values in the - * buffer because they are still valid. */ - *usLen += ucNBytes;; - } - } - else - { - eStatus = MB_EX_ILLEGAL_DATA_VALUE; - } - } - else - { - /* Can't be a valid read coil register request because the length - * is incorrect. */ - eStatus = MB_EX_ILLEGAL_DATA_VALUE; - } - return eStatus; -} - -#endif diff --git a/components/net/freemodbus/modbus/functions/mbfuncdisc_m.c b/components/net/freemodbus/modbus/functions/mbfuncdisc_m.c deleted file mode 100644 index 6c8d6c4741..0000000000 --- a/components/net/freemodbus/modbus/functions/mbfuncdisc_m.c +++ /dev/null @@ -1,162 +0,0 @@ -/* - * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. - * Copyright (C) 2013 Armink <[email protected]> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * File: $Id: mbfuncdisc_m.c,v 1.60 2013/10/15 8:48:20 Armink Add Master Functions Exp $ - */ - - - -/* ----------------------- System includes ----------------------------------*/ -#include "stdlib.h" -#include "string.h" - -/* ----------------------- Platform includes --------------------------------*/ -#include "port.h" - -/* ----------------------- Modbus includes ----------------------------------*/ -#include "mb.h" -#include "mb_m.h" -#include "mbframe.h" -#include "mbproto.h" -#include "mbconfig.h" - -/* ----------------------- Defines ------------------------------------------*/ -#define MB_PDU_REQ_READ_ADDR_OFF ( MB_PDU_DATA_OFF + 0 ) -#define MB_PDU_REQ_READ_DISCCNT_OFF ( MB_PDU_DATA_OFF + 2 ) -#define MB_PDU_REQ_READ_SIZE ( 4 ) -#define MB_PDU_FUNC_READ_DISCCNT_OFF ( MB_PDU_DATA_OFF + 0 ) -#define MB_PDU_FUNC_READ_VALUES_OFF ( MB_PDU_DATA_OFF + 1 ) -#define MB_PDU_FUNC_READ_SIZE_MIN ( 1 ) - -/* ----------------------- Static functions ---------------------------------*/ -eMBException prveMBError2Exception( eMBErrorCode eErrorCode ); - -/* ----------------------- Start implementation -----------------------------*/ -#if MB_MASTER_RTU_ENABLED > 0 || MB_MASTER_ASCII_ENABLED > 0 -#if MB_FUNC_READ_DISCRETE_INPUTS_ENABLED > 0 - -/** - * This function will request read discrete inputs. - * - * @param ucSndAddr salve address - * @param usDiscreteAddr discrete start address - * @param usNDiscreteIn discrete total number - * @param lTimeOut timeout (-1 will waiting forever) - * - * @return error code - */ -eMBMasterReqErrCode -eMBMasterReqReadDiscreteInputs( UCHAR ucSndAddr, USHORT usDiscreteAddr, USHORT usNDiscreteIn, LONG lTimeOut ) -{ - UCHAR *ucMBFrame; - eMBMasterReqErrCode eErrStatus = MB_MRE_NO_ERR; - - if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG; - else if ( xMBMasterRunResTake( lTimeOut ) == FALSE ) eErrStatus = MB_MRE_MASTER_BUSY; - else - { - vMBMasterGetPDUSndBuf(&ucMBFrame); - vMBMasterSetDestAddress(ucSndAddr); - ucMBFrame[MB_PDU_FUNC_OFF] = MB_FUNC_READ_DISCRETE_INPUTS; - ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF] = usDiscreteAddr >> 8; - ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF + 1] = usDiscreteAddr; - ucMBFrame[MB_PDU_REQ_READ_DISCCNT_OFF ] = usNDiscreteIn >> 8; - ucMBFrame[MB_PDU_REQ_READ_DISCCNT_OFF + 1] = usNDiscreteIn; - vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_READ_SIZE ); - ( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_SENT ); - eErrStatus = eMBMasterWaitRequestFinish( ); - } - return eErrStatus; -} - -eMBException -eMBMasterFuncReadDiscreteInputs( UCHAR * pucFrame, USHORT * usLen ) -{ - USHORT usRegAddress; - USHORT usDiscreteCnt; - UCHAR ucNBytes; - UCHAR *ucMBFrame; - - eMBException eStatus = MB_EX_NONE; - eMBErrorCode eRegStatus; - - /* If this request is broadcast, and it's read mode. This request don't need execute. */ - if ( xMBMasterRequestIsBroadcast() ) - { - eStatus = MB_EX_NONE; - } - else if( *usLen >= MB_PDU_SIZE_MIN + MB_PDU_FUNC_READ_SIZE_MIN ) - { - vMBMasterGetPDUSndBuf(&ucMBFrame); - usRegAddress = ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF] << 8 ); - usRegAddress |= ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF + 1] ); - usRegAddress++; - - usDiscreteCnt = ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_DISCCNT_OFF] << 8 ); - usDiscreteCnt |= ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_DISCCNT_OFF + 1] ); - - /* Test if the quantity of coils is a multiple of 8. If not last - * byte is only partially field with unused coils set to zero. */ - if( ( usDiscreteCnt & 0x0007 ) != 0 ) - { - ucNBytes = ( UCHAR )( usDiscreteCnt / 8 + 1 ); - } - else - { - ucNBytes = ( UCHAR )( usDiscreteCnt / 8 ); - } - - /* Check if the number of registers to read is valid. If not - * return Modbus illegal data value exception. - */ - if ((usDiscreteCnt >= 1) && ucNBytes == pucFrame[MB_PDU_FUNC_READ_DISCCNT_OFF]) - { - /* Make callback to fill the buffer. */ - eRegStatus = eMBMasterRegDiscreteCB( &pucFrame[MB_PDU_FUNC_READ_VALUES_OFF], usRegAddress, usDiscreteCnt ); - - /* If an error occured convert it into a Modbus exception. */ - if( eRegStatus != MB_ENOERR ) - { - eStatus = prveMBError2Exception( eRegStatus ); - } - } - else - { - eStatus = MB_EX_ILLEGAL_DATA_VALUE; - } - } - else - { - /* Can't be a valid read coil register request because the length - * is incorrect. */ - eStatus = MB_EX_ILLEGAL_DATA_VALUE; - } - return eStatus; -} - -#endif -#endif diff --git a/components/net/freemodbus/modbus/functions/mbfuncholding.c b/components/net/freemodbus/modbus/functions/mbfuncholding.c deleted file mode 100644 index 7921302f96..0000000000 --- a/components/net/freemodbus/modbus/functions/mbfuncholding.c +++ /dev/null @@ -1,308 +0,0 @@ -/* - * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. - * Copyright (c) 2006 Christian Walter <[email protected]> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * File: $Id: mbfuncholding.c,v 1.12 2007/02/18 23:48:22 wolti Exp $ - */ - -/* ----------------------- System includes ----------------------------------*/ -#include "stdlib.h" -#include "string.h" - -/* ----------------------- Platform includes --------------------------------*/ -#include "port.h" - -/* ----------------------- Modbus includes ----------------------------------*/ -#include "mb.h" -#include "mbframe.h" -#include "mbproto.h" -#include "mbconfig.h" - -/* ----------------------- Defines ------------------------------------------*/ -#define MB_PDU_FUNC_READ_ADDR_OFF ( MB_PDU_DATA_OFF + 0) -#define MB_PDU_FUNC_READ_REGCNT_OFF ( MB_PDU_DATA_OFF + 2 ) -#define MB_PDU_FUNC_READ_SIZE ( 4 ) -#define MB_PDU_FUNC_READ_REGCNT_MAX ( 0x007D ) - -#define MB_PDU_FUNC_WRITE_ADDR_OFF ( MB_PDU_DATA_OFF + 0) -#define MB_PDU_FUNC_WRITE_VALUE_OFF ( MB_PDU_DATA_OFF + 2 ) -#define MB_PDU_FUNC_WRITE_SIZE ( 4 ) - -#define MB_PDU_FUNC_WRITE_MUL_ADDR_OFF ( MB_PDU_DATA_OFF + 0 ) -#define MB_PDU_FUNC_WRITE_MUL_REGCNT_OFF ( MB_PDU_DATA_OFF + 2 ) -#define MB_PDU_FUNC_WRITE_MUL_BYTECNT_OFF ( MB_PDU_DATA_OFF + 4 ) -#define MB_PDU_FUNC_WRITE_MUL_VALUES_OFF ( MB_PDU_DATA_OFF + 5 ) -#define MB_PDU_FUNC_WRITE_MUL_SIZE_MIN ( 5 ) -#define MB_PDU_FUNC_WRITE_MUL_REGCNT_MAX ( 0x0078 ) - -#define MB_PDU_FUNC_READWRITE_READ_ADDR_OFF ( MB_PDU_DATA_OFF + 0 ) -#define MB_PDU_FUNC_READWRITE_READ_REGCNT_OFF ( MB_PDU_DATA_OFF + 2 ) -#define MB_PDU_FUNC_READWRITE_WRITE_ADDR_OFF ( MB_PDU_DATA_OFF + 4 ) -#define MB_PDU_FUNC_READWRITE_WRITE_REGCNT_OFF ( MB_PDU_DATA_OFF + 6 ) -#define MB_PDU_FUNC_READWRITE_BYTECNT_OFF ( MB_PDU_DATA_OFF + 8 ) -#define MB_PDU_FUNC_READWRITE_WRITE_VALUES_OFF ( MB_PDU_DATA_OFF + 9 ) -#define MB_PDU_FUNC_READWRITE_SIZE_MIN ( 9 ) - -/* ----------------------- Static functions ---------------------------------*/ -eMBException prveMBError2Exception( eMBErrorCode eErrorCode ); - -/* ----------------------- Start implementation -----------------------------*/ - -#if MB_FUNC_WRITE_HOLDING_ENABLED > 0 - -eMBException -eMBFuncWriteHoldingRegister( UCHAR * pucFrame, USHORT * usLen ) -{ - USHORT usRegAddress; - eMBException eStatus = MB_EX_NONE; - eMBErrorCode eRegStatus; - - if( *usLen == ( MB_PDU_FUNC_WRITE_SIZE + MB_PDU_SIZE_MIN ) ) - { - usRegAddress = ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_ADDR_OFF] << 8 ); - usRegAddress |= ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_ADDR_OFF + 1] ); - usRegAddress++; - - /* Make callback to update the value. */ - eRegStatus = eMBRegHoldingCB( &pucFrame[MB_PDU_FUNC_WRITE_VALUE_OFF], - usRegAddress, 1, MB_REG_WRITE ); - - /* If an error occured convert it into a Modbus exception. */ - if( eRegStatus != MB_ENOERR ) - { - eStatus = prveMBError2Exception( eRegStatus ); - } - } - else - { - /* Can't be a valid request because the length is incorrect. */ - eStatus = MB_EX_ILLEGAL_DATA_VALUE; - } - return eStatus; -} -#endif - -#if MB_FUNC_WRITE_MULTIPLE_HOLDING_ENABLED > 0 -eMBException -eMBFuncWriteMultipleHoldingRegister( UCHAR * pucFrame, USHORT * usLen ) -{ - USHORT usRegAddress; - USHORT usRegCount; - UCHAR ucRegByteCount; - - eMBException eStatus = MB_EX_NONE; - eMBErrorCode eRegStatus; - - if( *usLen >= ( MB_PDU_FUNC_WRITE_MUL_SIZE_MIN + MB_PDU_SIZE_MIN ) ) - { - usRegAddress = ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_MUL_ADDR_OFF] << 8 ); - usRegAddress |= ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_MUL_ADDR_OFF + 1] ); - usRegAddress++; - - usRegCount = ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_MUL_REGCNT_OFF] << 8 ); - usRegCount |= ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_MUL_REGCNT_OFF + 1] ); - - ucRegByteCount = pucFrame[MB_PDU_FUNC_WRITE_MUL_BYTECNT_OFF]; - - if( ( usRegCount >= 1 ) && - ( usRegCount <= MB_PDU_FUNC_WRITE_MUL_REGCNT_MAX ) && - ( ucRegByteCount == ( UCHAR ) ( 2 * usRegCount ) ) ) - { - /* Make callback to update the register values. */ - eRegStatus = - eMBRegHoldingCB( &pucFrame[MB_PDU_FUNC_WRITE_MUL_VALUES_OFF], - usRegAddress, usRegCount, MB_REG_WRITE ); - - /* If an error occured convert it into a Modbus exception. */ - if( eRegStatus != MB_ENOERR ) - { - eStatus = prveMBError2Exception( eRegStatus ); - } - else - { - /* The response contains the function code, the starting - * address and the quantity of registers. We reuse the - * old values in the buffer because they are still valid. - */ - *usLen = MB_PDU_FUNC_WRITE_MUL_BYTECNT_OFF; - } - } - else - { - eStatus = MB_EX_ILLEGAL_DATA_VALUE; - } - } - else - { - /* Can't be a valid request because the length is incorrect. */ - eStatus = MB_EX_ILLEGAL_DATA_VALUE; - } - return eStatus; -} -#endif - -#if MB_FUNC_READ_HOLDING_ENABLED > 0 - -eMBException -eMBFuncReadHoldingRegister( UCHAR * pucFrame, USHORT * usLen ) -{ - USHORT usRegAddress; - USHORT usRegCount; - UCHAR *pucFrameCur; - - eMBException eStatus = MB_EX_NONE; - eMBErrorCode eRegStatus; - - if( *usLen == ( MB_PDU_FUNC_READ_SIZE + MB_PDU_SIZE_MIN ) ) - { - usRegAddress = ( USHORT )( pucFrame[MB_PDU_FUNC_READ_ADDR_OFF] << 8 ); - usRegAddress |= ( USHORT )( pucFrame[MB_PDU_FUNC_READ_ADDR_OFF + 1] ); - usRegAddress++; - - usRegCount = ( USHORT )( pucFrame[MB_PDU_FUNC_READ_REGCNT_OFF] << 8 ); - usRegCount |= ( USHORT )( pucFrame[MB_PDU_FUNC_READ_REGCNT_OFF + 1] ); - - /* Check if the number of registers to read is valid. If not - * return Modbus illegal data value exception. - */ - if( ( usRegCount >= 1 ) && ( usRegCount <= MB_PDU_FUNC_READ_REGCNT_MAX ) ) - { - /* Set the current PDU data pointer to the beginning. */ - pucFrameCur = &pucFrame[MB_PDU_FUNC_OFF]; - *usLen = MB_PDU_FUNC_OFF; - - /* First byte contains the function code. */ - *pucFrameCur++ = MB_FUNC_READ_HOLDING_REGISTER; - *usLen += 1; - - /* Second byte in the response contain the number of bytes. */ - *pucFrameCur++ = ( UCHAR ) ( usRegCount * 2 ); - *usLen += 1; - - /* Make callback to fill the buffer. */ - eRegStatus = eMBRegHoldingCB( pucFrameCur, usRegAddress, usRegCount, MB_REG_READ ); - /* If an error occured convert it into a Modbus exception. */ - if( eRegStatus != MB_ENOERR ) - { - eStatus = prveMBError2Exception( eRegStatus ); - } - else - { - *usLen += usRegCount * 2; - } - } - else - { - eStatus = MB_EX_ILLEGAL_DATA_VALUE; - } - } - else - { - /* Can't be a valid request because the length is incorrect. */ - eStatus = MB_EX_ILLEGAL_DATA_VALUE; - } - return eStatus; -} - -#endif - -#if MB_FUNC_READWRITE_HOLDING_ENABLED > 0 - -eMBException -eMBFuncReadWriteMultipleHoldingRegister( UCHAR * pucFrame, USHORT * usLen ) -{ - USHORT usRegReadAddress; - USHORT usRegReadCount; - USHORT usRegWriteAddress; - USHORT usRegWriteCount; - UCHAR ucRegWriteByteCount; - UCHAR *pucFrameCur; - - eMBException eStatus = MB_EX_NONE; - eMBErrorCode eRegStatus; - - if( *usLen >= ( MB_PDU_FUNC_READWRITE_SIZE_MIN + MB_PDU_SIZE_MIN ) ) - { - usRegReadAddress = ( USHORT )( pucFrame[MB_PDU_FUNC_READWRITE_READ_ADDR_OFF] << 8U ); - usRegReadAddress |= ( USHORT )( pucFrame[MB_PDU_FUNC_READWRITE_READ_ADDR_OFF + 1] ); - usRegReadAddress++; - - usRegReadCount = ( USHORT )( pucFrame[MB_PDU_FUNC_READWRITE_READ_REGCNT_OFF] << 8U ); - usRegReadCount |= ( USHORT )( pucFrame[MB_PDU_FUNC_READWRITE_READ_REGCNT_OFF + 1] ); - - usRegWriteAddress = ( USHORT )( pucFrame[MB_PDU_FUNC_READWRITE_WRITE_ADDR_OFF] << 8U ); - usRegWriteAddress |= ( USHORT )( pucFrame[MB_PDU_FUNC_READWRITE_WRITE_ADDR_OFF + 1] ); - usRegWriteAddress++; - - usRegWriteCount = ( USHORT )( pucFrame[MB_PDU_FUNC_READWRITE_WRITE_REGCNT_OFF] << 8U ); - usRegWriteCount |= ( USHORT )( pucFrame[MB_PDU_FUNC_READWRITE_WRITE_REGCNT_OFF + 1] ); - - ucRegWriteByteCount = pucFrame[MB_PDU_FUNC_READWRITE_BYTECNT_OFF]; - - if( ( usRegReadCount >= 1 ) && ( usRegReadCount <= 0x7D ) && - ( usRegWriteCount >= 1 ) && ( usRegWriteCount <= 0x79 ) && - ( ( 2 * usRegWriteCount ) == ucRegWriteByteCount ) ) - { - /* Make callback to update the register values. */ - eRegStatus = eMBRegHoldingCB( &pucFrame[MB_PDU_FUNC_READWRITE_WRITE_VALUES_OFF], - usRegWriteAddress, usRegWriteCount, MB_REG_WRITE ); - - if( eRegStatus == MB_ENOERR ) - { - /* Set the current PDU data pointer to the beginning. */ - pucFrameCur = &pucFrame[MB_PDU_FUNC_OFF]; - *usLen = MB_PDU_FUNC_OFF; - - /* First byte contains the function code. */ - *pucFrameCur++ = MB_FUNC_READWRITE_MULTIPLE_REGISTERS; - *usLen += 1; - - /* Second byte in the response contain the number of bytes. */ - *pucFrameCur++ = ( UCHAR ) ( usRegReadCount * 2 ); - *usLen += 1; - - /* Make the read callback. */ - eRegStatus = - eMBRegHoldingCB( pucFrameCur, usRegReadAddress, usRegReadCount, MB_REG_READ ); - if( eRegStatus == MB_ENOERR ) - { - *usLen += 2 * usRegReadCount; - } - } - if( eRegStatus != MB_ENOERR ) - { - eStatus = prveMBError2Exception( eRegStatus ); - } - } - else - { - eStatus = MB_EX_ILLEGAL_DATA_VALUE; - } - } - return eStatus; -} - -#endif diff --git a/components/net/freemodbus/modbus/functions/mbfuncholding_m.c b/components/net/freemodbus/modbus/functions/mbfuncholding_m.c deleted file mode 100644 index e1fe69e383..0000000000 --- a/components/net/freemodbus/modbus/functions/mbfuncholding_m.c +++ /dev/null @@ -1,455 +0,0 @@ -/* - * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. - * Copyright (C) 2013 Armink <[email protected]> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * File: $Id: mbfuncholding_m.c,v 1.60 2013/09/02 14:13:40 Armink Add Master Functions Exp $ - */ - -/* ----------------------- System includes ----------------------------------*/ -#include "stdlib.h" -#include "string.h" - -/* ----------------------- Platform includes --------------------------------*/ -#include "port.h" - -/* ----------------------- Modbus includes ----------------------------------*/ -#include "mb.h" -#include "mb_m.h" -#include "mbframe.h" -#include "mbproto.h" -#include "mbconfig.h" - -/* ----------------------- Defines ------------------------------------------*/ -#define MB_PDU_REQ_READ_ADDR_OFF ( MB_PDU_DATA_OFF + 0 ) -#define MB_PDU_REQ_READ_REGCNT_OFF ( MB_PDU_DATA_OFF + 2 ) -#define MB_PDU_REQ_READ_SIZE ( 4 ) -#define MB_PDU_FUNC_READ_REGCNT_MAX ( 0x007D ) -#define MB_PDU_FUNC_READ_BYTECNT_OFF ( MB_PDU_DATA_OFF + 0 ) -#define MB_PDU_FUNC_READ_VALUES_OFF ( MB_PDU_DATA_OFF + 1 ) -#define MB_PDU_FUNC_READ_SIZE_MIN ( 1 ) - -#define MB_PDU_REQ_WRITE_ADDR_OFF ( MB_PDU_DATA_OFF + 0) -#define MB_PDU_REQ_WRITE_VALUE_OFF ( MB_PDU_DATA_OFF + 2 ) -#define MB_PDU_REQ_WRITE_SIZE ( 4 ) -#define MB_PDU_FUNC_WRITE_ADDR_OFF ( MB_PDU_DATA_OFF + 0) -#define MB_PDU_FUNC_WRITE_VALUE_OFF ( MB_PDU_DATA_OFF + 2 ) -#define MB_PDU_FUNC_WRITE_SIZE ( 4 ) - -#define MB_PDU_REQ_WRITE_MUL_ADDR_OFF ( MB_PDU_DATA_OFF + 0 ) -#define MB_PDU_REQ_WRITE_MUL_REGCNT_OFF ( MB_PDU_DATA_OFF + 2 ) -#define MB_PDU_REQ_WRITE_MUL_BYTECNT_OFF ( MB_PDU_DATA_OFF + 4 ) -#define MB_PDU_REQ_WRITE_MUL_VALUES_OFF ( MB_PDU_DATA_OFF + 5 ) -#define MB_PDU_REQ_WRITE_MUL_SIZE_MIN ( 5 ) -#define MB_PDU_REQ_WRITE_MUL_REGCNT_MAX ( 0x0078 ) -#define MB_PDU_FUNC_WRITE_MUL_ADDR_OFF ( MB_PDU_DATA_OFF + 0 ) -#define MB_PDU_FUNC_WRITE_MUL_REGCNT_OFF ( MB_PDU_DATA_OFF + 2 ) -#define MB_PDU_FUNC_WRITE_MUL_SIZE ( 4 ) - -#define MB_PDU_REQ_READWRITE_READ_ADDR_OFF ( MB_PDU_DATA_OFF + 0 ) -#define MB_PDU_REQ_READWRITE_READ_REGCNT_OFF ( MB_PDU_DATA_OFF + 2 ) -#define MB_PDU_REQ_READWRITE_WRITE_ADDR_OFF ( MB_PDU_DATA_OFF + 4 ) -#define MB_PDU_REQ_READWRITE_WRITE_REGCNT_OFF ( MB_PDU_DATA_OFF + 6 ) -#define MB_PDU_REQ_READWRITE_WRITE_BYTECNT_OFF ( MB_PDU_DATA_OFF + 8 ) -#define MB_PDU_REQ_READWRITE_WRITE_VALUES_OFF ( MB_PDU_DATA_OFF + 9 ) -#define MB_PDU_REQ_READWRITE_SIZE_MIN ( 9 ) -#define MB_PDU_FUNC_READWRITE_READ_BYTECNT_OFF ( MB_PDU_DATA_OFF + 0 ) -#define MB_PDU_FUNC_READWRITE_READ_VALUES_OFF ( MB_PDU_DATA_OFF + 1 ) -#define MB_PDU_FUNC_READWRITE_SIZE_MIN ( 1 ) - -/* ----------------------- Static functions ---------------------------------*/ -eMBException prveMBError2Exception( eMBErrorCode eErrorCode ); - -/* ----------------------- Start implementation -----------------------------*/ -#if MB_MASTER_RTU_ENABLED > 0 || MB_MASTER_ASCII_ENABLED > 0 -#if MB_FUNC_WRITE_HOLDING_ENABLED > 0 - -/** - * This function will request write holding register. - * - * @param ucSndAddr salve address - * @param usRegAddr register start address - * @param usRegData register data to be written - * @param lTimeOut timeout (-1 will waiting forever) - * - * @return error code - */ -eMBMasterReqErrCode -eMBMasterReqWriteHoldingRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usRegData, LONG lTimeOut ) -{ - UCHAR *ucMBFrame; - eMBMasterReqErrCode eErrStatus = MB_MRE_NO_ERR; - - if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG; - else if ( xMBMasterRunResTake( lTimeOut ) == FALSE ) eErrStatus = MB_MRE_MASTER_BUSY; - else - { - vMBMasterGetPDUSndBuf(&ucMBFrame); - vMBMasterSetDestAddress(ucSndAddr); - ucMBFrame[MB_PDU_FUNC_OFF] = MB_FUNC_WRITE_REGISTER; - ucMBFrame[MB_PDU_REQ_WRITE_ADDR_OFF] = usRegAddr >> 8; - ucMBFrame[MB_PDU_REQ_WRITE_ADDR_OFF + 1] = usRegAddr; - ucMBFrame[MB_PDU_REQ_WRITE_VALUE_OFF] = usRegData >> 8; - ucMBFrame[MB_PDU_REQ_WRITE_VALUE_OFF + 1] = usRegData ; - vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_WRITE_SIZE ); - ( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_SENT ); - eErrStatus = eMBMasterWaitRequestFinish( ); - } - return eErrStatus; -} - -eMBException -eMBMasterFuncWriteHoldingRegister( UCHAR * pucFrame, USHORT * usLen ) -{ - USHORT usRegAddress; - eMBException eStatus = MB_EX_NONE; - eMBErrorCode eRegStatus; - - if( *usLen == ( MB_PDU_SIZE_MIN + MB_PDU_FUNC_WRITE_SIZE ) ) - { - usRegAddress = ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_ADDR_OFF] << 8 ); - usRegAddress |= ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_ADDR_OFF + 1] ); - usRegAddress++; - - /* Make callback to update the value. */ - eRegStatus = eMBMasterRegHoldingCB( &pucFrame[MB_PDU_FUNC_WRITE_VALUE_OFF], - usRegAddress, 1, MB_REG_WRITE ); - - /* If an error occured convert it into a Modbus exception. */ - if( eRegStatus != MB_ENOERR ) - { - eStatus = prveMBError2Exception( eRegStatus ); - } - } - else - { - /* Can't be a valid request because the length is incorrect. */ - eStatus = MB_EX_ILLEGAL_DATA_VALUE; - } - return eStatus; -} -#endif - -#if MB_FUNC_WRITE_MULTIPLE_HOLDING_ENABLED > 0 - -/** - * This function will request write multiple holding register. - * - * @param ucSndAddr salve address - * @param usRegAddr register start address - * @param usNRegs register total number - * @param pusDataBuffer data to be written - * @param lTimeOut timeout (-1 will waiting forever) - * - * @return error code - */ -eMBMasterReqErrCode -eMBMasterReqWriteMultipleHoldingRegister( UCHAR ucSndAddr, - USHORT usRegAddr, USHORT usNRegs, USHORT * pusDataBuffer, LONG lTimeOut ) -{ - UCHAR *ucMBFrame; - USHORT usRegIndex = 0; - eMBMasterReqErrCode eErrStatus = MB_MRE_NO_ERR; - - if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG; - else if ( xMBMasterRunResTake( lTimeOut ) == FALSE ) eErrStatus = MB_MRE_MASTER_BUSY; - else - { - vMBMasterGetPDUSndBuf(&ucMBFrame); - vMBMasterSetDestAddress(ucSndAddr); - ucMBFrame[MB_PDU_FUNC_OFF] = MB_FUNC_WRITE_MULTIPLE_REGISTERS; - ucMBFrame[MB_PDU_REQ_WRITE_MUL_ADDR_OFF] = usRegAddr >> 8; - ucMBFrame[MB_PDU_REQ_WRITE_MUL_ADDR_OFF + 1] = usRegAddr; - ucMBFrame[MB_PDU_REQ_WRITE_MUL_REGCNT_OFF] = usNRegs >> 8; - ucMBFrame[MB_PDU_REQ_WRITE_MUL_REGCNT_OFF + 1] = usNRegs ; - ucMBFrame[MB_PDU_REQ_WRITE_MUL_BYTECNT_OFF] = usNRegs * 2; - ucMBFrame += MB_PDU_REQ_WRITE_MUL_VALUES_OFF; - while( usNRegs > usRegIndex) - { - *ucMBFrame++ = pusDataBuffer[usRegIndex] >> 8; - *ucMBFrame++ = pusDataBuffer[usRegIndex++] ; - } - vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_WRITE_MUL_SIZE_MIN + 2*usNRegs ); - ( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_SENT ); - eErrStatus = eMBMasterWaitRequestFinish( ); - } - return eErrStatus; -} - -eMBException -eMBMasterFuncWriteMultipleHoldingRegister( UCHAR * pucFrame, USHORT * usLen ) -{ - UCHAR *ucMBFrame; - USHORT usRegAddress; - USHORT usRegCount; - UCHAR ucRegByteCount; - - eMBException eStatus = MB_EX_NONE; - eMBErrorCode eRegStatus; - - /* If this request is broadcast, the *usLen is not need check. */ - if( ( *usLen == MB_PDU_SIZE_MIN + MB_PDU_FUNC_WRITE_MUL_SIZE ) || xMBMasterRequestIsBroadcast() ) - { - vMBMasterGetPDUSndBuf(&ucMBFrame); - usRegAddress = ( USHORT )( ucMBFrame[MB_PDU_REQ_WRITE_MUL_ADDR_OFF] << 8 ); - usRegAddress |= ( USHORT )( ucMBFrame[MB_PDU_REQ_WRITE_MUL_ADDR_OFF + 1] ); - usRegAddress++; - - usRegCount = ( USHORT )( ucMBFrame[MB_PDU_REQ_WRITE_MUL_REGCNT_OFF] << 8 ); - usRegCount |= ( USHORT )( ucMBFrame[MB_PDU_REQ_WRITE_MUL_REGCNT_OFF + 1] ); - - ucRegByteCount = ucMBFrame[MB_PDU_REQ_WRITE_MUL_BYTECNT_OFF]; - - if( ucRegByteCount == 2 * usRegCount ) - { - /* Make callback to update the register values. */ - eRegStatus = - eMBMasterRegHoldingCB( &ucMBFrame[MB_PDU_REQ_WRITE_MUL_VALUES_OFF], - usRegAddress, usRegCount, MB_REG_WRITE ); - - /* If an error occured convert it into a Modbus exception. */ - if( eRegStatus != MB_ENOERR ) - { - eStatus = prveMBError2Exception( eRegStatus ); - } - } - else - { - eStatus = MB_EX_ILLEGAL_DATA_VALUE; - } - } - else - { - /* Can't be a valid request because the length is incorrect. */ - eStatus = MB_EX_ILLEGAL_DATA_VALUE; - } - return eStatus; -} -#endif - -#if MB_FUNC_READ_HOLDING_ENABLED > 0 - -/** - * This function will request read holding register. - * - * @param ucSndAddr salve address - * @param usRegAddr register start address - * @param usNRegs register total number - * @param lTimeOut timeout (-1 will waiting forever) - * - * @return error code - */ -eMBMasterReqErrCode -eMBMasterReqReadHoldingRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usNRegs, LONG lTimeOut ) -{ - UCHAR *ucMBFrame; - eMBMasterReqErrCode eErrStatus = MB_MRE_NO_ERR; - - if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG; - else if ( xMBMasterRunResTake( lTimeOut ) == FALSE ) eErrStatus = MB_MRE_MASTER_BUSY; - else - { - vMBMasterGetPDUSndBuf(&ucMBFrame); - vMBMasterSetDestAddress(ucSndAddr); - ucMBFrame[MB_PDU_FUNC_OFF] = MB_FUNC_READ_HOLDING_REGISTER; - ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF] = usRegAddr >> 8; - ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF + 1] = usRegAddr; - ucMBFrame[MB_PDU_REQ_READ_REGCNT_OFF] = usNRegs >> 8; - ucMBFrame[MB_PDU_REQ_READ_REGCNT_OFF + 1] = usNRegs; - vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_READ_SIZE ); - ( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_SENT ); - eErrStatus = eMBMasterWaitRequestFinish( ); - } - return eErrStatus; -} - -eMBException -eMBMasterFuncReadHoldingRegister( UCHAR * pucFrame, USHORT * usLen ) -{ - UCHAR *ucMBFrame; - USHORT usRegAddress; - USHORT usRegCount; - - eMBException eStatus = MB_EX_NONE; - eMBErrorCode eRegStatus; - - /* If this request is broadcast, and it's read mode. This request don't need execute. */ - if ( xMBMasterRequestIsBroadcast() ) - { - eStatus = MB_EX_NONE; - } - else if( *usLen >= MB_PDU_SIZE_MIN + MB_PDU_FUNC_READ_SIZE_MIN ) - { - vMBMasterGetPDUSndBuf(&ucMBFrame); - usRegAddress = ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF] << 8 ); - usRegAddress |= ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF + 1] ); - usRegAddress++; - - usRegCount = ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_REGCNT_OFF] << 8 ); - usRegCount |= ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_REGCNT_OFF + 1] ); - - /* Check if the number of registers to read is valid. If not - * return Modbus illegal data value exception. - */ - if( ( usRegCount >= 1 ) && ( 2 * usRegCount == pucFrame[MB_PDU_FUNC_READ_BYTECNT_OFF] ) ) - { - /* Make callback to fill the buffer. */ - eRegStatus = eMBMasterRegHoldingCB( &pucFrame[MB_PDU_FUNC_READ_VALUES_OFF], usRegAddress, usRegCount, MB_REG_READ ); - /* If an error occured convert it into a Modbus exception. */ - if( eRegStatus != MB_ENOERR ) - { - eStatus = prveMBError2Exception( eRegStatus ); - } - } - else - { - eStatus = MB_EX_ILLEGAL_DATA_VALUE; - } - } - else - { - /* Can't be a valid request because the length is incorrect. */ - eStatus = MB_EX_ILLEGAL_DATA_VALUE; - } - return eStatus; -} - -#endif - -#if MB_FUNC_READWRITE_HOLDING_ENABLED > 0 - -/** - * This function will request read and write holding register. - * - * @param ucSndAddr salve address - * @param usReadRegAddr read register start address - * @param usNReadRegs read register total number - * @param pusDataBuffer data to be written - * @param usWriteRegAddr write register start address - * @param usNWriteRegs write register total number - * @param lTimeOut timeout (-1 will waiting forever) - * - * @return error code - */ -eMBMasterReqErrCode -eMBMasterReqReadWriteMultipleHoldingRegister( UCHAR ucSndAddr, - USHORT usReadRegAddr, USHORT usNReadRegs, USHORT * pusDataBuffer, - USHORT usWriteRegAddr, USHORT usNWriteRegs, LONG lTimeOut ) -{ - UCHAR *ucMBFrame; - USHORT usRegIndex = 0; - eMBMasterReqErrCode eErrStatus = MB_MRE_NO_ERR; - - if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG; - else if ( xMBMasterRunResTake( lTimeOut ) == FALSE ) eErrStatus = MB_MRE_MASTER_BUSY; - else - { - vMBMasterGetPDUSndBuf(&ucMBFrame); - vMBMasterSetDestAddress(ucSndAddr); - ucMBFrame[MB_PDU_FUNC_OFF] = MB_FUNC_READWRITE_MULTIPLE_REGISTERS; - ucMBFrame[MB_PDU_REQ_READWRITE_READ_ADDR_OFF] = usReadRegAddr >> 8; - ucMBFrame[MB_PDU_REQ_READWRITE_READ_ADDR_OFF + 1] = usReadRegAddr; - ucMBFrame[MB_PDU_REQ_READWRITE_READ_REGCNT_OFF] = usNReadRegs >> 8; - ucMBFrame[MB_PDU_REQ_READWRITE_READ_REGCNT_OFF + 1] = usNReadRegs ; - ucMBFrame[MB_PDU_REQ_READWRITE_WRITE_ADDR_OFF] = usWriteRegAddr >> 8; - ucMBFrame[MB_PDU_REQ_READWRITE_WRITE_ADDR_OFF + 1] = usWriteRegAddr; - ucMBFrame[MB_PDU_REQ_READWRITE_WRITE_REGCNT_OFF] = usNWriteRegs >> 8; - ucMBFrame[MB_PDU_REQ_READWRITE_WRITE_REGCNT_OFF + 1] = usNWriteRegs ; - ucMBFrame[MB_PDU_REQ_READWRITE_WRITE_BYTECNT_OFF] = usNWriteRegs * 2; - ucMBFrame += MB_PDU_REQ_READWRITE_WRITE_VALUES_OFF; - while( usNWriteRegs > usRegIndex) - { - *ucMBFrame++ = pusDataBuffer[usRegIndex] >> 8; - *ucMBFrame++ = pusDataBuffer[usRegIndex++] ; - } - vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_READWRITE_SIZE_MIN + 2*usNWriteRegs ); - ( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_SENT ); - eErrStatus = eMBMasterWaitRequestFinish( ); - } - return eErrStatus; -} - -eMBException -eMBMasterFuncReadWriteMultipleHoldingRegister( UCHAR * pucFrame, USHORT * usLen ) -{ - USHORT usRegReadAddress; - USHORT usRegReadCount; - USHORT usRegWriteAddress; - USHORT usRegWriteCount; - UCHAR *ucMBFrame; - - eMBException eStatus = MB_EX_NONE; - eMBErrorCode eRegStatus; - - /* If this request is broadcast, and it's read mode. This request don't need execute. */ - if ( xMBMasterRequestIsBroadcast() ) - { - eStatus = MB_EX_NONE; - } - else if( *usLen >= MB_PDU_SIZE_MIN + MB_PDU_FUNC_READWRITE_SIZE_MIN ) - { - vMBMasterGetPDUSndBuf(&ucMBFrame); - usRegReadAddress = ( USHORT )( ucMBFrame[MB_PDU_REQ_READWRITE_READ_ADDR_OFF] << 8U ); - usRegReadAddress |= ( USHORT )( ucMBFrame[MB_PDU_REQ_READWRITE_READ_ADDR_OFF + 1] ); - usRegReadAddress++; - - usRegReadCount = ( USHORT )( ucMBFrame[MB_PDU_REQ_READWRITE_READ_REGCNT_OFF] << 8U ); - usRegReadCount |= ( USHORT )( ucMBFrame[MB_PDU_REQ_READWRITE_READ_REGCNT_OFF + 1] ); - - usRegWriteAddress = ( USHORT )( ucMBFrame[MB_PDU_REQ_READWRITE_WRITE_ADDR_OFF] << 8U ); - usRegWriteAddress |= ( USHORT )( ucMBFrame[MB_PDU_REQ_READWRITE_WRITE_ADDR_OFF + 1] ); - usRegWriteAddress++; - - usRegWriteCount = ( USHORT )( ucMBFrame[MB_PDU_REQ_READWRITE_WRITE_REGCNT_OFF] << 8U ); - usRegWriteCount |= ( USHORT )( ucMBFrame[MB_PDU_REQ_READWRITE_WRITE_REGCNT_OFF + 1] ); - - if( ( 2 * usRegReadCount ) == pucFrame[MB_PDU_FUNC_READWRITE_READ_BYTECNT_OFF] ) - { - /* Make callback to update the register values. */ - eRegStatus = eMBMasterRegHoldingCB( &ucMBFrame[MB_PDU_REQ_READWRITE_WRITE_VALUES_OFF], - usRegWriteAddress, usRegWriteCount, MB_REG_WRITE ); - - if( eRegStatus == MB_ENOERR ) - { - /* Make the read callback. */ - eRegStatus = eMBMasterRegHoldingCB(&pucFrame[MB_PDU_FUNC_READWRITE_READ_VALUES_OFF], - usRegReadAddress, usRegReadCount, MB_REG_READ); - } - if( eRegStatus != MB_ENOERR ) - { - eStatus = prveMBError2Exception( eRegStatus ); - } - } - else - { - eStatus = MB_EX_ILLEGAL_DATA_VALUE; - } - } - return eStatus; -} - -#endif -#endif - diff --git a/components/net/freemodbus/modbus/functions/mbfuncinput.c b/components/net/freemodbus/modbus/functions/mbfuncinput.c deleted file mode 100644 index cceedbafea..0000000000 --- a/components/net/freemodbus/modbus/functions/mbfuncinput.c +++ /dev/null @@ -1,122 +0,0 @@ -/* - * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. - * Copyright (c) 2006 Christian Walter <[email protected]> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * File: $Id: mbfuncinput.c,v 1.10 2007/09/12 10:15:56 wolti Exp $ - */ - -/* ----------------------- System includes ----------------------------------*/ -#include "stdlib.h" -#include "string.h" - -/* ----------------------- Platform includes --------------------------------*/ -#include "port.h" - -/* ----------------------- Modbus includes ----------------------------------*/ -#include "mb.h" -#include "mbframe.h" -#include "mbproto.h" -#include "mbconfig.h" - -/* ----------------------- Defines ------------------------------------------*/ -#define MB_PDU_FUNC_READ_ADDR_OFF ( MB_PDU_DATA_OFF ) -#define MB_PDU_FUNC_READ_REGCNT_OFF ( MB_PDU_DATA_OFF + 2 ) -#define MB_PDU_FUNC_READ_SIZE ( 4 ) -#define MB_PDU_FUNC_READ_REGCNT_MAX ( 0x007D ) - -#define MB_PDU_FUNC_READ_RSP_BYTECNT_OFF ( MB_PDU_DATA_OFF ) - -/* ----------------------- Static functions ---------------------------------*/ -eMBException prveMBError2Exception( eMBErrorCode eErrorCode ); - -/* ----------------------- Start implementation -----------------------------*/ -#if MB_FUNC_READ_INPUT_ENABLED > 0 - -eMBException -eMBFuncReadInputRegister( UCHAR * pucFrame, USHORT * usLen ) -{ - USHORT usRegAddress; - USHORT usRegCount; - UCHAR *pucFrameCur; - - eMBException eStatus = MB_EX_NONE; - eMBErrorCode eRegStatus; - - if( *usLen == ( MB_PDU_FUNC_READ_SIZE + MB_PDU_SIZE_MIN ) ) - { - usRegAddress = ( USHORT )( pucFrame[MB_PDU_FUNC_READ_ADDR_OFF] << 8 ); - usRegAddress |= ( USHORT )( pucFrame[MB_PDU_FUNC_READ_ADDR_OFF + 1] ); - usRegAddress++; - - usRegCount = ( USHORT )( pucFrame[MB_PDU_FUNC_READ_REGCNT_OFF] << 8 ); - usRegCount |= ( USHORT )( pucFrame[MB_PDU_FUNC_READ_REGCNT_OFF + 1] ); - - /* Check if the number of registers to read is valid. If not - * return Modbus illegal data value exception. - */ - if( ( usRegCount >= 1 ) - && ( usRegCount < MB_PDU_FUNC_READ_REGCNT_MAX ) ) - { - /* Set the current PDU data pointer to the beginning. */ - pucFrameCur = &pucFrame[MB_PDU_FUNC_OFF]; - *usLen = MB_PDU_FUNC_OFF; - - /* First byte contains the function code. */ - *pucFrameCur++ = MB_FUNC_READ_INPUT_REGISTER; - *usLen += 1; - - /* Second byte in the response contain the number of bytes. */ - *pucFrameCur++ = ( UCHAR )( usRegCount * 2 ); - *usLen += 1; - - eRegStatus = - eMBRegInputCB( pucFrameCur, usRegAddress, usRegCount ); - - /* If an error occured convert it into a Modbus exception. */ - if( eRegStatus != MB_ENOERR ) - { - eStatus = prveMBError2Exception( eRegStatus ); - } - else - { - *usLen += usRegCount * 2; - } - } - else - { - eStatus = MB_EX_ILLEGAL_DATA_VALUE; - } - } - else - { - /* Can't be a valid read input register request because the length - * is incorrect. */ - eStatus = MB_EX_ILLEGAL_DATA_VALUE; - } - return eStatus; -} - -#endif diff --git a/components/net/freemodbus/modbus/functions/mbfuncinput_m.c b/components/net/freemodbus/modbus/functions/mbfuncinput_m.c deleted file mode 100644 index 2127efef67..0000000000 --- a/components/net/freemodbus/modbus/functions/mbfuncinput_m.c +++ /dev/null @@ -1,148 +0,0 @@ -/* - * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. - * Copyright (C) 2013 Armink <[email protected]> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * File: $Id: mbfuncinput_m.c,v 1.60 2013/10/12 14:23:40 Armink Add Master Functions Exp $ - */ - -/* ----------------------- System includes ----------------------------------*/ -#include "stdlib.h" -#include "string.h" - -/* ----------------------- Platform includes --------------------------------*/ -#include "port.h" - -/* ----------------------- Modbus includes ----------------------------------*/ -#include "mb.h" -#include "mb_m.h" -#include "mbframe.h" -#include "mbproto.h" -#include "mbconfig.h" - -/* ----------------------- Defines ------------------------------------------*/ -#define MB_PDU_REQ_READ_ADDR_OFF ( MB_PDU_DATA_OFF + 0 ) -#define MB_PDU_REQ_READ_REGCNT_OFF ( MB_PDU_DATA_OFF + 2 ) -#define MB_PDU_REQ_READ_SIZE ( 4 ) -#define MB_PDU_FUNC_READ_BYTECNT_OFF ( MB_PDU_DATA_OFF + 0 ) -#define MB_PDU_FUNC_READ_VALUES_OFF ( MB_PDU_DATA_OFF + 1 ) -#define MB_PDU_FUNC_READ_SIZE_MIN ( 1 ) - -#define MB_PDU_FUNC_READ_RSP_BYTECNT_OFF ( MB_PDU_DATA_OFF ) - -/* ----------------------- Static functions ---------------------------------*/ -eMBException prveMBError2Exception( eMBErrorCode eErrorCode ); - -/* ----------------------- Start implementation -----------------------------*/ -#if MB_MASTER_RTU_ENABLED > 0 || MB_MASTER_ASCII_ENABLED > 0 -#if MB_FUNC_READ_INPUT_ENABLED > 0 - -/** - * This function will request read input register. - * - * @param ucSndAddr salve address - * @param usRegAddr register start address - * @param usNRegs register total number - * @param lTimeOut timeout (-1 will waiting forever) - * - * @return error code - */ -eMBMasterReqErrCode -eMBMasterReqReadInputRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usNRegs, LONG lTimeOut ) -{ - UCHAR *ucMBFrame; - eMBMasterReqErrCode eErrStatus = MB_MRE_NO_ERR; - - if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG; - else if ( xMBMasterRunResTake( lTimeOut ) == FALSE ) eErrStatus = MB_MRE_MASTER_BUSY; - else - { - vMBMasterGetPDUSndBuf(&ucMBFrame); - vMBMasterSetDestAddress(ucSndAddr); - ucMBFrame[MB_PDU_FUNC_OFF] = MB_FUNC_READ_INPUT_REGISTER; - ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF] = usRegAddr >> 8; - ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF + 1] = usRegAddr; - ucMBFrame[MB_PDU_REQ_READ_REGCNT_OFF] = usNRegs >> 8; - ucMBFrame[MB_PDU_REQ_READ_REGCNT_OFF + 1] = usNRegs; - vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_READ_SIZE ); - ( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_SENT ); - eErrStatus = eMBMasterWaitRequestFinish( ); - } - return eErrStatus; -} - -eMBException -eMBMasterFuncReadInputRegister( UCHAR * pucFrame, USHORT * usLen ) -{ - UCHAR *ucMBFrame; - USHORT usRegAddress; - USHORT usRegCount; - - eMBException eStatus = MB_EX_NONE; - eMBErrorCode eRegStatus; - - /* If this request is broadcast, and it's read mode. This request don't need execute. */ - if ( xMBMasterRequestIsBroadcast() ) - { - eStatus = MB_EX_NONE; - } - else if( *usLen >= MB_PDU_SIZE_MIN + MB_PDU_FUNC_READ_SIZE_MIN ) - { - vMBMasterGetPDUSndBuf(&ucMBFrame); - usRegAddress = ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF] << 8 ); - usRegAddress |= ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF + 1] ); - usRegAddress++; - - usRegCount = ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_REGCNT_OFF] << 8 ); - usRegCount |= ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_REGCNT_OFF + 1] ); - - /* Check if the number of registers to read is valid. If not - * return Modbus illegal data value exception. - */ - if( ( usRegCount >= 1 ) && ( 2 * usRegCount == pucFrame[MB_PDU_FUNC_READ_BYTECNT_OFF] ) ) - { - /* Make callback to fill the buffer. */ - eRegStatus = eMBMasterRegInputCB( &pucFrame[MB_PDU_FUNC_READ_VALUES_OFF], usRegAddress, usRegCount ); - /* If an error occured convert it into a Modbus exception. */ - if( eRegStatus != MB_ENOERR ) - { - eStatus = prveMBError2Exception( eRegStatus ); - } - } - else - { - eStatus = MB_EX_ILLEGAL_DATA_VALUE; - } - } - else - { - /* Can't be a valid request because the length is incorrect. */ - eStatus = MB_EX_ILLEGAL_DATA_VALUE; - } - return eStatus; -} - -#endif -#endif diff --git a/components/net/freemodbus/modbus/functions/mbfuncother.c b/components/net/freemodbus/modbus/functions/mbfuncother.c deleted file mode 100644 index fcee972bf8..0000000000 --- a/components/net/freemodbus/modbus/functions/mbfuncother.c +++ /dev/null @@ -1,88 +0,0 @@ -/* - * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. - * Copyright (c) 2006 Christian Walter <[email protected]> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * File: $Id: mbfuncother.c,v 1.8 2006/12/07 22:10:34 wolti Exp $ - */ - -/* ----------------------- System includes ----------------------------------*/ -#include "stdlib.h" -#include "string.h" - -/* ----------------------- Platform includes --------------------------------*/ -#include "port.h" - -/* ----------------------- Modbus includes ----------------------------------*/ -#include "mb.h" -#include "mbframe.h" -#include "mbproto.h" -#include "mbconfig.h" - -#if MB_FUNC_OTHER_REP_SLAVEID_ENABLED > 0 - -/* ----------------------- Static variables ---------------------------------*/ -static UCHAR ucMBSlaveID[MB_FUNC_OTHER_REP_SLAVEID_BUF]; -static USHORT usMBSlaveIDLen; - -/* ----------------------- Start implementation -----------------------------*/ - -eMBErrorCode -eMBSetSlaveID( UCHAR ucSlaveID, BOOL xIsRunning, - UCHAR const *pucAdditional, USHORT usAdditionalLen ) -{ - eMBErrorCode eStatus = MB_ENOERR; - - /* the first byte and second byte in the buffer is reserved for - * the parameter ucSlaveID and the running flag. The rest of - * the buffer is available for additional data. */ - if( usAdditionalLen + 2 < MB_FUNC_OTHER_REP_SLAVEID_BUF ) - { - usMBSlaveIDLen = 0; - ucMBSlaveID[usMBSlaveIDLen++] = ucSlaveID; - ucMBSlaveID[usMBSlaveIDLen++] = ( UCHAR )( xIsRunning ? 0xFF : 0x00 ); - if( usAdditionalLen > 0 ) - { - memcpy( &ucMBSlaveID[usMBSlaveIDLen], pucAdditional, - ( size_t )usAdditionalLen ); - usMBSlaveIDLen += usAdditionalLen; - } - } - else - { - eStatus = MB_ENORES; - } - return eStatus; -} - -eMBException -eMBFuncReportSlaveID( UCHAR * pucFrame, USHORT * usLen ) -{ - memcpy( &pucFrame[MB_PDU_DATA_OFF], &ucMBSlaveID[0], ( size_t )usMBSlaveIDLen ); - *usLen = ( USHORT )( MB_PDU_DATA_OFF + usMBSlaveIDLen ); - return MB_EX_NONE; -} - -#endif diff --git a/components/net/freemodbus/modbus/functions/mbutils.c b/components/net/freemodbus/modbus/functions/mbutils.c deleted file mode 100644 index 2afe3b84b7..0000000000 --- a/components/net/freemodbus/modbus/functions/mbutils.c +++ /dev/null @@ -1,141 +0,0 @@ -/* - * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. - * Copyright (c) 2006 Christian Walter <[email protected]> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * File: $Id: mbutils.c,v 1.6 2007/02/18 23:49:07 wolti Exp $ - */ - -/* ----------------------- System includes ----------------------------------*/ -#include "stdlib.h" -#include "string.h" - -/* ----------------------- Platform includes --------------------------------*/ -#include "port.h" - -/* ----------------------- Modbus includes ----------------------------------*/ -#include "mb.h" -#include "mbproto.h" - -/* ----------------------- Defines ------------------------------------------*/ -#define BITS_UCHAR 8U - -/* ----------------------- Start implementation -----------------------------*/ -void -xMBUtilSetBits( UCHAR * ucByteBuf, USHORT usBitOffset, UCHAR ucNBits, - UCHAR ucValue ) -{ - USHORT usWordBuf; - USHORT usMask; - USHORT usByteOffset; - USHORT usNPreBits; - USHORT usValue = ucValue; - - RT_ASSERT( ucNBits <= 8 ); - RT_ASSERT( ( size_t )BITS_UCHAR == sizeof( UCHAR ) * 8 ); - - /* Calculate byte offset for first byte containing the bit values starting - * at usBitOffset. */ - usByteOffset = ( USHORT )( ( usBitOffset ) / BITS_UCHAR ); - - /* How many bits precede our bits to set. */ - usNPreBits = ( USHORT )( usBitOffset - usByteOffset * BITS_UCHAR ); - - /* Move bit field into position over bits to set */ - usValue <<= usNPreBits; - - /* Prepare a mask for setting the new bits. */ - usMask = ( USHORT )( ( 1 << ( USHORT ) ucNBits ) - 1 ); - usMask <<= usBitOffset - usByteOffset * BITS_UCHAR; - - /* copy bits into temporary storage. */ - usWordBuf = ucByteBuf[usByteOffset]; - usWordBuf |= ucByteBuf[usByteOffset + 1] << BITS_UCHAR; - - /* Zero out bit field bits and then or value bits into them. */ - usWordBuf = ( USHORT )( ( usWordBuf & ( ~usMask ) ) | usValue ); - - /* move bits back into storage */ - ucByteBuf[usByteOffset] = ( UCHAR )( usWordBuf & 0xFF ); - ucByteBuf[usByteOffset + 1] = ( UCHAR )( usWordBuf >> BITS_UCHAR ); -} - -UCHAR -xMBUtilGetBits( UCHAR * ucByteBuf, USHORT usBitOffset, UCHAR ucNBits ) -{ - USHORT usWordBuf; - USHORT usMask; - USHORT usByteOffset; - USHORT usNPreBits; - - /* Calculate byte offset for first byte containing the bit values starting - * at usBitOffset. */ - usByteOffset = ( USHORT )( ( usBitOffset ) / BITS_UCHAR ); - - /* How many bits precede our bits to set. */ - usNPreBits = ( USHORT )( usBitOffset - usByteOffset * BITS_UCHAR ); - - /* Prepare a mask for setting the new bits. */ - usMask = ( USHORT )( ( 1 << ( USHORT ) ucNBits ) - 1 ); - - /* copy bits into temporary storage. */ - usWordBuf = ucByteBuf[usByteOffset]; - usWordBuf |= ucByteBuf[usByteOffset + 1] << BITS_UCHAR; - - /* throw away unneeded bits. */ - usWordBuf >>= usNPreBits; - - /* mask away bits above the requested bitfield. */ - usWordBuf &= usMask; - - return ( UCHAR ) usWordBuf; -} - -eMBException -prveMBError2Exception( eMBErrorCode eErrorCode ) -{ - eMBException eStatus; - - switch ( eErrorCode ) - { - case MB_ENOERR: - eStatus = MB_EX_NONE; - break; - - case MB_ENOREG: - eStatus = MB_EX_ILLEGAL_DATA_ADDRESS; - break; - - case MB_ETIMEDOUT: - eStatus = MB_EX_SLAVE_BUSY; - break; - - default: - eStatus = MB_EX_SLAVE_DEVICE_FAILURE; - break; - } - - return eStatus; -} diff --git a/components/net/freemodbus/modbus/include/mb.h b/components/net/freemodbus/modbus/include/mb.h deleted file mode 100644 index 8d6be7b422..0000000000 --- a/components/net/freemodbus/modbus/include/mb.h +++ /dev/null @@ -1,417 +0,0 @@ -/* - * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. - * Copyright (c) 2006 Christian Walter <[email protected]> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * File: $Id: mb.h,v 1.17 2006/12/07 22:10:34 wolti Exp $ - */ - -#ifndef _MB_H -#define _MB_H - -#include "port.h" - -#ifdef __cplusplus -PR_BEGIN_EXTERN_C -#endif - -#include "mbport.h" -#include "mbproto.h" - -/*! \defgroup modbus Modbus - * \code #include "mb.h" \endcode - * - * This module defines the interface for the application. It contains - * the basic functions and types required to use the Modbus protocol stack. - * A typical application will want to call eMBInit() first. If the device - * is ready to answer network requests it must then call eMBEnable() to activate - * the protocol stack. In the main loop the function eMBPoll() must be called - * periodically. The time interval between pooling depends on the configured - * Modbus timeout. If an RTOS is available a separate task should be created - * and the task should always call the function eMBPoll(). - * - * \code - * // Initialize protocol stack in RTU mode for a slave with address 10 = 0x0A - * eMBInit( MB_RTU, 0x0A, 38400, MB_PAR_EVEN ); - * // Enable the Modbus Protocol Stack. - * eMBEnable( ); - * for( ;; ) - * { - * // Call the main polling loop of the Modbus protocol stack. - * eMBPoll( ); - * ... - * } - * \endcode - */ - -/* ----------------------- Defines ------------------------------------------*/ - -/*! \ingroup modbus - * \brief Use the default Modbus TCP port (502) - */ -#define MB_TCP_PORT_USE_DEFAULT 0 - -/* ----------------------- Type definitions ---------------------------------*/ - -/*! \ingroup modbus - * \brief Modbus serial transmission modes (RTU/ASCII). - * - * Modbus serial supports two transmission modes. Either ASCII or RTU. RTU - * is faster but has more hardware requirements and requires a network with - * a low jitter. ASCII is slower and more reliable on slower links (E.g. modems) - */ - typedef enum -{ - MB_RTU, /*!< RTU transmission mode. */ - MB_ASCII, /*!< ASCII transmission mode. */ - MB_TCP /*!< TCP mode. */ -} eMBMode; - -/*! \ingroup modbus - * \brief If register should be written or read. - * - * This value is passed to the callback functions which support either - * reading or writing register values. Writing means that the application - * registers should be updated and reading means that the modbus protocol - * stack needs to know the current register values. - * - * \see eMBRegHoldingCB( ), eMBRegCoilsCB( ), eMBRegDiscreteCB( ) and - * eMBRegInputCB( ). - */ -typedef enum -{ - MB_REG_READ, /*!< Read register values and pass to protocol stack. */ - MB_REG_WRITE /*!< Update register values. */ -} eMBRegisterMode; - -/*! \ingroup modbus - * \brief Errorcodes used by all function in the protocol stack. - */ -typedef enum -{ - MB_ENOERR, /*!< no error. */ - MB_ENOREG, /*!< illegal register address. */ - MB_EINVAL, /*!< illegal argument. */ - MB_EPORTERR, /*!< porting layer error. */ - MB_ENORES, /*!< insufficient resources. */ - MB_EIO, /*!< I/O error. */ - MB_EILLSTATE, /*!< protocol stack in illegal state. */ - MB_ETIMEDOUT /*!< timeout error occurred. */ -} eMBErrorCode; - - -/* ----------------------- Function prototypes ------------------------------*/ -/*! \ingroup modbus - * \brief Initialize the Modbus protocol stack. - * - * This functions initializes the ASCII or RTU module and calls the - * init functions of the porting layer to prepare the hardware. Please - * note that the receiver is still disabled and no Modbus frames are - * processed until eMBEnable( ) has been called. - * - * \param eMode If ASCII or RTU mode should be used. - * \param ucSlaveAddress The slave address. Only frames sent to this - * address or to the broadcast address are processed. - * \param ucPort The port to use. E.g. 1 for COM1 on windows. This value - * is platform dependent and some ports simply choose to ignore it. - * \param ulBaudRate The baudrate. E.g. 19200. Supported baudrates depend - * on the porting layer. - * \param eParity Parity used for serial transmission. - * - * \return If no error occurs the function returns eMBErrorCode::MB_ENOERR. - * The protocol is then in the disabled state and ready for activation - * by calling eMBEnable( ). Otherwise one of the following error codes - * is returned: - * - eMBErrorCode::MB_EINVAL If the slave address was not valid. Valid - * slave addresses are in the range 1 - 247. - * - eMBErrorCode::MB_EPORTERR IF the porting layer returned an error. - */ -eMBErrorCode eMBInit( eMBMode eMode, UCHAR ucSlaveAddress, - UCHAR ucPort, ULONG ulBaudRate, eMBParity eParity ); - -/*! \ingroup modbus - * \brief Initialize the Modbus protocol stack for Modbus TCP. - * - * This function initializes the Modbus TCP Module. Please note that - * frame processing is still disabled until eMBEnable( ) is called. - * - * \param usTCPPort The TCP port to listen on. - * \return If the protocol stack has been initialized correctly the function - * returns eMBErrorCode::MB_ENOERR. Otherwise one of the following error - * codes is returned: - * - eMBErrorCode::MB_EINVAL If the slave address was not valid. Valid - * slave addresses are in the range 1 - 247. - * - eMBErrorCode::MB_EPORTERR IF the porting layer returned an error. - */ -eMBErrorCode eMBTCPInit( USHORT usTCPPort ); - -/*! \ingroup modbus - * \brief Release resources used by the protocol stack. - * - * This function disables the Modbus protocol stack and release all - * hardware resources. It must only be called when the protocol stack - * is disabled. - * - * \note Note all ports implement this function. A port which wants to - * get an callback must define the macro MB_PORT_HAS_CLOSE to 1. - * - * \return If the resources where released it return eMBErrorCode::MB_ENOERR. - * If the protocol stack is not in the disabled state it returns - * eMBErrorCode::MB_EILLSTATE. - */ -eMBErrorCode eMBClose( void ); - -/*! \ingroup modbus - * \brief Enable the Modbus protocol stack. - * - * This function enables processing of Modbus frames. Enabling the protocol - * stack is only possible if it is in the disabled state. - * - * \return If the protocol stack is now in the state enabled it returns - * eMBErrorCode::MB_ENOERR. If it was not in the disabled state it - * return eMBErrorCode::MB_EILLSTATE. - */ -eMBErrorCode eMBEnable( void ); - -/*! \ingroup modbus - * \brief Disable the Modbus protocol stack. - * - * This function disables processing of Modbus frames. - * - * \return If the protocol stack has been disabled it returns - * eMBErrorCode::MB_ENOERR. If it was not in the enabled state it returns - * eMBErrorCode::MB_EILLSTATE. - */ -eMBErrorCode eMBDisable( void ); - -/*! \ingroup modbus - * \brief The main pooling loop of the Modbus protocol stack. - * - * This function must be called periodically. The timer interval required - * is given by the application dependent Modbus slave timeout. Internally the - * function calls xMBPortEventGet() and waits for an event from the receiver or - * transmitter state machines. - * - * \return If the protocol stack is not in the enabled state the function - * returns eMBErrorCode::MB_EILLSTATE. Otherwise it returns - * eMBErrorCode::MB_ENOERR. - */ -eMBErrorCode eMBPoll( void ); - -/*! \ingroup modbus - * \brief Configure the slave id of the device. - * - * This function should be called when the Modbus function <em>Report Slave ID</em> - * is enabled ( By defining MB_FUNC_OTHER_REP_SLAVEID_ENABLED in mbconfig.h ). - * - * \param ucSlaveID Values is returned in the <em>Slave ID</em> byte of the - * <em>Report Slave ID</em> response. - * \param xIsRunning If TRUE the <em>Run Indicator Status</em> byte is set to 0xFF. - * otherwise the <em>Run Indicator Status</em> is 0x00. - * \param pucAdditional Values which should be returned in the <em>Additional</em> - * bytes of the <em> Report Slave ID</em> response. - * \param usAdditionalLen Length of the buffer <code>pucAdditonal</code>. - * - * \return If the static buffer defined by MB_FUNC_OTHER_REP_SLAVEID_BUF in - * mbconfig.h is to small it returns eMBErrorCode::MB_ENORES. Otherwise - * it returns eMBErrorCode::MB_ENOERR. - */ -eMBErrorCode eMBSetSlaveID( UCHAR ucSlaveID, BOOL xIsRunning, - UCHAR const *pucAdditional, - USHORT usAdditionalLen ); - -/*! \ingroup modbus - * \brief Registers a callback handler for a given function code. - * - * This function registers a new callback handler for a given function code. - * The callback handler supplied is responsible for interpreting the Modbus PDU and - * the creation of an appropriate response. In case of an error it should return - * one of the possible Modbus exceptions which results in a Modbus exception frame - * sent by the protocol stack. - * - * \param ucFunctionCode The Modbus function code for which this handler should - * be registers. Valid function codes are in the range 1 to 127. - * \param pxHandler The function handler which should be called in case - * such a frame is received. If \c NULL a previously registered function handler - * for this function code is removed. - * - * \return eMBErrorCode::MB_ENOERR if the handler has been installed. If no - * more resources are available it returns eMBErrorCode::MB_ENORES. In this - * case the values in mbconfig.h should be adjusted. If the argument was not - * valid it returns eMBErrorCode::MB_EINVAL. - */ -eMBErrorCode eMBRegisterCB( UCHAR ucFunctionCode, - pxMBFunctionHandler pxHandler ); - -/* ----------------------- Callback -----------------------------------------*/ - -/*! \defgroup modbus_registers Modbus Registers - * \code #include "mb.h" \endcode - * The protocol stack does not internally allocate any memory for the - * registers. This makes the protocol stack very small and also usable on - * low end targets. In addition the values don't have to be in the memory - * and could for example be stored in a flash.<br> - * Whenever the protocol stack requires a value it calls one of the callback - * function with the register address and the number of registers to read - * as an argument. The application should then read the actual register values - * (for example the ADC voltage) and should store the result in the supplied - * buffer.<br> - * If the protocol stack wants to update a register value because a write - * register function was received a buffer with the new register values is - * passed to the callback function. The function should then use these values - * to update the application register values. - */ - -/*! \ingroup modbus_registers - * \brief Callback function used if the value of a <em>Input Register</em> - * is required by the protocol stack. The starting register address is given - * by \c usAddress and the last register is given by <tt>usAddress + - * usNRegs - 1</tt>. - * - * \param pucRegBuffer A buffer where the callback function should write - * the current value of the modbus registers to. - * \param usAddress The starting address of the register. Input registers - * are in the range 1 - 65535. - * \param usNRegs Number of registers the callback function must supply. - * - * \return The function must return one of the following error codes: - * - eMBErrorCode::MB_ENOERR If no error occurred. In this case a normal - * Modbus response is sent. - * - eMBErrorCode::MB_ENOREG If the application can not supply values - * for registers within this range. In this case a - * <b>ILLEGAL DATA ADDRESS</b> exception frame is sent as a response. - * - eMBErrorCode::MB_ETIMEDOUT If the requested register block is - * currently not available and the application dependent response - * timeout would be violated. In this case a <b>SLAVE DEVICE BUSY</b> - * exception is sent as a response. - * - eMBErrorCode::MB_EIO If an unrecoverable error occurred. In this case - * a <b>SLAVE DEVICE FAILURE</b> exception is sent as a response. - */ -eMBErrorCode eMBRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, - USHORT usNRegs ); - -/*! \ingroup modbus_registers - * \brief Callback function used if a <em>Holding Register</em> value is - * read or written by the protocol stack. The starting register address - * is given by \c usAddress and the last register is given by - * <tt>usAddress + usNRegs - 1</tt>. - * - * \param pucRegBuffer If the application registers values should be updated the - * buffer points to the new registers values. If the protocol stack needs - * to now the current values the callback function should write them into - * this buffer. - * \param usAddress The starting address of the register. - * \param usNRegs Number of registers to read or write. - * \param eMode If eMBRegisterMode::MB_REG_WRITE the application register - * values should be updated from the values in the buffer. For example - * this would be the case when the Modbus master has issued an - * <b>WRITE SINGLE REGISTER</b> command. - * If the value eMBRegisterMode::MB_REG_READ the application should copy - * the current values into the buffer \c pucRegBuffer. - * - * \return The function must return one of the following error codes: - * - eMBErrorCode::MB_ENOERR If no error occurred. In this case a normal - * Modbus response is sent. - * - eMBErrorCode::MB_ENOREG If the application can not supply values - * for registers within this range. In this case a - * <b>ILLEGAL DATA ADDRESS</b> exception frame is sent as a response. - * - eMBErrorCode::MB_ETIMEDOUT If the requested register block is - * currently not available and the application dependent response - * timeout would be violated. In this case a <b>SLAVE DEVICE BUSY</b> - * exception is sent as a response. - * - eMBErrorCode::MB_EIO If an unrecoverable error occurred. In this case - * a <b>SLAVE DEVICE FAILURE</b> exception is sent as a response. - */ -eMBErrorCode eMBRegHoldingCB( UCHAR * pucRegBuffer, USHORT usAddress, - USHORT usNRegs, eMBRegisterMode eMode ); - -/*! \ingroup modbus_registers - * \brief Callback function used if a <em>Coil Register</em> value is - * read or written by the protocol stack. If you are going to use - * this function you might use the functions xMBUtilSetBits( ) and - * xMBUtilGetBits( ) for working with bitfields. - * - * \param pucRegBuffer The bits are packed in bytes where the first coil - * starting at address \c usAddress is stored in the LSB of the - * first byte in the buffer <code>pucRegBuffer</code>. - * If the buffer should be written by the callback function unused - * coil values (I.e. if not a multiple of eight coils is used) should be set - * to zero. - * \param usAddress The first coil number. - * \param usNCoils Number of coil values requested. - * \param eMode If eMBRegisterMode::MB_REG_WRITE the application values should - * be updated from the values supplied in the buffer \c pucRegBuffer. - * If eMBRegisterMode::MB_REG_READ the application should store the current - * values in the buffer \c pucRegBuffer. - * - * \return The function must return one of the following error codes: - * - eMBErrorCode::MB_ENOERR If no error occurred. In this case a normal - * Modbus response is sent. - * - eMBErrorCode::MB_ENOREG If the application does not map an coils - * within the requested address range. In this case a - * <b>ILLEGAL DATA ADDRESS</b> is sent as a response. - * - eMBErrorCode::MB_ETIMEDOUT If the requested register block is - * currently not available and the application dependent response - * timeout would be violated. In this case a <b>SLAVE DEVICE BUSY</b> - * exception is sent as a response. - * - eMBErrorCode::MB_EIO If an unrecoverable error occurred. In this case - * a <b>SLAVE DEVICE FAILURE</b> exception is sent as a response. - */ -eMBErrorCode eMBRegCoilsCB( UCHAR * pucRegBuffer, USHORT usAddress, - USHORT usNCoils, eMBRegisterMode eMode ); - -/*! \ingroup modbus_registers - * \brief Callback function used if a <em>Input Discrete Register</em> value is - * read by the protocol stack. - * - * If you are going to use his function you might use the functions - * xMBUtilSetBits( ) and xMBUtilGetBits( ) for working with bitfields. - * - * \param pucRegBuffer The buffer should be updated with the current - * coil values. The first discrete input starting at \c usAddress must be - * stored at the LSB of the first byte in the buffer. If the requested number - * is not a multiple of eight the remaining bits should be set to zero. - * \param usAddress The starting address of the first discrete input. - * \param usNDiscrete Number of discrete input values. - * \return The function must return one of the following error codes: - * - eMBErrorCode::MB_ENOERR If no error occurred. In this case a normal - * Modbus response is sent. - * - eMBErrorCode::MB_ENOREG If no such discrete inputs exists. - * In this case a <b>ILLEGAL DATA ADDRESS</b> exception frame is sent - * as a response. - * - eMBErrorCode::MB_ETIMEDOUT If the requested register block is - * currently not available and the application dependent response - * timeout would be violated. In this case a <b>SLAVE DEVICE BUSY</b> - * exception is sent as a response. - * - eMBErrorCode::MB_EIO If an unrecoverable error occurred. In this case - * a <b>SLAVE DEVICE FAILURE</b> exception is sent as a response. - */ -eMBErrorCode eMBRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress, - USHORT usNDiscrete ); - -#ifdef __cplusplus -PR_END_EXTERN_C -#endif -#endif diff --git a/components/net/freemodbus/modbus/include/mb_m.h b/components/net/freemodbus/modbus/include/mb_m.h deleted file mode 100644 index f6b25e2cf3..0000000000 --- a/components/net/freemodbus/modbus/include/mb_m.h +++ /dev/null @@ -1,402 +0,0 @@ -/* - * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. - * Copyright (C) 2013 Armink <[email protected]> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * File: $Id: mb_m.h,v 1.60 2013/09/03 10:20:05 Armink Add Master Functions $ - */ - -#ifndef _MB_M_H -#define _MB_M_H - -#ifdef __cplusplus -PR_BEGIN_EXTERN_C -#endif - -/*! \defgroup modbus Modbus - * \code #include "mb_m.h" \endcode - * - * This module defines the interface for the application. It contains - * the basic functions and types required to use the Modbus Master protocol stack. - * A typical application will want to call eMBMasterInit() first. If the device - * is ready to answer network requests it must then call eMBEnable() to activate - * the protocol stack. In the main loop the function eMBMasterPoll() must be called - * periodically. The time interval between pooling depends on the configured - * Modbus timeout. If an RTOS is available a separate task should be created - * and the task should always call the function eMBMasterPoll(). - * - * \code - * // Initialize protocol stack in RTU mode for a Master - * eMBMasterInit( MB_RTU, 38400, MB_PAR_EVEN ); - * // Enable the Modbus Protocol Stack. - * eMBMasterEnable( ); - * for( ;; ) - * { - * // Call the main polling loop of the Modbus Master protocol stack. - * eMBMasterPoll( ); - * ... - * } - * \endcode - */ - -/* ----------------------- Defines ------------------------------------------*/ - -/*! \ingroup modbus - * \brief Use the default Modbus Master TCP port (502) - */ -#define MB_MASTER_TCP_PORT_USE_DEFAULT 0 - -/* ----------------------- Type definitions ---------------------------------*/ -/*! \ingroup modbus - * \brief Errorcodes used by all function in the Master request. - */ -typedef enum -{ - MB_MRE_NO_ERR, /*!< no error. */ - MB_MRE_NO_REG, /*!< illegal register address. */ - MB_MRE_ILL_ARG, /*!< illegal argument. */ - MB_MRE_REV_DATA, /*!< receive data error. */ - MB_MRE_TIMEDOUT, /*!< timeout error occurred. */ - MB_MRE_MASTER_BUSY, /*!< master is busy now. */ - MB_MRE_EXE_FUN /*!< execute function error. */ -} eMBMasterReqErrCode; -/*! \ingroup modbus - * \brief TimerMode is Master 3 kind of Timer modes. - */ -typedef enum -{ - MB_TMODE_T35, /*!< Master receive frame T3.5 timeout. */ - MB_TMODE_RESPOND_TIMEOUT, /*!< Master wait respond for slave. */ - MB_TMODE_CONVERT_DELAY /*!< Master sent broadcast ,then delay sometime.*/ -}eMBMasterTimerMode; - -/* ----------------------- Function prototypes ------------------------------*/ -/*! \ingroup modbus - * \brief Initialize the Modbus Master protocol stack. - * - * This functions initializes the ASCII or RTU module and calls the - * init functions of the porting layer to prepare the hardware. Please - * note that the receiver is still disabled and no Modbus frames are - * processed until eMBMasterEnable( ) has been called. - * - * \param eMode If ASCII or RTU mode should be used. - * \param ucPort The port to use. E.g. 1 for COM1 on windows. This value - * is platform dependent and some ports simply choose to ignore it. - * \param ulBaudRate The baudrate. E.g. 19200. Supported baudrates depend - * on the porting layer. - * \param eParity Parity used for serial transmission. - * - * \return If no error occurs the function returns eMBErrorCode::MB_ENOERR. - * The protocol is then in the disabled state and ready for activation - * by calling eMBMasterEnable( ). Otherwise one of the following error codes - * is returned: - * - eMBErrorCode::MB_EPORTERR IF the porting layer returned an error. - */ -eMBErrorCode eMBMasterInit( eMBMode eMode, UCHAR ucPort, - ULONG ulBaudRate, eMBParity eParity ); - -/*! \ingroup modbus - * \brief Initialize the Modbus Master protocol stack for Modbus TCP. - * - * This function initializes the Modbus TCP Module. Please note that - * frame processing is still disabled until eMBEnable( ) is called. - * - * \param usTCPPort The TCP port to listen on. - * \return If the protocol stack has been initialized correctly the function - * returns eMBErrorCode::MB_ENOERR. Otherwise one of the following error - * codes is returned: - * - eMBErrorCode::MB_EINVAL If the slave address was not valid. Valid - * slave addresses are in the range 1 - 247. - * - eMBErrorCode::MB_EPORTERR IF the porting layer returned an error. - */ -eMBErrorCode eMBMasterTCPInit( USHORT usTCPPort ); - -/*! \ingroup modbus - * \brief Release resources used by the protocol stack. - * - * This function disables the Modbus Master protocol stack and release all - * hardware resources. It must only be called when the protocol stack - * is disabled. - * - * \note Note all ports implement this function. A port which wants to - * get an callback must define the macro MB_PORT_HAS_CLOSE to 1. - * - * \return If the resources where released it return eMBErrorCode::MB_ENOERR. - * If the protocol stack is not in the disabled state it returns - * eMBErrorCode::MB_EILLSTATE. - */ -eMBErrorCode eMBMasterClose( void ); - -/*! \ingroup modbus - * \brief Enable the Modbus Master protocol stack. - * - * This function enables processing of Modbus Master frames. Enabling the protocol - * stack is only possible if it is in the disabled state. - * - * \return If the protocol stack is now in the state enabled it returns - * eMBErrorCode::MB_ENOERR. If it was not in the disabled state it - * return eMBErrorCode::MB_EILLSTATE. - */ -eMBErrorCode eMBMasterEnable( void ); - -/*! \ingroup modbus - * \brief Disable the Modbus Master protocol stack. - * - * This function disables processing of Modbus frames. - * - * \return If the protocol stack has been disabled it returns - * eMBErrorCode::MB_ENOERR. If it was not in the enabled state it returns - * eMBErrorCode::MB_EILLSTATE. - */ -eMBErrorCode eMBMasterDisable( void ); - -/*! \ingroup modbus - * \brief The main pooling loop of the Modbus Master protocol stack. - * - * This function must be called periodically. The timer interval required - * is given by the application dependent Modbus slave timeout. Internally the - * function calls xMBMasterPortEventGet() and waits for an event from the receiver or - * transmitter state machines. - * - * \return If the protocol stack is not in the enabled state the function - * returns eMBErrorCode::MB_EILLSTATE. Otherwise it returns - * eMBErrorCode::MB_ENOERR. - */ -eMBErrorCode eMBMasterPoll( void ); - -/*! \ingroup modbus - * \brief Registers a callback handler for a given function code. - * - * This function registers a new callback handler for a given function code. - * The callback handler supplied is responsible for interpreting the Modbus PDU and - * the creation of an appropriate response. In case of an error it should return - * one of the possible Modbus exceptions which results in a Modbus exception frame - * sent by the protocol stack. - * - * \param ucFunctionCode The Modbus function code for which this handler should - * be registers. Valid function codes are in the range 1 to 127. - * \param pxHandler The function handler which should be called in case - * such a frame is received. If \c NULL a previously registered function handler - * for this function code is removed. - * - * \return eMBErrorCode::MB_ENOERR if the handler has been installed. If no - * more resources are available it returns eMBErrorCode::MB_ENORES. In this - * case the values in mbconfig.h should be adjusted. If the argument was not - * valid it returns eMBErrorCode::MB_EINVAL. - */ -eMBErrorCode eMBMasterRegisterCB( UCHAR ucFunctionCode, - pxMBFunctionHandler pxHandler ); - -/* ----------------------- Callback -----------------------------------------*/ - -/*! \defgroup modbus_master registers Modbus Registers - * \code #include "mb_m.h" \endcode - * The protocol stack does not internally allocate any memory for the - * registers. This makes the protocol stack very small and also usable on - * low end targets. In addition the values don't have to be in the memory - * and could for example be stored in a flash.<br> - * Whenever the protocol stack requires a value it calls one of the callback - * function with the register address and the number of registers to read - * as an argument. The application should then read the actual register values - * (for example the ADC voltage) and should store the result in the supplied - * buffer.<br> - * If the protocol stack wants to update a register value because a write - * register function was received a buffer with the new register values is - * passed to the callback function. The function should then use these values - * to update the application register values. - */ - -/*! \ingroup modbus_registers - * \brief Callback function used if the value of a <em>Input Register</em> - * is required by the protocol stack. The starting register address is given - * by \c usAddress and the last register is given by <tt>usAddress + - * usNRegs - 1</tt>. - * - * \param pucRegBuffer A buffer where the callback function should write - * the current value of the modbus registers to. - * \param usAddress The starting address of the register. Input registers - * are in the range 1 - 65535. - * \param usNRegs Number of registers the callback function must supply. - * - * \return The function must return one of the following error codes: - * - eMBErrorCode::MB_ENOERR If no error occurred. In this case a normal - * Modbus response is sent. - * - eMBErrorCode::MB_ENOREG If the application does not map an coils - * within the requested address range. In this case a - * <b>ILLEGAL DATA ADDRESS</b> is sent as a response. - */ -eMBErrorCode eMBMasterRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, - USHORT usNRegs ); - -/*! \ingroup modbus_registers - * \brief Callback function used if a <em>Holding Register</em> value is - * read or written by the protocol stack. The starting register address - * is given by \c usAddress and the last register is given by - * <tt>usAddress + usNRegs - 1</tt>. - * - * \param pucRegBuffer If the application registers values should be updated the - * buffer points to the new registers values. If the protocol stack needs - * to now the current values the callback function should write them into - * this buffer. - * \param usAddress The starting address of the register. - * \param usNRegs Number of registers to read or write. - * \param eMode If eMBRegisterMode::MB_REG_WRITE the application register - * values should be updated from the values in the buffer. For example - * this would be the case when the Modbus master has issued an - * <b>WRITE SINGLE REGISTER</b> command. - * If the value eMBRegisterMode::MB_REG_READ the application should copy - * the current values into the buffer \c pucRegBuffer. - * - * \return The function must return one of the following error codes: - * - eMBErrorCode::MB_ENOERR If no error occurred. In this case a normal - * Modbus response is sent. - * - eMBErrorCode::MB_ENOREG If the application does not map an coils - * within the requested address range. In this case a - * <b>ILLEGAL DATA ADDRESS</b> is sent as a response. - */ -eMBErrorCode eMBMasterRegHoldingCB( UCHAR * pucRegBuffer, USHORT usAddress, - USHORT usNRegs, eMBRegisterMode eMode ); - -/*! \ingroup modbus_registers - * \brief Callback function used if a <em>Coil Register</em> value is - * read or written by the protocol stack. If you are going to use - * this function you might use the functions xMBUtilSetBits( ) and - * xMBUtilGetBits( ) for working with bitfields. - * - * \param pucRegBuffer The bits are packed in bytes where the first coil - * starting at address \c usAddress is stored in the LSB of the - * first byte in the buffer <code>pucRegBuffer</code>. - * If the buffer should be written by the callback function unused - * coil values (I.e. if not a multiple of eight coils is used) should be set - * to zero. - * \param usAddress The first coil number. - * \param usNCoils Number of coil values requested. - * \param eMode If eMBRegisterMode::MB_REG_WRITE the application values should - * be updated from the values supplied in the buffer \c pucRegBuffer. - * If eMBRegisterMode::MB_REG_READ the application should store the current - * values in the buffer \c pucRegBuffer. - * - * \return The function must return one of the following error codes: - * - eMBErrorCode::MB_ENOERR If no error occurred. In this case a normal - * Modbus response is sent. - * - eMBErrorCode::MB_ENOREG If the application does not map an coils - * within the requested address range. In this case a - * <b>ILLEGAL DATA ADDRESS</b> is sent as a response. - */ -eMBErrorCode eMBMasterRegCoilsCB( UCHAR * pucRegBuffer, USHORT usAddress, - USHORT usNCoils, eMBRegisterMode eMode ); - -/*! \ingroup modbus_registers - * \brief Callback function used if a <em>Input Discrete Register</em> value is - * read by the protocol stack. - * - * If you are going to use his function you might use the functions - * xMBUtilSetBits( ) and xMBUtilGetBits( ) for working with bitfields. - * - * \param pucRegBuffer The buffer should be updated with the current - * coil values. The first discrete input starting at \c usAddress must be - * stored at the LSB of the first byte in the buffer. If the requested number - * is not a multiple of eight the remaining bits should be set to zero. - * \param usAddress The starting address of the first discrete input. - * \param usNDiscrete Number of discrete input values. - * \return The function must return one of the following error codes: - * - eMBErrorCode::MB_ENOERR If no error occurred. In this case a normal - * Modbus response is sent. - * - eMBErrorCode::MB_ENOREG If the application does not map an coils - * within the requested address range. In this case a - * <b>ILLEGAL DATA ADDRESS</b> is sent as a response. - */ -eMBErrorCode eMBMasterRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress, - USHORT usNDiscrete ); - -/*! \ingroup modbus - *\brief These Modbus functions are called for user when Modbus run in Master Mode. - */ -eMBMasterReqErrCode -eMBMasterReqReadInputRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usNRegs, LONG lTimeOut ); -eMBMasterReqErrCode -eMBMasterReqWriteHoldingRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usRegData, LONG lTimeOut ); -eMBMasterReqErrCode -eMBMasterReqWriteMultipleHoldingRegister( UCHAR ucSndAddr, USHORT usRegAddr, - USHORT usNRegs, USHORT * pusDataBuffer, LONG lTimeOut ); -eMBMasterReqErrCode -eMBMasterReqReadHoldingRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usNRegs, LONG lTimeOut ); -eMBMasterReqErrCode -eMBMasterReqReadWriteMultipleHoldingRegister( UCHAR ucSndAddr, - USHORT usReadRegAddr, USHORT usNReadRegs, USHORT * pusDataBuffer, - USHORT usWriteRegAddr, USHORT usNWriteRegs, LONG lTimeOut ); -eMBMasterReqErrCode -eMBMasterReqReadCoils( UCHAR ucSndAddr, USHORT usCoilAddr, USHORT usNCoils, LONG lTimeOut ); -eMBMasterReqErrCode -eMBMasterReqWriteCoil( UCHAR ucSndAddr, USHORT usCoilAddr, USHORT usCoilData, LONG lTimeOut ); -eMBMasterReqErrCode -eMBMasterReqWriteMultipleCoils( UCHAR ucSndAddr, - USHORT usCoilAddr, USHORT usNCoils, UCHAR * pucDataBuffer, LONG lTimeOut ); -eMBMasterReqErrCode -eMBMasterReqReadDiscreteInputs( UCHAR ucSndAddr, USHORT usDiscreteAddr, USHORT usNDiscreteIn, LONG lTimeOut ); - -eMBException -eMBMasterFuncReportSlaveID( UCHAR * pucFrame, USHORT * usLen ); -eMBException -eMBMasterFuncReadInputRegister( UCHAR * pucFrame, USHORT * usLen ); -eMBException -eMBMasterFuncReadHoldingRegister( UCHAR * pucFrame, USHORT * usLen ); -eMBException -eMBMasterFuncWriteHoldingRegister( UCHAR * pucFrame, USHORT * usLen ); -eMBException -eMBMasterFuncWriteMultipleHoldingRegister( UCHAR * pucFrame, USHORT * usLen ); -eMBException -eMBMasterFuncReadCoils( UCHAR * pucFrame, USHORT * usLen ); -eMBException -eMBMasterFuncWriteCoil( UCHAR * pucFrame, USHORT * usLen ); -eMBException -eMBMasterFuncWriteMultipleCoils( UCHAR * pucFrame, USHORT * usLen ); -eMBException -eMBMasterFuncReadDiscreteInputs( UCHAR * pucFrame, USHORT * usLen ); -eMBException -eMBMasterFuncReadWriteMultipleHoldingRegister( UCHAR * pucFrame, USHORT * usLen ); - -/*�� \ingroup modbus - *\brief These functions are interface for Modbus Master - */ -void vMBMasterGetPDUSndBuf( UCHAR ** pucFrame ); -UCHAR ucMBMasterGetDestAddress( void ); -void vMBMasterSetDestAddress( UCHAR Address ); -BOOL xMBMasterGetCBRunInMasterMode( void ); -void vMBMasterSetCBRunInMasterMode( BOOL IsMasterMode ); -USHORT usMBMasterGetPDUSndLength( void ); -void vMBMasterSetPDUSndLength( USHORT SendPDULength ); -void vMBMasterSetCurTimerMode( eMBMasterTimerMode eMBTimerMode ); -BOOL xMBMasterRequestIsBroadcast( void ); -eMBMasterErrorEventType eMBMasterGetErrorType( void ); -void vMBMasterSetErrorType( eMBMasterErrorEventType errorType ); -eMBMasterReqErrCode eMBMasterWaitRequestFinish( void ); - -/* ----------------------- Callback -----------------------------------------*/ - -#ifdef __cplusplus -PR_END_EXTERN_C -#endif -#endif diff --git a/components/net/freemodbus/modbus/include/mbconfig.h b/components/net/freemodbus/modbus/include/mbconfig.h deleted file mode 100644 index 89030b7abd..0000000000 --- a/components/net/freemodbus/modbus/include/mbconfig.h +++ /dev/null @@ -1,124 +0,0 @@ -/* - * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. - * Copyright (c) 2006 Christian Walter <[email protected]> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * File: $Id: mbconfig.h,v 1.14 2006/12/07 22:10:34 wolti Exp $ - * $Id: mbconfig.h,v 1.60 2013/08/13 21:19:55 Armink Add Master Functions $ - */ - -#ifndef _MB_CONFIG_H -#define _MB_CONFIG_H - -#ifdef __cplusplus -PR_BEGIN_EXTERN_C -#endif -/* ----------------------- Defines ------------------------------------------*/ -/*! \defgroup modbus_cfg Modbus Configuration - * - * Most modules in the protocol stack are completly optional and can be - * excluded. This is specially important if target resources are very small - * and program memory space should be saved.<br> - * - * All of these settings are available in the file <code>mbconfig.h</code> - */ -/*! \addtogroup modbus_cfg - * @{ - */ -/*! \brief If Modbus Master ASCII support is enabled. */ -#define MB_MASTER_ASCII_ENABLED ( 0 ) -/*! \brief If Modbus Master RTU support is enabled. */ -#define MB_MASTER_RTU_ENABLED ( 1 ) -/*! \brief If Modbus Master TCP support is enabled. */ -#define MB_MASTER_TCP_ENABLED ( 0 ) -/*! \brief If Modbus Slave ASCII support is enabled. */ -#define MB_SLAVE_ASCII_ENABLED ( 0 ) -/*! \brief If Modbus Slave RTU support is enabled. */ -#define MB_SLAVE_RTU_ENABLED ( 1 ) -/*! \brief If Modbus Slave TCP support is enabled. */ -#define MB_SLAVE_TCP_ENABLED ( 0 ) -/*! \brief The character timeout value for Modbus ASCII. - * - * The character timeout value is not fixed for Modbus ASCII and is therefore - * a configuration option. It should be set to the maximum expected delay - * time of the network. - */ -#define MB_ASCII_TIMEOUT_SEC ( 1 ) -/*! \brief Maximum number of Modbus functions codes the protocol stack - * should support. - * - * The maximum number of supported Modbus functions must be greater than - * the sum of all enabled functions in this file and custom function - * handlers. If set to small adding more functions will fail. - */ -#define MB_FUNC_HANDLERS_MAX ( 16 ) -/*! \brief Number of bytes which should be allocated for the <em>Report Slave ID - * </em>command. - * - * This number limits the maximum size of the additional segment in the - * report slave id function. See eMBSetSlaveID( ) for more information on - * how to set this value. It is only used if MB_FUNC_OTHER_REP_SLAVEID_ENABLED - * is set to <code>1</code>. - */ -#define MB_FUNC_OTHER_REP_SLAVEID_BUF ( 32 ) -/*! \brief If the <em>Report Slave ID</em> function should be enabled. */ -#define MB_FUNC_OTHER_REP_SLAVEID_ENABLED ( 1 ) -/*! \brief If the <em>Read Input Registers</em> function should be enabled. */ -#define MB_FUNC_READ_INPUT_ENABLED ( 1 ) -/*! \brief If the <em>Read Holding Registers</em> function should be enabled. */ -#define MB_FUNC_READ_HOLDING_ENABLED ( 1 ) -/*! \brief If the <em>Write Single Register</em> function should be enabled. */ -#define MB_FUNC_WRITE_HOLDING_ENABLED ( 1 ) -/*! \brief If the <em>Write Multiple registers</em> function should be enabled. */ -#define MB_FUNC_WRITE_MULTIPLE_HOLDING_ENABLED ( 1 ) -/*! \brief If the <em>Read Coils</em> function should be enabled. */ -#define MB_FUNC_READ_COILS_ENABLED ( 1 ) -/*! \brief If the <em>Write Coils</em> function should be enabled. */ -#define MB_FUNC_WRITE_COIL_ENABLED ( 1 ) -/*! \brief If the <em>Write Multiple Coils</em> function should be enabled. */ -#define MB_FUNC_WRITE_MULTIPLE_COILS_ENABLED ( 1 ) -/*! \brief If the <em>Read Discrete Inputs</em> function should be enabled. */ -#define MB_FUNC_READ_DISCRETE_INPUTS_ENABLED ( 1 ) -/*! \brief If the <em>Read/Write Multiple Registers</em> function should be enabled. */ -#define MB_FUNC_READWRITE_HOLDING_ENABLED ( 1 ) -/*! @} */ -#ifdef __cplusplus - PR_END_EXTERN_C -#endif - -#if MB_MASTER_RTU_ENABLED > 0 || MB_MASTER_ASCII_ENABLED > 0 -/*! \brief If master send a broadcast frame,the master will wait time of convert to delay, - * then master can send other frame */ -#define MB_MASTER_DELAY_MS_CONVERT (200 ) -/*! \brief If master send a frame which is not broadcast,the master will wait sometime for slave. - * And if slave is not respond in this time,the master will process this timeout error. - * Then master can send other frame */ -#define MB_MASTER_TIMEOUT_MS_RESPOND (100 ) -/*! \brief The total slaves in Modbus Master system. Default 16. - * \note : The slave ID must be continuous from 1.*/ -#define MB_MASTER_TOTAL_SLAVE_NUM ( 16 ) -#endif - -#endif diff --git a/components/net/freemodbus/modbus/include/mbframe.h b/components/net/freemodbus/modbus/include/mbframe.h deleted file mode 100644 index 99d59c613e..0000000000 --- a/components/net/freemodbus/modbus/include/mbframe.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. - * Copyright (c) 2006 Christian Walter <[email protected]> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * File: $Id: mbframe.h,v 1.9 2006/12/07 22:10:34 wolti Exp $ - */ - -#ifndef _MB_FRAME_H -#define _MB_FRAME_H - -#ifdef __cplusplus -PR_BEGIN_EXTERN_C -#endif - -/*! - * Constants which defines the format of a modbus frame. The example is - * shown for a Modbus RTU/ASCII frame. Note that the Modbus PDU is not - * dependent on the underlying transport. - * - * <code> - * <------------------------ MODBUS SERIAL LINE PDU (1) -------------------> - * <----------- MODBUS PDU (1') ----------------> - * +-----------+---------------+----------------------------+-------------+ - * | Address | Function Code | Data | CRC/LRC | - * +-----------+---------------+----------------------------+-------------+ - * | | | | - * (2) (3/2') (3') (4) - * - * (1) ... MB_SER_PDU_SIZE_MAX = 256 - * (2) ... MB_SER_PDU_ADDR_OFF = 0 - * (3) ... MB_SER_PDU_PDU_OFF = 1 - * (4) ... MB_SER_PDU_SIZE_CRC = 2 - * - * (1') ... MB_PDU_SIZE_MAX = 253 - * (2') ... MB_PDU_FUNC_OFF = 0 - * (3') ... MB_PDU_DATA_OFF = 1 - * </code> - */ - -/* ----------------------- Defines ------------------------------------------*/ -#define MB_PDU_SIZE_MAX 253 /*!< Maximum size of a PDU. */ -#define MB_PDU_SIZE_MIN 1 /*!< Function Code */ -#define MB_PDU_FUNC_OFF 0 /*!< Offset of function code in PDU. */ -#define MB_PDU_DATA_OFF 1 /*!< Offset for response data in PDU. */ - -/* ----------------------- Prototypes 0-------------------------------------*/ -typedef void ( *pvMBFrameStart ) ( void ); - -typedef void ( *pvMBFrameStop ) ( void ); - -typedef eMBErrorCode( *peMBFrameReceive ) ( UCHAR * pucRcvAddress, - UCHAR ** pucFrame, - USHORT * pusLength ); - -typedef eMBErrorCode( *peMBFrameSend ) ( UCHAR slaveAddress, - const UCHAR * pucFrame, - USHORT usLength ); - -typedef void( *pvMBFrameClose ) ( void ); - -#ifdef __cplusplus -PR_END_EXTERN_C -#endif -#endif diff --git a/components/net/freemodbus/modbus/include/mbfunc.h b/components/net/freemodbus/modbus/include/mbfunc.h deleted file mode 100644 index 3f9c2725a1..0000000000 --- a/components/net/freemodbus/modbus/include/mbfunc.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. - * Copyright (c) 2006 Christian Walter <[email protected]> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * File: $Id: mbfunc.h,v 1.12 2006/12/07 22:10:34 wolti Exp $ - */ - -#ifndef _MB_FUNC_H -#define _MB_FUNC_H - -#ifdef __cplusplus -PR_BEGIN_EXTERN_C -#endif -#if MB_FUNC_OTHER_REP_SLAVEID_BUF > 0 -eMBException eMBFuncReportSlaveID( UCHAR * pucFrame, USHORT * usLen ); -#endif - -#if MB_FUNC_READ_INPUT_ENABLED > 0 -eMBException eMBFuncReadInputRegister( UCHAR * pucFrame, USHORT * usLen ); -#endif - -#if MB_FUNC_READ_HOLDING_ENABLED > 0 -eMBException eMBFuncReadHoldingRegister( UCHAR * pucFrame, USHORT * usLen ); -#endif - -#if MB_FUNC_WRITE_HOLDING_ENABLED > 0 -eMBException eMBFuncWriteHoldingRegister( UCHAR * pucFrame, USHORT * usLen ); -#endif - -#if MB_FUNC_WRITE_MULTIPLE_HOLDING_ENABLED > 0 -eMBException eMBFuncWriteMultipleHoldingRegister( UCHAR * pucFrame, USHORT * usLen ); -#endif - -#if MB_FUNC_READ_COILS_ENABLED > 0 -eMBException eMBFuncReadCoils( UCHAR * pucFrame, USHORT * usLen ); -#endif - -#if MB_FUNC_WRITE_COIL_ENABLED > 0 -eMBException eMBFuncWriteCoil( UCHAR * pucFrame, USHORT * usLen ); -#endif - -#if MB_FUNC_WRITE_MULTIPLE_COILS_ENABLED > 0 -eMBException eMBFuncWriteMultipleCoils( UCHAR * pucFrame, USHORT * usLen ); -#endif - -#if MB_FUNC_READ_DISCRETE_INPUTS_ENABLED > 0 -eMBException eMBFuncReadDiscreteInputs( UCHAR * pucFrame, USHORT * usLen ); -#endif - -#if MB_FUNC_READWRITE_HOLDING_ENABLED > 0 -eMBException eMBFuncReadWriteMultipleHoldingRegister( UCHAR * pucFrame, USHORT * usLen ); -#endif - -#ifdef __cplusplus -PR_END_EXTERN_C -#endif -#endif diff --git a/components/net/freemodbus/modbus/include/mbport.h b/components/net/freemodbus/modbus/include/mbport.h deleted file mode 100644 index 11794a2929..0000000000 --- a/components/net/freemodbus/modbus/include/mbport.h +++ /dev/null @@ -1,205 +0,0 @@ -/* - * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. - * Copyright (c) 2006 Christian Walter <[email protected]> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * File: $Id: mbport.h,v 1.17 2006/12/07 22:10:34 wolti Exp $ - * mbport.h,v 1.60 2013/08/17 11:42:56 Armink Add Master Functions $ - */ - -#ifndef _MB_PORT_H -#define _MB_PORT_H - -#ifdef __cplusplus -PR_BEGIN_EXTERN_C -#endif - -/* ----------------------- Defines ------------------------------------------*/ - -/* ----------------------- Type definitions ---------------------------------*/ - -typedef enum -{ - EV_READY = 1<<0, /*!< Startup finished. */ - EV_FRAME_RECEIVED = 1<<1, /*!< Frame received. */ - EV_EXECUTE = 1<<2, /*!< Execute function. */ - EV_FRAME_SENT = 1<<3 /*!< Frame sent. */ -} eMBEventType; - -typedef enum -{ - EV_MASTER_READY = 1<<0, /*!< Startup finished. */ - EV_MASTER_FRAME_RECEIVED = 1<<1, /*!< Frame received. */ - EV_MASTER_EXECUTE = 1<<2, /*!< Execute function. */ - EV_MASTER_FRAME_SENT = 1<<3, /*!< Frame sent. */ - EV_MASTER_ERROR_PROCESS = 1<<4, /*!< Frame error process. */ - EV_MASTER_PROCESS_SUCESS = 1<<5, /*!< Request process success. */ - EV_MASTER_ERROR_RESPOND_TIMEOUT = 1<<6, /*!< Request respond timeout. */ - EV_MASTER_ERROR_RECEIVE_DATA = 1<<7, /*!< Request receive data error. */ - EV_MASTER_ERROR_EXECUTE_FUNCTION = 1<<8, /*!< Request execute function error. */ -} eMBMasterEventType; - -typedef enum -{ - EV_ERROR_RESPOND_TIMEOUT, /*!< Slave respond timeout. */ - EV_ERROR_RECEIVE_DATA, /*!< Receive frame data erroe. */ - EV_ERROR_EXECUTE_FUNCTION, /*!< Execute function error. */ -} eMBMasterErrorEventType; - -/*! \ingroup modbus - * \brief Parity used for characters in serial mode. - * - * The parity which should be applied to the characters sent over the serial - * link. Please note that this values are actually passed to the porting - * layer and therefore not all parity modes might be available. - */ -typedef enum -{ - MB_PAR_NONE, /*!< No parity. */ - MB_PAR_ODD, /*!< Odd parity. */ - MB_PAR_EVEN /*!< Even parity. */ -} eMBParity; - -/* ----------------------- Supporting functions -----------------------------*/ -BOOL xMBPortEventInit( void ); - -BOOL xMBPortEventPost( eMBEventType eEvent ); - -BOOL xMBPortEventGet( /*@out@ */ eMBEventType * eEvent ); - -BOOL xMBMasterPortEventInit( void ); - -BOOL xMBMasterPortEventPost( eMBMasterEventType eEvent ); - -BOOL xMBMasterPortEventGet( /*@out@ */ eMBMasterEventType * eEvent ); - -void vMBMasterOsResInit( void ); - -BOOL xMBMasterRunResTake( int32_t time ); - -void vMBMasterRunResRelease( void ); - -/* ----------------------- Serial port functions ----------------------------*/ - -BOOL xMBPortSerialInit( UCHAR ucPort, ULONG ulBaudRate, - UCHAR ucDataBits, eMBParity eParity ); - -void vMBPortClose( void ); - -void xMBPortSerialClose( void ); - -void vMBPortSerialEnable( BOOL xRxEnable, BOOL xTxEnable ); - -INLINE BOOL xMBPortSerialGetByte( CHAR * pucByte ); - -INLINE BOOL xMBPortSerialPutByte( CHAR ucByte ); - -BOOL xMBMasterPortSerialInit( UCHAR ucPort, ULONG ulBaudRate, - UCHAR ucDataBits, eMBParity eParity ); - -void vMBMasterPortClose( void ); - -void xMBMasterPortSerialClose( void ); - -void vMBMasterPortSerialEnable( BOOL xRxEnable, BOOL xTxEnable ); - -INLINE BOOL xMBMasterPortSerialGetByte( CHAR * pucByte ); - -INLINE BOOL xMBMasterPortSerialPutByte( CHAR ucByte ); - -/* ----------------------- Timers functions ---------------------------------*/ -BOOL xMBPortTimersInit( USHORT usTimeOut50us ); - -void xMBPortTimersClose( void ); - -INLINE void vMBPortTimersEnable( void ); - -INLINE void vMBPortTimersDisable( void ); - -BOOL xMBMasterPortTimersInit( USHORT usTimeOut50us ); - -void xMBMasterPortTimersClose( void ); - -INLINE void vMBMasterPortTimersT35Enable( void ); - -INLINE void vMBMasterPortTimersConvertDelayEnable( void ); - -INLINE void vMBMasterPortTimersRespondTimeoutEnable( void ); - -INLINE void vMBMasterPortTimersDisable( void ); - -/* ----------------- Callback for the master error process ------------------*/ -void vMBMasterErrorCBRespondTimeout( UCHAR ucDestAddress, const UCHAR* pucPDUData, - USHORT ucPDULength ); - -void vMBMasterErrorCBReceiveData( UCHAR ucDestAddress, const UCHAR* pucPDUData, - USHORT ucPDULength ); - -void vMBMasterErrorCBExecuteFunction( UCHAR ucDestAddress, const UCHAR* pucPDUData, - USHORT ucPDULength ); - -void vMBMasterCBRequestScuuess( void ); - -/* ----------------------- Callback for the protocol stack ------------------*/ - -/*! - * \brief Callback function for the porting layer when a new byte is - * available. - * - * Depending upon the mode this callback function is used by the RTU or - * ASCII transmission layers. In any case a call to xMBPortSerialGetByte() - * must immediately return a new character. - * - * \return <code>TRUE</code> if a event was posted to the queue because - * a new byte was received. The port implementation should wake up the - * tasks which are currently blocked on the eventqueue. - */ -extern BOOL( *pxMBFrameCBByteReceived ) ( void ); - -extern BOOL( *pxMBFrameCBTransmitterEmpty ) ( void ); - -extern BOOL( *pxMBPortCBTimerExpired ) ( void ); - -extern BOOL( *pxMBMasterFrameCBByteReceived ) ( void ); - -extern BOOL( *pxMBMasterFrameCBTransmitterEmpty ) ( void ); - -extern BOOL( *pxMBMasterPortCBTimerExpired ) ( void ); - -/* ----------------------- TCP port functions -------------------------------*/ -BOOL xMBTCPPortInit( USHORT usTCPPort ); - -void vMBTCPPortClose( void ); - -void vMBTCPPortDisable( void ); - -BOOL xMBTCPPortGetRequest( UCHAR **ppucMBTCPFrame, USHORT * usTCPLength ); - -BOOL xMBTCPPortSendResponse( const UCHAR *pucMBTCPFrame, USHORT usTCPLength ); - -#ifdef __cplusplus -PR_END_EXTERN_C -#endif -#endif diff --git a/components/net/freemodbus/modbus/include/mbproto.h b/components/net/freemodbus/modbus/include/mbproto.h deleted file mode 100644 index 786aaf4030..0000000000 --- a/components/net/freemodbus/modbus/include/mbproto.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. - * Copyright (c) 2006 Christian Walter <[email protected]> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * File: $Id: mbproto.h,v 1.14 2006/12/07 22:10:34 wolti Exp $ - */ - -#ifndef _MB_PROTO_H -#define _MB_PROTO_H - -#ifdef __cplusplus -PR_BEGIN_EXTERN_C -#endif -/* ----------------------- Defines ------------------------------------------*/ -#define MB_ADDRESS_BROADCAST ( 0 ) /*! Modbus broadcast address. */ -#define MB_ADDRESS_MIN ( 1 ) /*! Smallest possible slave address. */ -#define MB_ADDRESS_MAX ( 247 ) /*! Biggest possible slave address. */ -#define MB_FUNC_NONE ( 0 ) -#define MB_FUNC_READ_COILS ( 1 ) -#define MB_FUNC_READ_DISCRETE_INPUTS ( 2 ) -#define MB_FUNC_WRITE_SINGLE_COIL ( 5 ) -#define MB_FUNC_WRITE_MULTIPLE_COILS ( 15 ) -#define MB_FUNC_READ_HOLDING_REGISTER ( 3 ) -#define MB_FUNC_READ_INPUT_REGISTER ( 4 ) -#define MB_FUNC_WRITE_REGISTER ( 6 ) -#define MB_FUNC_WRITE_MULTIPLE_REGISTERS ( 16 ) -#define MB_FUNC_READWRITE_MULTIPLE_REGISTERS ( 23 ) -#define MB_FUNC_DIAG_READ_EXCEPTION ( 7 ) -#define MB_FUNC_DIAG_DIAGNOSTIC ( 8 ) -#define MB_FUNC_DIAG_GET_COM_EVENT_CNT ( 11 ) -#define MB_FUNC_DIAG_GET_COM_EVENT_LOG ( 12 ) -#define MB_FUNC_OTHER_REPORT_SLAVEID ( 17 ) -#define MB_FUNC_ERROR ( 128 ) -/* ----------------------- Type definitions ---------------------------------*/ - typedef enum -{ - MB_EX_NONE = 0x00, - MB_EX_ILLEGAL_FUNCTION = 0x01, - MB_EX_ILLEGAL_DATA_ADDRESS = 0x02, - MB_EX_ILLEGAL_DATA_VALUE = 0x03, - MB_EX_SLAVE_DEVICE_FAILURE = 0x04, - MB_EX_ACKNOWLEDGE = 0x05, - MB_EX_SLAVE_BUSY = 0x06, - MB_EX_MEMORY_PARITY_ERROR = 0x08, - MB_EX_GATEWAY_PATH_FAILED = 0x0A, - MB_EX_GATEWAY_TGT_FAILED = 0x0B -} eMBException; - -typedef eMBException( *pxMBFunctionHandler ) ( UCHAR * pucFrame, USHORT * pusLength ); - -typedef struct -{ - UCHAR ucFunctionCode; - pxMBFunctionHandler pxHandler; -} xMBFunctionHandler; - -#ifdef __cplusplus -PR_END_EXTERN_C -#endif -#endif diff --git a/components/net/freemodbus/modbus/include/mbutils.h b/components/net/freemodbus/modbus/include/mbutils.h deleted file mode 100644 index 61495751d4..0000000000 --- a/components/net/freemodbus/modbus/include/mbutils.h +++ /dev/null @@ -1,108 +0,0 @@ -/* - * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. - * Copyright (c) 2006 Christian Walter <[email protected]> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * File: $Id: mbutils.h,v 1.5 2006/12/07 22:10:34 wolti Exp $ - */ - -#ifndef _MB_UTILS_H -#define _MB_UTILS_H - -#ifdef __cplusplus -PR_BEGIN_EXTERN_C -#endif -/*! \defgroup modbus_utils Utilities - * - * This module contains some utility functions which can be used by - * the application. It includes some special functions for working with - * bitfields backed by a character array buffer. - * - */ -/*! \addtogroup modbus_utils - * @{ - */ -/*! \brief Function to set bits in a byte buffer. - * - * This function allows the efficient use of an array to implement bitfields. - * The array used for storing the bits must always be a multiple of two - * bytes. Up to eight bits can be set or cleared in one operation. - * - * \param ucByteBuf A buffer where the bit values are stored. Must be a - * multiple of 2 bytes. No length checking is performed and if - * usBitOffset / 8 is greater than the size of the buffer memory contents - * is overwritten. - * \param usBitOffset The starting address of the bits to set. The first - * bit has the offset 0. - * \param ucNBits Number of bits to modify. The value must always be smaller - * than 8. - * \param ucValues Thew new values for the bits. The value for the first bit - * starting at <code>usBitOffset</code> is the LSB of the value - * <code>ucValues</code> - * - * \code - * ucBits[2] = {0, 0}; - * - * // Set bit 4 to 1 (read: set 1 bit starting at bit offset 4 to value 1) - * xMBUtilSetBits( ucBits, 4, 1, 1 ); - * - * // Set bit 7 to 1 and bit 8 to 0. - * xMBUtilSetBits( ucBits, 7, 2, 0x01 ); - * - * // Set bits 8 - 11 to 0x05 and bits 12 - 15 to 0x0A; - * xMBUtilSetBits( ucBits, 8, 8, 0x5A); - * \endcode - */ -void xMBUtilSetBits( UCHAR * ucByteBuf, USHORT usBitOffset, - UCHAR ucNBits, UCHAR ucValues ); - -/*! \brief Function to read bits in a byte buffer. - * - * This function is used to extract up bit values from an array. Up to eight - * bit values can be extracted in one step. - * - * \param ucByteBuf A buffer where the bit values are stored. - * \param usBitOffset The starting address of the bits to set. The first - * bit has the offset 0. - * \param ucNBits Number of bits to modify. The value must always be smaller - * than 8. - * - * \code - * UCHAR ucBits[2] = {0, 0}; - * UCHAR ucResult; - * - * // Extract the bits 3 - 10. - * ucResult = xMBUtilGetBits( ucBits, 3, 8 ); - * \endcode - */ -UCHAR xMBUtilGetBits( UCHAR * ucByteBuf, USHORT usBitOffset, - UCHAR ucNBits ); - -/*! @} */ - -#ifdef __cplusplus -PR_END_EXTERN_C -#endif -#endif diff --git a/components/net/freemodbus/modbus/mb.c b/components/net/freemodbus/modbus/mb.c deleted file mode 100644 index 96d693c910..0000000000 --- a/components/net/freemodbus/modbus/mb.c +++ /dev/null @@ -1,412 +0,0 @@ -/* - * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. - * Copyright (c) 2006 Christian Walter <[email protected]> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * File: $Id: mb.c,v 1.27 2007/02/18 23:45:41 wolti Exp $ - */ - -/* ----------------------- System includes ----------------------------------*/ -#include "stdlib.h" -#include "string.h" - -/* ----------------------- Platform includes --------------------------------*/ -#include "port.h" - -/* ----------------------- Modbus includes ----------------------------------*/ - -#include "mb.h" -#include "mbconfig.h" -#include "mbframe.h" -#include "mbproto.h" -#include "mbfunc.h" - -#include "mbport.h" -#if MB_SLAVE_RTU_ENABLED == 1 -#include "mbrtu.h" -#endif -#if MB_SLAVE_ASCII_ENABLED == 1 -#include "mbascii.h" -#endif -#if MB_SLAVE_TCP_ENABLED == 1 -#include "mbtcp.h" -#endif - -#ifndef MB_PORT_HAS_CLOSE -#define MB_PORT_HAS_CLOSE 0 -#endif - -/* ----------------------- Static variables ---------------------------------*/ - -static UCHAR ucMBAddress; -static eMBMode eMBCurrentMode; - -static enum -{ - STATE_ENABLED, - STATE_DISABLED, - STATE_NOT_INITIALIZED -} eMBState = STATE_NOT_INITIALIZED; - -/* Functions pointer which are initialized in eMBInit( ). Depending on the - * mode (RTU or ASCII) the are set to the correct implementations. - * Using for Modbus Slave - */ -static peMBFrameSend peMBFrameSendCur; -static pvMBFrameStart pvMBFrameStartCur; -static pvMBFrameStop pvMBFrameStopCur; -static peMBFrameReceive peMBFrameReceiveCur; -static pvMBFrameClose pvMBFrameCloseCur; - -/* Callback functions required by the porting layer. They are called when - * an external event has happend which includes a timeout or the reception - * or transmission of a character. - * Using for Modbus Slave - */ -BOOL( *pxMBFrameCBByteReceived ) ( void ); -BOOL( *pxMBFrameCBTransmitterEmpty ) ( void ); -BOOL( *pxMBPortCBTimerExpired ) ( void ); - -BOOL( *pxMBFrameCBReceiveFSMCur ) ( void ); -BOOL( *pxMBFrameCBTransmitFSMCur ) ( void ); - -/* An array of Modbus functions handlers which associates Modbus function - * codes with implementing functions. - */ -static xMBFunctionHandler xFuncHandlers[MB_FUNC_HANDLERS_MAX] = { -#if MB_FUNC_OTHER_REP_SLAVEID_ENABLED > 0 - {MB_FUNC_OTHER_REPORT_SLAVEID, eMBFuncReportSlaveID}, -#endif -#if MB_FUNC_READ_INPUT_ENABLED > 0 - {MB_FUNC_READ_INPUT_REGISTER, eMBFuncReadInputRegister}, -#endif -#if MB_FUNC_READ_HOLDING_ENABLED > 0 - {MB_FUNC_READ_HOLDING_REGISTER, eMBFuncReadHoldingRegister}, -#endif -#if MB_FUNC_WRITE_MULTIPLE_HOLDING_ENABLED > 0 - {MB_FUNC_WRITE_MULTIPLE_REGISTERS, eMBFuncWriteMultipleHoldingRegister}, -#endif -#if MB_FUNC_WRITE_HOLDING_ENABLED > 0 - {MB_FUNC_WRITE_REGISTER, eMBFuncWriteHoldingRegister}, -#endif -#if MB_FUNC_READWRITE_HOLDING_ENABLED > 0 - {MB_FUNC_READWRITE_MULTIPLE_REGISTERS, eMBFuncReadWriteMultipleHoldingRegister}, -#endif -#if MB_FUNC_READ_COILS_ENABLED > 0 - {MB_FUNC_READ_COILS, eMBFuncReadCoils}, -#endif -#if MB_FUNC_WRITE_COIL_ENABLED > 0 - {MB_FUNC_WRITE_SINGLE_COIL, eMBFuncWriteCoil}, -#endif -#if MB_FUNC_WRITE_MULTIPLE_COILS_ENABLED > 0 - {MB_FUNC_WRITE_MULTIPLE_COILS, eMBFuncWriteMultipleCoils}, -#endif -#if MB_FUNC_READ_DISCRETE_INPUTS_ENABLED > 0 - {MB_FUNC_READ_DISCRETE_INPUTS, eMBFuncReadDiscreteInputs}, -#endif -}; - -/* ----------------------- Start implementation -----------------------------*/ -eMBErrorCode -eMBInit( eMBMode eMode, UCHAR ucSlaveAddress, UCHAR ucPort, ULONG ulBaudRate, eMBParity eParity ) -{ - eMBErrorCode eStatus = MB_ENOERR; - - /* check preconditions */ - if( ( ucSlaveAddress == MB_ADDRESS_BROADCAST ) || - ( ucSlaveAddress < MB_ADDRESS_MIN ) || ( ucSlaveAddress > MB_ADDRESS_MAX ) ) - { - eStatus = MB_EINVAL; - } - else - { - ucMBAddress = ucSlaveAddress; - - switch ( eMode ) - { -#if MB_SLAVE_RTU_ENABLED > 0 - case MB_RTU: - pvMBFrameStartCur = eMBRTUStart; - pvMBFrameStopCur = eMBRTUStop; - peMBFrameSendCur = eMBRTUSend; - peMBFrameReceiveCur = eMBRTUReceive; - pvMBFrameCloseCur = MB_PORT_HAS_CLOSE ? vMBPortClose : NULL; - pxMBFrameCBByteReceived = xMBRTUReceiveFSM; - pxMBFrameCBTransmitterEmpty = xMBRTUTransmitFSM; - pxMBPortCBTimerExpired = xMBRTUTimerT35Expired; - - eStatus = eMBRTUInit( ucMBAddress, ucPort, ulBaudRate, eParity ); - break; -#endif -#if MB_SLAVE_ASCII_ENABLED > 0 - case MB_ASCII: - pvMBFrameStartCur = eMBASCIIStart; - pvMBFrameStopCur = eMBASCIIStop; - peMBFrameSendCur = eMBASCIISend; - peMBFrameReceiveCur = eMBASCIIReceive; - pvMBFrameCloseCur = MB_PORT_HAS_CLOSE ? vMBPortClose : NULL; - pxMBFrameCBByteReceived = xMBASCIIReceiveFSM; - pxMBFrameCBTransmitterEmpty = xMBASCIITransmitFSM; - pxMBPortCBTimerExpired = xMBASCIITimerT1SExpired; - - eStatus = eMBASCIIInit( ucMBAddress, ucPort, ulBaudRate, eParity ); - break; -#endif - default: - eStatus = MB_EINVAL; - break; - } - - if( eStatus == MB_ENOERR ) - { - if( !xMBPortEventInit( ) ) - { - /* port dependent event module initalization failed. */ - eStatus = MB_EPORTERR; - } - else - { - eMBCurrentMode = eMode; - eMBState = STATE_DISABLED; - } - } - } - return eStatus; -} - -#if MB_SLAVE_TCP_ENABLED > 0 -eMBErrorCode -eMBTCPInit( USHORT ucTCPPort ) -{ - eMBErrorCode eStatus = MB_ENOERR; - - if( ( eStatus = eMBTCPDoInit( ucTCPPort ) ) != MB_ENOERR ) - { - eMBState = STATE_DISABLED; - } - else if( !xMBPortEventInit( ) ) - { - /* Port dependent event module initalization failed. */ - eStatus = MB_EPORTERR; - } - else - { - pvMBFrameStartCur = eMBTCPStart; - pvMBFrameStopCur = eMBTCPStop; - peMBFrameReceiveCur = eMBTCPReceive; - peMBFrameSendCur = eMBTCPSend; - pvMBFrameCloseCur = MB_PORT_HAS_CLOSE ? vMBTCPPortClose : NULL; - ucMBAddress = MB_TCP_PSEUDO_ADDRESS; - eMBCurrentMode = MB_TCP; - eMBState = STATE_DISABLED; - } - return eStatus; -} -#endif - -eMBErrorCode -eMBRegisterCB( UCHAR ucFunctionCode, pxMBFunctionHandler pxHandler ) -{ - int i; - eMBErrorCode eStatus; - - if( ( 0 < ucFunctionCode ) && ( ucFunctionCode <= 127 ) ) - { - ENTER_CRITICAL_SECTION( ); - if( pxHandler != NULL ) - { - for( i = 0; i < MB_FUNC_HANDLERS_MAX; i++ ) - { - if( ( xFuncHandlers[i].pxHandler == NULL ) || - ( xFuncHandlers[i].pxHandler == pxHandler ) ) - { - xFuncHandlers[i].ucFunctionCode = ucFunctionCode; - xFuncHandlers[i].pxHandler = pxHandler; - break; - } - } - eStatus = ( i != MB_FUNC_HANDLERS_MAX ) ? MB_ENOERR : MB_ENORES; - } - else - { - for( i = 0; i < MB_FUNC_HANDLERS_MAX; i++ ) - { - if( xFuncHandlers[i].ucFunctionCode == ucFunctionCode ) - { - xFuncHandlers[i].ucFunctionCode = 0; - xFuncHandlers[i].pxHandler = NULL; - break; - } - } - /* Remove can't fail. */ - eStatus = MB_ENOERR; - } - EXIT_CRITICAL_SECTION( ); - } - else - { - eStatus = MB_EINVAL; - } - return eStatus; -} - - -eMBErrorCode -eMBClose( void ) -{ - eMBErrorCode eStatus = MB_ENOERR; - - if( eMBState == STATE_DISABLED ) - { - if( pvMBFrameCloseCur != NULL ) - { - pvMBFrameCloseCur( ); - } - } - else - { - eStatus = MB_EILLSTATE; - } - return eStatus; -} - - -eMBErrorCode -eMBEnable( void ) -{ - eMBErrorCode eStatus = MB_ENOERR; - - if( eMBState == STATE_DISABLED ) - { - /* Activate the protocol stack. */ - pvMBFrameStartCur( ); - eMBState = STATE_ENABLED; - } - else - { - eStatus = MB_EILLSTATE; - } - return eStatus; -} - -eMBErrorCode -eMBDisable( void ) -{ - eMBErrorCode eStatus; - - if( eMBState == STATE_ENABLED ) - { - pvMBFrameStopCur( ); - eMBState = STATE_DISABLED; - eStatus = MB_ENOERR; - } - else if( eMBState == STATE_DISABLED ) - { - eStatus = MB_ENOERR; - } - else - { - eStatus = MB_EILLSTATE; - } - return eStatus; -} - -eMBErrorCode eMBPoll( void ) -{ - static UCHAR *ucMBFrame; - static UCHAR ucRcvAddress; - static UCHAR ucFunctionCode; - static USHORT usLength; - static eMBException eException; - - int i; - eMBErrorCode eStatus = MB_ENOERR; - eMBEventType eEvent; - - /* Check if the protocol stack is ready. */ - if( eMBState != STATE_ENABLED ) - { - return MB_EILLSTATE; - } - - /* Check if there is a event available. If not return control to caller. - * Otherwise we will handle the event. */ - if( xMBPortEventGet( &eEvent ) == TRUE ) - { - switch ( eEvent ) - { - case EV_READY: - break; - - case EV_FRAME_RECEIVED: - eStatus = peMBFrameReceiveCur( &ucRcvAddress, &ucMBFrame, &usLength ); - if( eStatus == MB_ENOERR ) - { - /* Check if the frame is for us. If not ignore the frame. */ - if( ( ucRcvAddress == ucMBAddress ) || ( ucRcvAddress == MB_ADDRESS_BROADCAST ) ) - { - ( void )xMBPortEventPost( EV_EXECUTE ); - } - } - break; - - case EV_EXECUTE: - ucFunctionCode = ucMBFrame[MB_PDU_FUNC_OFF]; - eException = MB_EX_ILLEGAL_FUNCTION; - for( i = 0; i < MB_FUNC_HANDLERS_MAX; i++ ) - { - /* No more function handlers registered. Abort. */ - if( xFuncHandlers[i].ucFunctionCode == 0 ) - { - break; - } - else if( xFuncHandlers[i].ucFunctionCode == ucFunctionCode ) - { - eException = xFuncHandlers[i].pxHandler( ucMBFrame, &usLength ); - break; - } - } - - /* If the request was not sent to the broadcast address we - * return a reply. */ - if( ucRcvAddress != MB_ADDRESS_BROADCAST ) - { - if( eException != MB_EX_NONE ) - { - /* An exception occured. Build an error frame. */ - usLength = 0; - ucMBFrame[usLength++] = ( UCHAR )( ucFunctionCode | MB_FUNC_ERROR ); - ucMBFrame[usLength++] = eException; - } - eStatus = peMBFrameSendCur( ucMBAddress, ucMBFrame, usLength ); - } - break; - - case EV_FRAME_SENT: - break; - } - } - return MB_ENOERR; -} diff --git a/components/net/freemodbus/modbus/mb_m.c b/components/net/freemodbus/modbus/mb_m.c deleted file mode 100644 index 4e7c4b2b74..0000000000 --- a/components/net/freemodbus/modbus/mb_m.c +++ /dev/null @@ -1,406 +0,0 @@ -/* - * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. - * Copyright (C) 2013 Armink <[email protected]> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * File: $Id: mbrtu_m.c,v 1.60 2013/08/20 11:18:10 Armink Add Master Functions $ - */ - -/* ----------------------- System includes ----------------------------------*/ -#include "stdlib.h" -#include "string.h" - -/* ----------------------- Platform includes --------------------------------*/ -#include "port.h" - -/* ----------------------- Modbus includes ----------------------------------*/ - -#include "mb.h" -#include "mb_m.h" -#include "mbconfig.h" -#include "mbframe.h" -#include "mbproto.h" -#include "mbfunc.h" - -#include "mbport.h" -#if MB_MASTER_RTU_ENABLED == 1 -#include "mbrtu.h" -#endif -#if MB_MASTER_ASCII_ENABLED == 1 -#include "mbascii.h" -#endif -#if MB_MASTER_TCP_ENABLED == 1 -#include "mbtcp.h" -#endif - -#if MB_MASTER_RTU_ENABLED > 0 || MB_MASTER_ASCII_ENABLED > 0 - -#ifndef MB_PORT_HAS_CLOSE -#define MB_PORT_HAS_CLOSE 0 -#endif - -/* ----------------------- Static variables ---------------------------------*/ - -static UCHAR ucMBMasterDestAddress; -static BOOL xMBRunInMasterMode = FALSE; -static eMBMasterErrorEventType eMBMasterCurErrorType; - -static enum -{ - STATE_ENABLED, - STATE_DISABLED, - STATE_NOT_INITIALIZED -} eMBState = STATE_NOT_INITIALIZED; - -/* Functions pointer which are initialized in eMBInit( ). Depending on the - * mode (RTU or ASCII) the are set to the correct implementations. - * Using for Modbus Master,Add by Armink 20130813 - */ -static peMBFrameSend peMBMasterFrameSendCur; -static pvMBFrameStart pvMBMasterFrameStartCur; -static pvMBFrameStop pvMBMasterFrameStopCur; -static peMBFrameReceive peMBMasterFrameReceiveCur; -static pvMBFrameClose pvMBMasterFrameCloseCur; - -/* Callback functions required by the porting layer. They are called when - * an external event has happend which includes a timeout or the reception - * or transmission of a character. - * Using for Modbus Master,Add by Armink 20130813 - */ -BOOL( *pxMBMasterFrameCBByteReceived ) ( void ); -BOOL( *pxMBMasterFrameCBTransmitterEmpty ) ( void ); -BOOL( *pxMBMasterPortCBTimerExpired ) ( void ); - -BOOL( *pxMBMasterFrameCBReceiveFSMCur ) ( void ); -BOOL( *pxMBMasterFrameCBTransmitFSMCur ) ( void ); - -/* An array of Modbus functions handlers which associates Modbus function - * codes with implementing functions. - */ -static xMBFunctionHandler xMasterFuncHandlers[MB_FUNC_HANDLERS_MAX] = { -#if MB_FUNC_OTHER_REP_SLAVEID_ENABLED > 0 - //TODO Add Master function define - {MB_FUNC_OTHER_REPORT_SLAVEID, eMBFuncReportSlaveID}, -#endif -#if MB_FUNC_READ_INPUT_ENABLED > 0 - {MB_FUNC_READ_INPUT_REGISTER, eMBMasterFuncReadInputRegister}, -#endif -#if MB_FUNC_READ_HOLDING_ENABLED > 0 - {MB_FUNC_READ_HOLDING_REGISTER, eMBMasterFuncReadHoldingRegister}, -#endif -#if MB_FUNC_WRITE_MULTIPLE_HOLDING_ENABLED > 0 - {MB_FUNC_WRITE_MULTIPLE_REGISTERS, eMBMasterFuncWriteMultipleHoldingRegister}, -#endif -#if MB_FUNC_WRITE_HOLDING_ENABLED > 0 - {MB_FUNC_WRITE_REGISTER, eMBMasterFuncWriteHoldingRegister}, -#endif -#if MB_FUNC_READWRITE_HOLDING_ENABLED > 0 - {MB_FUNC_READWRITE_MULTIPLE_REGISTERS, eMBMasterFuncReadWriteMultipleHoldingRegister}, -#endif -#if MB_FUNC_READ_COILS_ENABLED > 0 - {MB_FUNC_READ_COILS, eMBMasterFuncReadCoils}, -#endif -#if MB_FUNC_WRITE_COIL_ENABLED > 0 - {MB_FUNC_WRITE_SINGLE_COIL, eMBMasterFuncWriteCoil}, -#endif -#if MB_FUNC_WRITE_MULTIPLE_COILS_ENABLED > 0 - {MB_FUNC_WRITE_MULTIPLE_COILS, eMBMasterFuncWriteMultipleCoils}, -#endif -#if MB_FUNC_READ_DISCRETE_INPUTS_ENABLED > 0 - {MB_FUNC_READ_DISCRETE_INPUTS, eMBMasterFuncReadDiscreteInputs}, -#endif -}; - -/* ----------------------- Start implementation -----------------------------*/ -eMBErrorCode -eMBMasterInit( eMBMode eMode, UCHAR ucPort, ULONG ulBaudRate, eMBParity eParity ) -{ - eMBErrorCode eStatus = MB_ENOERR; - - switch (eMode) - { -#if MB_MASTER_RTU_ENABLED > 0 - case MB_RTU: - pvMBMasterFrameStartCur = eMBMasterRTUStart; - pvMBMasterFrameStopCur = eMBMasterRTUStop; - peMBMasterFrameSendCur = eMBMasterRTUSend; - peMBMasterFrameReceiveCur = eMBMasterRTUReceive; - pvMBMasterFrameCloseCur = MB_PORT_HAS_CLOSE ? vMBMasterPortClose : NULL; - pxMBMasterFrameCBByteReceived = xMBMasterRTUReceiveFSM; - pxMBMasterFrameCBTransmitterEmpty = xMBMasterRTUTransmitFSM; - pxMBMasterPortCBTimerExpired = xMBMasterRTUTimerExpired; - - eStatus = eMBMasterRTUInit(ucPort, ulBaudRate, eParity); - break; -#endif -#if MB_MASTER_ASCII_ENABLED > 0 - case MB_ASCII: - pvMBMasterFrameStartCur = eMBMasterASCIIStart; - pvMBMasterFrameStopCur = eMBMasterASCIIStop; - peMBMasterFrameSendCur = eMBMasterASCIISend; - peMBMasterFrameReceiveCur = eMBMasterASCIIReceive; - pvMBMasterFrameCloseCur = MB_PORT_HAS_CLOSE ? vMBMasterPortClose : NULL; - pxMBMasterFrameCBByteReceived = xMBMasterASCIIReceiveFSM; - pxMBMasterFrameCBTransmitterEmpty = xMBMasterASCIITransmitFSM; - pxMBMasterPortCBTimerExpired = xMBMasterASCIITimerT1SExpired; - - eStatus = eMBMasterASCIIInit(ucPort, ulBaudRate, eParity ); - break; -#endif - default: - eStatus = MB_EINVAL; - break; - } - - if (eStatus == MB_ENOERR) - { - if (!xMBMasterPortEventInit()) - { - /* port dependent event module initalization failed. */ - eStatus = MB_EPORTERR; - } - else - { - eMBState = STATE_DISABLED; - } - /* initialize the OS resource for modbus master. */ - vMBMasterOsResInit(); - } - return eStatus; -} - -eMBErrorCode -eMBMasterClose( void ) -{ - eMBErrorCode eStatus = MB_ENOERR; - - if( eMBState == STATE_DISABLED ) - { - if( pvMBMasterFrameCloseCur != NULL ) - { - pvMBMasterFrameCloseCur( ); - } - } - else - { - eStatus = MB_EILLSTATE; - } - return eStatus; -} - -eMBErrorCode -eMBMasterEnable( void ) -{ - eMBErrorCode eStatus = MB_ENOERR; - - if( eMBState == STATE_DISABLED ) - { - /* Activate the protocol stack. */ - pvMBMasterFrameStartCur( ); - eMBState = STATE_ENABLED; - } - else - { - eStatus = MB_EILLSTATE; - } - return eStatus; -} - -eMBErrorCode -eMBMasterDisable( void ) -{ - eMBErrorCode eStatus; - - if( eMBState == STATE_ENABLED ) - { - pvMBMasterFrameStopCur( ); - eMBState = STATE_DISABLED; - eStatus = MB_ENOERR; - } - else if( eMBState == STATE_DISABLED ) - { - eStatus = MB_ENOERR; - } - else - { - eStatus = MB_EILLSTATE; - } - return eStatus; -} - -eMBErrorCode -eMBMasterPoll( void ) -{ - static UCHAR *ucMBFrame; - static UCHAR ucRcvAddress; - static UCHAR ucFunctionCode; - static USHORT usLength; - static eMBException eException; - - int i , j; - eMBErrorCode eStatus = MB_ENOERR; - eMBMasterEventType eEvent; - eMBMasterErrorEventType errorType; - - /* Check if the protocol stack is ready. */ - if( eMBState != STATE_ENABLED ) - { - return MB_EILLSTATE; - } - - /* Check if there is a event available. If not return control to caller. - * Otherwise we will handle the event. */ - if( xMBMasterPortEventGet( &eEvent ) == TRUE ) - { - switch ( eEvent ) - { - case EV_MASTER_READY: - break; - - case EV_MASTER_FRAME_RECEIVED: - eStatus = peMBMasterFrameReceiveCur( &ucRcvAddress, &ucMBFrame, &usLength ); - /* Check if the frame is for us. If not ,send an error process event. */ - if ( ( eStatus == MB_ENOERR ) && ( ucRcvAddress == ucMBMasterGetDestAddress() ) ) - { - ( void ) xMBMasterPortEventPost( EV_MASTER_EXECUTE ); - } - else - { - vMBMasterSetErrorType(EV_ERROR_RECEIVE_DATA); - ( void ) xMBMasterPortEventPost( EV_MASTER_ERROR_PROCESS ); - } - break; - - case EV_MASTER_EXECUTE: - ucFunctionCode = ucMBFrame[MB_PDU_FUNC_OFF]; - eException = MB_EX_ILLEGAL_FUNCTION; - /* If receive frame has exception .The receive function code highest bit is 1.*/ - if(ucFunctionCode >> 7) { - eException = (eMBException)ucMBFrame[MB_PDU_DATA_OFF]; - } - else - { - for (i = 0; i < MB_FUNC_HANDLERS_MAX; i++) - { - /* No more function handlers registered. Abort. */ - if (xMasterFuncHandlers[i].ucFunctionCode == 0) { - break; - } - else if (xMasterFuncHandlers[i].ucFunctionCode == ucFunctionCode) { - vMBMasterSetCBRunInMasterMode(TRUE); - /* If master request is broadcast, - * the master need execute function for all slave. - */ - if ( xMBMasterRequestIsBroadcast() ) { - usLength = usMBMasterGetPDUSndLength(); - for(j = 1; j <= MB_MASTER_TOTAL_SLAVE_NUM; j++){ - vMBMasterSetDestAddress(j); - eException = xMasterFuncHandlers[i].pxHandler(ucMBFrame, &usLength); - } - } - else { - eException = xMasterFuncHandlers[i].pxHandler(ucMBFrame, &usLength); - } - vMBMasterSetCBRunInMasterMode(FALSE); - break; - } - } - } - /* If master has exception ,Master will send error process.Otherwise the Master is idle.*/ - if (eException != MB_EX_NONE) { - vMBMasterSetErrorType(EV_ERROR_EXECUTE_FUNCTION); - ( void ) xMBMasterPortEventPost( EV_MASTER_ERROR_PROCESS ); - } - else { - vMBMasterCBRequestScuuess( ); - vMBMasterRunResRelease( ); - } - break; - - case EV_MASTER_FRAME_SENT: - /* Master is busy now. */ - vMBMasterGetPDUSndBuf( &ucMBFrame ); - eStatus = peMBMasterFrameSendCur( ucMBMasterGetDestAddress(), ucMBFrame, usMBMasterGetPDUSndLength() ); - break; - - case EV_MASTER_ERROR_PROCESS: - /* Execute specified error process callback function. */ - errorType = eMBMasterGetErrorType(); - vMBMasterGetPDUSndBuf( &ucMBFrame ); - switch (errorType) { - case EV_ERROR_RESPOND_TIMEOUT: - vMBMasterErrorCBRespondTimeout(ucMBMasterGetDestAddress(), - ucMBFrame, usMBMasterGetPDUSndLength()); - break; - case EV_ERROR_RECEIVE_DATA: - vMBMasterErrorCBReceiveData(ucMBMasterGetDestAddress(), - ucMBFrame, usMBMasterGetPDUSndLength()); - break; - case EV_ERROR_EXECUTE_FUNCTION: - vMBMasterErrorCBExecuteFunction(ucMBMasterGetDestAddress(), - ucMBFrame, usMBMasterGetPDUSndLength()); - break; - } - vMBMasterRunResRelease(); - break; - } - } - return MB_ENOERR; -} - -/* Get whether the Modbus Master is run in master mode.*/ -BOOL xMBMasterGetCBRunInMasterMode( void ) -{ - return xMBRunInMasterMode; -} -/* Set whether the Modbus Master is run in master mode.*/ -void vMBMasterSetCBRunInMasterMode( BOOL IsMasterMode ) -{ - xMBRunInMasterMode = IsMasterMode; -} -/* Get Modbus Master send destination address. */ -UCHAR ucMBMasterGetDestAddress( void ) -{ - return ucMBMasterDestAddress; -} -/* Set Modbus Master send destination address. */ -void vMBMasterSetDestAddress( UCHAR Address ) -{ - ucMBMasterDestAddress = Address; -} -/* Get Modbus Master current error event type. */ -eMBMasterErrorEventType eMBMasterGetErrorType( void ) -{ - return eMBMasterCurErrorType; -} -/* Set Modbus Master current error event type. */ -void vMBMasterSetErrorType( eMBMasterErrorEventType errorType ) -{ - eMBMasterCurErrorType = errorType; -} - - - -#endif diff --git a/components/net/freemodbus/modbus/rtu/mbcrc.c b/components/net/freemodbus/modbus/rtu/mbcrc.c deleted file mode 100644 index 29b9ea765a..0000000000 --- a/components/net/freemodbus/modbus/rtu/mbcrc.c +++ /dev/null @@ -1,98 +0,0 @@ -/* - * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. - * Copyright (c) 2006 Christian Walter <[email protected]> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * File: $Id: mbcrc.c,v 1.7 2007/02/18 23:50:27 wolti Exp $ - */ - -/* ----------------------- Platform includes --------------------------------*/ -#include "port.h" - -static const UCHAR aucCRCHi[] = { - 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, - 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, - 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, - 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, - 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, - 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, - 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, - 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, - 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, - 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, - 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, - 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, - 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, - 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, - 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, - 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, - 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, - 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, - 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, - 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, - 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, - 0x00, 0xC1, 0x81, 0x40 -}; - -static const UCHAR aucCRCLo[] = { - 0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7, - 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E, - 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09, 0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, - 0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, - 0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3, - 0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32, - 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D, - 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A, 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, - 0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, - 0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26, - 0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1, - 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4, - 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F, 0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, - 0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, - 0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5, - 0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0, - 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97, - 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C, 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, - 0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, - 0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C, - 0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83, - 0x41, 0x81, 0x80, 0x40 -}; - -USHORT -usMBCRC16( UCHAR * pucFrame, USHORT usLen ) -{ - UCHAR ucCRCHi = 0xFF; - UCHAR ucCRCLo = 0xFF; - int iIndex; - - while( usLen-- ) - { - iIndex = ucCRCLo ^ *( pucFrame++ ); - ucCRCLo = ( UCHAR )( ucCRCHi ^ aucCRCHi[iIndex] ); - ucCRCHi = aucCRCLo[iIndex]; - } - return ( USHORT )( ucCRCHi << 8 | ucCRCLo ); -} diff --git a/components/net/freemodbus/modbus/rtu/mbcrc.h b/components/net/freemodbus/modbus/rtu/mbcrc.h deleted file mode 100644 index db227763f1..0000000000 --- a/components/net/freemodbus/modbus/rtu/mbcrc.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. - * Copyright (c) 2006 Christian Walter <[email protected]> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * File: $Id: mbcrc.h,v 1.5 2006/12/07 22:10:34 wolti Exp $ - */ - -#ifndef _MB_CRC_H -#define _MB_CRC_H - -USHORT usMBCRC16( UCHAR * pucFrame, USHORT usLen ); - -#endif diff --git a/components/net/freemodbus/modbus/rtu/mbrtu.c b/components/net/freemodbus/modbus/rtu/mbrtu.c deleted file mode 100644 index 40c29348ce..0000000000 --- a/components/net/freemodbus/modbus/rtu/mbrtu.c +++ /dev/null @@ -1,354 +0,0 @@ -/* - * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. - * Copyright (c) 2006 Christian Walter <[email protected]> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * File: $Id: mbrtu.c,v 1.18 2007/09/12 10:15:56 wolti Exp $ - */ - -/* ----------------------- System includes ----------------------------------*/ -#include "stdlib.h" -#include "string.h" - -/* ----------------------- Platform includes --------------------------------*/ -#include "port.h" - -/* ----------------------- Modbus includes ----------------------------------*/ -#include "mb.h" -#include "mbrtu.h" -#include "mbframe.h" - -#include "mbcrc.h" -#include "mbport.h" - -/* ----------------------- Defines ------------------------------------------*/ -#define MB_SER_PDU_SIZE_MIN 4 /*!< Minimum size of a Modbus RTU frame. */ -#define MB_SER_PDU_SIZE_MAX 256 /*!< Maximum size of a Modbus RTU frame. */ -#define MB_SER_PDU_SIZE_CRC 2 /*!< Size of CRC field in PDU. */ -#define MB_SER_PDU_ADDR_OFF 0 /*!< Offset of slave address in Ser-PDU. */ -#define MB_SER_PDU_PDU_OFF 1 /*!< Offset of Modbus-PDU in Ser-PDU. */ - -/* ----------------------- Type definitions ---------------------------------*/ -typedef enum -{ - STATE_RX_INIT, /*!< Receiver is in initial state. */ - STATE_RX_IDLE, /*!< Receiver is in idle state. */ - STATE_RX_RCV, /*!< Frame is beeing received. */ - STATE_RX_ERROR /*!< If the frame is invalid. */ -} eMBRcvState; - -typedef enum -{ - STATE_TX_IDLE, /*!< Transmitter is in idle state. */ - STATE_TX_XMIT /*!< Transmitter is in transfer state. */ -} eMBSndState; - -/* ----------------------- Static variables ---------------------------------*/ -static volatile eMBSndState eSndState; -static volatile eMBRcvState eRcvState; - -volatile UCHAR ucRTUBuf[MB_SER_PDU_SIZE_MAX]; - -static volatile UCHAR *pucSndBufferCur; -static volatile USHORT usSndBufferCount; - -static volatile USHORT usRcvBufferPos; - -/* ----------------------- Start implementation -----------------------------*/ -eMBErrorCode -eMBRTUInit( UCHAR ucSlaveAddress, UCHAR ucPort, ULONG ulBaudRate, eMBParity eParity ) -{ - eMBErrorCode eStatus = MB_ENOERR; - ULONG usTimerT35_50us; - - ( void )ucSlaveAddress; - ENTER_CRITICAL_SECTION( ); - - /* Modbus RTU uses 8 Databits. */ - if( xMBPortSerialInit( ucPort, ulBaudRate, 8, eParity ) != TRUE ) - { - eStatus = MB_EPORTERR; - } - else - { - /* If baudrate > 19200 then we should use the fixed timer values - * t35 = 1750us. Otherwise t35 must be 3.5 times the character time. - */ - if( ulBaudRate > 19200 ) - { - usTimerT35_50us = 35; /* 1800us. */ - } - else - { - /* The timer reload value for a character is given by: - * - * ChTimeValue = Ticks_per_1s / ( Baudrate / 11 ) - * = 11 * Ticks_per_1s / Baudrate - * = 220000 / Baudrate - * The reload for t3.5 is 1.5 times this value and similary - * for t3.5. - */ - usTimerT35_50us = ( 7UL * 220000UL ) / ( 2UL * ulBaudRate ); - } - if( xMBPortTimersInit( ( USHORT ) usTimerT35_50us ) != TRUE ) - { - eStatus = MB_EPORTERR; - } - } - EXIT_CRITICAL_SECTION( ); - - return eStatus; -} - -void -eMBRTUStart( void ) -{ - ENTER_CRITICAL_SECTION( ); - /* Initially the receiver is in the state STATE_RX_INIT. we start - * the timer and if no character is received within t3.5 we change - * to STATE_RX_IDLE. This makes sure that we delay startup of the - * modbus protocol stack until the bus is free. - */ - eRcvState = STATE_RX_INIT; - vMBPortSerialEnable( TRUE, FALSE ); - vMBPortTimersEnable( ); - - EXIT_CRITICAL_SECTION( ); -} - -void -eMBRTUStop( void ) -{ - ENTER_CRITICAL_SECTION( ); - vMBPortSerialEnable( FALSE, FALSE ); - vMBPortTimersDisable( ); - EXIT_CRITICAL_SECTION( ); -} - -eMBErrorCode -eMBRTUReceive( UCHAR * pucRcvAddress, UCHAR ** pucFrame, USHORT * pusLength ) -{ - eMBErrorCode eStatus = MB_ENOERR; - - ENTER_CRITICAL_SECTION( ); - RT_ASSERT( usRcvBufferPos <= MB_SER_PDU_SIZE_MAX ); - - /* Length and CRC check */ - if( ( usRcvBufferPos >= MB_SER_PDU_SIZE_MIN ) - && ( usMBCRC16( ( UCHAR * ) ucRTUBuf, usRcvBufferPos ) == 0 ) ) - { - /* Save the address field. All frames are passed to the upper layed - * and the decision if a frame is used is done there. - */ - *pucRcvAddress = ucRTUBuf[MB_SER_PDU_ADDR_OFF]; - - /* Total length of Modbus-PDU is Modbus-Serial-Line-PDU minus - * size of address field and CRC checksum. - */ - *pusLength = ( USHORT )( usRcvBufferPos - MB_SER_PDU_PDU_OFF - MB_SER_PDU_SIZE_CRC ); - - /* Return the start of the Modbus PDU to the caller. */ - *pucFrame = ( UCHAR * ) & ucRTUBuf[MB_SER_PDU_PDU_OFF]; - } - else - { - eStatus = MB_EIO; - } - - EXIT_CRITICAL_SECTION( ); - return eStatus; -} - -eMBErrorCode -eMBRTUSend( UCHAR ucSlaveAddress, const UCHAR * pucFrame, USHORT usLength ) -{ - eMBErrorCode eStatus = MB_ENOERR; - USHORT usCRC16; - - ENTER_CRITICAL_SECTION( ); - - /* Check if the receiver is still in idle state. If not we where to - * slow with processing the received frame and the master sent another - * frame on the network. We have to abort sending the frame. - */ - if( eRcvState == STATE_RX_IDLE ) - { - /* First byte before the Modbus-PDU is the slave address. */ - pucSndBufferCur = ( UCHAR * ) pucFrame - 1; - usSndBufferCount = 1; - - /* Now copy the Modbus-PDU into the Modbus-Serial-Line-PDU. */ - pucSndBufferCur[MB_SER_PDU_ADDR_OFF] = ucSlaveAddress; - usSndBufferCount += usLength; - - /* Calculate CRC16 checksum for Modbus-Serial-Line-PDU. */ - usCRC16 = usMBCRC16( ( UCHAR * ) pucSndBufferCur, usSndBufferCount ); - ucRTUBuf[usSndBufferCount++] = ( UCHAR )( usCRC16 & 0xFF ); - ucRTUBuf[usSndBufferCount++] = ( UCHAR )( usCRC16 >> 8 ); - - /* Activate the transmitter. */ - eSndState = STATE_TX_XMIT; - vMBPortSerialEnable( FALSE, TRUE ); - } - else - { - eStatus = MB_EIO; - } - EXIT_CRITICAL_SECTION( ); - return eStatus; -} - -BOOL -xMBRTUReceiveFSM( void ) -{ - BOOL xTaskNeedSwitch = FALSE; - UCHAR ucByte; - - RT_ASSERT( eSndState == STATE_TX_IDLE ); - - /* Always read the character. */ - ( void )xMBPortSerialGetByte( ( CHAR * ) & ucByte ); - - switch ( eRcvState ) - { - /* If we have received a character in the init state we have to - * wait until the frame is finished. - */ - case STATE_RX_INIT: - vMBPortTimersEnable( ); - break; - - /* In the error state we wait until all characters in the - * damaged frame are transmitted. - */ - case STATE_RX_ERROR: - vMBPortTimersEnable( ); - break; - - /* In the idle state we wait for a new character. If a character - * is received the t1.5 and t3.5 timers are started and the - * receiver is in the state STATE_RX_RECEIVCE. - */ - case STATE_RX_IDLE: - usRcvBufferPos = 0; - ucRTUBuf[usRcvBufferPos++] = ucByte; - eRcvState = STATE_RX_RCV; - - /* Enable t3.5 timers. */ - vMBPortTimersEnable( ); - break; - - /* We are currently receiving a frame. Reset the timer after - * every character received. If more than the maximum possible - * number of bytes in a modbus frame is received the frame is - * ignored. - */ - case STATE_RX_RCV: - if( usRcvBufferPos < MB_SER_PDU_SIZE_MAX ) - { - ucRTUBuf[usRcvBufferPos++] = ucByte; - } - else - { - eRcvState = STATE_RX_ERROR; - } - vMBPortTimersEnable(); - break; - } - return xTaskNeedSwitch; -} - -BOOL -xMBRTUTransmitFSM( void ) -{ - BOOL xNeedPoll = FALSE; - - RT_ASSERT( eRcvState == STATE_RX_IDLE ); - - switch ( eSndState ) - { - /* We should not get a transmitter event if the transmitter is in - * idle state. */ - case STATE_TX_IDLE: - /* enable receiver/disable transmitter. */ - vMBPortSerialEnable( TRUE, FALSE ); - break; - - case STATE_TX_XMIT: - /* check if we are finished. */ - if( usSndBufferCount != 0 ) - { - xMBPortSerialPutByte( ( CHAR )*pucSndBufferCur ); - pucSndBufferCur++; /* next byte in sendbuffer. */ - usSndBufferCount--; - } - else - { - xNeedPoll = xMBPortEventPost( EV_FRAME_SENT ); - /* Disable transmitter. This prevents another transmit buffer - * empty interrupt. */ - vMBPortSerialEnable( TRUE, FALSE ); - eSndState = STATE_TX_IDLE; - } - break; - } - - return xNeedPoll; -} - -BOOL -xMBRTUTimerT35Expired( void ) -{ - BOOL xNeedPoll = FALSE; - - switch ( eRcvState ) - { - /* Timer t35 expired. Startup phase is finished. */ - case STATE_RX_INIT: - xNeedPoll = xMBPortEventPost( EV_READY ); - break; - - /* A frame was received and t35 expired. Notify the listener that - * a new frame was received. */ - case STATE_RX_RCV: - xNeedPoll = xMBPortEventPost( EV_FRAME_RECEIVED ); - break; - - /* An error occured while receiving the frame. */ - case STATE_RX_ERROR: - break; - - /* Function called in an illegal state. */ - default: - RT_ASSERT( ( eRcvState == STATE_RX_INIT ) || - ( eRcvState == STATE_RX_RCV ) || ( eRcvState == STATE_RX_ERROR ) ); - break; - } - - vMBPortTimersDisable( ); - eRcvState = STATE_RX_IDLE; - - return xNeedPoll; -} diff --git a/components/net/freemodbus/modbus/rtu/mbrtu.h b/components/net/freemodbus/modbus/rtu/mbrtu.h deleted file mode 100644 index 98c43de4aa..0000000000 --- a/components/net/freemodbus/modbus/rtu/mbrtu.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. - * Copyright (c) 2006 Christian Walter <[email protected]> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * File: $Id: mbrtu.h,v 1.9 2006/12/07 22:10:34 wolti Exp $ - * File: $Id: mbrtu.h,v 1.60 2013/08/17 13:11:42 Armink Add Master Functions $ - */ -#include "mbconfig.h" - -#ifndef _MB_RTU_H -#define _MB_RTU_H - -#ifdef __cplusplus -PR_BEGIN_EXTERN_C -#endif -eMBErrorCode eMBRTUInit( UCHAR slaveAddress, UCHAR ucPort, ULONG ulBaudRate, - eMBParity eParity ); -void eMBRTUStart( void ); -void eMBRTUStop( void ); -eMBErrorCode eMBRTUReceive( UCHAR * pucRcvAddress, UCHAR ** pucFrame, USHORT * pusLength ); -eMBErrorCode eMBRTUSend( UCHAR slaveAddress, const UCHAR * pucFrame, USHORT usLength ); -BOOL xMBRTUReceiveFSM( void ); -BOOL xMBRTUTransmitFSM( void ); -BOOL xMBRTUTimerT15Expired( void ); -BOOL xMBRTUTimerT35Expired( void ); - -#if MB_MASTER_RTU_ENABLED > 0 -eMBErrorCode eMBMasterRTUInit( UCHAR ucPort, ULONG ulBaudRate,eMBParity eParity ); -void eMBMasterRTUStart( void ); -void eMBMasterRTUStop( void ); -eMBErrorCode eMBMasterRTUReceive( UCHAR * pucRcvAddress, UCHAR ** pucFrame, USHORT * pusLength ); -eMBErrorCode eMBMasterRTUSend( UCHAR slaveAddress, const UCHAR * pucFrame, USHORT usLength ); -BOOL xMBMasterRTUReceiveFSM( void ); -BOOL xMBMasterRTUTransmitFSM( void ); -BOOL xMBMasterRTUTimerExpired( void ); -#endif - -#ifdef __cplusplus -PR_END_EXTERN_C -#endif -#endif diff --git a/components/net/freemodbus/modbus/rtu/mbrtu_m.c b/components/net/freemodbus/modbus/rtu/mbrtu_m.c deleted file mode 100644 index 0c024e2b09..0000000000 --- a/components/net/freemodbus/modbus/rtu/mbrtu_m.c +++ /dev/null @@ -1,443 +0,0 @@ -/* - * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. - * Copyright (c) 2013 China Beijing Armink <[email protected]> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * File: $Id: mbrtu_m.c,v 1.60 2013/08/17 11:42:56 Armink Add Master Functions $ - */ - -/* ----------------------- System includes ----------------------------------*/ -#include "stdlib.h" -#include "string.h" - -/* ----------------------- Platform includes --------------------------------*/ -#include "port.h" - -/* ----------------------- Modbus includes ----------------------------------*/ -#include "mb.h" -#include "mb_m.h" -#include "mbrtu.h" -#include "mbframe.h" - -#include "mbcrc.h" -#include "mbport.h" - -#if MB_MASTER_RTU_ENABLED > 0 -/* ----------------------- Defines ------------------------------------------*/ -#define MB_SER_PDU_SIZE_MIN 4 /*!< Minimum size of a Modbus RTU frame. */ -#define MB_SER_PDU_SIZE_MAX 256 /*!< Maximum size of a Modbus RTU frame. */ -#define MB_SER_PDU_SIZE_CRC 2 /*!< Size of CRC field in PDU. */ -#define MB_SER_PDU_ADDR_OFF 0 /*!< Offset of slave address in Ser-PDU. */ -#define MB_SER_PDU_PDU_OFF 1 /*!< Offset of Modbus-PDU in Ser-PDU. */ - -/* ----------------------- Type definitions ---------------------------------*/ -typedef enum -{ - STATE_M_RX_INIT, /*!< Receiver is in initial state. */ - STATE_M_RX_IDLE, /*!< Receiver is in idle state. */ - STATE_M_RX_RCV, /*!< Frame is beeing received. */ - STATE_M_RX_ERROR, /*!< If the frame is invalid. */ -} eMBMasterRcvState; - -typedef enum -{ - STATE_M_TX_IDLE, /*!< Transmitter is in idle state. */ - STATE_M_TX_XMIT, /*!< Transmitter is in transfer state. */ - STATE_M_TX_XFWR, /*!< Transmitter is in transfer finish and wait receive state. */ -} eMBMasterSndState; - -/* ----------------------- Static variables ---------------------------------*/ -static volatile eMBMasterSndState eSndState; -static volatile eMBMasterRcvState eRcvState; - -static volatile UCHAR ucMasterRTUSndBuf[MB_PDU_SIZE_MAX]; -static volatile UCHAR ucMasterRTURcvBuf[MB_SER_PDU_SIZE_MAX]; -static volatile USHORT usMasterSendPDULength; - -static volatile UCHAR *pucMasterSndBufferCur; -static volatile USHORT usMasterSndBufferCount; - -static volatile USHORT usMasterRcvBufferPos; -static volatile BOOL xFrameIsBroadcast = FALSE; - -static volatile eMBMasterTimerMode eMasterCurTimerMode; - -/* ----------------------- Start implementation -----------------------------*/ -eMBErrorCode -eMBMasterRTUInit(UCHAR ucPort, ULONG ulBaudRate, eMBParity eParity ) -{ - eMBErrorCode eStatus = MB_ENOERR; - ULONG usTimerT35_50us; - - ENTER_CRITICAL_SECTION( ); - - /* Modbus RTU uses 8 Databits. */ - if( xMBMasterPortSerialInit( ucPort, ulBaudRate, 8, eParity ) != TRUE ) - { - eStatus = MB_EPORTERR; - } - else - { - /* If baudrate > 19200 then we should use the fixed timer values - * t35 = 1750us. Otherwise t35 must be 3.5 times the character time. - */ - if( ulBaudRate > 19200 ) - { - usTimerT35_50us = 35; /* 1800us. */ - } - else - { - /* The timer reload value for a character is given by: - * - * ChTimeValue = Ticks_per_1s / ( Baudrate / 11 ) - * = 11 * Ticks_per_1s / Baudrate - * = 220000 / Baudrate - * The reload for t3.5 is 1.5 times this value and similary - * for t3.5. - */ - usTimerT35_50us = ( 7UL * 220000UL ) / ( 2UL * ulBaudRate ); - } - if( xMBMasterPortTimersInit( ( USHORT ) usTimerT35_50us ) != TRUE ) - { - eStatus = MB_EPORTERR; - } - } - EXIT_CRITICAL_SECTION( ); - - return eStatus; -} - -void -eMBMasterRTUStart( void ) -{ - ENTER_CRITICAL_SECTION( ); - /* Initially the receiver is in the state STATE_M_RX_INIT. we start - * the timer and if no character is received within t3.5 we change - * to STATE_M_RX_IDLE. This makes sure that we delay startup of the - * modbus protocol stack until the bus is free. - */ - eRcvState = STATE_M_RX_INIT; - vMBMasterPortSerialEnable( TRUE, FALSE ); - vMBMasterPortTimersT35Enable( ); - - EXIT_CRITICAL_SECTION( ); -} - -void -eMBMasterRTUStop( void ) -{ - ENTER_CRITICAL_SECTION( ); - vMBMasterPortSerialEnable( FALSE, FALSE ); - vMBMasterPortTimersDisable( ); - EXIT_CRITICAL_SECTION( ); -} - -eMBErrorCode -eMBMasterRTUReceive( UCHAR * pucRcvAddress, UCHAR ** pucFrame, USHORT * pusLength ) -{ - eMBErrorCode eStatus = MB_ENOERR; - - ENTER_CRITICAL_SECTION( ); - RT_ASSERT( usMasterRcvBufferPos < MB_SER_PDU_SIZE_MAX ); - - /* Length and CRC check */ - if( ( usMasterRcvBufferPos >= MB_SER_PDU_SIZE_MIN ) - && ( usMBCRC16( ( UCHAR * ) ucMasterRTURcvBuf, usMasterRcvBufferPos ) == 0 ) ) - { - /* Save the address field. All frames are passed to the upper layed - * and the decision if a frame is used is done there. - */ - *pucRcvAddress = ucMasterRTURcvBuf[MB_SER_PDU_ADDR_OFF]; - - /* Total length of Modbus-PDU is Modbus-Serial-Line-PDU minus - * size of address field and CRC checksum. - */ - *pusLength = ( USHORT )( usMasterRcvBufferPos - MB_SER_PDU_PDU_OFF - MB_SER_PDU_SIZE_CRC ); - - /* Return the start of the Modbus PDU to the caller. */ - *pucFrame = ( UCHAR * ) & ucMasterRTURcvBuf[MB_SER_PDU_PDU_OFF]; - } - else - { - eStatus = MB_EIO; - } - - EXIT_CRITICAL_SECTION( ); - return eStatus; -} - -eMBErrorCode -eMBMasterRTUSend( UCHAR ucSlaveAddress, const UCHAR * pucFrame, USHORT usLength ) -{ - eMBErrorCode eStatus = MB_ENOERR; - USHORT usCRC16; - - if ( ucSlaveAddress > MB_MASTER_TOTAL_SLAVE_NUM ) return MB_EINVAL; - - ENTER_CRITICAL_SECTION( ); - - /* Check if the receiver is still in idle state. If not we where to - * slow with processing the received frame and the master sent another - * frame on the network. We have to abort sending the frame. - */ - if( eRcvState == STATE_M_RX_IDLE ) - { - /* First byte before the Modbus-PDU is the slave address. */ - pucMasterSndBufferCur = ( UCHAR * ) pucFrame - 1; - usMasterSndBufferCount = 1; - - /* Now copy the Modbus-PDU into the Modbus-Serial-Line-PDU. */ - pucMasterSndBufferCur[MB_SER_PDU_ADDR_OFF] = ucSlaveAddress; - usMasterSndBufferCount += usLength; - - /* Calculate CRC16 checksum for Modbus-Serial-Line-PDU. */ - usCRC16 = usMBCRC16( ( UCHAR * ) pucMasterSndBufferCur, usMasterSndBufferCount ); - ucMasterRTUSndBuf[usMasterSndBufferCount++] = ( UCHAR )( usCRC16 & 0xFF ); - ucMasterRTUSndBuf[usMasterSndBufferCount++] = ( UCHAR )( usCRC16 >> 8 ); - - /* Activate the transmitter. */ - eSndState = STATE_M_TX_XMIT; - vMBMasterPortSerialEnable( FALSE, TRUE ); - } - else - { - eStatus = MB_EIO; - } - EXIT_CRITICAL_SECTION( ); - return eStatus; -} - -BOOL -xMBMasterRTUReceiveFSM( void ) -{ - BOOL xTaskNeedSwitch = FALSE; - UCHAR ucByte; - - RT_ASSERT(( eSndState == STATE_M_TX_IDLE ) || ( eSndState == STATE_M_TX_XFWR )); - - /* Always read the character. */ - ( void )xMBMasterPortSerialGetByte( ( CHAR * ) & ucByte ); - - switch ( eRcvState ) - { - /* If we have received a character in the init state we have to - * wait until the frame is finished. - */ - case STATE_M_RX_INIT: - vMBMasterPortTimersT35Enable( ); - break; - - /* In the error state we wait until all characters in the - * damaged frame are transmitted. - */ - case STATE_M_RX_ERROR: - vMBMasterPortTimersT35Enable( ); - break; - - /* In the idle state we wait for a new character. If a character - * is received the t1.5 and t3.5 timers are started and the - * receiver is in the state STATE_RX_RECEIVCE and disable early - * the timer of respond timeout . - */ - case STATE_M_RX_IDLE: - /* In time of respond timeout,the receiver receive a frame. - * Disable timer of respond timeout and change the transmiter state to idle. - */ - vMBMasterPortTimersDisable( ); - eSndState = STATE_M_TX_IDLE; - - usMasterRcvBufferPos = 0; - ucMasterRTURcvBuf[usMasterRcvBufferPos++] = ucByte; - eRcvState = STATE_M_RX_RCV; - - /* Enable t3.5 timers. */ - vMBMasterPortTimersT35Enable( ); - break; - - /* We are currently receiving a frame. Reset the timer after - * every character received. If more than the maximum possible - * number of bytes in a modbus frame is received the frame is - * ignored. - */ - case STATE_M_RX_RCV: - if( usMasterRcvBufferPos < MB_SER_PDU_SIZE_MAX ) - { - ucMasterRTURcvBuf[usMasterRcvBufferPos++] = ucByte; - } - else - { - eRcvState = STATE_M_RX_ERROR; - } - vMBMasterPortTimersT35Enable(); - break; - } - return xTaskNeedSwitch; -} - -BOOL -xMBMasterRTUTransmitFSM( void ) -{ - BOOL xNeedPoll = FALSE; - - RT_ASSERT( eRcvState == STATE_M_RX_IDLE ); - - switch ( eSndState ) - { - /* We should not get a transmitter event if the transmitter is in - * idle state. */ - case STATE_M_TX_IDLE: - /* enable receiver/disable transmitter. */ - vMBMasterPortSerialEnable( TRUE, FALSE ); - break; - - case STATE_M_TX_XMIT: - /* check if we are finished. */ - if( usMasterSndBufferCount != 0 ) - { - xMBMasterPortSerialPutByte( ( CHAR )*pucMasterSndBufferCur ); - pucMasterSndBufferCur++; /* next byte in sendbuffer. */ - usMasterSndBufferCount--; - } - else - { - xFrameIsBroadcast = ( ucMasterRTUSndBuf[MB_SER_PDU_ADDR_OFF] == MB_ADDRESS_BROADCAST ) ? TRUE : FALSE; - /* Disable transmitter. This prevents another transmit buffer - * empty interrupt. */ - vMBMasterPortSerialEnable( TRUE, FALSE ); - eSndState = STATE_M_TX_XFWR; - /* If the frame is broadcast ,master will enable timer of convert delay, - * else master will enable timer of respond timeout. */ - if ( xFrameIsBroadcast == TRUE ) - { - vMBMasterPortTimersConvertDelayEnable( ); - } - else - { - vMBMasterPortTimersRespondTimeoutEnable( ); - } - } - break; - } - - return xNeedPoll; -} - -BOOL -xMBMasterRTUTimerExpired(void) -{ - BOOL xNeedPoll = FALSE; - - switch (eRcvState) - { - /* Timer t35 expired. Startup phase is finished. */ - case STATE_M_RX_INIT: - xNeedPoll = xMBMasterPortEventPost(EV_MASTER_READY); - break; - - /* A frame was received and t35 expired. Notify the listener that - * a new frame was received. */ - case STATE_M_RX_RCV: - xNeedPoll = xMBMasterPortEventPost(EV_MASTER_FRAME_RECEIVED); - break; - - /* An error occured while receiving the frame. */ - case STATE_M_RX_ERROR: - vMBMasterSetErrorType(EV_ERROR_RECEIVE_DATA); - xNeedPoll = xMBMasterPortEventPost( EV_MASTER_ERROR_PROCESS ); - break; - - /* Function called in an illegal state. */ - default: - RT_ASSERT( - ( eRcvState == STATE_M_RX_INIT ) || ( eRcvState == STATE_M_RX_RCV ) || - ( eRcvState == STATE_M_RX_ERROR ) || ( eRcvState == STATE_M_RX_IDLE )); - break; - } - eRcvState = STATE_M_RX_IDLE; - - switch (eSndState) - { - /* A frame was send finish and convert delay or respond timeout expired. - * If the frame is broadcast,The master will idle,and if the frame is not - * broadcast.Notify the listener process error.*/ - case STATE_M_TX_XFWR: - if ( xFrameIsBroadcast == FALSE ) { - vMBMasterSetErrorType(EV_ERROR_RESPOND_TIMEOUT); - xNeedPoll = xMBMasterPortEventPost(EV_MASTER_ERROR_PROCESS); - } - break; - /* Function called in an illegal state. */ - default: - RT_ASSERT( - ( eSndState == STATE_M_TX_XFWR ) || ( eSndState == STATE_M_TX_IDLE )); - break; - } - eSndState = STATE_M_TX_IDLE; - - vMBMasterPortTimersDisable( ); - /* If timer mode is convert delay, the master event then turns EV_MASTER_EXECUTE status. */ - if (eMasterCurTimerMode == MB_TMODE_CONVERT_DELAY) { - xNeedPoll = xMBMasterPortEventPost( EV_MASTER_EXECUTE ); - } - - return xNeedPoll; -} - -/* Get Modbus Master send RTU's buffer address pointer.*/ -void vMBMasterGetRTUSndBuf( UCHAR ** pucFrame ) -{ - *pucFrame = ( UCHAR * ) ucMasterRTUSndBuf; -} - -/* Get Modbus Master send PDU's buffer address pointer.*/ -void vMBMasterGetPDUSndBuf( UCHAR ** pucFrame ) -{ - *pucFrame = ( UCHAR * ) &ucMasterRTUSndBuf[MB_SER_PDU_PDU_OFF]; -} - -/* Set Modbus Master send PDU's buffer length.*/ -void vMBMasterSetPDUSndLength( USHORT SendPDULength ) -{ - usMasterSendPDULength = SendPDULength; -} - -/* Get Modbus Master send PDU's buffer length.*/ -USHORT usMBMasterGetPDUSndLength( void ) -{ - return usMasterSendPDULength; -} - -/* Set Modbus Master current timer mode.*/ -void vMBMasterSetCurTimerMode( eMBMasterTimerMode eMBTimerMode ) -{ - eMasterCurTimerMode = eMBTimerMode; -} - -/* The master request is broadcast? */ -BOOL xMBMasterRequestIsBroadcast( void ){ - return xFrameIsBroadcast; -} -#endif - diff --git a/components/net/freemodbus/modbus/tcp/mbtcp.c b/components/net/freemodbus/modbus/tcp/mbtcp.c deleted file mode 100644 index 3eb3b7071f..0000000000 --- a/components/net/freemodbus/modbus/tcp/mbtcp.c +++ /dev/null @@ -1,158 +0,0 @@ -/* - * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. - * Copyright (c) 2006 Christian Walter <[email protected]> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * File: $Id: mbtcp.c,v 1.3 2006/12/07 22:10:34 wolti Exp $ - */ - -/* ----------------------- System includes ----------------------------------*/ -#include "stdlib.h" -#include "string.h" - -/* ----------------------- Platform includes --------------------------------*/ -#include "port.h" - -/* ----------------------- Modbus includes ----------------------------------*/ -#include "mb.h" -#include "mbconfig.h" -#include "mbtcp.h" -#include "mbframe.h" -#include "mbport.h" - -#if MB_SLAVE_TCP_ENABLED > 0 - -/* ----------------------- Defines ------------------------------------------*/ - -/* ----------------------- MBAP Header --------------------------------------*/ -/* - * - * <------------------------ MODBUS TCP/IP ADU(1) -------------------------> - * <----------- MODBUS PDU (1') ----------------> - * +-----------+---------------+------------------------------------------+ - * | TID | PID | Length | UID |Code | Data | - * +-----------+---------------+------------------------------------------+ - * | | | | | - * (2) (3) (4) (5) (6) - * - * (2) ... MB_TCP_TID = 0 (Transaction Identifier - 2 Byte) - * (3) ... MB_TCP_PID = 2 (Protocol Identifier - 2 Byte) - * (4) ... MB_TCP_LEN = 4 (Number of bytes - 2 Byte) - * (5) ... MB_TCP_UID = 6 (Unit Identifier - 1 Byte) - * (6) ... MB_TCP_FUNC = 7 (Modbus Function Code) - * - * (1) ... Modbus TCP/IP Application Data Unit - * (1') ... Modbus Protocol Data Unit - */ - -#define MB_TCP_TID 0 -#define MB_TCP_PID 2 -#define MB_TCP_LEN 4 -#define MB_TCP_UID 6 -#define MB_TCP_FUNC 7 - -#define MB_TCP_PROTOCOL_ID 0 /* 0 = Modbus Protocol */ - - -/* ----------------------- Start implementation -----------------------------*/ -eMBErrorCode -eMBTCPDoInit( USHORT ucTCPPort ) -{ - eMBErrorCode eStatus = MB_ENOERR; - - if( xMBTCPPortInit( ucTCPPort ) == FALSE ) - { - eStatus = MB_EPORTERR; - } - return eStatus; -} - -void -eMBTCPStart( void ) -{ -} - -void -eMBTCPStop( void ) -{ - /* Make sure that no more clients are connected. */ - vMBTCPPortDisable( ); -} - -eMBErrorCode -eMBTCPReceive( UCHAR * pucRcvAddress, UCHAR ** ppucFrame, USHORT * pusLength ) -{ - eMBErrorCode eStatus = MB_EIO; - UCHAR *pucMBTCPFrame; - USHORT usLength; - USHORT usPID; - - if( xMBTCPPortGetRequest( &pucMBTCPFrame, &usLength ) != FALSE ) - { - usPID = pucMBTCPFrame[MB_TCP_PID] << 8U; - usPID |= pucMBTCPFrame[MB_TCP_PID + 1]; - - if( usPID == MB_TCP_PROTOCOL_ID ) - { - *ppucFrame = &pucMBTCPFrame[MB_TCP_FUNC]; - *pusLength = usLength - MB_TCP_FUNC; - eStatus = MB_ENOERR; - - /* Modbus TCP does not use any addresses. Fake the source address such - * that the processing part deals with this frame. - */ - *pucRcvAddress = MB_TCP_PSEUDO_ADDRESS; - } - } - else - { - eStatus = MB_EIO; - } - return eStatus; -} - -eMBErrorCode -eMBTCPSend( UCHAR _unused, const UCHAR * pucFrame, USHORT usLength ) -{ - eMBErrorCode eStatus = MB_ENOERR; - UCHAR *pucMBTCPFrame = ( UCHAR * ) pucFrame - MB_TCP_FUNC; - USHORT usTCPLength = usLength + MB_TCP_FUNC; - - /* The MBAP header is already initialized because the caller calls this - * function with the buffer returned by the previous call. Therefore we - * only have to update the length in the header. Note that the length - * header includes the size of the Modbus PDU and the UID Byte. Therefore - * the length is usLength plus one. - */ - pucMBTCPFrame[MB_TCP_LEN] = ( usLength + 1 ) >> 8U; - pucMBTCPFrame[MB_TCP_LEN + 1] = ( usLength + 1 ) & 0xFF; - if( xMBTCPPortSendResponse( pucMBTCPFrame, usTCPLength ) == FALSE ) - { - eStatus = MB_EIO; - } - return eStatus; -} - -#endif diff --git a/components/net/freemodbus/modbus/tcp/mbtcp.h b/components/net/freemodbus/modbus/tcp/mbtcp.h deleted file mode 100644 index 905d113c5a..0000000000 --- a/components/net/freemodbus/modbus/tcp/mbtcp.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU. - * Copyright (c) 2006 Christian Walter <[email protected]> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * File: $Id: mbtcp.h,v 1.2 2006/12/07 22:10:34 wolti Exp $ - */ - -#ifndef _MB_TCP_H -#define _MB_TCP_H - -#ifdef __cplusplus -PR_BEGIN_EXTERN_C -#endif - -/* ----------------------- Defines ------------------------------------------*/ -#define MB_TCP_PSEUDO_ADDRESS 255 - -/* ----------------------- Function prototypes ------------------------------*/ - eMBErrorCode eMBTCPDoInit( USHORT ucTCPPort ); -void eMBTCPStart( void ); -void eMBTCPStop( void ); -eMBErrorCode eMBTCPReceive( UCHAR * pucRcvAddress, UCHAR ** pucFrame, - USHORT * pusLength ); -eMBErrorCode eMBTCPSend( UCHAR _unused, const UCHAR * pucFrame, - USHORT usLength ); - -#ifdef __cplusplus -PR_END_EXTERN_C -#endif -#endif diff --git a/components/net/freemodbus/port/port.c b/components/net/freemodbus/port/port.c deleted file mode 100644 index d01c5c9d6a..0000000000 --- a/components/net/freemodbus/port/port.c +++ /dev/null @@ -1,38 +0,0 @@ - /* - * FreeModbus Libary: RT-Thread Port - * Copyright (C) 2013 Armink <[email protected]> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * File: $Id: port.c,v 1.60 2015/02/01 9:18:05 Armink $ - */ - -/* ----------------------- System includes --------------------------------*/ - -/* ----------------------- Modbus includes ----------------------------------*/ -#include "port.h" -/* ----------------------- Variables ----------------------------------------*/ -static rt_base_t level; -/* ----------------------- Start implementation -----------------------------*/ -void EnterCriticalSection(void) -{ - level = rt_hw_interrupt_disable(); -} - -void ExitCriticalSection(void) -{ - rt_hw_interrupt_enable(level); -} - diff --git a/components/net/freemodbus/port/port.h b/components/net/freemodbus/port/port.h deleted file mode 100644 index 97b648a8bb..0000000000 --- a/components/net/freemodbus/port/port.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * FreeModbus Libary: BARE Port - * Copyright (C) 2013 Armink <[email protected]> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * File: $Id: port.h ,v 1.60 2013/08/13 15:07:05 Armink add Master Functions $ - */ - -#ifndef _PORT_H -#define _PORT_H - -#include "mbconfig.h" -#include <rthw.h> -#include <rtthread.h> - -#include <assert.h> -#include <inttypes.h> - -#define INLINE -#define PR_BEGIN_EXTERN_C extern "C" { -#define PR_END_EXTERN_C } - -#define ENTER_CRITICAL_SECTION() EnterCriticalSection() -#define EXIT_CRITICAL_SECTION() ExitCriticalSection() - -typedef uint8_t BOOL; - -typedef unsigned char UCHAR; -typedef char CHAR; - -typedef uint16_t USHORT; -typedef int16_t SHORT; - -typedef uint32_t ULONG; -typedef int32_t LONG; - -#ifndef TRUE -#define TRUE 1 -#endif - -#ifndef FALSE -#define FALSE 0 -#endif - -void EnterCriticalSection(void); -void ExitCriticalSection(void); - -#endif diff --git a/components/net/freemodbus/port/portevent.c b/components/net/freemodbus/port/portevent.c deleted file mode 100644 index 1a881166be..0000000000 --- a/components/net/freemodbus/port/portevent.c +++ /dev/null @@ -1,68 +0,0 @@ -/* - * FreeModbus Libary: RT-Thread Port - * Copyright (C) 2013 Armink <[email protected]> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * File: $Id: portevent.c,v 1.60 2013/08/13 15:07:05 Armink $ - */ - -/* ----------------------- Modbus includes ----------------------------------*/ -#include "mb.h" -#include "mbport.h" - -/* ----------------------- Variables ----------------------------------------*/ -static struct rt_event xSlaveOsEvent; -/* ----------------------- Start implementation -----------------------------*/ -BOOL -xMBPortEventInit( void ) -{ - rt_event_init(&xSlaveOsEvent,"slave event",RT_IPC_FLAG_PRIO); - return TRUE; -} - -BOOL -xMBPortEventPost( eMBEventType eEvent ) -{ - rt_event_send(&xSlaveOsEvent, eEvent); - return TRUE; -} - -BOOL -xMBPortEventGet( eMBEventType * eEvent ) -{ - rt_uint32_t recvedEvent; - /* waiting forever OS event */ - rt_event_recv(&xSlaveOsEvent, - EV_READY | EV_FRAME_RECEIVED | EV_EXECUTE | EV_FRAME_SENT, - RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, RT_WAITING_FOREVER, - &recvedEvent); - switch (recvedEvent) - { - case EV_READY: - *eEvent = EV_READY; - break; - case EV_FRAME_RECEIVED: - *eEvent = EV_FRAME_RECEIVED; - break; - case EV_EXECUTE: - *eEvent = EV_EXECUTE; - break; - case EV_FRAME_SENT: - *eEvent = EV_FRAME_SENT; - break; - } - return TRUE; -} diff --git a/components/net/freemodbus/port/portevent_m.c b/components/net/freemodbus/port/portevent_m.c deleted file mode 100644 index 031a3b84ef..0000000000 --- a/components/net/freemodbus/port/portevent_m.c +++ /dev/null @@ -1,239 +0,0 @@ -/* - * FreeModbus Libary: RT-Thread Port - * Copyright (C) 2013 Armink <[email protected]> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * File: $Id: portevent_m.c v 1.60 2013/08/13 15:07:05 Armink add Master Functions$ - */ - -/* ----------------------- Modbus includes ----------------------------------*/ -#include "mb.h" -#include "mb_m.h" -#include "mbport.h" -#include "port.h" - -#if MB_MASTER_RTU_ENABLED > 0 || MB_MASTER_ASCII_ENABLED > 0 -/* ----------------------- Defines ------------------------------------------*/ -/* ----------------------- Variables ----------------------------------------*/ -static struct rt_semaphore xMasterRunRes; -static struct rt_event xMasterOsEvent; -/* ----------------------- Start implementation -----------------------------*/ -BOOL -xMBMasterPortEventInit( void ) -{ - rt_event_init(&xMasterOsEvent,"master event",RT_IPC_FLAG_PRIO); - return TRUE; -} - -BOOL -xMBMasterPortEventPost( eMBMasterEventType eEvent ) -{ - rt_event_send(&xMasterOsEvent, eEvent); - return TRUE; -} - -BOOL -xMBMasterPortEventGet( eMBMasterEventType * eEvent ) -{ - rt_uint32_t recvedEvent; - /* waiting forever OS event */ - rt_event_recv(&xMasterOsEvent, - EV_MASTER_READY | EV_MASTER_FRAME_RECEIVED | EV_MASTER_EXECUTE | - EV_MASTER_FRAME_SENT | EV_MASTER_ERROR_PROCESS, - RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, RT_WAITING_FOREVER, - &recvedEvent); - /* the enum type couldn't convert to int type */ - switch (recvedEvent) - { - case EV_MASTER_READY: - *eEvent = EV_MASTER_READY; - break; - case EV_MASTER_FRAME_RECEIVED: - *eEvent = EV_MASTER_FRAME_RECEIVED; - break; - case EV_MASTER_EXECUTE: - *eEvent = EV_MASTER_EXECUTE; - break; - case EV_MASTER_FRAME_SENT: - *eEvent = EV_MASTER_FRAME_SENT; - break; - case EV_MASTER_ERROR_PROCESS: - *eEvent = EV_MASTER_ERROR_PROCESS; - break; - } - return TRUE; -} -/** - * This function is initialize the OS resource for modbus master. - * Note:The resource is define by OS.If you not use OS this function can be empty. - * - */ -void vMBMasterOsResInit( void ) -{ - rt_sem_init(&xMasterRunRes, "master res", 0x01 , RT_IPC_FLAG_PRIO); -} - -/** - * This function is take Mobus Master running resource. - * Note:The resource is define by Operating System.If you not use OS this function can be just return TRUE. - * - * @param lTimeOut the waiting time. - * - * @return resource taked result - */ -BOOL xMBMasterRunResTake( LONG lTimeOut ) -{ - /*If waiting time is -1 .It will wait forever */ - return rt_sem_take(&xMasterRunRes, lTimeOut) ? FALSE : TRUE ; -} - -/** - * This function is release Mobus Master running resource. - * Note:The resource is define by Operating System.If you not use OS this function can be empty. - * - */ -void vMBMasterRunResRelease( void ) -{ - /* release resource */ - rt_sem_release(&xMasterRunRes); -} - -/** - * This is modbus master respond timeout error process callback function. - * @note There functions will block modbus master poll while execute OS waiting. - * So,for real-time of system.Do not execute too much waiting process. - * - * @param ucDestAddress destination salve address - * @param pucPDUData PDU buffer data - * @param ucPDULength PDU buffer length - * - */ -void vMBMasterErrorCBRespondTimeout(UCHAR ucDestAddress, const UCHAR* pucPDUData, - USHORT ucPDULength) { - /** - * @note This code is use OS's event mechanism for modbus master protocol stack. - * If you don't use OS, you can change it. - */ - rt_event_send(&xMasterOsEvent, EV_MASTER_ERROR_RESPOND_TIMEOUT); - - /* You can add your code under here. */ - -} - -/** - * This is modbus master receive data error process callback function. - * @note There functions will block modbus master poll while execute OS waiting. - * So,for real-time of system.Do not execute too much waiting process. - * - * @param ucDestAddress destination salve address - * @param pucPDUData PDU buffer data - * @param ucPDULength PDU buffer length - * - */ -void vMBMasterErrorCBReceiveData(UCHAR ucDestAddress, const UCHAR* pucPDUData, - USHORT ucPDULength) { - /** - * @note This code is use OS's event mechanism for modbus master protocol stack. - * If you don't use OS, you can change it. - */ - rt_event_send(&xMasterOsEvent, EV_MASTER_ERROR_RECEIVE_DATA); - - /* You can add your code under here. */ - -} - -/** - * This is modbus master execute function error process callback function. - * @note There functions will block modbus master poll while execute OS waiting. - * So,for real-time of system.Do not execute too much waiting process. - * - * @param ucDestAddress destination salve address - * @param pucPDUData PDU buffer data - * @param ucPDULength PDU buffer length - * - */ -void vMBMasterErrorCBExecuteFunction(UCHAR ucDestAddress, const UCHAR* pucPDUData, - USHORT ucPDULength) { - /** - * @note This code is use OS's event mechanism for modbus master protocol stack. - * If you don't use OS, you can change it. - */ - rt_event_send(&xMasterOsEvent, EV_MASTER_ERROR_EXECUTE_FUNCTION); - - /* You can add your code under here. */ - -} - -/** - * This is modbus master request process success callback function. - * @note There functions will block modbus master poll while execute OS waiting. - * So,for real-time of system.Do not execute too much waiting process. - * - */ -void vMBMasterCBRequestScuuess( void ) { - /** - * @note This code is use OS's event mechanism for modbus master protocol stack. - * If you don't use OS, you can change it. - */ - rt_event_send(&xMasterOsEvent, EV_MASTER_PROCESS_SUCESS); - - /* You can add your code under here. */ - -} - -/** - * This function is wait for modbus master request finish and return result. - * Waiting result include request process success, request respond timeout, - * receive data error and execute function error.You can use the above callback function. - * @note If you are use OS, you can use OS's event mechanism. Otherwise you have to run - * much user custom delay for waiting. - * - * @return request error code - */ -eMBMasterReqErrCode eMBMasterWaitRequestFinish( void ) { - eMBMasterReqErrCode eErrStatus = MB_MRE_NO_ERR; - rt_uint32_t recvedEvent; - /* waiting for OS event */ - rt_event_recv(&xMasterOsEvent, - EV_MASTER_PROCESS_SUCESS | EV_MASTER_ERROR_RESPOND_TIMEOUT - | EV_MASTER_ERROR_RECEIVE_DATA - | EV_MASTER_ERROR_EXECUTE_FUNCTION, - RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, RT_WAITING_FOREVER, - &recvedEvent); - switch (recvedEvent) - { - case EV_MASTER_PROCESS_SUCESS: - break; - case EV_MASTER_ERROR_RESPOND_TIMEOUT: - { - eErrStatus = MB_MRE_TIMEDOUT; - break; - } - case EV_MASTER_ERROR_RECEIVE_DATA: - { - eErrStatus = MB_MRE_REV_DATA; - break; - } - case EV_MASTER_ERROR_EXECUTE_FUNCTION: - { - eErrStatus = MB_MRE_EXE_FUN; - break; - } - } - return eErrStatus; -} - -#endif diff --git a/components/net/freemodbus/port/portserial.c b/components/net/freemodbus/port/portserial.c deleted file mode 100644 index cbd846d7ff..0000000000 --- a/components/net/freemodbus/port/portserial.c +++ /dev/null @@ -1,225 +0,0 @@ -/* - * FreeModbus Libary: RT-Thread Port - * Copyright (C) 2013 Armink <[email protected]> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * File: $Id: portserial.c,v 1.60 2013/08/13 15:07:05 Armink $ - */ - -#include "port.h" - -/* ----------------------- Modbus includes ----------------------------------*/ -#include "mb.h" -#include "mbport.h" -#include "rtdevice.h" -#include "board.h" - -/* ----------------------- Static variables ---------------------------------*/ -ALIGN(RT_ALIGN_SIZE) -/* software simulation serial transmit IRQ handler thread stack */ -static rt_uint8_t serial_soft_trans_irq_stack[512]; -/* software simulation serial transmit IRQ handler thread */ -static struct rt_thread thread_serial_soft_trans_irq; -/* serial event */ -static struct rt_event event_serial; -/* modbus slave serial device */ -static rt_serial_t *serial; - -/* ----------------------- Defines ------------------------------------------*/ -/* serial transmit event */ -#define EVENT_SERIAL_TRANS_START (1<<0) - -/* ----------------------- static functions ---------------------------------*/ -static void prvvUARTTxReadyISR(void); -static void prvvUARTRxISR(void); -static rt_err_t serial_rx_ind(rt_device_t dev, rt_size_t size); -static void serial_soft_trans_irq(void* parameter); - -/* ----------------------- Start implementation -----------------------------*/ -BOOL xMBPortSerialInit(UCHAR ucPORT, ULONG ulBaudRate, UCHAR ucDataBits, - eMBParity eParity) -{ - rt_device_t dev = RT_NULL; - char uart_name[20]; - /** - * set 485 mode receive and transmit control IO - * @note MODBUS_SLAVE_RT_CONTROL_PIN_INDEX need be defined by user - */ -#if defined(RT_MODBUS_SLAVE_USE_CONTROL_PIN) - rt_pin_mode(MODBUS_SLAVE_RT_CONTROL_PIN_INDEX, PIN_MODE_OUTPUT); -#endif - /* set serial name */ - rt_snprintf(uart_name,sizeof(uart_name), "uart%d", ucPORT); - - dev = rt_device_find(uart_name); - if(dev == RT_NULL) - { - /* can not find uart */ - return FALSE; - } - else - { - serial = (struct rt_serial_device*)dev; - } - - /* set serial configure parameter */ - serial->config.baud_rate = ulBaudRate; - serial->config.stop_bits = STOP_BITS_1; - switch(eParity){ - case MB_PAR_NONE: { - serial->config.data_bits = DATA_BITS_8; - serial->config.parity = PARITY_NONE; - break; - } - case MB_PAR_ODD: { - serial->config.data_bits = DATA_BITS_9; - serial->config.parity = PARITY_ODD; - break; - } - case MB_PAR_EVEN: { - serial->config.data_bits = DATA_BITS_9; - serial->config.parity = PARITY_EVEN; - break; - } - } - /* set serial configure */ - serial->ops->configure(serial, &(serial->config)); - - /* open serial device */ - if (!rt_device_open(&serial->parent, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_INT_RX)) { - rt_device_set_rx_indicate(&serial->parent, serial_rx_ind); - } else { - return FALSE; - } - - /* software initialize */ - rt_event_init(&event_serial, "slave event", RT_IPC_FLAG_PRIO); - rt_thread_init(&thread_serial_soft_trans_irq, - "slave trans", - serial_soft_trans_irq, - RT_NULL, - serial_soft_trans_irq_stack, - sizeof(serial_soft_trans_irq_stack), - 10, 5); - rt_thread_startup(&thread_serial_soft_trans_irq); - - return TRUE; -} - -void vMBPortSerialEnable(BOOL xRxEnable, BOOL xTxEnable) -{ - rt_uint32_t recved_event; - if (xRxEnable) - { - /* enable RX interrupt */ - serial->ops->control(serial, RT_DEVICE_CTRL_SET_INT, (void *)RT_DEVICE_FLAG_INT_RX); - /* switch 485 to receive mode */ -#if defined(RT_MODBUS_SLAVE_USE_CONTROL_PIN) - rt_pin_write(MODBUS_SLAVE_RT_CONTROL_PIN_INDEX, PIN_LOW); -#endif - } - else - { - /* switch 485 to transmit mode */ -#if defined(RT_MODBUS_SLAVE_USE_CONTROL_PIN) - rt_pin_write(MODBUS_SLAVE_RT_CONTROL_PIN_INDEX, PIN_HIGH); -#endif - /* disable RX interrupt */ - serial->ops->control(serial, RT_DEVICE_CTRL_CLR_INT, (void *)RT_DEVICE_FLAG_INT_RX); - } - if (xTxEnable) - { - /* start serial transmit */ - rt_event_send(&event_serial, EVENT_SERIAL_TRANS_START); - } - else - { - /* stop serial transmit */ - rt_event_recv(&event_serial, EVENT_SERIAL_TRANS_START, - RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, 0, - &recved_event); - } -} - -void vMBPortClose(void) -{ - serial->parent.close(&(serial->parent)); -} - -BOOL xMBPortSerialPutByte(CHAR ucByte) -{ - serial->parent.write(&(serial->parent), 0, &ucByte, 1); - return TRUE; -} - -BOOL xMBPortSerialGetByte(CHAR * pucByte) -{ - serial->parent.read(&(serial->parent), 0, pucByte, 1); - return TRUE; -} - -/* - * Create an interrupt handler for the transmit buffer empty interrupt - * (or an equivalent) for your target processor. This function should then - * call pxMBFrameCBTransmitterEmpty( ) which tells the protocol stack that - * a new character can be sent. The protocol stack will then call - * xMBPortSerialPutByte( ) to send the character. - */ -void prvvUARTTxReadyISR(void) -{ - pxMBFrameCBTransmitterEmpty(); -} - -/* - * Create an interrupt handler for the receive interrupt for your target - * processor. This function should then call pxMBFrameCBByteReceived( ). The - * protocol stack will then call xMBPortSerialGetByte( ) to retrieve the - * character. - */ -void prvvUARTRxISR(void) -{ - pxMBFrameCBByteReceived(); -} - -/** - * Software simulation serial transmit IRQ handler. - * - * @param parameter parameter - */ -static void serial_soft_trans_irq(void* parameter) { - rt_uint32_t recved_event; - while (1) - { - /* waiting for serial transmit start */ - rt_event_recv(&event_serial, EVENT_SERIAL_TRANS_START, RT_EVENT_FLAG_OR, - RT_WAITING_FOREVER, &recved_event); - /* execute modbus callback */ - prvvUARTTxReadyISR(); - } -} - -/** - * This function is serial receive callback function - * - * @param dev the device of serial - * @param size the data size that receive - * - * @return return RT_EOK - */ -static rt_err_t serial_rx_ind(rt_device_t dev, rt_size_t size) { - prvvUARTRxISR(); - return RT_EOK; -} diff --git a/components/net/freemodbus/port/portserial_m.c b/components/net/freemodbus/port/portserial_m.c deleted file mode 100644 index 47a70dd905..0000000000 --- a/components/net/freemodbus/port/portserial_m.c +++ /dev/null @@ -1,229 +0,0 @@ -/* - * FreeModbus Libary: RT-Thread Port - * Copyright (C) 2013 Armink <[email protected]> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * File: $Id: portserial_m.c,v 1.60 2013/08/13 15:07:05 Armink add Master Functions $ - */ - -#include "port.h" - -/* ----------------------- Modbus includes ----------------------------------*/ -#include "mb.h" -#include "mbport.h" -#include "rtdevice.h" -#include "board.h" - -#if MB_MASTER_RTU_ENABLED > 0 || MB_MASTER_ASCII_ENABLED > 0 -/* ----------------------- Static variables ---------------------------------*/ -ALIGN(RT_ALIGN_SIZE) -/* software simulation serial transmit IRQ handler thread stack */ -static rt_uint8_t serial_soft_trans_irq_stack[512]; -/* software simulation serial transmit IRQ handler thread */ -static struct rt_thread thread_serial_soft_trans_irq; -/* serial event */ -static struct rt_event event_serial; -/* modbus master serial device */ -static rt_serial_t *serial; - -/* ----------------------- Defines ------------------------------------------*/ -/* serial transmit event */ -#define EVENT_SERIAL_TRANS_START (1<<0) - -/* ----------------------- static functions ---------------------------------*/ -static void prvvUARTTxReadyISR(void); -static void prvvUARTRxISR(void); -static rt_err_t serial_rx_ind(rt_device_t dev, rt_size_t size); -static void serial_soft_trans_irq(void* parameter); - -/* ----------------------- Start implementation -----------------------------*/ -BOOL xMBMasterPortSerialInit(UCHAR ucPORT, ULONG ulBaudRate, UCHAR ucDataBits, - eMBParity eParity) -{ - rt_device_t dev = RT_NULL; - char uart_name[20]; - - /** - * set 485 mode receive and transmit control IO - * @note MODBUS_MASTER_RT_CONTROL_PIN_INDEX need be defined by user - */ -#if defined(RT_MODBUS_MASTER_USE_CONTROL_PIN) - rt_pin_mode(MODBUS_MASTER_RT_CONTROL_PIN_INDEX, PIN_MODE_OUTPUT); -#endif - /* set serial name */ - rt_snprintf(uart_name,sizeof(uart_name), "uart%d", ucPORT); - - dev = rt_device_find(uart_name); - if(dev == RT_NULL) - { - /* can not find uart */ - return FALSE; - } - else - { - serial = (struct rt_serial_device*)dev; - } - - /* set serial configure parameter */ - serial->config.baud_rate = ulBaudRate; - serial->config.stop_bits = STOP_BITS_1; - switch(eParity){ - case MB_PAR_NONE: { - serial->config.data_bits = DATA_BITS_8; - serial->config.parity = PARITY_NONE; - break; - } - case MB_PAR_ODD: { - serial->config.data_bits = DATA_BITS_9; - serial->config.parity = PARITY_ODD; - break; - } - case MB_PAR_EVEN: { - serial->config.data_bits = DATA_BITS_9; - serial->config.parity = PARITY_EVEN; - break; - } - } - /* set serial configure */ - serial->ops->configure(serial, &(serial->config)); - - /* open serial device */ - if (!rt_device_open(&serial->parent, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_INT_RX)) { - rt_device_set_rx_indicate(&serial->parent, serial_rx_ind); - } else { - return FALSE; - } - - /* software initialize */ - rt_event_init(&event_serial, "master event", RT_IPC_FLAG_PRIO); - rt_thread_init(&thread_serial_soft_trans_irq, - "master trans", - serial_soft_trans_irq, - RT_NULL, - serial_soft_trans_irq_stack, - sizeof(serial_soft_trans_irq_stack), - 10, 5); - rt_thread_startup(&thread_serial_soft_trans_irq); - - return TRUE; -} - -void vMBMasterPortSerialEnable(BOOL xRxEnable, BOOL xTxEnable) -{ - rt_uint32_t recved_event; - if (xRxEnable) - { - /* enable RX interrupt */ - serial->ops->control(serial, RT_DEVICE_CTRL_SET_INT, (void *)RT_DEVICE_FLAG_INT_RX); - /* switch 485 to receive mode */ -#if defined(RT_MODBUS_MASTER_USE_CONTROL_PIN) - rt_pin_write(MODBUS_MASTER_RT_CONTROL_PIN_INDEX, PIN_LOW); -#endif - } - else - { - /* switch 485 to transmit mode */ -#if defined(RT_MODBUS_MASTER_USE_CONTROL_PIN) - rt_pin_write(MODBUS_MASTER_RT_CONTROL_PIN_INDEX, PIN_HIGH); -#endif - /* disable RX interrupt */ - serial->ops->control(serial, RT_DEVICE_CTRL_CLR_INT, (void *)RT_DEVICE_FLAG_INT_RX); - } - if (xTxEnable) - { - /* start serial transmit */ - rt_event_send(&event_serial, EVENT_SERIAL_TRANS_START); - } - else - { - /* stop serial transmit */ - rt_event_recv(&event_serial, EVENT_SERIAL_TRANS_START, - RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, 0, - &recved_event); - } -} - -void vMBMasterPortClose(void) -{ - serial->parent.close(&(serial->parent)); -} - -BOOL xMBMasterPortSerialPutByte(CHAR ucByte) -{ - serial->parent.write(&(serial->parent), 0, &ucByte, 1); - return TRUE; -} - -BOOL xMBMasterPortSerialGetByte(CHAR * pucByte) -{ - serial->parent.read(&(serial->parent), 0, pucByte, 1); - return TRUE; -} - -/* - * Create an interrupt handler for the transmit buffer empty interrupt - * (or an equivalent) for your target processor. This function should then - * call pxMBFrameCBTransmitterEmpty( ) which tells the protocol stack that - * a new character can be sent. The protocol stack will then call - * xMBPortSerialPutByte( ) to send the character. - */ -void prvvUARTTxReadyISR(void) -{ - pxMBMasterFrameCBTransmitterEmpty(); -} - -/* - * Create an interrupt handler for the receive interrupt for your target - * processor. This function should then call pxMBFrameCBByteReceived( ). The - * protocol stack will then call xMBPortSerialGetByte( ) to retrieve the - * character. - */ -void prvvUARTRxISR(void) -{ - pxMBMasterFrameCBByteReceived(); -} - -/** - * Software simulation serial transmit IRQ handler. - * - * @param parameter parameter - */ -static void serial_soft_trans_irq(void* parameter) { - rt_uint32_t recved_event; - while (1) - { - /* waiting for serial transmit start */ - rt_event_recv(&event_serial, EVENT_SERIAL_TRANS_START, RT_EVENT_FLAG_OR, - RT_WAITING_FOREVER, &recved_event); - /* execute modbus callback */ - prvvUARTTxReadyISR(); - } -} - -/** - * This function is serial receive callback function - * - * @param dev the device of serial - * @param size the data size that receive - * - * @return return RT_EOK - */ -static rt_err_t serial_rx_ind(rt_device_t dev, rt_size_t size) { - prvvUARTRxISR(); - return RT_EOK; -} - -#endif diff --git a/components/net/freemodbus/port/porttimer.c b/components/net/freemodbus/port/porttimer.c deleted file mode 100644 index 8c51ad06d5..0000000000 --- a/components/net/freemodbus/port/porttimer.c +++ /dev/null @@ -1,63 +0,0 @@ -/* - * FreeModbus Libary: RT-Thread Port - * Copyright (C) 2013 Armink <[email protected]> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * File: $Id: porttimer.c,v 1.60 2013/08/13 15:07:05 Armink $ - */ - -/* ----------------------- Platform includes --------------------------------*/ -#include "port.h" - -/* ----------------------- Modbus includes ----------------------------------*/ -#include "mb.h" -#include "mbport.h" - -/* ----------------------- static functions ---------------------------------*/ -static struct rt_timer timer; -static void prvvTIMERExpiredISR(void); -static void timer_timeout_ind(void* parameter); - -/* ----------------------- Start implementation -----------------------------*/ -BOOL xMBPortTimersInit(USHORT usTim1Timerout50us) -{ - rt_timer_init(&timer, "slave timer", - timer_timeout_ind, /* bind timeout callback function */ - RT_NULL, - (50 * usTim1Timerout50us) / (1000 * 1000 / RT_TICK_PER_SECOND) + 1, - RT_TIMER_FLAG_ONE_SHOT); /* one shot */ - return TRUE; -} - -void vMBPortTimersEnable() -{ - rt_timer_start(&timer); -} - -void vMBPortTimersDisable() -{ - rt_timer_stop(&timer); -} - -void prvvTIMERExpiredISR(void) -{ - (void) pxMBPortCBTimerExpired(); -} - -static void timer_timeout_ind(void* parameter) -{ - prvvTIMERExpiredISR(); -} diff --git a/components/net/freemodbus/port/porttimer_m.c b/components/net/freemodbus/port/porttimer_m.c deleted file mode 100644 index ebf80004d8..0000000000 --- a/components/net/freemodbus/port/porttimer_m.c +++ /dev/null @@ -1,107 +0,0 @@ -/* - * FreeModbus Libary: RT-Thread Port - * Copyright (C) 2013 Armink <[email protected]> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * File: $Id: porttimer_m.c,v 1.60 2013/08/13 15:07:05 Armink add Master Functions$ - */ - -/* ----------------------- Platform includes --------------------------------*/ -#include "port.h" - -/* ----------------------- Modbus includes ----------------------------------*/ -#include "mb.h" -#include "mb_m.h" -#include "mbport.h" - -#if MB_MASTER_RTU_ENABLED > 0 || MB_MASTER_ASCII_ENABLED > 0 -/* ----------------------- Variables ----------------------------------------*/ -static USHORT usT35TimeOut50us; -static struct rt_timer timer; -static void prvvTIMERExpiredISR(void); -static void timer_timeout_ind(void* parameter); - -/* ----------------------- static functions ---------------------------------*/ -static void prvvTIMERExpiredISR(void); - -/* ----------------------- Start implementation -----------------------------*/ -BOOL xMBMasterPortTimersInit(USHORT usTimeOut50us) -{ - /* backup T35 ticks */ - usT35TimeOut50us = usTimeOut50us; - - rt_timer_init(&timer, "master timer", - timer_timeout_ind, /* bind timeout callback function */ - RT_NULL, - (50 * usT35TimeOut50us) / (1000 * 1000 / RT_TICK_PER_SECOND) + 1, - RT_TIMER_FLAG_ONE_SHOT); /* one shot */ - - return TRUE; -} - -void vMBMasterPortTimersT35Enable() -{ - rt_tick_t timer_tick = (50 * usT35TimeOut50us) - / (1000 * 1000 / RT_TICK_PER_SECOND); - - /* Set current timer mode, don't change it.*/ - vMBMasterSetCurTimerMode(MB_TMODE_T35); - - rt_timer_control(&timer, RT_TIMER_CTRL_SET_TIME, &timer_tick); - - rt_timer_start(&timer); -} - -void vMBMasterPortTimersConvertDelayEnable() -{ - rt_tick_t timer_tick = MB_MASTER_DELAY_MS_CONVERT * RT_TICK_PER_SECOND / 1000; - - /* Set current timer mode, don't change it.*/ - vMBMasterSetCurTimerMode(MB_TMODE_CONVERT_DELAY); - - rt_timer_control(&timer, RT_TIMER_CTRL_SET_TIME, &timer_tick); - - rt_timer_start(&timer); -} - -void vMBMasterPortTimersRespondTimeoutEnable() -{ - rt_tick_t timer_tick = MB_MASTER_TIMEOUT_MS_RESPOND * RT_TICK_PER_SECOND / 1000; - - /* Set current timer mode, don't change it.*/ - vMBMasterSetCurTimerMode(MB_TMODE_RESPOND_TIMEOUT); - - rt_timer_control(&timer, RT_TIMER_CTRL_SET_TIME, &timer_tick); - - rt_timer_start(&timer); -} - -void vMBMasterPortTimersDisable() -{ - rt_timer_stop(&timer); -} - -void prvvTIMERExpiredISR(void) -{ - (void) pxMBMasterPortCBTimerExpired(); -} - -static void timer_timeout_ind(void* parameter) -{ - prvvTIMERExpiredISR(); -} - -#endif diff --git a/components/net/freemodbus/port/user_mb_app.c b/components/net/freemodbus/port/user_mb_app.c deleted file mode 100644 index 8da7376336..0000000000 --- a/components/net/freemodbus/port/user_mb_app.c +++ /dev/null @@ -1,286 +0,0 @@ -/* - * FreeModbus Libary: user callback functions and buffer define in slave mode - * Copyright (C) 2013 Armink <[email protected]> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * File: $Id: user_mb_app.c,v 1.60 2013/11/23 11:49:05 Armink $ - */ -#include "user_mb_app.h" - -/*------------------------Slave mode use these variables----------------------*/ -//Slave mode:DiscreteInputs variables -USHORT usSDiscInStart = S_DISCRETE_INPUT_START; -#if S_DISCRETE_INPUT_NDISCRETES%8 -UCHAR ucSDiscInBuf[S_DISCRETE_INPUT_NDISCRETES/8+1]; -#else -UCHAR ucSDiscInBuf[S_DISCRETE_INPUT_NDISCRETES/8] ; -#endif -//Slave mode:Coils variables -USHORT usSCoilStart = S_COIL_START; -#if S_COIL_NCOILS%8 -UCHAR ucSCoilBuf[S_COIL_NCOILS/8+1] ; -#else -UCHAR ucSCoilBuf[S_COIL_NCOILS/8] ; -#endif -//Slave mode:InputRegister variables -USHORT usSRegInStart = S_REG_INPUT_START; -USHORT usSRegInBuf[S_REG_INPUT_NREGS] ; -//Slave mode:HoldingRegister variables -USHORT usSRegHoldStart = S_REG_HOLDING_START; -USHORT usSRegHoldBuf[S_REG_HOLDING_NREGS] ; - -/** - * Modbus slave input register callback function. - * - * @param pucRegBuffer input register buffer - * @param usAddress input register address - * @param usNRegs input register number - * - * @return result - */ -eMBErrorCode eMBRegInputCB(UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs ) -{ - eMBErrorCode eStatus = MB_ENOERR; - USHORT iRegIndex; - USHORT * pusRegInputBuf; - USHORT REG_INPUT_START; - USHORT REG_INPUT_NREGS; - USHORT usRegInStart; - - pusRegInputBuf = usSRegInBuf; - REG_INPUT_START = S_REG_INPUT_START; - REG_INPUT_NREGS = S_REG_INPUT_NREGS; - usRegInStart = usSRegInStart; - - /* it already plus one in modbus function method. */ - usAddress--; - - if ((usAddress >= REG_INPUT_START) - && (usAddress + usNRegs <= REG_INPUT_START + REG_INPUT_NREGS)) - { - iRegIndex = usAddress - usRegInStart; - while (usNRegs > 0) - { - *pucRegBuffer++ = (UCHAR) (pusRegInputBuf[iRegIndex] >> 8); - *pucRegBuffer++ = (UCHAR) (pusRegInputBuf[iRegIndex] & 0xFF); - iRegIndex++; - usNRegs--; - } - } - else - { - eStatus = MB_ENOREG; - } - - return eStatus; -} - -/** - * Modbus slave holding register callback function. - * - * @param pucRegBuffer holding register buffer - * @param usAddress holding register address - * @param usNRegs holding register number - * @param eMode read or write - * - * @return result - */ -eMBErrorCode eMBRegHoldingCB(UCHAR * pucRegBuffer, USHORT usAddress, - USHORT usNRegs, eMBRegisterMode eMode) -{ - eMBErrorCode eStatus = MB_ENOERR; - USHORT iRegIndex; - USHORT * pusRegHoldingBuf; - USHORT REG_HOLDING_START; - USHORT REG_HOLDING_NREGS; - USHORT usRegHoldStart; - - pusRegHoldingBuf = usSRegHoldBuf; - REG_HOLDING_START = S_REG_HOLDING_START; - REG_HOLDING_NREGS = S_REG_HOLDING_NREGS; - usRegHoldStart = usSRegHoldStart; - - /* it already plus one in modbus function method. */ - usAddress--; - - if ((usAddress >= REG_HOLDING_START) - && (usAddress + usNRegs <= REG_HOLDING_START + REG_HOLDING_NREGS)) - { - iRegIndex = usAddress - usRegHoldStart; - switch (eMode) - { - /* read current register values from the protocol stack. */ - case MB_REG_READ: - while (usNRegs > 0) - { - *pucRegBuffer++ = (UCHAR) (pusRegHoldingBuf[iRegIndex] >> 8); - *pucRegBuffer++ = (UCHAR) (pusRegHoldingBuf[iRegIndex] & 0xFF); - iRegIndex++; - usNRegs--; - } - break; - - /* write current register values with new values from the protocol stack. */ - case MB_REG_WRITE: - while (usNRegs > 0) - { - pusRegHoldingBuf[iRegIndex] = *pucRegBuffer++ << 8; - pusRegHoldingBuf[iRegIndex] |= *pucRegBuffer++; - iRegIndex++; - usNRegs--; - } - break; - } - } - else - { - eStatus = MB_ENOREG; - } - return eStatus; -} - -/** - * Modbus slave coils callback function. - * - * @param pucRegBuffer coils buffer - * @param usAddress coils address - * @param usNCoils coils number - * @param eMode read or write - * - * @return result - */ -eMBErrorCode eMBRegCoilsCB(UCHAR * pucRegBuffer, USHORT usAddress, - USHORT usNCoils, eMBRegisterMode eMode) -{ - eMBErrorCode eStatus = MB_ENOERR; - USHORT iRegIndex , iRegBitIndex , iNReg; - UCHAR * pucCoilBuf; - USHORT COIL_START; - USHORT COIL_NCOILS; - USHORT usCoilStart; - iNReg = usNCoils / 8 + 1; - - pucCoilBuf = ucSCoilBuf; - COIL_START = S_COIL_START; - COIL_NCOILS = S_COIL_NCOILS; - usCoilStart = usSCoilStart; - - /* it already plus one in modbus function method. */ - usAddress--; - - if( ( usAddress >= COIL_START ) && - ( usAddress + usNCoils <= COIL_START + COIL_NCOILS ) ) - { - iRegIndex = (USHORT) (usAddress - usCoilStart) / 8; - iRegBitIndex = (USHORT) (usAddress - usCoilStart) % 8; - switch ( eMode ) - { - /* read current coil values from the protocol stack. */ - case MB_REG_READ: - while (iNReg > 0) - { - *pucRegBuffer++ = xMBUtilGetBits(&pucCoilBuf[iRegIndex++], - iRegBitIndex, 8); - iNReg--; - } - pucRegBuffer--; - /* last coils */ - usNCoils = usNCoils % 8; - /* filling zero to high bit */ - *pucRegBuffer = *pucRegBuffer << (8 - usNCoils); - *pucRegBuffer = *pucRegBuffer >> (8 - usNCoils); - break; - - /* write current coil values with new values from the protocol stack. */ - case MB_REG_WRITE: - while (iNReg > 1) - { - xMBUtilSetBits(&pucCoilBuf[iRegIndex++], iRegBitIndex, 8, - *pucRegBuffer++); - iNReg--; - } - /* last coils */ - usNCoils = usNCoils % 8; - /* xMBUtilSetBits has bug when ucNBits is zero */ - if (usNCoils != 0) - { - xMBUtilSetBits(&pucCoilBuf[iRegIndex++], iRegBitIndex, usNCoils, - *pucRegBuffer++); - } - break; - } - } - else - { - eStatus = MB_ENOREG; - } - return eStatus; -} - -/** - * Modbus slave discrete callback function. - * - * @param pucRegBuffer discrete buffer - * @param usAddress discrete address - * @param usNDiscrete discrete number - * - * @return result - */ -eMBErrorCode eMBRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNDiscrete ) -{ - eMBErrorCode eStatus = MB_ENOERR; - USHORT iRegIndex , iRegBitIndex , iNReg; - UCHAR * pucDiscreteInputBuf; - USHORT DISCRETE_INPUT_START; - USHORT DISCRETE_INPUT_NDISCRETES; - USHORT usDiscreteInputStart; - iNReg = usNDiscrete / 8 + 1; - - pucDiscreteInputBuf = ucSDiscInBuf; - DISCRETE_INPUT_START = S_DISCRETE_INPUT_START; - DISCRETE_INPUT_NDISCRETES = S_DISCRETE_INPUT_NDISCRETES; - usDiscreteInputStart = usSDiscInStart; - - /* it already plus one in modbus function method. */ - usAddress--; - - if ((usAddress >= DISCRETE_INPUT_START) - && (usAddress + usNDiscrete <= DISCRETE_INPUT_START + DISCRETE_INPUT_NDISCRETES)) - { - iRegIndex = (USHORT) (usAddress - usDiscreteInputStart) / 8; - iRegBitIndex = (USHORT) (usAddress - usDiscreteInputStart) % 8; - - while (iNReg > 0) - { - *pucRegBuffer++ = xMBUtilGetBits(&pucDiscreteInputBuf[iRegIndex++], - iRegBitIndex, 8); - iNReg--; - } - pucRegBuffer--; - /* last discrete */ - usNDiscrete = usNDiscrete % 8; - /* filling zero to high bit */ - *pucRegBuffer = *pucRegBuffer << (8 - usNDiscrete); - *pucRegBuffer = *pucRegBuffer >> (8 - usNDiscrete); - } - else - { - eStatus = MB_ENOREG; - } - - return eStatus; -} - diff --git a/components/net/freemodbus/port/user_mb_app.h b/components/net/freemodbus/port/user_mb_app.h deleted file mode 100644 index 864c3860bf..0000000000 --- a/components/net/freemodbus/port/user_mb_app.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef USER_APP -#define USER_APP -/* ----------------------- Modbus includes ----------------------------------*/ -#include "mb.h" -#include "mb_m.h" -#include "mbconfig.h" -#include "mbframe.h" -#include "mbutils.h" - -/* -----------------------Slave Defines -------------------------------------*/ -#define S_DISCRETE_INPUT_START 0 -#define S_DISCRETE_INPUT_NDISCRETES 16 -#define S_COIL_START 0 -#define S_COIL_NCOILS 64 -#define S_REG_INPUT_START 0 -#define S_REG_INPUT_NREGS 100 -#define S_REG_HOLDING_START 0 -#define S_REG_HOLDING_NREGS 100 -/* salve mode: holding register's all address */ -#define S_HD_RESERVE 0 -/* salve mode: input register's all address */ -#define S_IN_RESERVE 0 -/* salve mode: coil's all address */ -#define S_CO_RESERVE 0 -/* salve mode: discrete's all address */ -#define S_DI_RESERVE 0 - -/* -----------------------Master Defines -------------------------------------*/ -#define M_DISCRETE_INPUT_START 0 -#define M_DISCRETE_INPUT_NDISCRETES 16 -#define M_COIL_START 0 -#define M_COIL_NCOILS 64 -#define M_REG_INPUT_START 0 -#define M_REG_INPUT_NREGS 100 -#define M_REG_HOLDING_START 0 -#define M_REG_HOLDING_NREGS 100 -/* master mode: holding register's all address */ -#define M_HD_RESERVE 0 -/* master mode: input register's all address */ -#define M_IN_RESERVE 0 -/* master mode: coil's all address */ -#define M_CO_RESERVE 0 -/* master mode: discrete's all address */ -#define M_DI_RESERVE 0 - -#endif diff --git a/components/net/freemodbus/port/user_mb_app_m.c b/components/net/freemodbus/port/user_mb_app_m.c deleted file mode 100644 index 12fabf21ac..0000000000 --- a/components/net/freemodbus/port/user_mb_app_m.c +++ /dev/null @@ -1,294 +0,0 @@ -/* - * FreeModbus Libary: user callback functions and buffer define in master mode - * Copyright (C) 2013 Armink <[email protected]> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * File: $Id: user_mb_app_m.c,v 1.60 2013/11/23 11:49:05 Armink $ - */ -#include "user_mb_app.h" - -/*-----------------------Master mode use these variables----------------------*/ -#if MB_MASTER_RTU_ENABLED > 0 || MB_MASTER_ASCII_ENABLED > 0 -//Master mode:DiscreteInputs variables -USHORT usMDiscInStart = M_DISCRETE_INPUT_START; -#if M_DISCRETE_INPUT_NDISCRETES%8 -UCHAR ucMDiscInBuf[MB_MASTER_TOTAL_SLAVE_NUM][M_DISCRETE_INPUT_NDISCRETES/8+1]; -#else -UCHAR ucMDiscInBuf[MB_MASTER_TOTAL_SLAVE_NUM][M_DISCRETE_INPUT_NDISCRETES/8]; -#endif -//Master mode:Coils variables -USHORT usMCoilStart = M_COIL_START; -#if M_COIL_NCOILS%8 -UCHAR ucMCoilBuf[MB_MASTER_TOTAL_SLAVE_NUM][M_COIL_NCOILS/8+1]; -#else -UCHAR ucMCoilBuf[MB_MASTER_TOTAL_SLAVE_NUM][M_COIL_NCOILS/8]; -#endif -//Master mode:InputRegister variables -USHORT usMRegInStart = M_REG_INPUT_START; -USHORT usMRegInBuf[MB_MASTER_TOTAL_SLAVE_NUM][M_REG_INPUT_NREGS]; -//Master mode:HoldingRegister variables -USHORT usMRegHoldStart = M_REG_HOLDING_START; -USHORT usMRegHoldBuf[MB_MASTER_TOTAL_SLAVE_NUM][M_REG_HOLDING_NREGS]; - -/** - * Modbus master input register callback function. - * - * @param pucRegBuffer input register buffer - * @param usAddress input register address - * @param usNRegs input register number - * - * @return result - */ -eMBErrorCode eMBMasterRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs ) -{ - eMBErrorCode eStatus = MB_ENOERR; - USHORT iRegIndex; - USHORT * pusRegInputBuf; - USHORT REG_INPUT_START; - USHORT REG_INPUT_NREGS; - USHORT usRegInStart; - - pusRegInputBuf = usMRegInBuf[ucMBMasterGetDestAddress() - 1]; - REG_INPUT_START = M_REG_INPUT_START; - REG_INPUT_NREGS = M_REG_INPUT_NREGS; - usRegInStart = usMRegInStart; - - /* it already plus one in modbus function method. */ - usAddress--; - - if ((usAddress >= REG_INPUT_START) - && (usAddress + usNRegs <= REG_INPUT_START + REG_INPUT_NREGS)) - { - iRegIndex = usAddress - usRegInStart; - while (usNRegs > 0) - { - pusRegInputBuf[iRegIndex] = *pucRegBuffer++ << 8; - pusRegInputBuf[iRegIndex] |= *pucRegBuffer++; - iRegIndex++; - usNRegs--; - } - } - else - { - eStatus = MB_ENOREG; - } - - return eStatus; -} - -/** - * Modbus master holding register callback function. - * - * @param pucRegBuffer holding register buffer - * @param usAddress holding register address - * @param usNRegs holding register number - * @param eMode read or write - * - * @return result - */ -eMBErrorCode eMBMasterRegHoldingCB(UCHAR * pucRegBuffer, USHORT usAddress, - USHORT usNRegs, eMBRegisterMode eMode) -{ - eMBErrorCode eStatus = MB_ENOERR; - USHORT iRegIndex; - USHORT * pusRegHoldingBuf; - USHORT REG_HOLDING_START; - USHORT REG_HOLDING_NREGS; - USHORT usRegHoldStart; - - pusRegHoldingBuf = usMRegHoldBuf[ucMBMasterGetDestAddress() - 1]; - REG_HOLDING_START = M_REG_HOLDING_START; - REG_HOLDING_NREGS = M_REG_HOLDING_NREGS; - usRegHoldStart = usMRegHoldStart; - /* if mode is read, the master will write the received date to buffer. */ - eMode = MB_REG_WRITE; - - /* it already plus one in modbus function method. */ - usAddress--; - - if ((usAddress >= REG_HOLDING_START) - && (usAddress + usNRegs <= REG_HOLDING_START + REG_HOLDING_NREGS)) - { - iRegIndex = usAddress - usRegHoldStart; - switch (eMode) - { - /* read current register values from the protocol stack. */ - case MB_REG_READ: - while (usNRegs > 0) - { - *pucRegBuffer++ = (UCHAR) (pusRegHoldingBuf[iRegIndex] >> 8); - *pucRegBuffer++ = (UCHAR) (pusRegHoldingBuf[iRegIndex] & 0xFF); - iRegIndex++; - usNRegs--; - } - break; - /* write current register values with new values from the protocol stack. */ - case MB_REG_WRITE: - while (usNRegs > 0) - { - pusRegHoldingBuf[iRegIndex] = *pucRegBuffer++ << 8; - pusRegHoldingBuf[iRegIndex] |= *pucRegBuffer++; - iRegIndex++; - usNRegs--; - } - break; - } - } - else - { - eStatus = MB_ENOREG; - } - return eStatus; -} - -/** - * Modbus master coils callback function. - * - * @param pucRegBuffer coils buffer - * @param usAddress coils address - * @param usNCoils coils number - * @param eMode read or write - * - * @return result - */ -eMBErrorCode eMBMasterRegCoilsCB(UCHAR * pucRegBuffer, USHORT usAddress, - USHORT usNCoils, eMBRegisterMode eMode) -{ - eMBErrorCode eStatus = MB_ENOERR; - USHORT iRegIndex , iRegBitIndex , iNReg; - UCHAR * pucCoilBuf; - USHORT COIL_START; - USHORT COIL_NCOILS; - USHORT usCoilStart; - iNReg = usNCoils / 8 + 1; - - pucCoilBuf = ucMCoilBuf[ucMBMasterGetDestAddress() - 1]; - COIL_START = M_COIL_START; - COIL_NCOILS = M_COIL_NCOILS; - usCoilStart = usMCoilStart; - - /* if mode is read,the master will write the received date to buffer. */ - eMode = MB_REG_WRITE; - - /* it already plus one in modbus function method. */ - usAddress--; - - if ((usAddress >= COIL_START) - && (usAddress + usNCoils <= COIL_START + COIL_NCOILS)) - { - iRegIndex = (USHORT) (usAddress - usCoilStart) / 8; - iRegBitIndex = (USHORT) (usAddress - usCoilStart) % 8; - switch (eMode) - { - /* read current coil values from the protocol stack. */ - case MB_REG_READ: - while (iNReg > 0) - { - *pucRegBuffer++ = xMBUtilGetBits(&pucCoilBuf[iRegIndex++], - iRegBitIndex, 8); - iNReg--; - } - pucRegBuffer--; - /* last coils */ - usNCoils = usNCoils % 8; - /* filling zero to high bit */ - *pucRegBuffer = *pucRegBuffer << (8 - usNCoils); - *pucRegBuffer = *pucRegBuffer >> (8 - usNCoils); - break; - - /* write current coil values with new values from the protocol stack. */ - case MB_REG_WRITE: - while (iNReg > 1) - { - xMBUtilSetBits(&pucCoilBuf[iRegIndex++], iRegBitIndex, 8, - *pucRegBuffer++); - iNReg--; - } - /* last coils */ - usNCoils = usNCoils % 8; - /* xMBUtilSetBits has bug when ucNBits is zero */ - if (usNCoils != 0) - { - xMBUtilSetBits(&pucCoilBuf[iRegIndex++], iRegBitIndex, usNCoils, - *pucRegBuffer++); - } - break; - } - } - else - { - eStatus = MB_ENOREG; - } - return eStatus; -} - -/** - * Modbus master discrete callback function. - * - * @param pucRegBuffer discrete buffer - * @param usAddress discrete address - * @param usNDiscrete discrete number - * - * @return result - */ -eMBErrorCode eMBMasterRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNDiscrete ) -{ - eMBErrorCode eStatus = MB_ENOERR; - USHORT iRegIndex , iRegBitIndex , iNReg; - UCHAR * pucDiscreteInputBuf; - USHORT DISCRETE_INPUT_START; - USHORT DISCRETE_INPUT_NDISCRETES; - USHORT usDiscreteInputStart; - iNReg = usNDiscrete / 8 + 1; - - pucDiscreteInputBuf = ucMDiscInBuf[ucMBMasterGetDestAddress() - 1]; - DISCRETE_INPUT_START = M_DISCRETE_INPUT_START; - DISCRETE_INPUT_NDISCRETES = M_DISCRETE_INPUT_NDISCRETES; - usDiscreteInputStart = usMDiscInStart; - - /* it already plus one in modbus function method. */ - usAddress--; - - if ((usAddress >= DISCRETE_INPUT_START) - && (usAddress + usNDiscrete <= DISCRETE_INPUT_START + DISCRETE_INPUT_NDISCRETES)) - { - iRegIndex = (USHORT) (usAddress - usDiscreteInputStart) / 8; - iRegBitIndex = (USHORT) (usAddress - usDiscreteInputStart) % 8; - - /* write current discrete values with new values from the protocol stack. */ - while (iNReg > 1) - { - xMBUtilSetBits(&pucDiscreteInputBuf[iRegIndex++], iRegBitIndex, 8, - *pucRegBuffer++); - iNReg--; - } - /* last discrete */ - usNDiscrete = usNDiscrete % 8; - /* xMBUtilSetBits has bug when ucNBits is zero */ - if (usNDiscrete != 0) - { - xMBUtilSetBits(&pucDiscreteInputBuf[iRegIndex++], iRegBitIndex, - usNDiscrete, *pucRegBuffer++); - } - } - else - { - eStatus = MB_ENOREG; - } - - return eStatus; -} -#endif diff --git a/components/net/lwip-1.4.1/src/arch/sys_arch.c b/components/net/lwip-1.4.1/src/arch/sys_arch.c index dc20ee97a1..c31bd59c1d 100644 --- a/components/net/lwip-1.4.1/src/arch/sys_arch.c +++ b/components/net/lwip-1.4.1/src/arch/sys_arch.c @@ -198,7 +198,7 @@ int lwip_system_init(void) return 0; } -INIT_COMPONENT_EXPORT(lwip_system_init); +INIT_PREV_EXPORT(lwip_system_init); void sys_init(void) { @@ -497,8 +497,7 @@ u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout) t = timeout / (1000/RT_TICK_PER_SECOND); } - ret = rt_mb_recv(*mbox, (rt_uint32_t *)msg, t); - + ret = rt_mb_recv(*mbox, (rt_ubase_t *)msg, t); if(ret == -RT_ETIMEOUT) { return SYS_ARCH_TIMEOUT; @@ -530,8 +529,7 @@ u32_t sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg) { int ret; - ret = rt_mb_recv(*mbox, (rt_uint32_t *)msg, 0); - + ret = rt_mb_recv(*mbox, (rt_ubase_t *)msg, 0); if(ret == -RT_ETIMEOUT) { return SYS_ARCH_TIMEOUT; diff --git a/components/net/lwip-1.4.1/src/core/dns.c b/components/net/lwip-1.4.1/src/core/dns.c index 18c73d0a8c..2e1356ca97 100644 --- a/components/net/lwip-1.4.1/src/core/dns.c +++ b/components/net/lwip-1.4.1/src/core/dns.c @@ -279,13 +279,14 @@ dns_setserver(u8_t numdns, ip_addr_t *dnsserver) dns_servers[numdns] = (*dnsserver); #ifdef RT_USING_NETDEV - extern struct netif *netif_default; + extern struct netif *netif_list; extern struct netdev *netdev_get_by_name(const char *name); extern void netdev_low_level_set_dns_server(struct netdev *netdev, uint8_t dns_num, const ip_addr_t *dns_server); + struct netif *netif = NULL; /* set network interface device DNS server address */ - if (netif_default) { - netdev_low_level_set_dns_server(netdev_get_by_name(netif_default->name), numdns, dnsserver); + for (netif = netif_list; netif != NULL; netif = netif->next) { + netdev_low_level_set_dns_server(netdev_get_by_name(netif->name), numdns, dnsserver); } #endif /* RT_USING_NETDEV */ } diff --git a/components/net/lwip-1.4.1/src/netif/ethernetif.c b/components/net/lwip-1.4.1/src/netif/ethernetif.c index 10bcaa0c95..9d8fa650a4 100644 --- a/components/net/lwip-1.4.1/src/netif/ethernetif.c +++ b/components/net/lwip-1.4.1/src/netif/ethernetif.c @@ -146,8 +146,8 @@ static int lwip_netdev_set_addr_info(struct netdev *netif, ip_addr_t *ip_addr, i #ifdef RT_LWIP_DNS static int lwip_netdev_set_dns_server(struct netdev *netif, uint8_t dns_num, ip_addr_t *dns_server) { - extern void set_dns(uint8_t dns_num, char* dns_server); - set_dns(dns_num, ipaddr_ntoa(dns_server)); + extern void dns_setserver(uint8_t dns_num, ip_addr_t *dns_server); + dns_setserver(dns_num, dns_server); return ERR_OK; } #endif /* RT_LWIP_DNS */ @@ -160,6 +160,7 @@ static int lwip_netdev_set_dhcp(struct netdev *netif, rt_bool_t is_enabled) } #endif /* RT_LWIP_DHCP */ +#ifdef RT_USING_FINSH #ifdef RT_LWIP_USING_PING extern int lwip_ping_recv(int s, int *ttl); extern err_t lwip_ping_send(int s, ip_addr_t *addr, int size); @@ -250,6 +251,13 @@ void lwip_netdev_netstat(struct netdev *netif) #endif } #endif /* RT_LWIP_TCP || RT_LWIP_UDP */ +#endif /* RT_USING_FINSH */ + +static int lwip_netdev_set_default(struct netdev *netif) +{ + netif_set_default((struct netif *)netif->user_data); + return ERR_OK; +} const struct netdev_ops lwip_netdev_ops = { @@ -269,6 +277,7 @@ const struct netdev_ops lwip_netdev_ops = NULL, #endif /* RT_LWIP_DHCP */ +#ifdef RT_USING_FINSH #ifdef RT_LWIP_USING_PING lwip_netdev_ping, #else @@ -278,6 +287,9 @@ const struct netdev_ops lwip_netdev_ops = #if defined (RT_LWIP_TCP) || defined (RT_LWIP_UDP) lwip_netdev_netstat, #endif /* RT_LWIP_TCP || RT_LWIP_UDP */ +#endif /* RT_USING_FINSH */ + + lwip_netdev_set_default, }; static int netdev_add(struct netif *lwip_netif) @@ -295,12 +307,6 @@ static int netdev_add(struct netif *lwip_netif) return -ERR_IF; } - netdev->flags = lwip_netif->flags; - netdev->mtu = lwip_netif->mtu; - netdev->ops = &lwip_netdev_ops; - netdev->hwaddr_len = lwip_netif->hwaddr_len; - rt_memcpy(netdev->hwaddr, lwip_netif->hwaddr, lwip_netif->hwaddr_len); - #ifdef SAL_USING_LWIP extern int sal_lwip_netdev_set_pf_info(struct netdev *netdev); /* set the lwIP network interface device protocol family information */ @@ -309,7 +315,17 @@ static int netdev_add(struct netif *lwip_netif) rt_strncpy(name, lwip_netif->name, LWIP_NETIF_NAME_LEN); result = netdev_register(netdev, name, (void *)lwip_netif); - + + /* Update netdev info after registered */ + netdev->flags = lwip_netif->flags; + netdev->mtu = lwip_netif->mtu; + netdev->ops = &lwip_netdev_ops; + netdev->hwaddr_len = lwip_netif->hwaddr_len; + rt_memcpy(netdev->hwaddr, lwip_netif->hwaddr, lwip_netif->hwaddr_len); + netdev->ip_addr = lwip_netif->ip_addr; + netdev->gw = lwip_netif->gw; + netdev->netmask = lwip_netif->netmask; + #ifdef RT_LWIP_DHCP netdev_low_level_set_dhcp_status(netdev, RT_TRUE); #endif @@ -678,8 +694,6 @@ int eth_system_device_init(void) } INIT_PREV_EXPORT(eth_system_device_init); -#ifdef RT_USING_FINSH -#include <finsh.h> void set_if(char* netif_name, char* ip_addr, char* gw_addr, char* nm_addr) { struct ip_addr *ip; @@ -725,6 +739,9 @@ void set_if(char* netif_name, char* ip_addr, char* gw_addr, char* nm_addr) netif_set_netmask(netif, ip); } } + +#ifdef RT_USING_FINSH +#include <finsh.h> FINSH_FUNCTION_EXPORT(set_if, set network interface address); #if LWIP_DNS diff --git a/components/net/lwip-2.0.2/src/arch/sys_arch.c b/components/net/lwip-2.0.2/src/arch/sys_arch.c index 7a92170886..b2abaeab54 100644 --- a/components/net/lwip-2.0.2/src/arch/sys_arch.c +++ b/components/net/lwip-2.0.2/src/arch/sys_arch.c @@ -508,7 +508,7 @@ u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout) t = timeout / (1000/RT_TICK_PER_SECOND); } - ret = rt_mb_recv(*mbox, (rt_uint32_t *)msg, t); + ret = rt_mb_recv(*mbox, (rt_ubase_t *)msg, t); if(ret == -RT_ETIMEOUT) return SYS_ARCH_TIMEOUT; @@ -539,7 +539,7 @@ u32_t sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg) { int ret; - ret = rt_mb_recv(*mbox, (rt_uint32_t *)msg, 0); + ret = rt_mb_recv(*mbox, (rt_ubase_t *)msg, 0); if(ret == -RT_ETIMEOUT) return SYS_ARCH_TIMEOUT; diff --git a/components/net/lwip-2.0.2/src/core/dns.c b/components/net/lwip-2.0.2/src/core/dns.c index c793b320a4..cd4de06229 100644 --- a/components/net/lwip-2.0.2/src/core/dns.c +++ b/components/net/lwip-2.0.2/src/core/dns.c @@ -370,13 +370,14 @@ dns_setserver(u8_t numdns, const ip_addr_t *dnsserver) dns_servers[numdns] = (*dnsserver); #ifdef RT_USING_NETDEV - extern struct netif *netif_default; + extern struct netif *netif_list; extern struct netdev *netdev_get_by_name(const char *name); extern void netdev_low_level_set_dns_server(struct netdev *netdev, uint8_t dns_num, const ip_addr_t *dns_server); + struct netif *netif = NULL; /* set network interface device DNS server address */ - if (netif_default) { - netdev_low_level_set_dns_server(netdev_get_by_name(netif_default->name), numdns, dnsserver); + for (netif = netif_list; netif != NULL; netif = netif->next) { + netdev_low_level_set_dns_server(netdev_get_by_name(netif->name), numdns, dnsserver); } #endif /* RT_USING_NETDEV */ } else { diff --git a/components/net/lwip-2.0.2/src/core/netif.c b/components/net/lwip-2.0.2/src/core/netif.c index 01e83676da..ee57bb9a9d 100644 --- a/components/net/lwip-2.0.2/src/core/netif.c +++ b/components/net/lwip-2.0.2/src/core/netif.c @@ -544,7 +544,7 @@ netif_set_ipaddr(struct netif *netif, const ip4_addr_t *ipaddr) #ifdef RT_USING_NETDEV /* rt-thread sal network interface device set IP address operations */ - netdev_low_level_set_ipaddr(netdev_get_by_name(netif->name), (ip_addr_t *)ipaddr); + netdev_low_level_set_ipaddr(netdev_get_by_name(netif->name), &netif->ip_addr); #endif /* RT_USING_NETDEV */ } @@ -579,7 +579,7 @@ netif_set_gw(struct netif *netif, const ip4_addr_t *gw) #ifdef RT_USING_NETDEV /* rt_thread network interface device set gateway address */ - netdev_low_level_set_gw(netdev_get_by_name(netif->name), (ip_addr_t *)gw); + netdev_low_level_set_gw(netdev_get_by_name(netif->name), &netif->gw); #endif /* RT_USING_NETDEV */ } @@ -610,7 +610,7 @@ netif_set_netmask(struct netif *netif, const ip4_addr_t *netmask) #ifdef RT_USING_NETDEV /* rt-thread network interface device set netmask address */ - netdev_low_level_set_netmask(netdev_get_by_name(netif->name), (ip_addr_t *)netmask); + netdev_low_level_set_netmask(netdev_get_by_name(netif->name), &netif->netmask); #endif /* RT_USING_NETDEV */ } #endif /* LWIP_IPV4 */ @@ -1241,6 +1241,11 @@ netif_create_ip6_linklocal_address(struct netif *netif, u8_t from_mac_48bit) } } +#ifdef RT_USING_NETDEV + /* rt-thread network interface device set ipv6 address */ + ip_addr_copy(netdev_get_by_name(netif->name)->ip6_addr[0], netif->ip6_addr[0]); +#endif /* RT_USING_NETDEV */ + /* Set address state. */ #if LWIP_IPV6_DUP_DETECT_ATTEMPTS /* Will perform duplicate address detection (DAD). */ @@ -1279,6 +1284,10 @@ netif_add_ip6_address(struct netif *netif, const ip6_addr_t *ip6addr, s8_t *chos for (i = 1; i < LWIP_IPV6_NUM_ADDRESSES; i++) { if (ip6_addr_isinvalid(netif_ip6_addr_state(netif, i))) { ip_addr_copy_from_ip6(netif->ip6_addr[i], *ip6addr); +#ifdef RT_USING_NETDEV + /* rt-thread network interface device set ipv6 address */ + ip_addr_copy(netdev_get_by_name(netif->name)->ip6_addr[i], netif->ip6_addr[i]); +#endif /* RT_USING_NETDEV */ netif_ip6_addr_set_state(netif, i, IP6_ADDR_TENTATIVE); if (chosen_idx != NULL) { *chosen_idx = i; diff --git a/components/net/lwip-2.0.2/src/include/netif/ethernetif.h b/components/net/lwip-2.0.2/src/include/netif/ethernetif.h index 1c969e6e25..244bafdd1b 100644 --- a/components/net/lwip-2.0.2/src/include/netif/ethernetif.h +++ b/components/net/lwip-2.0.2/src/include/netif/ethernetif.h @@ -41,6 +41,7 @@ extern "C" { rt_err_t eth_device_init(struct eth_device * dev, const char *name); rt_err_t eth_device_init_with_flag(struct eth_device *dev, const char *name, rt_uint16_t flag); rt_err_t eth_device_linkchange(struct eth_device* dev, rt_bool_t up); + void eth_device_deinit(struct eth_device *dev); int eth_system_device_init(void); diff --git a/components/net/lwip-2.0.2/src/netif/ethernetif.c b/components/net/lwip-2.0.2/src/netif/ethernetif.c index f19ec094fa..a7bed3065f 100644 --- a/components/net/lwip-2.0.2/src/netif/ethernetif.c +++ b/components/net/lwip-2.0.2/src/netif/ethernetif.c @@ -128,23 +128,23 @@ static int lwip_netdev_set_addr_info(struct netdev *netif, ip_addr_t *ip_addr, i { if (ip_addr && netmask && gw) { - netif_set_addr((struct netif *)netif->user_data, ip_addr, netmask, gw); + netif_set_addr((struct netif *)netif->user_data, ip_2_ip4(ip_addr), ip_2_ip4(netmask), ip_2_ip4(gw)); } else { if (ip_addr) { - netif_set_ipaddr((struct netif *)netif->user_data, ip_addr); + netif_set_ipaddr((struct netif *)netif->user_data, ip_2_ip4(ip_addr)); } if (netmask) { - netif_set_netmask((struct netif *)netif->user_data, netmask); + netif_set_netmask((struct netif *)netif->user_data, ip_2_ip4(netmask)); } if (gw) { - netif_set_gw((struct netif *)netif->user_data, gw); + netif_set_gw((struct netif *)netif->user_data, ip_2_ip4(gw)); } } @@ -154,8 +154,8 @@ static int lwip_netdev_set_addr_info(struct netdev *netif, ip_addr_t *ip_addr, i #ifdef RT_LWIP_DNS static int lwip_netdev_set_dns_server(struct netdev *netif, uint8_t dns_num, ip_addr_t *dns_server) { - extern void set_dns(uint8_t dns_num, char* dns_server); - set_dns(dns_num, ipaddr_ntoa(dns_server)); + extern void dns_setserver(uint8_t dns_num, const ip_addr_t *dns_server); + dns_setserver(dns_num, dns_server); return ERR_OK; } #endif /* RT_LWIP_DNS */ @@ -168,6 +168,7 @@ static int lwip_netdev_set_dhcp(struct netdev *netif, rt_bool_t is_enabled) } #endif /* RT_LWIP_DHCP */ +#ifdef RT_USING_FINSH #ifdef RT_LWIP_USING_PING extern int lwip_ping_recv(int s, int *ttl); extern err_t lwip_ping_send(int s, ip_addr_t *addr, int size); @@ -258,6 +259,13 @@ void lwip_netdev_netstat(struct netdev *netif) #endif } #endif /* RT_LWIP_TCP || RT_LWIP_UDP */ +#endif /* RT_USING_FINSH */ + +static int lwip_netdev_set_default(struct netdev *netif) +{ + netif_set_default((struct netif *)netif->user_data); + return ERR_OK; +} const struct netdev_ops lwip_netdev_ops = { @@ -277,6 +285,7 @@ const struct netdev_ops lwip_netdev_ops = NULL, #endif /* RT_LWIP_DHCP */ +#ifdef RT_USING_FINSH #ifdef RT_LWIP_USING_PING lwip_netdev_ping, #else @@ -286,6 +295,9 @@ const struct netdev_ops lwip_netdev_ops = #if defined (RT_LWIP_TCP) || defined (RT_LWIP_UDP) lwip_netdev_netstat, #endif /* RT_LWIP_TCP || RT_LWIP_UDP */ +#endif /* RT_USING_FINSH */ + + lwip_netdev_set_default, }; static int netdev_add(struct netif *lwip_netif) @@ -303,12 +315,6 @@ static int netdev_add(struct netif *lwip_netif) return -ERR_IF; } - netdev->flags = lwip_netif->flags; - netdev->mtu = lwip_netif->mtu; - netdev->ops = &lwip_netdev_ops; - netdev->hwaddr_len = lwip_netif->hwaddr_len; - rt_memcpy(netdev->hwaddr, lwip_netif->hwaddr, lwip_netif->hwaddr_len); - #ifdef SAL_USING_LWIP extern int sal_lwip_netdev_set_pf_info(struct netdev *netdev); /* set the lwIP network interface device protocol family information */ @@ -317,7 +323,17 @@ static int netdev_add(struct netif *lwip_netif) rt_strncpy(name, lwip_netif->name, LWIP_NETIF_NAME_LEN); result = netdev_register(netdev, name, (void *)lwip_netif); - + + /* Update netdev info after registered */ + netdev->flags = lwip_netif->flags; + netdev->mtu = lwip_netif->mtu; + netdev->ops = &lwip_netdev_ops; + netdev->hwaddr_len = lwip_netif->hwaddr_len; + rt_memcpy(netdev->hwaddr, lwip_netif->hwaddr, lwip_netif->hwaddr_len); + netdev->ip_addr = lwip_netif->ip_addr; + netdev->gw = lwip_netif->gw; + netdev->netmask = lwip_netif->netmask; + #ifdef RT_LWIP_DHCP netdev_low_level_set_dhcp_status(netdev, RT_TRUE); #endif @@ -325,6 +341,19 @@ static int netdev_add(struct netif *lwip_netif) return result; } +static void netdev_del(struct netif *lwip_netif) +{ + char name[LWIP_NETIF_NAME_LEN + 1]; + struct netdev *netdev; + + RT_ASSERT(lwip_netif); + + rt_strncpy(name, lwip_netif->name, LWIP_NETIF_NAME_LEN); + netdev = netdev_get_by_name(name); + netdev_unregister(netdev); + rt_free(netdev); +} + /* synchronize lwIP network interface device and network interface device flags */ static int netdev_flags_sync(struct netif *lwip_netif) { @@ -530,6 +559,25 @@ rt_err_t eth_device_init(struct eth_device * dev, const char *name) return eth_device_init_with_flag(dev, name, flags); } +void eth_device_deinit(struct eth_device *dev) +{ + struct netif* netif = dev->netif; + +#if LWIP_DHCP + dhcp_stop(netif); + dhcp_cleanup(netif); +#endif + netif_set_down(netif); + netif_remove(netif); +#ifdef RT_USING_NETDEV + netdev_del(netif); +#endif + rt_device_close(&(dev->parent)); + rt_device_unregister(&(dev->parent)); + rt_sem_detach(&(dev->tx_ack)); + rt_free(netif); +} + #ifndef LWIP_NO_RX_THREAD rt_err_t eth_device_ready(struct eth_device* dev) { @@ -707,8 +755,6 @@ int eth_system_device_init_private(void) return (int)result; } -#ifdef RT_USING_FINSH -#include <finsh.h> void set_if(char* netif_name, char* ip_addr, char* gw_addr, char* nm_addr) { ip4_addr_t *ip; @@ -754,6 +800,9 @@ void set_if(char* netif_name, char* ip_addr, char* gw_addr, char* nm_addr) netif_set_netmask(netif, ip); } } + +#ifdef RT_USING_FINSH +#include <finsh.h> FINSH_FUNCTION_EXPORT(set_if, set network interface address); #if LWIP_DNS diff --git a/components/net/lwip-2.1.0/src/arch/sys_arch.c b/components/net/lwip-2.1.0/src/arch/sys_arch.c index 17ebdfbacf..dc08715ecc 100644 --- a/components/net/lwip-2.1.0/src/arch/sys_arch.c +++ b/components/net/lwip-2.1.0/src/arch/sys_arch.c @@ -522,7 +522,7 @@ u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout) t = timeout / (1000/RT_TICK_PER_SECOND); } - ret = rt_mb_recv(*mbox, (rt_uint32_t *)msg, t); + ret = rt_mb_recv(*mbox, (rt_ubase_t *)msg, t); if(ret == -RT_ETIMEOUT) return SYS_ARCH_TIMEOUT; @@ -553,7 +553,7 @@ u32_t sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg) { int ret; - ret = rt_mb_recv(*mbox, (rt_uint32_t *)msg, 0); + ret = rt_mb_recv(*mbox, (rt_ubase_t *)msg, 0); if(ret == -RT_ETIMEOUT) return SYS_ARCH_TIMEOUT; diff --git a/components/net/lwip-2.1.0/src/core/dns.c b/components/net/lwip-2.1.0/src/core/dns.c index 5129b7f3bc..c688cb2205 100644 --- a/components/net/lwip-2.1.0/src/core/dns.c +++ b/components/net/lwip-2.1.0/src/core/dns.c @@ -367,13 +367,14 @@ dns_setserver(u8_t numdns, const ip_addr_t *dnsserver) dns_servers[numdns] = (*dnsserver); #ifdef RT_USING_NETDEV - extern struct netif *netif_default; + extern struct netif *netif_list; extern struct netdev *netdev_get_by_name(const char *name); extern void netdev_low_level_set_dns_server(struct netdev *netdev, uint8_t dns_num, const ip_addr_t *dns_server); + struct netif *netif = NULL; /* set network interface device DNS server address */ - if (netif_default) { - netdev_low_level_set_dns_server(netdev_get_by_name(netif_default->name), numdns, dnsserver); + for (netif = netif_list; netif != NULL; netif = netif->next) { + netdev_low_level_set_dns_server(netdev_get_by_name(netif->name), numdns, dnsserver); } #endif /* RT_USING_NETDEV */ } else { diff --git a/components/net/lwip-2.1.0/src/core/netif.c b/components/net/lwip-2.1.0/src/core/netif.c index 5b31c627e9..b2b4adf85b 100644 --- a/components/net/lwip-2.1.0/src/core/netif.c +++ b/components/net/lwip-2.1.0/src/core/netif.c @@ -491,7 +491,7 @@ netif_do_set_ipaddr(struct netif *netif, const ip4_addr_t *ipaddr, ip_addr_t *ol #ifdef RT_USING_NETDEV /* rt-thread sal network interface device set IP address operations */ - netdev_low_level_set_ipaddr(netdev_get_by_name(netif->name), (ip_addr_t *)ipaddr); + netdev_low_level_set_ipaddr(netdev_get_by_name(netif->name), &netif->ip_addr); #endif /* RT_USING_NETDEV */ return 1; /* address changed */ @@ -557,7 +557,7 @@ netif_do_set_netmask(struct netif *netif, const ip4_addr_t *netmask, ip_addr_t * #ifdef RT_USING_NETDEV /* rt-thread network interface device set netmask address */ - netdev_low_level_set_netmask(netdev_get_by_name(netif->name), (ip_addr_t *)netmask); + netdev_low_level_set_netmask(netdev_get_by_name(netif->name), &netif->netmask); #endif /* RT_USING_NETDEV */ return 1; /* netmask changed */ @@ -625,7 +625,7 @@ netif_do_set_gw(struct netif *netif, const ip4_addr_t *gw, ip_addr_t *old_gw) #ifdef RT_USING_NETDEV /* rt_thread network interface device set gateway address */ - netdev_low_level_set_gw(netdev_get_by_name(netif->name), (ip_addr_t *)gw); + netdev_low_level_set_gw(netdev_get_by_name(netif->name), &netif->gw); #endif /* RT_USING_NETDEV */ return 1; /* gateway changed */ @@ -1586,6 +1586,11 @@ netif_create_ip6_linklocal_address(struct netif *netif, u8_t from_mac_48bit) * zone field, so this should not create any compatibility problems. */ ip6_addr_assign_zone(ip_2_ip6(&netif->ip6_addr[0]), IP6_UNICAST, netif); +#ifdef RT_USING_NETDEV + /* rt-thread network interface device set ipv6 address */ + ip_addr_copy(netdev_get_by_name(netif->name)->ip6_addr[0], netif->ip6_addr[0]); +#endif /* RT_USING_NETDEV */ + /* Set address state. */ #if LWIP_IPV6_DUP_DETECT_ATTEMPTS /* Will perform duplicate address detection (DAD). */ @@ -1629,6 +1634,10 @@ netif_add_ip6_address(struct netif *netif, const ip6_addr_t *ip6addr, s8_t *chos for (i = ip6_addr_islinklocal(ip6addr) ? 0 : 1; i < LWIP_IPV6_NUM_ADDRESSES; i++) { if (ip6_addr_isinvalid(netif_ip6_addr_state(netif, i))) { ip_addr_copy_from_ip6(netif->ip6_addr[i], *ip6addr); +#ifdef RT_USING_NETDEV + /* rt-thread network interface device set ipv6 address */ + ip_addr_copy(netdev_get_by_name(netif->name)->ip6_addr[i], netif->ip6_addr[i]); +#endif /* RT_USING_NETDEV */ ip6_addr_assign_zone(ip_2_ip6(&netif->ip6_addr[i]), IP6_UNICAST, netif); netif_ip6_addr_set_state(netif, i, IP6_ADDR_TENTATIVE); if (chosen_idx != NULL) { diff --git a/components/net/lwip-2.1.0/src/include/netif/ethernetif.h b/components/net/lwip-2.1.0/src/include/netif/ethernetif.h index 1c969e6e25..244bafdd1b 100644 --- a/components/net/lwip-2.1.0/src/include/netif/ethernetif.h +++ b/components/net/lwip-2.1.0/src/include/netif/ethernetif.h @@ -41,6 +41,7 @@ extern "C" { rt_err_t eth_device_init(struct eth_device * dev, const char *name); rt_err_t eth_device_init_with_flag(struct eth_device *dev, const char *name, rt_uint16_t flag); rt_err_t eth_device_linkchange(struct eth_device* dev, rt_bool_t up); + void eth_device_deinit(struct eth_device *dev); int eth_system_device_init(void); diff --git a/components/net/lwip-2.1.0/src/netif/ethernetif.c b/components/net/lwip-2.1.0/src/netif/ethernetif.c index db28a4a55b..66ea1d2376 100644 --- a/components/net/lwip-2.1.0/src/netif/ethernetif.c +++ b/components/net/lwip-2.1.0/src/netif/ethernetif.c @@ -129,23 +129,23 @@ static int lwip_netdev_set_addr_info(struct netdev *netif, ip_addr_t *ip_addr, i { if (ip_addr && netmask && gw) { - netif_set_addr((struct netif *)netif->user_data, ip_addr, netmask, gw); + netif_set_addr((struct netif *)netif->user_data, ip_2_ip4(ip_addr), ip_2_ip4(netmask), ip_2_ip4(gw)); } else { if (ip_addr) { - netif_set_ipaddr((struct netif *)netif->user_data, ip_addr); + netif_set_ipaddr((struct netif *)netif->user_data, ip_2_ip4(ip_addr)); } if (netmask) { - netif_set_netmask((struct netif *)netif->user_data, netmask); + netif_set_netmask((struct netif *)netif->user_data, ip_2_ip4(netmask)); } if (gw) { - netif_set_gw((struct netif *)netif->user_data, gw); + netif_set_gw((struct netif *)netif->user_data, ip_2_ip4(gw)); } } @@ -155,8 +155,8 @@ static int lwip_netdev_set_addr_info(struct netdev *netif, ip_addr_t *ip_addr, i #ifdef RT_LWIP_DNS static int lwip_netdev_set_dns_server(struct netdev *netif, uint8_t dns_num, ip_addr_t *dns_server) { - extern void set_dns(uint8_t dns_num, char* dns_server); - set_dns(dns_num, ipaddr_ntoa(dns_server)); + extern void dns_setserver(uint8_t dns_num, const ip_addr_t *dns_server); + dns_setserver(dns_num, dns_server); return ERR_OK; } #endif /* RT_LWIP_DNS */ @@ -169,6 +169,7 @@ static int lwip_netdev_set_dhcp(struct netdev *netif, rt_bool_t is_enabled) } #endif /* RT_LWIP_DHCP */ +#ifdef RT_USING_FINSH #ifdef RT_LWIP_USING_PING extern int lwip_ping_recv(int s, int *ttl); extern err_t lwip_ping_send(int s, ip_addr_t *addr, int size); @@ -259,6 +260,13 @@ void lwip_netdev_netstat(struct netdev *netif) #endif } #endif /* RT_LWIP_TCP || RT_LWIP_UDP */ +#endif /* RT_USING_FINSH */ + +static int lwip_netdev_set_default(struct netdev *netif) +{ + netif_set_default((struct netif *)netif->user_data); + return ERR_OK; +} const struct netdev_ops lwip_netdev_ops = { @@ -278,6 +286,7 @@ const struct netdev_ops lwip_netdev_ops = NULL, #endif /* RT_LWIP_DHCP */ +#ifdef RT_USING_FINSH #ifdef RT_LWIP_USING_PING lwip_netdev_ping, #else @@ -287,6 +296,9 @@ const struct netdev_ops lwip_netdev_ops = #if defined (RT_LWIP_TCP) || defined (RT_LWIP_UDP) lwip_netdev_netstat, #endif /* RT_LWIP_TCP || RT_LWIP_UDP */ +#endif /* RT_USING_FINSH */ + + lwip_netdev_set_default, }; static int netdev_add(struct netif *lwip_netif) @@ -303,11 +315,6 @@ static int netdev_add(struct netif *lwip_netif) { return -ERR_IF; } - - netdev->flags = lwip_netif->flags; - netdev->ops = &lwip_netdev_ops; - netdev->hwaddr_len = lwip_netif->hwaddr_len; - rt_memcpy(netdev->hwaddr, lwip_netif->hwaddr, lwip_netif->hwaddr_len); #ifdef SAL_USING_LWIP extern int sal_lwip_netdev_set_pf_info(struct netdev *netdev); @@ -317,6 +324,16 @@ static int netdev_add(struct netif *lwip_netif) rt_strncpy(name, lwip_netif->name, LWIP_NETIF_NAME_LEN); result = netdev_register(netdev, name, (void *)lwip_netif); + + /* Update netdev info after registered */ + netdev->flags = lwip_netif->flags; + netdev->mtu = lwip_netif->mtu; + netdev->ops = &lwip_netdev_ops; + netdev->hwaddr_len = lwip_netif->hwaddr_len; + rt_memcpy(netdev->hwaddr, lwip_netif->hwaddr, lwip_netif->hwaddr_len); + netdev->ip_addr = lwip_netif->ip_addr; + netdev->gw = lwip_netif->gw; + netdev->netmask = lwip_netif->netmask; #ifdef RT_LWIP_DHCP netdev_low_level_set_dhcp_status(netdev, RT_TRUE); @@ -325,6 +342,19 @@ static int netdev_add(struct netif *lwip_netif) return result; } +static void netdev_del(struct netif *lwip_netif) +{ + char name[LWIP_NETIF_NAME_LEN + 1]; + struct netdev *netdev; + + RT_ASSERT(lwip_netif); + + rt_strncpy(name, lwip_netif->name, LWIP_NETIF_NAME_LEN); + netdev = netdev_get_by_name(name); + netdev_unregister(netdev); + rt_free(netdev); +} + /* synchronize lwIP network interface device and network interface device flags */ static int netdev_flags_sync(struct netif *lwip_netif) { @@ -534,6 +564,25 @@ rt_err_t eth_device_init(struct eth_device * dev, const char *name) return eth_device_init_with_flag(dev, name, flags); } +void eth_device_deinit(struct eth_device *dev) +{ + struct netif* netif = dev->netif; + +#if LWIP_DHCP + dhcp_stop(netif); + dhcp_cleanup(netif); +#endif + netif_set_down(netif); + netif_remove(netif); +#ifdef RT_USING_NETDEV + netdev_del(netif); +#endif + rt_device_close(&(dev->parent)); + rt_device_unregister(&(dev->parent)); + rt_sem_detach(&(dev->tx_ack)); + rt_free(netif); +} + #ifndef LWIP_NO_RX_THREAD rt_err_t eth_device_ready(struct eth_device* dev) { @@ -711,8 +760,6 @@ int eth_system_device_init_private(void) return (int)result; } -#ifdef RT_USING_FINSH -#include <finsh.h> void set_if(char* netif_name, char* ip_addr, char* gw_addr, char* nm_addr) { ip4_addr_t *ip; @@ -758,6 +805,9 @@ void set_if(char* netif_name, char* ip_addr, char* gw_addr, char* nm_addr) netif_set_netmask(netif, ip); } } + +#ifdef RT_USING_FINSH +#include <finsh.h> FINSH_FUNCTION_EXPORT(set_if, set network interface address); #if LWIP_DNS diff --git a/components/net/lwip-2.1.0/src/netif/lowpan6.c b/components/net/lwip-2.1.0/src/netif/lowpan6.c index 5769522d5e..6397b0cb5d 100644 --- a/components/net/lwip-2.1.0/src/netif/lowpan6.c +++ b/components/net/lwip-2.1.0/src/netif/lowpan6.c @@ -50,7 +50,7 @@ #include "netif/lowpan6.h" -#if LWIP_IPV6 +#if LWIP_IPV6 && LWIP_6LOWPAN #include "lwip/ip.h" #include "lwip/pbuf.h" diff --git a/components/net/lwip_dhcpd/SConscript b/components/net/lwip_dhcpd/SConscript index f7513cb0e3..16c673036a 100644 --- a/components/net/lwip_dhcpd/SConscript +++ b/components/net/lwip_dhcpd/SConscript @@ -2,7 +2,7 @@ from building import * cwd = GetCurrentDir() -if GetDepend('RT_USING_LWIP202'): +if GetDepend('RT_USING_LWIP202') or GetDepend('RT_USING_LWIP210') : src = ['dhcp_server_raw.c'] else: src = ['dhcp_server.c'] diff --git a/components/net/lwip_dhcpd/dhcp_server.c b/components/net/lwip_dhcpd/dhcp_server.c index c548ecfa98..93b4ad16f0 100644 --- a/components/net/lwip_dhcpd/dhcp_server.c +++ b/components/net/lwip_dhcpd/dhcp_server.c @@ -279,6 +279,7 @@ static void dhcpd_thread_entry(void *parameter) { /* bind failed. */ DEBUG_PRINTF("bind server address failed, errno=%d\n", errno); + closesocket(sock); rt_free(recv_data); return; } @@ -290,7 +291,13 @@ static void dhcpd_thread_entry(void *parameter) { bytes_read = recvfrom(sock, recv_data, BUFSZ - 1, 0, (struct sockaddr *)&client_addr, &addr_len); - if (bytes_read < DHCP_MSG_LEN) + if (bytes_read <= 0) + { + closesocket(sock); + rt_free(recv_data); + return; + } + else if (bytes_read < DHCP_MSG_LEN) { DEBUG_PRINTF("packet too short, wait for next!\n"); continue; @@ -546,4 +553,3 @@ void dhcpd_start(const char *netif_name) rt_thread_startup(thread); } } - diff --git a/components/net/lwip_dhcpd/dhcp_server.h b/components/net/lwip_dhcpd/dhcp_server.h index a8056540ec..ea68d6b8ec 100644 --- a/components/net/lwip_dhcpd/dhcp_server.h +++ b/components/net/lwip_dhcpd/dhcp_server.h @@ -44,6 +44,7 @@ extern "C" { #endif void dhcpd_start(const char *netif_name); +void dhcpd_stop(const char *netif_name); #ifdef __cplusplus } diff --git a/components/net/lwip_dhcpd/dhcp_server_raw.c b/components/net/lwip_dhcpd/dhcp_server_raw.c index 6b359eea4e..6c786301be 100644 --- a/components/net/lwip_dhcpd/dhcp_server_raw.c +++ b/components/net/lwip_dhcpd/dhcp_server_raw.c @@ -97,6 +97,10 @@ #define LWIP_NETIF_LOCK(...) #define LWIP_NETIF_UNLOCK(...) +#ifndef DHCP_SERVER_PORT +#define DHCP_SERVER_PORT 67 +#endif + /** * The dhcp client node struct. */ @@ -662,6 +666,7 @@ dhcp_server_start(struct netif *netif, ip4_addr_t *start, ip4_addr_t *end) return ERR_OK; } +extern void set_if(const char *netif_name, const char *ip_addr, const char *gw_addr, const char *nm_addr); void dhcpd_start(const char *netif_name) { @@ -697,8 +702,6 @@ void dhcpd_start(const char *netif_name) if (1) { - extern void set_if(const char *netif_name, const char *ip_addr, const char *gw_addr, const char *nm_addr); - dhcp_stop(netif); set_if(netif_name, DHCPD_SERVER_IP, "0.0.0.0", "255.255.255.0"); @@ -746,4 +749,83 @@ _exit: return; } +void dhcpd_stop(const char *netif_name) +{ + struct dhcp_server *dhcp_server, *server_node; + struct netif *netif = netif_list; + struct dhcp_client_node *node, *next; + + DEBUG_PRINTF("%s: %s\r\n", __FUNCTION__, netif_name); + + LWIP_NETIF_LOCK(); + if (strlen(netif_name) > sizeof(netif->name)) + { + DEBUG_PRINTF("network interface name too long!\r\n"); + goto _exit; + } + while (netif != RT_NULL) + { + if (strncmp(netif_name, netif->name, sizeof(netif->name)) == 0) + break; + + netif = netif->next; + if (netif == RT_NULL) + { + DEBUG_PRINTF("network interface: %s not found!\r\n", netif_name); + break; + } + } + + if (netif == RT_NULL) + { + goto _exit; + } + + /* If this netif alreday use the dhcp server. */ + for (dhcp_server = lw_dhcp_server; dhcp_server != NULL; dhcp_server = dhcp_server->next) + { + if (dhcp_server->netif == netif) + { + break; + } + } + if (dhcp_server == RT_NULL) + { + goto _exit; + } + + /* remove dhcp server */ + if (dhcp_server == lw_dhcp_server) + { + lw_dhcp_server = lw_dhcp_server->next; + } + else + { + server_node = lw_dhcp_server; + while (server_node->next && server_node->next != dhcp_server) + { + server_node = server_node->next; + } + if (server_node->next != RT_NULL) + { + server_node->next = server_node->next->next; + } + } + + udp_disconnect(dhcp_server->pcb); + udp_remove(dhcp_server->pcb); + + /* remove all client node */ + for (node = dhcp_server->node_list; node != NULL; node = next) + { + next = node->next; + mem_free(node); + } + + mem_free(dhcp_server); + set_if(netif_name, "0.0.0.0", "0.0.0.0", "0.0.0.0"); + +_exit: + LWIP_NETIF_UNLOCK(); +} diff --git a/components/net/netdev/include/netdev.h b/components/net/netdev/include/netdev.h index 0be2a2bda3..e11a8929b0 100644 --- a/components/net/netdev/include/netdev.h +++ b/components/net/netdev/include/netdev.h @@ -27,6 +27,13 @@ extern "C" { #define NETDEV_DNS_SERVERS_NUM 2U #endif +#if NETDEV_IPV6 +/* the maximum of dns server number supported */ +#ifndef NETDEV_IPV6_NUM_ADDRESSES +#define NETDEV_IPV6_NUM_ADDRESSES 3U +#endif +#endif /* NETDEV_IPV6 */ + /* whether the network interface device is 'up' (set by the network interface driver or application) */ #define NETDEV_FLAG_UP 0x01U /* if set, the network interface device has broadcast capability, only supported in the 'lwIP' stack */ @@ -78,6 +85,9 @@ struct netdev ip_addr_t ip_addr; /* IP address */ ip_addr_t netmask; /* subnet mask */ ip_addr_t gw; /* gateway */ +#if NETDEV_IPV6 + ip_addr_t ip6_addr[NETDEV_IPV6_NUM_ADDRESSES]; /* array of IPv6 addresses */ +#endif /* NETDEV_IPV6 */ ip_addr_t dns_servers[NETDEV_DNS_SERVERS_NUM]; /* DNS server */ uint8_t hwaddr_len; /* hardware address length */ uint8_t hwaddr[NETDEV_HWADDR_MAX_LEN]; /* hardware address */ @@ -122,10 +132,14 @@ struct netdev_ops int (*set_dns_server)(struct netdev *netdev, uint8_t dns_num, ip_addr_t *dns_server); int (*set_dhcp)(struct netdev *netdev, rt_bool_t is_enabled); +#ifdef RT_USING_FINSH /* set network interface device common network interface device operations */ int (*ping)(struct netdev *netdev, const char *host, size_t data_len, uint32_t timeout, struct netdev_ping_resp *ping_resp); void (*netstat)(struct netdev *netdev); +#endif + /* set default network interface device in current network stack*/ + int (*set_default)(struct netdev *netdev); }; /* The network interface device registered and unregistered*/ @@ -163,6 +177,7 @@ int netdev_set_dns_server(struct netdev *netdev, uint8_t dns_num, const ip_addr_ /* Set network interface device callback, it can be called when the status or address changed */ void netdev_set_status_callback(struct netdev *netdev, netdev_callback_fn status_callback); +void netdev_set_addr_callback(struct netdev *netdev, netdev_callback_fn addr_callback); /* Set network interface device status and address, this function can only be called in the network interface device driver */ void netdev_low_level_set_ipaddr(struct netdev *netdev, const ip_addr_t *ipaddr); diff --git a/components/net/netdev/include/netdev_ipaddr.h b/components/net/netdev/include/netdev_ipaddr.h index c2e13cd118..65970ec5b7 100644 --- a/components/net/netdev/include/netdev_ipaddr.h +++ b/components/net/netdev/include/netdev_ipaddr.h @@ -12,21 +12,53 @@ #define __NETDEV_IPADDR_H__ #include <stdint.h> +#include <rtconfig.h> #ifdef __cplusplus extern "C" { #endif -/* Only supports the IPV4 protocol */ -#ifndef NETDEV_IPV4 -#define NETDEV_IPV4 1 -#endif +/* + * Definitions of bits in internet address integers. + * On subnets, the decomposition of addresses to host and net parts + * is done according to subnet mask, not the masks here. + */ +#define IN_CLASSA(i) (((long)(i) & 0x80000000) == 0) +#define IN_CLASSA_NET 0xff000000 +#define IN_CLASSA_NSHIFT 24 +#define IN_CLASSA_HOST 0x00ffffff +#define IN_CLASSA_MAX 128 -#ifndef NETDEV_IPV6 -#define NETDEV_IPV6 0 -#endif +#define IN_CLASSB(i) (((long)(i) & 0xc0000000) == 0x80000000) +#define IN_CLASSB_NET 0xffff0000 +#define IN_CLASSB_NSHIFT 16 +#define IN_CLASSB_HOST 0x0000ffff +#define IN_CLASSB_MAX 65536 + +#define IN_CLASSC(i) (((long)(i) & 0xe0000000) == 0xc0000000) +#define IN_CLASSC_NET 0xffffff00 +#define IN_CLASSC_NSHIFT 8 +#define IN_CLASSC_HOST 0x000000ff + +#define IN_CLASSD(i) (((long)(i) & 0xf0000000) == 0xe0000000) +#define IN_MULTICAST(i) IN_CLASSD(i) -#ifdef NETDEV_IPV4 +#define IN_EXPERIMENTAL(i) (((long)(i) & 0xe0000000) == 0xe0000000) +#define IN_BADCLASS(i) (((long)(i) & 0xf0000000) == 0xf0000000) + +#define IN_LOOPBACKNET 127 /* official! */ + +/* IP address types for use in ip_addr_t.type member */ +enum netdev_ip_addr_type { + /** IPv4 */ + IPADDR_TYPE_V4 = 0U, + /** IPv6 */ + IPADDR_TYPE_V6 = 6U, + /** IPv4+IPv6 ("dual-stack") */ + IPADDR_TYPE_ANY = 46U +}; + +#if NETDEV_IPV4 /** IPv4 only: set the IP address given as an u32_t */ #define ip4_addr_set_u32(dest_ipaddr, src_u32) ((dest_ipaddr)->addr = (src_u32)) /** IPv4 only: get the IP address as an u32_t */ @@ -68,7 +100,42 @@ typedef struct ip4_addr uint32_t addr; } ip4_addr_t; -typedef ip4_addr_t ip_addr_t; +/** 255.255.255.255 */ +#define IPADDR_NONE ((uint32_t)0xffffffffUL) +/** 127.0.0.1 */ +#define IPADDR_LOOPBACK ((uint32_t)0x7f000001UL) +/** 0.0.0.0 */ +#define IPADDR_ANY ((uint32_t)0x00000000UL) +/** 255.255.255.255 */ +#define IPADDR_BROADCAST ((uint32_t)0xffffffffUL) + +/** 255.255.255.255 */ +#define INADDR_NONE IPADDR_NONE +/** 127.0.0.1 */ +#define INADDR_LOOPBACK IPADDR_LOOPBACK +/** 0.0.0.0 */ +#define INADDR_ANY IPADDR_ANY +/** 255.255.255.255 */ +#define INADDR_BROADCAST IPADDR_BROADCAST + +#define IPADDR_BROADCAST_STRING "255.255.255.255" + +/** Copy IP address - faster than ip4_addr_set: no NULL check */ +#define ip4_addr_copy(dest, src) ((dest).addr = (src).addr) +#define ip4_addr_cmp(addr1, addr2) ((addr1)->addr == (addr2)->addr) +/** Safely copy one IP address to another (src may be NULL) */ +#define ip4_addr_set(dest, src) ((dest)->addr = ((src) == NULL ? 0 : (src)->addr)) +/** Set complete address to zero */ +#define ip4_addr_set_zero(ipaddr) ((ipaddr)->addr = 0) +/** Set address to IPADDR_ANY (no need for htonl()) */ +#define ip4_addr_set_any(ipaddr) ((ipaddr)->addr = IPADDR_ANY) +#define ip4_addr_isany_val(ipaddr) ((ipaddr).addr == IPADDR_ANY) +#define ip4_addr_isany(ipaddr) ((ipaddr) == NULL || ip4_addr_isany_val(*(ipaddr))) + +in_addr_t netdev_ipaddr_addr(const char *cp); +int netdev_ip4addr_aton(const char *cp, ip4_addr_t *addr); +char *netdev_ip4addr_ntoa(const ip4_addr_t *addr); +char *netdev_ip4addr_ntoa_r(const ip4_addr_t *addr, char *buf, int buflen); #endif /* NETIF_IPV4 */ #if NETDEV_IPV6 @@ -85,23 +152,55 @@ struct in6_addr typedef struct ip6_addr { uint32_t addr[4]; +#ifdef NETDEV_IPV6_SCOPES + uint8_t zone; +#endif /* NETDEV_IPV6_SCOPES */ } ip6_addr_t; -typedef ip6_addr ip_addr_t +/** This macro can be used to initialize a variable of type struct in6_addr + to the IPv6 wildcard address. */ +#define IN6ADDR_ANY_INIT {{{0,0,0,0}}} +/** This macro can be used to initialize a variable of type struct in6_addr + to the IPv6 loopback address. */ +#define IN6ADDR_LOOPBACK_INIT {{{0,0,0,PP_HTONL(1)}}} + +/** This variable is initialized by the system to contain the wildcard IPv6 address. + */ +extern const struct in6_addr in6addr_any; + +#define ip6_addr_cmp(addr1, addr2) (((addr1)->addr[0] == (addr2)->addr[0]) && \ + ((addr1)->addr[1] == (addr2)->addr[1]) && \ + ((addr1)->addr[2] == (addr2)->addr[2]) && \ + ((addr1)->addr[3] == (addr2)->addr[3])) +/** Copy IPv6 address - faster than ip6_addr_set: no NULL check */ +#define ip6_addr_copy(dest, src) do{(dest).addr[0] = (src).addr[0]; \ + (dest).addr[1] = (src).addr[1]; \ + (dest).addr[2] = (src).addr[2]; \ + (dest).addr[3] = (src).addr[3];}while(0) +/** Safely copy one IPv6 address to another (src may be NULL) */ +#define ip6_addr_set(dest, src) do{(dest)->addr[0] = (src) == NULL ? 0 : (src)->addr[0]; \ + (dest)->addr[1] = (src) == NULL ? 0 : (src)->addr[1]; \ + (dest)->addr[2] = (src) == NULL ? 0 : (src)->addr[2]; \ + (dest)->addr[3] = (src) == NULL ? 0 : (src)->addr[3];}while(0) +/** Set complete address to zero */ +#define ip6_addr_set_zero(ip6addr) do{(ip6addr)->addr[0] = 0; \ + (ip6addr)->addr[1] = 0; \ + (ip6addr)->addr[2] = 0; \ + (ip6addr)->addr[3] = 0;}while(0) +/** Set address to ipv6 'any' (no need for lwip_htonl()) */ +#define ip6_addr_set_any(ip6addr) ip6_addr_set_zero(ip6addr) +#define ip6_addr_isany_val(ip6addr) (((ip6addr).addr[0] == 0) && \ + ((ip6addr).addr[1] == 0) && \ + ((ip6addr).addr[2] == 0) && \ + ((ip6addr).addr[3] == 0)) +#define ip6_addr_isany(ip6addr) (((ip6addr) == NULL) || ip6_addr_isany_val(*(ip6addr))) + +int netdev_ip6addr_aton(const char *cp, ip6_addr_t *addr); +char *netdev_ip6addr_ntoa(const ip6_addr_t *addr); +char *netdev_ip6addr_ntoa_r(const ip6_addr_t *addr, char *buf, int buflen); #endif /* NETIF_IPV6 */ #if NETDEV_IPV4 && NETDEV_IPV6 -/* IP address types for use in ip_addr_t.type member */ -enum netdev_ip_addr_type -{ - /** IPv4 */ - IPADDR_TYPE_V4 = 0U, - /** IPv6 */ - IPADDR_TYPE_V6 = 6U, - /** IPv4+IPv6 ("dual-stack") */ - IPADDR_TYPE_ANY = 46U -}; - /* A union struct for both IP version's addresses */ typedef struct _ip_addr { @@ -113,54 +212,102 @@ typedef struct _ip_addr /** @ref netdev_ip_addr_type */ uint8_t type; } ip_addr_t; -#endif /* NETIF_IPV4 && NETIF_IPV6 */ -/** 255.255.255.255 */ -#define IPADDR_NONE ((uint32_t)0xffffffffUL) -/** 127.0.0.1 */ -#define IPADDR_LOOPBACK ((uint32_t)0x7f000001UL) -/** 0.0.0.0 */ -#define IPADDR_ANY ((uint32_t)0x00000000UL) -/** 255.255.255.255 */ -#define IPADDR_BROADCAST ((uint32_t)0xffffffffUL) +#define IP_SET_TYPE_VAL(ipaddr, iptype) do { (ipaddr).type = (iptype); }while(0) +#define IP_SET_TYPE(ipaddr, iptype) do { if((ipaddr) != NULL) { IP_SET_TYPE_VAL(*(ipaddr), iptype); }}while(0) +#define IP_GET_TYPE(ipaddr) ((ipaddr)->type) -/** 255.255.255.255 */ -#define INADDR_NONE IPADDR_NONE -/** 127.0.0.1 */ -#define INADDR_LOOPBACK IPADDR_LOOPBACK -/** 0.0.0.0 */ -#define INADDR_ANY IPADDR_ANY -/** 255.255.255.255 */ -#define INADDR_BROADCAST IPADDR_BROADCAST +#define IP_IS_V4_VAL(ipaddr) (IP_GET_TYPE(&ipaddr) == IPADDR_TYPE_V4) +#define IP_IS_V6_VAL(ipaddr) (IP_GET_TYPE(&ipaddr) == IPADDR_TYPE_V6) +#define IP_IS_V4(ipaddr) (((ipaddr) == NULL) || IP_IS_V4_VAL(*(ipaddr))) +#define IP_IS_V6(ipaddr) (((ipaddr) != NULL) && IP_IS_V6_VAL(*(ipaddr))) -#define IPADDR_BROADCAST_STRING "255.255.255.255" +/** Convert generic ip address to specific protocol version */ +#define ip_2_ip6(ipaddr) (&((ipaddr)->u_addr.ip6)) +/** Convert generic ip address to specific protocol version */ +#define ip_2_ip4(ipaddr) (&((ipaddr)->u_addr.ip4)) -#ifdef NETDEV_IPV4 +#define ip_addr_copy(dest, src) do{ IP_SET_TYPE_VAL(dest, IP_GET_TYPE(&src)); if(IP_IS_V6_VAL(src)){ \ + ip6_addr_copy(*ip_2_ip6(&(dest)), *ip_2_ip6(&(src))); }else{ \ + ip4_addr_copy(*ip_2_ip4(&(dest)), *ip_2_ip4(&(src))); }}while(0) +#define ip_addr_cmp(addr1, addr2) ((IP_GET_TYPE(addr1) != IP_GET_TYPE(addr2)) ? 0 : (IP_IS_V6_VAL(*(addr1)) ? \ + ip6_addr_cmp(ip_2_ip6(addr1), ip_2_ip6(addr2)) : \ + ip4_addr_cmp(ip_2_ip4(addr1), ip_2_ip4(addr2)))) +#define ip_addr_set(dest, src) do{ IP_SET_TYPE(dest, IP_GET_TYPE(src)); if(IP_IS_V6(src)){ \ + ip6_addr_set(ip_2_ip6(dest), ip_2_ip6(src)); }else{ \ + ip4_addr_set(ip_2_ip4(dest), ip_2_ip4(src)); }}while(0) +#define ip_addr_set_zero(ipaddr) do{ ip6_addr_set_zero(ip_2_ip6(ipaddr)); IP_SET_TYPE(ipaddr, 0); }while(0) +#define ip_addr_set_any(is_ipv6, ipaddr) do{ if(is_ipv6){ \ + ip6_addr_set_any(ip_2_ip6(ipaddr)); IP_SET_TYPE(ipaddr, IPADDR_TYPE_V6); }else{ \ + ip4_addr_set_any(ip_2_ip4(ipaddr)); IP_SET_TYPE(ipaddr, IPADDR_TYPE_V4); }}while(0) -/** Copy IP address - faster than ip4_addr_set: no NULL check */ -#define ip4_addr_copy(dest, src) ((dest).addr = (src).addr) -#define ip4_addr_cmp(addr1, addr2) ((addr1)->addr == (addr2)->addr) -/** Set complete address to zero */ -#define ip4_addr_set_zero(ipaddr) ((ipaddr)->addr = 0) -#define ip4_addr_isany_val(ipaddr) ((ipaddr).addr == IPADDR_ANY) -#define ip4_addr_isany(ipaddr) ((ipaddr) == NULL || ip4_addr_isany_val(*(ipaddr))) +#define ip_addr_isany_val(ipaddr) ((IP_IS_V6_VAL(ipaddr)) ? \ + ip6_addr_isany_val(*ip_2_ip6(&(ipaddr))) : \ + ip4_addr_isany_val(*ip_2_ip4(&(ipaddr)))) +#define ip_addr_isany(ipaddr) ((IP_IS_V6(ipaddr)) ? \ + ip6_addr_isany(ip_2_ip6(ipaddr)) : \ + ip4_addr_isany(ip_2_ip4(ipaddr))) + +/* directly map this to the lwip internal functions */ +#define inet_addr(cp) netdev_ipaddr_addr(cp) +#define inet_aton(cp, addr) ((IP_IS_V6_VAL(*addr)) ? \ + netdev_ip6addr_aton(cp, ip_2_ip6(addr)) : \ + netdev_ip4addr_aton(cp, ip_2_ip4(addr))) +#define inet_ntoa(addr) ((IP_IS_V6_VAL(addr)) ? \ + netdev_ip6addr_ntoa(ip_2_ip6(&addr)) : \ + netdev_ip4addr_ntoa(ip_2_ip4(&addr))) +#define inet_ntoa_r(addr, buf, buflen) ((IP_IS_V6_VAL(addr)) ? \ + netdev_ip6addr_ntoa_r(ip_2_ip6(&addr), buf, buflen) : \ + netdev_ip4addr_ntoa_r(ip_2_ip4(&addr), buf, buflen)) +#elif NETDEV_IPV4 /* NETDEV_IPV4 */ + +typedef ip4_addr_t ip_addr_t; + +#define IP_SET_TYPE_VAL(ipaddr, iptype) +#define IP_SET_TYPE(ipaddr, iptype) +#define IP_GET_TYPE(ipaddr) IPADDR_TYPE_V4 #define ip_addr_copy(dest, src) ip4_addr_copy(dest, src) #define ip_addr_cmp(addr1, addr2) ip4_addr_cmp(addr1, addr2) +#define ip_addr_set(dest, src) ip4_addr_set(dest, src) #define ip_addr_set_zero(ipaddr) ip4_addr_set_zero(ipaddr) +#define ip_addr_set_any(is_ipv6, ipaddr) ip4_addr_set_any(ipaddr) +#define ip_addr_isany_val(ipaddr) ip4_addr_isany_val(ipaddr) #define ip_addr_isany(ipaddr) ip4_addr_isany(ipaddr) -in_addr_t netdev_ipaddr_addr(const char *cp); -int netdev_ip4addr_aton(const char *cp, ip4_addr_t *addr); -char *netdev_ip4addr_ntoa(const ip4_addr_t *addr); -char *netdev_ip4addr_ntoa_r(const ip4_addr_t *addr, char *buf, int buflen); - +/* directly map this to the lwip internal functions */ #define inet_addr(cp) netdev_ipaddr_addr(cp) #define inet_aton(cp, addr) netdev_ip4addr_aton(cp,(ip4_addr_t*)addr) #define inet_ntoa(addr) netdev_ip4addr_ntoa((const ip4_addr_t*)&(addr)) #define inet_ntoa_r(addr, buf, buflen) netdev_ip4addr_ntoa_r((const ip4_addr_t*)&(addr), buf, buflen) +#else /* NETDEV_IPV6 */ + +typedef ip6_addr_t ip_addr_t; + +#define IP_SET_TYPE_VAL(ipaddr, iptype) +#define IP_SET_TYPE(ipaddr, iptype) +#define IP_GET_TYPE(ipaddr) IPADDR_TYPE_V6 + +#define ip_addr_copy(dest, src) ip6_addr_copy(dest, src) +#define ip_addr_cmp(addr1, addr2) ip6_addr_cmp(addr1, addr2) +#define ip_addr_set(dest, src) ip6_addr_set(dest, src) +#define ip_addr_set_zero(ipaddr) ip6_addr_set_zero(ipaddr) +#define ip_addr_set_any(is_ipv6, ipaddr) ip6_addr_set_any(ipaddr) +#define ip_addr_isany_val(ipaddr) ip6_addr_isany_val(ipaddr) +#define ip_addr_isany(ipaddr) ip6_addr_isany(ipaddr) + +/* directly map this to the lwip internal functions */ +#define inet_aton(cp, addr) netdev_ip6addr_aton(cp, (ip6_addr_t*)addr) +#define inet_ntoa(addr) netdev_ip6addr_ntoa((const ip6_addr_t*)&(addr)) +#define inet_ntoa_r(addr, buf, buflen) netdev_ip6addr_ntoa_r((const ip6_addr_t*)&(addr), buf, buflen) +#endif /* NTDEV_IPV4 && NTDEV_IPV6 */ + + +const char *netdev_inet_ntop(int af, const void *src, char *dst, int32_t size); +int netdev_inet_pton(int af, const char *src, void *dst); -#endif /* NETDEV_IPV4 */ +#define inet_ntop(af, src, dst, size) netdev_inet_ntop(af, src, dst, size) +#define inet_pton(af, src, dst) netdev_inet_pton(af, src, dst) #ifdef __cplusplus } diff --git a/components/net/netdev/src/netdev.c b/components/net/netdev/src/netdev.c index 5f49a46f17..68e5364a9e 100644 --- a/components/net/netdev/src/netdev.c +++ b/components/net/netdev/src/netdev.c @@ -34,11 +34,11 @@ struct netdev *netdev_default; /** * This function will register network interface device and * add it to network interface device list. - * + * * @param netdev the network interface device object * @param name the network interface device name * @param user_data user-specific data - * + * * @return 0: registered successfully * -1: registered failed */ @@ -58,9 +58,21 @@ int netdev_register(struct netdev *netdev, const char *name, void *user_data) ip_addr_set_zero(&(netdev->ip_addr)); ip_addr_set_zero(&(netdev->netmask)); ip_addr_set_zero(&(netdev->gw)); + + IP_SET_TYPE_VAL(netdev->ip_addr, IPADDR_TYPE_V4); + IP_SET_TYPE_VAL(netdev->netmask, IPADDR_TYPE_V4); + IP_SET_TYPE_VAL(netdev->gw, IPADDR_TYPE_V4); +#if NETDEV_IPV6 + for (index = 0; index < NETDEV_IPV6_NUM_ADDRESSES; index++) + { + ip_addr_set_zero(&(netdev->ip6_addr[index])); + IP_SET_TYPE_VAL(netdev->ip_addr, IPADDR_TYPE_V6); + } +#endif /* NETDEV_IPV6 */ for (index = 0; index < NETDEV_DNS_SERVERS_NUM; index++) { ip_addr_set_zero(&(netdev->dns_servers[index])); + IP_SET_TYPE_VAL(netdev->ip_addr, IPADDR_TYPE_V4); } netdev->status_callback = RT_NULL; netdev->addr_callback = RT_NULL; @@ -87,15 +99,15 @@ int netdev_register(struct netdev *netdev, const char *name, void *user_data) rt_hw_interrupt_enable(level); - return RT_EOK; + return RT_EOK; } /** * This function will unregister network interface device and * delete it from network interface device list. - * + * * @param netdev the network interface device object - * + * * @return 0: unregistered successfully * -1: unregistered failed */ @@ -106,7 +118,7 @@ int netdev_unregister(struct netdev *netdev) struct netdev *cur_netdev = RT_NULL; RT_ASSERT(netdev); - + if (netdev_list == RT_NULL) { return -RT_ERROR; @@ -117,29 +129,46 @@ int netdev_unregister(struct netdev *netdev) for (node = &(netdev_list->list); node; node = rt_slist_next(node)) { cur_netdev = rt_slist_entry(node, struct netdev, list); - if (cur_netdev && (rt_memcpy(cur_netdev, netdev, sizeof(struct netdev)) == 0)) + if (cur_netdev == netdev) { - rt_slist_remove(&(netdev_list->list), &(cur_netdev->list)); - rt_hw_interrupt_enable(level); - - return RT_EOK; + /* find this network interface device in network interface device list */ + if (netdev_list == netdev && rt_slist_next(&netdev_list->list) == RT_NULL) + { + netdev_list = RT_NULL; + } + else + { + rt_slist_remove(&(netdev_list->list), &(cur_netdev->list)); + } + if (netdev_default == netdev) + { + netdev_default = netdev_list; + } + break; } } - rt_hw_interrupt_enable(level); - /* not find this network interface device in network interface device list */ + if (cur_netdev == netdev) + { +#ifdef RT_USING_SAL + extern int sal_netdev_cleanup(struct netdev *netdev); + sal_netdev_cleanup(netdev); +#endif + rt_memset(netdev, 0, sizeof(*netdev)); + } + return -RT_ERROR; } /** * This function will get the first network interface device * with the flags in network interface device list. - * + * * @param flags the network interface device flags - * + * * @return != NULL: network interface device object - * NULL: get failed + * NULL: get failed */ struct netdev *netdev_get_first_by_flags(uint16_t flags) { @@ -172,11 +201,11 @@ struct netdev *netdev_get_first_by_flags(uint16_t flags) /** * This function will get the first network interface device * in network interface device list by IP address. - * + * * @param addr the network interface device IP address - * + * * @return != NULL: network interface device object - * NULL: get failed + * NULL: get failed */ struct netdev *netdev_get_by_ipaddr(ip_addr_t *ip_addr) { @@ -209,11 +238,11 @@ struct netdev *netdev_get_by_ipaddr(ip_addr_t *ip_addr) /** * This function will get network interface device * in network interface device list by netdev name. - * + * * @param name the network interface device name - * + * * @return != NULL: network interface device object - * NULL: get failed + * NULL: get failed */ struct netdev *netdev_get_by_name(const char *name) { @@ -247,11 +276,11 @@ struct netdev *netdev_get_by_name(const char *name) /** * This function will get the first network interface device * in network interface device list by protocol family type. - * + * * @param family the network interface device protocol family type - * + * * @return != NULL: network interface device object - * NULL: get failed + * NULL: get failed */ struct netdev *netdev_get_by_family(int family) { @@ -296,15 +325,15 @@ struct netdev *netdev_get_by_family(int family) /** * This function will get the family type from network interface device - * + * * @param netdev network interface device object - * + * * @return the network interface device family type */ int netdev_family_get(struct netdev *netdev) { - RT_ASSERT(netdev); - + RT_ASSERT(netdev); + return ((struct sal_proto_family *)netdev->sal_user_data)->family; } @@ -312,7 +341,7 @@ int netdev_family_get(struct netdev *netdev) /** * This function will set default network interface device. - * + * * @param netdev the network interface device to change */ void netdev_set_default(struct netdev *netdev) @@ -320,15 +349,21 @@ void netdev_set_default(struct netdev *netdev) if (netdev) { netdev_default = netdev; - LOG_D("Setting default network interface device name(%s) successfully.", netdev->name); + + if (netdev->ops->set_default) + { + /* set default network interface device in the current network stack */ + netdev->ops->set_default(netdev); + } + LOG_D("Setting default network interface device name(%s) successfully.", netdev->name); } } /** * This function will enable network interface device . - * + * * @param netdev the network interface device to change - * + * * @return 0: set status successfully * -1: set status failed */ @@ -341,7 +376,7 @@ int netdev_set_up(struct netdev *netdev) LOG_E("The network interface device(%s) not support to set status.", netdev->name); return -RT_ERROR; } - + /* network interface device status flags check */ if (netdev_is_up(netdev)) { @@ -353,9 +388,9 @@ int netdev_set_up(struct netdev *netdev) } /** * This function will disable network interface device. - * + * * @param netdev the network interface device to change - * + * * @return 0: set status successfully * -1: set sttaus failed */ @@ -368,7 +403,7 @@ int netdev_set_down(struct netdev *netdev) LOG_E("The network interface device(%s) not support to set status.", netdev->name); return -RT_ERROR; } - + /* network interface device status flags check */ if (!netdev_is_up(netdev)) { @@ -381,10 +416,10 @@ int netdev_set_down(struct netdev *netdev) /** * This function will control network interface device DHCP capability enable or disable. - * + * * @param netdev the network interface device device to change * @param is_enable the new DHCP status - * + * * @return 0: set DHCP status successfully * -1: set DHCP status failed */ @@ -403,17 +438,17 @@ int netdev_dhcp_enabled(struct netdev *netdev, rt_bool_t is_enabled) { return RT_EOK; } - + /* execute network interface device DHCP capability control operations */ return netdev->ops->set_dhcp(netdev, is_enabled); } /** * This function will set network interface device IP address. - * + * * @param netdev the network interface device to change * @param ipaddr the new IP address - * + * * @return 0: set IP address successfully * -1: set IP address failed */ @@ -427,7 +462,7 @@ int netdev_set_ipaddr(struct netdev *netdev, const ip_addr_t *ip_addr) LOG_E("The network interface device(%s) not support to set IP address.", netdev->name); return -RT_ERROR; } - + if (netdev_is_dhcp_enabled(netdev)) { LOG_E("The network interface device(%s) DHCP capability is enable, not support set IP address.", netdev->name); @@ -440,10 +475,10 @@ int netdev_set_ipaddr(struct netdev *netdev, const ip_addr_t *ip_addr) /** * This function will set network interface device netmask address. - * + * * @param netdev the network interface device to change * @param netmask the new netmask address - * + * * @return 0: set netmask address successfully * -1: set netmask address failed */ @@ -457,7 +492,7 @@ int netdev_set_netmask(struct netdev *netdev, const ip_addr_t *netmask) LOG_E("The network interface device(%s) not support to set netmask address.", netdev->name); return -RT_ERROR; } - + if (netdev_is_dhcp_enabled(netdev)) { LOG_E("The network interface device(%s) DHCP capability is enable, not support set netmask address.", netdev->name); @@ -470,10 +505,10 @@ int netdev_set_netmask(struct netdev *netdev, const ip_addr_t *netmask) /** * This function will set network interface device gateway address. - * + * * @param netdev the network interface device to change - * @param gateway the new gateway address - * + * @param gateway the new gateway address + * * @return 0: set gateway address successfully * -1: set gateway address failed */ @@ -487,7 +522,7 @@ int netdev_set_gw(struct netdev *netdev, const ip_addr_t *gw) LOG_E("The network interface device(%s) not support to set gateway address.", netdev->name); return -RT_ERROR; } - + if (netdev_is_dhcp_enabled(netdev)) { LOG_E("The network interface device(%s) DHCP capability is enable, not support set gateway address.", netdev->name); @@ -500,10 +535,10 @@ int netdev_set_gw(struct netdev *netdev, const ip_addr_t *gw) /** * This function will set network interface device DNS server address. - * + * * @param netdev the network interface device to change * @param dns_server the new DNS server address - * + * * @return 0: set netmask address successfully * -1: set netmask address failed */ @@ -530,7 +565,7 @@ int netdev_set_dns_server(struct netdev *netdev, uint8_t dns_num, const ip_addr_ /** * This function will set callback to be called when the network interface device status has been changed. - * + * * @param netdev the network interface device to change * @param status_callback the callback be called when the status has been changed. */ @@ -544,7 +579,7 @@ void netdev_set_status_callback(struct netdev *netdev, netdev_callback_fn status /** * This function will set callback to be called when the network interface device address has been changed. - * + * * @param netdev the network interface device to change * @param addr_callback the callback be called when the address has been changed. */ @@ -560,7 +595,7 @@ void netdev_set_addr_callback(struct netdev *netdev, netdev_callback_fn addr_cal /** * This function will set network interface device IP address. * @NOTE it can only be called in the network interface device driver. - * + * * @param netdev the network interface device to change * @param ipaddr the new IP address */ @@ -591,7 +626,7 @@ void netdev_low_level_set_ipaddr(struct netdev *netdev, const ip_addr_t *ip_addr /** * This function will set network interface device netmask address. * @NOTE it can only be called in the network interface device driver. - * + * * @param netdev the network interface device to change * @param netmask the new netmask address */ @@ -605,7 +640,7 @@ void netdev_low_level_set_netmask(struct netdev *netdev, const ip_addr_t *netmas #ifdef RT_USING_SAL /* set network interface device flags to internet up */ - if (netdev_is_up(netdev) && netdev_is_link_up(netdev) && + if (netdev_is_up(netdev) && netdev_is_link_up(netdev) && !ip_addr_isany(&(netdev->ip_addr))) { sal_check_netdev_internet_up(netdev); @@ -623,7 +658,7 @@ void netdev_low_level_set_netmask(struct netdev *netdev, const ip_addr_t *netmas /** * This function will set network interface device gateway address. * @NOTE it can only be called in the network interface device driver. - * + * * @param netdev the network interface device to change * @param gateway the new gateway address */ @@ -637,7 +672,7 @@ void netdev_low_level_set_gw(struct netdev *netdev, const ip_addr_t *gw) #ifdef RT_USING_SAL /* set network interface device flags to internet up */ - if (netdev_is_up(netdev) && netdev_is_link_up(netdev) && + if (netdev_is_up(netdev) && netdev_is_link_up(netdev) && !ip_addr_isany(&(netdev->ip_addr))) { sal_check_netdev_internet_up(netdev); @@ -655,10 +690,10 @@ void netdev_low_level_set_gw(struct netdev *netdev, const ip_addr_t *gw) /** * This function will set network interface device DNS server address. * @NOTE it can only be called in the network interface device driver. - * + * * @param netdev the network interface device to change * @param dns_server the new DNS server address - * + * */ void netdev_low_level_set_dns_server(struct netdev *netdev, uint8_t dns_num, const ip_addr_t *dns_server) { @@ -666,6 +701,10 @@ void netdev_low_level_set_dns_server(struct netdev *netdev, uint8_t dns_num, con RT_ASSERT(dns_server); + if (netdev == RT_NULL) + { + return; + } /* check DNS servers is exist */ for (index = 0; index < NETDEV_DNS_SERVERS_NUM; index++) { @@ -675,7 +714,7 @@ void netdev_low_level_set_dns_server(struct netdev *netdev, uint8_t dns_num, con } } - if (netdev && dns_num < NETDEV_DNS_SERVERS_NUM) + if (dns_num < NETDEV_DNS_SERVERS_NUM) { ip_addr_copy(netdev->dns_servers[dns_num], *dns_server); @@ -707,7 +746,7 @@ static void netdev_auto_change_default(struct netdev *netdev) /** * This function will set network interface device status. * @NOTE it can only be called in the network interface device driver. - * + * * @param netdev the network interface device to change * @param is_up the new status */ @@ -740,14 +779,14 @@ void netdev_low_level_set_status(struct netdev *netdev, rt_bool_t is_up) /** * This function will set network interface device active link status. * @NOTE it can only be called in the network interface device driver. - * + * * @param netdev the network interface device to change * @param is_up the new link status */ void netdev_low_level_set_link_status(struct netdev *netdev, rt_bool_t is_up) { if (netdev && netdev_is_link_up(netdev) != is_up) - { + { if (is_up) { netdev->flags |= NETDEV_FLAG_LINK_UP; @@ -763,7 +802,7 @@ void netdev_low_level_set_link_status(struct netdev *netdev, rt_bool_t is_up) else { netdev->flags &= ~NETDEV_FLAG_LINK_UP; - + /* set network interface device flags to internet down */ netdev->flags &= ~NETDEV_FLAG_INTERNET_UP; @@ -784,7 +823,7 @@ void netdev_low_level_set_link_status(struct netdev *netdev, rt_bool_t is_up) /** * This function will set network interface device DHCP status. * @NOTE it can only be called in the network interface device driver. - * + * * @param netdev the network interface device to change * @param is_up the new DHCP status */ @@ -809,7 +848,7 @@ void netdev_low_level_set_dhcp_status(struct netdev *netdev, rt_bool_t is_enable } } -#ifdef FINSH_USING_MSH +#ifdef RT_USING_FINSH #include <finsh.h> @@ -820,7 +859,6 @@ static void netdev_list_if(void) #define NETDEV_IFCONFIG_IEMI_MAX_LEN 8 rt_ubase_t index; - rt_base_t level; rt_slist_t *node = RT_NULL; struct netdev *netdev = RT_NULL; struct netdev *cur_netdev_list = netdev_list; @@ -831,15 +869,13 @@ static void netdev_list_if(void) return; } - level = rt_hw_interrupt_disable(); - for (node = &(cur_netdev_list->list); node; node = rt_slist_next(node)) { netdev = rt_list_entry(node, struct netdev, list); - rt_kprintf("network interface device: %s%s\n", - netdev->name, - (netdev == netdev_default)?" (Default)":""); + rt_kprintf("network interface device: %.*s%s\n", + RT_NAME_MAX, netdev->name, + (netdev == netdev_default) ? " (Default)" : ""); rt_kprintf("MTU: %d\n", netdev->mtu); /* 6 - MAC address, 8 - IEMI */ @@ -853,13 +889,13 @@ static void netdev_list_if(void) } else if (netdev->hwaddr_len == NETDEV_IFCONFIG_IEMI_MAX_LEN) { - rt_kprintf("IEMI: "); + rt_kprintf("IMEI: "); for (index = 0; index < netdev->hwaddr_len; index++) { /* two numbers are displayed at one time*/ if (netdev->hwaddr[index] < 10 && index != netdev->hwaddr_len - 1) rt_kprintf("0"); - + rt_kprintf("%d", netdev->hwaddr[index]); } } @@ -881,18 +917,38 @@ static void netdev_list_if(void) rt_kprintf("gw address: %s\n", inet_ntoa(netdev->gw)); rt_kprintf("net mask : %s\n", inet_ntoa(netdev->netmask)); +#if NETDEV_IPV6 + { + ip_addr_t *addr; + int i; + + addr = &netdev->ip6_addr[0]; + + if (!ip_addr_isany(addr)) + { + rt_kprintf("ipv6 link-local: %s %s\n", inet_ntoa(*addr), + !ip_addr_isany(addr) ? "VALID" : "INVALID"); + + for (i = 1; i < NETDEV_IPV6_NUM_ADDRESSES; i++) + { + addr = &netdev->ip6_addr[i]; + rt_kprintf("ipv6[%d] address: %s %s\n", i, inet_ntoa(*addr), + !ip_addr_isany(addr) ? "VALID" : "INVALID"); + } + } + } +#endif /* NETDEV_IPV6 */ + for (index = 0; index < NETDEV_DNS_SERVERS_NUM; index++) { rt_kprintf("dns server #%d: %s\n", index, inet_ntoa(netdev->dns_servers[index])); } - + if (rt_slist_next(node)) { rt_kprintf("\n"); } } - - rt_hw_interrupt_enable(level); } static void netdev_set_if(char* netdev_name, char* ip_addr, char* gw_addr, char* nm_addr) @@ -951,7 +1007,7 @@ FINSH_FUNCTION_EXPORT_ALIAS(netdev_ifconfig, __cmd_ifconfig, list the informatio #endif /* NETDEV_USING_IFCONFIG */ #ifdef NETDEV_USING_PING -static int netdev_cmd_ping(char* target_name, rt_uint32_t times, rt_size_t size) +int netdev_cmd_ping(char* target_name, rt_uint32_t times, rt_size_t size) { #define NETDEV_PING_DATA_SIZE 32 /** ping receive timeout - in milliseconds */ @@ -966,7 +1022,7 @@ static int netdev_cmd_ping(char* target_name, rt_uint32_t times, rt_size_t size) struct netdev *netdev = RT_NULL; struct netdev_ping_resp ping_resp; int index, ret = 0; - + if (size == 0) { size = NETDEV_PING_DATA_SIZE; @@ -981,20 +1037,34 @@ static int netdev_cmd_ping(char* target_name, rt_uint32_t times, rt_size_t size) { /* using first internet up status network interface device */ netdev = netdev_get_first_by_flags(NETDEV_FLAG_LINK_UP); - if (netdev == RT_NULL || NETDEV_PING_IS_COMMONICABLE(netdev) == 0) + if (netdev == RT_NULL) + { + rt_kprintf("ping: not found available network interface device.\n"); + return -RT_ERROR; + } + else if (netdev->ops == RT_NULL || netdev->ops->ping == RT_NULL) + { + rt_kprintf("ping: network interface device(%s) not support ping feature.\n", netdev->name); + return -RT_ERROR; + } + else if (!netdev_is_up(netdev) || !netdev_is_link_up(netdev)) { - rt_kprintf("ping: network interface device get error.\n"); + rt_kprintf("ping: network interface device(%s) status error.\n", netdev->name); return -RT_ERROR; } } for (index = 0; index < times; index++) { + int delay_tick = 0; + rt_tick_t start_tick = 0; + rt_memset(&ping_resp, 0x00, sizeof(struct netdev_ping_resp)); + start_tick = rt_tick_get(); ret = netdev->ops->ping(netdev, (const char *)target_name, size, NETDEV_PING_RECV_TIMEO, &ping_resp); if (ret == -RT_ETIMEOUT) { - rt_kprintf("ping: from %s icmp_seq=%d timeout\n", + rt_kprintf("ping: from %s icmp_seq=%d timeout\n", (ip_addr_isany(&(ping_resp.ip_addr))) ? target_name : inet_ntoa(ping_resp.ip_addr), index); } else if (ret == -RT_ERROR) @@ -1007,17 +1077,19 @@ static int netdev_cmd_ping(char* target_name, rt_uint32_t times, rt_size_t size) { if (ping_resp.ttl == 0) { - rt_kprintf("%d bytes from %s icmp_seq=%d time=%d ms\n", + rt_kprintf("%d bytes from %s icmp_seq=%d time=%d ms\n", ping_resp.data_len, inet_ntoa(ping_resp.ip_addr), index, ping_resp.ticks); } else { - rt_kprintf("%d bytes from %s icmp_seq=%d ttl=%d time=%d ms\n", + rt_kprintf("%d bytes from %s icmp_seq=%d ttl=%d time=%d ms\n", ping_resp.data_len, inet_ntoa(ping_resp.ip_addr), index, ping_resp.ttl, ping_resp.ticks); } } - - rt_thread_mdelay(NETDEV_PING_DELAY); + + /* if the response time is more than NETDEV_PING_DELAY, no nead to delay */ + delay_tick = ((rt_tick_get() - start_tick) > NETDEV_PING_DELAY) || (index == times) ? 0 : NETDEV_PING_DELAY; + rt_thread_delay(delay_tick); } return RT_EOK; @@ -1041,33 +1113,28 @@ FINSH_FUNCTION_EXPORT_ALIAS(netdev_ping, __cmd_ping, ping network host); static void netdev_list_dns(void) { - rt_base_t level; int index = 0; struct netdev *netdev = RT_NULL; rt_slist_t *node = RT_NULL; - level = rt_hw_interrupt_disable(); - for (node = &(netdev_list->list); node; node = rt_slist_next(node)) { netdev = rt_list_entry(node, struct netdev, list); - rt_kprintf("network interface device: %s%s\n", - netdev->name, + rt_kprintf("network interface device: %.*s%s\n", + RT_NAME_MAX, netdev->name, (netdev == netdev_default)?" (Default)":""); for(index = 0; index < NETDEV_DNS_SERVERS_NUM; index++) { rt_kprintf("dns server #%d: %s\n", index, inet_ntoa(netdev->dns_servers[index])); } - + if (rt_slist_next(node)) { rt_kprintf("\n"); } } - - rt_hw_interrupt_enable(level); } static void netdev_set_dns(char *netdev_name, uint8_t dns_num, char *dns_server) @@ -1083,9 +1150,10 @@ static void netdev_set_dns(char *netdev_name, uint8_t dns_num, char *dns_server) } inet_aton(dns_server, &dns_addr); - netdev_set_dns_server(netdev, dns_num, &dns_addr); - - rt_kprintf("set network interface device(%s) dns server #0: %s\n", netdev_name, dns_server); + if (netdev_set_dns_server(netdev, dns_num, &dns_addr) == RT_EOK) + { + rt_kprintf("set network interface device(%s) dns server #%d: %s\n", netdev_name, dns_num, dns_server); + } } int netdev_dns(int argc, char **argv) @@ -1115,7 +1183,6 @@ FINSH_FUNCTION_EXPORT_ALIAS(netdev_dns, __cmd_dns, list and set the information #ifdef NETDEV_USING_NETSTAT static void netdev_cmd_netstat(void) { - rt_base_t level; rt_slist_t *node = RT_NULL; struct netdev *netdev = RT_NULL; struct netdev *cur_netdev_list = netdev_list; @@ -1126,8 +1193,6 @@ static void netdev_cmd_netstat(void) return; } - level = rt_hw_interrupt_disable(); - for (node = &(cur_netdev_list->list); node; node = rt_slist_next(node)) { netdev = rt_list_entry(node, struct netdev, list); @@ -1138,9 +1203,14 @@ static void netdev_cmd_netstat(void) } } - rt_hw_interrupt_enable(level); - - netdev->ops->netstat(netdev); + if (netdev->ops->netstat != RT_NULL) + { + netdev->ops->netstat(netdev); + } + else + { + rt_kprintf("netstat: this command is not supported!\n"); + } } int netdev_netstat(int argc, char **argv) @@ -1149,7 +1219,7 @@ int netdev_netstat(int argc, char **argv) { rt_kprintf("Please input: netstat \n"); } - else + else { netdev_cmd_netstat(); } @@ -1159,4 +1229,4 @@ int netdev_netstat(int argc, char **argv) FINSH_FUNCTION_EXPORT_ALIAS(netdev_netstat, __cmd_netstat, list the information of TCP / IP); #endif /* NETDEV_USING_NETSTAT */ -#endif /* FINSH_USING_MSH */ +#endif /* RT_USING_FINSH */ diff --git a/components/net/netdev/src/netdev_ipaddr.c b/components/net/netdev/src/netdev_ipaddr.c index 988bd50eb7..8d83937da9 100644 --- a/components/net/netdev/src/netdev_ipaddr.c +++ b/components/net/netdev/src/netdev_ipaddr.c @@ -19,8 +19,10 @@ #define isxdigit(c) (isdigit(c) || in_range(c, 'a', 'f') || in_range(c, 'A', 'F')) #define islower(c) in_range(c, 'a', 'z') #define isspace(c) (c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v') +#define xchar(i) ((i) < 10 ? '0' + (i) : 'A' + (i) - 10) #endif +#if NETDEV_IPV4 /** * Check whether "cp" is a valid ascii representation @@ -255,3 +257,358 @@ in_addr_t netdev_ipaddr_addr(const char *cp) } return (IPADDR_NONE); } + +#endif /* NETDEV_IPV4 */ + + +#if NETDEV_IPV6 + +RT_WEAK const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT; + +/** + * Check whether "cp" is a valid ascii representation + * of an IPv6 address and convert to a binary address. + * Returns 1 if the address is valid, 0 if not. + * + * @param cp IPv6 address in ascii representation (e.g. "FF01::1") + * @param addr pointer to which to save the ip address in network order + * @return 1 if cp could be converted to addr, 0 on failure + */ +int +netdev_ip6addr_aton(const char *cp, ip6_addr_t *addr) +{ + uint32_t addr_index, zero_blocks, current_block_index, current_block_value; + const char *s; + + /* Count the number of colons, to count the number of blocks in a "::" sequence + zero_blocks may be 1 even if there are no :: sequences */ + zero_blocks = 8; + for (s = cp; *s != 0; s++) + { + if (*s == ':') + { + zero_blocks--; + } + else if (!isxdigit(*s)) + { + break; + } + } + + /* parse each block */ + addr_index = 0; + current_block_index = 0; + current_block_value = 0; + for (s = cp; *s != 0; s++) + { + if (*s == ':') + { + if (addr) + { + if (current_block_index & 0x1) + { + addr->addr[addr_index++] |= current_block_value; + } + else + { + addr->addr[addr_index] = current_block_value << 16; + } + } + current_block_index++; + current_block_value = 0; + if (current_block_index > 7) + { + /* address too long! */ + return 0; + } + if (s[1] == ':') + { + if (s[2] == ':') + { + /* invalid format: three successive colons */ + return 0; + } + s++; + /* "::" found, set zeros */ + while (zero_blocks > 0) + { + zero_blocks--; + if (current_block_index & 0x1) + { + addr_index++; + } + else + { + if (addr) + { + addr->addr[addr_index] = 0; + } + } + current_block_index++; + if (current_block_index > 7) + { + /* address too long! */ + return 0; + } + } + } + } + else if (isxdigit(*s)) + { + /* add current digit */ + current_block_value = (current_block_value << 4) + + (isdigit(*s) ? (uint32_t)(*s - '0') : (uint32_t)(10 + (islower(*s) ? *s - 'a' : *s - 'A'))); + } + else + { + /* unexpected digit, space? CRLF? */ + break; + } + } + + if (addr) + { + if (current_block_index & 0x1) + { + addr->addr[addr_index++] |= current_block_value; + } + else + { + addr->addr[addr_index] = current_block_value << 16; + } + } + + /* convert to network byte order. */ + if (addr) + { + for (addr_index = 0; addr_index < 4; addr_index++) + { + addr->addr[addr_index] = htonl(addr->addr[addr_index]); + } + } + + if (current_block_index != 7) + { + return 0; + } + + return 1; +} + +/** + * Same as ipaddr_ntoa, but reentrant since a user-supplied buffer is used. + * + * @param addr ip6 address in network order to convert + * @param buf target buffer where the string is stored + * @param buflen length of buf + * @return either pointer to buf which now holds the ASCII + * representation of addr or NULL if buf was too small + */ +char * +netdev_ip6addr_ntoa_r(const ip6_addr_t *addr, char *buf, int buflen) +{ + uint32_t current_block_index, current_block_value, next_block_value; + int32_t i; + uint8_t zero_flag, empty_block_flag; + + i = 0; + empty_block_flag = 0; /* used to indicate a zero chain for "::' */ + + for (current_block_index = 0; current_block_index < 8; current_block_index++) + { + /* get the current 16-bit block */ + current_block_value = htonl(addr->addr[current_block_index >> 1]); + if ((current_block_index & 0x1) == 0) + { + current_block_value = current_block_value >> 16; + } + current_block_value &= 0xffff; + + /* Check for empty block. */ + if (current_block_value == 0) + { + if (current_block_index == 7 && empty_block_flag == 1) + { + /* special case, we must render a ':' for the last block. */ + buf[i++] = ':'; + if (i >= buflen) + { + return NULL; + } + break; + } + if (empty_block_flag == 0) + { + /* generate empty block "::", but only if more than one contiguous zero block, + * according to current formatting suggestions RFC 5952. */ + next_block_value = htonl(addr->addr[(current_block_index + 1) >> 1]); + if ((current_block_index & 0x1) == 0x01) + { + next_block_value = next_block_value >> 16; + } + next_block_value &= 0xffff; + if (next_block_value == 0) + { + empty_block_flag = 1; + buf[i++] = ':'; + if (i >= buflen) + { + return NULL; + } + continue; /* move on to next block. */ + } + } + else if (empty_block_flag == 1) + { + /* move on to next block. */ + continue; + } + } + else if (empty_block_flag == 1) + { + /* Set this flag value so we don't produce multiple empty blocks. */ + empty_block_flag = 2; + } + + if (current_block_index > 0) + { + buf[i++] = ':'; + if (i >= buflen) + { + return NULL; + } + } + + if ((current_block_value & 0xf000) == 0) + { + zero_flag = 1; + } + else + { + buf[i++] = xchar(((current_block_value & 0xf000) >> 12)); + zero_flag = 0; + if (i >= buflen) + { + return NULL; + } + } + + if (((current_block_value & 0xf00) == 0) && (zero_flag)) + { + /* do nothing */ + } + else + { + buf[i++] = xchar(((current_block_value & 0xf00) >> 8)); + zero_flag = 0; + if (i >= buflen) + { + return NULL; + } + } + + if (((current_block_value & 0xf0) == 0) && (zero_flag)) + { + /* do nothing */ + } + else + { + buf[i++] = xchar(((current_block_value & 0xf0) >> 4)); + zero_flag = 0; + if (i >= buflen) + { + return NULL; + } + } + + buf[i++] = xchar((current_block_value & 0xf)); + if (i >= buflen) + { + return NULL; + } + } + + buf[i] = 0; + + return buf; +} + +/** + * Convert numeric IPv6 address into ASCII representation. + * returns ptr to static buffer; not reentrant! + * + * @param addr ip6 address in network order to convert + * @return pointer to a global static (!) buffer that holds the ASCII + * representation of addr + */ +char * +netdev_ip6addr_ntoa(const ip6_addr_t *addr) +{ + static char str[40]; + return netdev_ip6addr_ntoa_r(addr, str, 40); +} + +#endif /* NETDEV_IPV6 */ + +const char * +netdev_inet_ntop(int af, const void *src, char *dst, int32_t size) +{ +#define AF_INET 2 +#define AF_INET6 10 + + const char *ret = NULL; + int size_int = (int)size; + if (size_int < 0) + { + return NULL; + } + switch (af) + { +#if NTEDEV_IPV4 + case AF_INET: + return netdev_ip4addr_ntoa_r((const ip4_addr_t *)src, dst, size_int); +#endif +#if NETDEV_IPV6 + case AF_INET6: + return netdev_ip6addr_ntoa_r((const ip6_addr_t *)src, dst, size_int); +#endif + default: + break; + } + return ret; +} + +int +netdev_inet_pton(int af, const char *src, void *dst) +{ +#define AF_INET 2 +#define AF_INET6 10 + + int err; + switch (af) + { +#if NETDEV_IPV4 + case AF_INET: + err = netdev_ip4addr_aton(src, (ip4_addr_t *)dst); + break; +#endif +#if NETDEV_IPV6 + case AF_INET6: + { + /* convert into temporary variable since ip6_addr_t might be larger + than in6_addr when scopes are enabled */ + ip6_addr_t addr; + err = netdev_ip6addr_aton(src, &addr); + if (err) + { + rt_memcpy(dst, &addr.addr, sizeof(addr.addr)); + } + break; + } +#endif + default: + err = -1; + break; + } + return err; +} diff --git a/components/net/sal_socket/impl/af_inet_lwip.c b/components/net/sal_socket/impl/af_inet_lwip.c index 95e7633635..56df735ab9 100644 --- a/components/net/sal_socket/impl/af_inet_lwip.c +++ b/components/net/sal_socket/impl/af_inet_lwip.c @@ -25,6 +25,12 @@ #include <netdev.h> +#if (LWIP_VERSION < 0x2000000) && NETDEV_IPV6 +#error "The lwIP version is not support IPV6, please disable netdev IPV6 configuration " +#elif (LWIP_VERSION > 0x2000000) && (NETDEV_IPV6 != LWIP_IPV6) +#error "IPV6 configuration error, Please check and synchronize netdev and lwip IPV6 configuration." +#endif + #if LWIP_VERSION < 0x2000000 #define SELWAIT_T int #else @@ -267,6 +273,8 @@ static int inet_poll(struct dfs_fd *file, struct rt_pollreq *req) if (sock->errevent) { mask |= POLLERR; + /* clean error event */ + sock->errevent = 0; } rt_hw_interrupt_enable(level); } @@ -308,7 +316,11 @@ static const struct sal_netdb_ops lwip_netdb_ops = static const struct sal_proto_family lwip_inet_family = { AF_INET, +#if LWIP_VERSION > 0x2000000 + AF_INET6, +#else AF_INET, +#endif &lwip_socket_ops, &lwip_netdb_ops, }; diff --git a/components/net/sal_socket/include/sal_socket.h b/components/net/sal_socket/include/sal_socket.h index d72f1e4c3c..b620bbe23c 100644 --- a/components/net/sal_socket/include/sal_socket.h +++ b/components/net/sal_socket/include/sal_socket.h @@ -157,6 +157,7 @@ struct sockaddr char sa_data[14]; }; +#if NETDEV_IPV4 /* members are in network byte order */ struct sockaddr_in { @@ -167,6 +168,19 @@ struct sockaddr_in #define SIN_ZERO_LEN 8 char sin_zero[SIN_ZERO_LEN]; }; +#endif /* NETDEV_IPV4 */ + +#if NETDEV_IPV6 +struct sockaddr_in6 +{ + uint8_t sin6_len; /* length of this structure */ + sa_family_t sin6_family; /* AF_INET6 */ + in_port_t sin6_port; /* Transport layer port # */ + uint32_t sin6_flowinfo; /* IPv6 flow information */ + struct in6_addr sin6_addr; /* IPv6 address */ + uint32_t sin6_scope_id; /* Set of interfaces for scope */ +}; +#endif /* NETDEV_IPV6 */ struct sockaddr_storage { @@ -174,9 +188,9 @@ struct sockaddr_storage sa_family_t ss_family; char s2_data1[2]; uint32_t s2_data2[3]; -#if SAL_IPV6 - u32_t s2_data3[3]; -#endif /* SAL_IPV6 */ +#if NETDEV_IPV6 + uint32_t s2_data3[3]; +#endif /* NETDEV_IPV6 */ }; int sal_accept(int socket, struct sockaddr *addr, socklen_t *addrlen); diff --git a/components/net/sal_socket/socket/net_sockets.c b/components/net/sal_socket/socket/net_sockets.c index 12024c8173..a53b2f1f9c 100644 --- a/components/net/sal_socket/socket/net_sockets.c +++ b/components/net/sal_socket/socket/net_sockets.c @@ -105,9 +105,7 @@ int shutdown(int s, int how) rt_set_errno(-ENOTSOCK); error = -1; } - - /* socket has been closed, delete it from file system fd */ - fd_put(d); + fd_put(d); return error; diff --git a/components/net/sal_socket/src/sal_socket.c b/components/net/sal_socket/src/sal_socket.c index 8f3149abd5..e5c55f8bf8 100644 --- a/components/net/sal_socket/src/sal_socket.c +++ b/components/net/sal_socket/src/sal_socket.c @@ -94,12 +94,12 @@ do { * SAL (Socket Abstraction Layer) initialize. * * @return result 0: initialize success - * -1: initialize failed + * -1: initialize failed */ int sal_init(void) { int cn; - + if (init_ok) { LOG_D("Socket Abstraction Layer is already initialized."); @@ -115,7 +115,7 @@ int sal_init(void) LOG_E("No memory for socket table.\n"); return -1; } - + /* create sal socket lock */ rt_mutex_init(&sal_core_lock, "sal_lock", RT_IPC_FLAG_FIFO); @@ -131,7 +131,7 @@ static void check_netdev_internet_up_work(struct rt_work *work, void *work_data) { #define SAL_INTERNET_VERSION 0x00 #define SAL_INTERNET_BUFF_LEN 12 -#define SAL_INTERNET_TIMEOUT (2 * RT_TICK_PER_SECOND) +#define SAL_INTERNET_TIMEOUT (2) #define SAL_INTERNET_HOST "link.rt-thread.org" #define SAL_INTERNET_PORT 8101 @@ -148,7 +148,7 @@ static void check_netdev_internet_up_work(struct rt_work *work, void *work_data) char send_data[SAL_INTERNET_BUFF_LEN], recv_data = 0; struct rt_delayed_work *delay_work = (struct rt_delayed_work *)work; - const char month[][SAL_INTERNET_MONTH_LEN] = {"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"}; + const char month[][SAL_INTERNET_MONTH_LEN] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; char date[SAL_INTERNET_DATE_LEN]; int moth_num = 0; @@ -175,7 +175,7 @@ static void check_netdev_internet_up_work(struct rt_work *work, void *work_data) } skt_ops = pf->skt_ops; - if((sockfd = skt_ops->socket(AF_INET, SOCK_DGRAM, 0)) < 0) + if ((sockfd = skt_ops->socket(AF_INET, SOCK_DGRAM, 0)) < 0) { result = -RT_ERROR; goto __exit; @@ -224,7 +224,7 @@ static void check_netdev_internet_up_work(struct rt_work *work, void *work_data) send_data[11] = RT_REVISION; skt_ops->sendto(sockfd, send_data, SAL_INTERNET_BUFF_LEN, 0, - (struct sockaddr *)&server_addr, sizeof(struct sockaddr)); + (struct sockaddr *)&server_addr, sizeof(struct sockaddr)); result = skt_ops->recvfrom(sockfd, &recv_data, sizeof(recv_data), 0, (struct sockaddr *)&server_addr, &addr_len); if (result < 0) @@ -242,7 +242,7 @@ __exit: if (result > 0) { LOG_D("Set network interface device(%s) internet status up.", netdev->name); - netdev->flags |= NETDEV_FLAG_INTERNET_UP; + netdev->flags |= NETDEV_FLAG_INTERNET_UP; } else { @@ -277,7 +277,7 @@ int sal_check_netdev_internet_up(struct netdev *netdev) rt_delayed_work_init(net_work, check_netdev_internet_up_work, (void *)netdev); rt_work_submit(&(net_work->work), RT_TICK_PER_SECOND); - + return 0; } @@ -316,10 +316,7 @@ struct sal_socket *sal_get_socket(int socket) socket = socket - SAL_SOCKET_OFFSET; /* check socket structure valid or not */ - if (st->sockets[socket]->magic != SAL_SOCKET_MAGIC) - { - return RT_NULL; - } + RT_ASSERT(st->sockets[socket]->magic == SAL_SOCKET_MAGIC); return st->sockets[socket]; } @@ -351,6 +348,38 @@ static void sal_unlock(void) } /** + * This function will clean the netdev. + * + * @note please don't invoke it on ISR. + */ +int sal_netdev_cleanup(struct netdev *netdev) +{ + int idx = 0, find_dev; + + do + { + find_dev = 0; + sal_lock(); + for (idx = 0; idx < socket_table.max_socket; idx++) + { + if (socket_table.sockets[idx] && socket_table.sockets[idx]->netdev == netdev) + { + find_dev = 1; + break; + } + } + sal_unlock(); + if (find_dev) + { + rt_thread_mdelay(100); + } + } + while (find_dev); + + return 0; +} + +/** * This function will initialize sal socket object and set socket options * * @param family protocol family @@ -397,7 +426,7 @@ static int socket_init(int family, int type, int protocol, struct sal_socket **r flag = RT_TRUE; } } - + if (flag == RT_FALSE) { /* get network interface device by protocol family */ @@ -421,8 +450,7 @@ static int socket_alloc(struct sal_socket_table *st, int f_socket) /* find an empty socket entry */ for (idx = f_socket; idx < (int) st->max_socket; idx++) { - if (st->sockets[idx] == RT_NULL || - st->sockets[idx]->netdev == RT_NULL) + if (st->sockets[idx] == RT_NULL) { break; } @@ -466,6 +494,15 @@ __result: return idx; } +static void socket_free(struct sal_socket_table *st, int idx) +{ + struct sal_socket *sock; + + sock = st->sockets[idx]; + st->sockets[idx] = RT_NULL; + rt_free(sock); +} + static int socket_new(void) { struct sal_socket *sock; @@ -498,18 +535,38 @@ __result: return idx + SAL_SOCKET_OFFSET; } +static void socket_delete(int socket) +{ + struct sal_socket *sock; + struct sal_socket_table *st = &socket_table; + int idx; + + idx = socket - SAL_SOCKET_OFFSET; + if (idx < 0 || idx >= (int) st->max_socket) + { + return; + } + sal_lock(); + sock = sal_get_socket(socket); + RT_ASSERT(sock != RT_NULL); + sock->magic = 0; + sock->netdev = RT_NULL; + socket_free(st, idx); + sal_unlock(); +} + int sal_accept(int socket, struct sockaddr *addr, socklen_t *addrlen) { int new_socket; struct sal_socket *sock; - struct sal_proto_family *pf; + struct sal_proto_family *pf; /* get the socket object by socket descriptor */ SAL_SOCKET_OBJ_GET(sock, socket); /* check the network interface socket operations */ SAL_NETDEV_SOCKETOPS_VALID(sock->netdev, pf, accept); - + new_socket = pf->skt_ops->accept((int) sock->user_data, addr, addrlen); if (new_socket != -1) { @@ -519,18 +576,20 @@ int sal_accept(int socket, struct sockaddr *addr, socklen_t *addrlen) /* allocate a new socket structure and registered socket options */ new_sal_socket = socket_new(); - if (new_sal_socket < 0) + new_sock = sal_get_socket(new_sal_socket); + if (new_sock == RT_NULL) { pf->skt_ops->closesocket(new_socket); return -1; } - new_sock = sal_get_socket(new_sal_socket); retval = socket_init(sock->domain, sock->type, sock->protocol, &new_sock); if (retval < 0) { pf->skt_ops->closesocket(new_socket); rt_memset(new_sock, 0x00, sizeof(struct sal_socket)); + /* socket init failed, delete socket */ + socket_delete(new_sal_socket); LOG_E("New socket registered failed, return error %d.", retval); return -1; } @@ -549,20 +608,20 @@ static void sal_sockaddr_to_ipaddr(const struct sockaddr *name, ip_addr_t *local const struct sockaddr_in *svr_addr = (const struct sockaddr_in *) name; #if NETDEV_IPV4 && NETDEV_IPV6 - (*local_ipaddr).u_addr.ip4.addr = svr_addr->sin_addr.s_addr; + local_ipaddr->u_addr.ip4.addr = svr_addr->sin_addr.s_addr; + local_ipaddr->type = IPADDR_TYPE_V4; #elif NETDEV_IPV4 - (*local_ipaddr).addr = svr_addr->sin_addr.s_addr; + local_ipaddr->addr = svr_addr->sin_addr.s_addr; #elif NETDEV_IPV6 - LOG_E("not support IPV6"); -#endif /* SAL_IPV4 && SAL_IPV6*/ -} +#error "not only support IPV6" +#endif /* NETDEV_IPV4 && NETDEV_IPV6*/ +} int sal_bind(int socket, const struct sockaddr *name, socklen_t namelen) { struct sal_socket *sock; struct sal_proto_family *pf; - struct netdev *new_netdev; - ip_addr_t local_addr; + ip_addr_t input_ipaddr; RT_ASSERT(name); @@ -570,44 +629,43 @@ int sal_bind(int socket, const struct sockaddr *name, socklen_t namelen) SAL_SOCKET_OBJ_GET(sock, socket); /* bind network interface by ip address */ - sal_sockaddr_to_ipaddr(name, &local_addr); + sal_sockaddr_to_ipaddr(name, &input_ipaddr); /* check input ipaddr is default netdev ipaddr */ - if (local_addr.addr == INADDR_ANY) + if (!ip_addr_isany_val(input_ipaddr)) { - SAL_NETDEV_SOCKETOPS_VALID(sock->netdev, pf, bind); - return pf->skt_ops->bind((int) sock->user_data, name, namelen); - } - - new_netdev = netdev_get_by_ipaddr(&local_addr); - if (new_netdev == RT_NULL) - { - LOG_E("Not find network interface device ipaddr(%s).", inet_ntoa(local_addr)); - return -1; - } + struct sal_proto_family *input_pf = RT_NULL, *local_pf = RT_NULL; + struct netdev *new_netdev = RT_NULL; - /* change network interface device parameter in sal socket object */ - if (sock->netdev != new_netdev) - { - struct sal_proto_family *old_pf, *new_pf; - int new_socket = 0; + new_netdev = netdev_get_by_ipaddr(&input_ipaddr); + if (new_netdev == RT_NULL) + { + return -1; + } - /* close old netdev socket */ - SAL_NETDEV_SOCKETOPS_VALID(sock->netdev, old_pf, closesocket); - old_pf->skt_ops->closesocket(socket); + /* get input and local ip address proto_family */ + SAL_NETDEV_SOCKETOPS_VALID(sock->netdev, local_pf, bind); + SAL_NETDEV_SOCKETOPS_VALID(new_netdev, input_pf, bind); - /* open new netdev socket */ - SAL_NETDEV_SOCKETOPS_VALID(new_netdev, new_pf, socket); - new_socket = new_pf->skt_ops->socket(sock->domain, sock->type, sock->protocol); - if (new_socket < 0) + /* check the network interface protocol family type */ + if (input_pf->family != local_pf->family) { - return -1; + int new_socket = -1; + + /* protocol family is different, close old socket and create new socket by input ip address */ + local_pf->skt_ops->closesocket(socket); + + new_socket = input_pf->skt_ops->socket(input_pf->family, sock->type, sock->protocol); + if (new_socket < 0) + { + return -1; + } + sock->netdev = new_netdev; + sock->user_data = (void *) new_socket; } - sock->netdev = new_netdev; - sock->user_data = (void *) new_socket; } - /* check the network interface socket opreation */ + /* check and get protocol families by the network interface device */ SAL_NETDEV_SOCKETOPS_VALID(sock->netdev, pf, bind); return pf->skt_ops->bind((int) sock->user_data, name, namelen); } @@ -643,9 +701,6 @@ int sal_shutdown(int socket, int how) error = -1; } - /* free socket */ - rt_free(sock); - socket_table.sockets[socket] = RT_NULL; return error; } @@ -761,7 +816,7 @@ int sal_connect(int socket, const struct sockaddr *name, socklen_t namelen) { return -1; } - + return ret; } #endif @@ -784,7 +839,7 @@ int sal_listen(int socket, int backlog) } int sal_recvfrom(int socket, void *mem, size_t len, int flags, - struct sockaddr *from, socklen_t *fromlen) + struct sockaddr *from, socklen_t *fromlen) { struct sal_socket *sock; struct sal_proto_family *pf; @@ -801,11 +856,11 @@ int sal_recvfrom(int socket, void *mem, size_t len, int flags, if (SAL_SOCKOPS_PROTO_TLS_VALID(sock, recv)) { int ret; - + if ((ret = proto_tls->ops->recv(sock->user_data_tls, mem, len)) < 0) { return -1; - } + } return ret; } else @@ -818,7 +873,7 @@ int sal_recvfrom(int socket, void *mem, size_t len, int flags, } int sal_sendto(int socket, const void *dataptr, size_t size, int flags, - const struct sockaddr *to, socklen_t tolen) + const struct sockaddr *to, socklen_t tolen) { struct sal_socket *sock; struct sal_proto_family *pf; @@ -835,11 +890,11 @@ int sal_sendto(int socket, const void *dataptr, size_t size, int flags, if (SAL_SOCKOPS_PROTO_TLS_VALID(sock, send)) { int ret; - + if ((ret = proto_tls->ops->send(sock->user_data_tls, dataptr, size)) < 0) { return -1; - } + } return ret; } else @@ -877,6 +932,7 @@ int sal_socket(int domain, int type, int protocol) if (retval < 0) { LOG_E("SAL socket protocol family input failed, return error %d.", retval); + socket_delete(socket); return -1; } @@ -892,6 +948,7 @@ int sal_socket(int domain, int type, int protocol) sock->user_data_tls = proto_tls->ops->socket(socket); if (sock->user_data_tls == RT_NULL) { + socket_delete(socket); return -1; } } @@ -934,9 +991,8 @@ int sal_closesocket(int socket) error = -1; } - /* free socket */ - rt_free(sock); - socket_table.sockets[socket] = RT_NULL; + /* delete socket */ + socket_delete(socket); return error; } @@ -997,7 +1053,7 @@ struct hostent *sal_gethostbyname(const char *name) } int sal_gethostbyname_r(const char *name, struct hostent *ret, char *buf, - size_t buflen, struct hostent **result, int *h_errnop) + size_t buflen, struct hostent **result, int *h_errnop) { struct netdev *netdev = netdev_default; struct sal_proto_family *pf; @@ -1020,9 +1076,9 @@ int sal_gethostbyname_r(const char *name, struct hostent *ret, char *buf, } int sal_getaddrinfo(const char *nodename, - const char *servname, - const struct addrinfo *hints, - struct addrinfo **res) + const char *servname, + const struct addrinfo *hints, + struct addrinfo **res) { struct netdev *netdev = netdev_default; struct sal_proto_family *pf; diff --git a/components/utilities/Kconfig b/components/utilities/Kconfig index 250239aea6..7fa6b47601 100644 --- a/components/utilities/Kconfig +++ b/components/utilities/Kconfig @@ -2,8 +2,15 @@ menu "Utilities" config RT_USING_RYM bool "Enable Ymodem" + depends on RT_USING_DFS = y default n + if RT_USING_RYM + config YMODEM_DISABLE_CRC_TABLE + bool "Disable CRC Table" + default n + endif + config RT_USING_ULOG bool "Enable ulog" default n @@ -146,7 +153,6 @@ config RT_USING_ULOG config ULOG_TIME_USING_TIMESTAMP bool "Enable timestamp format for time." default n - select RT_USING_LIBC depends on ULOG_OUTPUT_TIME config ULOG_OUTPUT_LEVEL diff --git a/components/utilities/ulog/backend/console_be.c b/components/utilities/ulog/backend/console_be.c index 04b0d91add..95dd547426 100644 --- a/components/utilities/ulog/backend/console_be.c +++ b/components/utilities/ulog/backend/console_be.c @@ -22,9 +22,9 @@ static struct ulog_backend console; void ulog_console_backend_output(struct ulog_backend *backend, rt_uint32_t level, const char *tag, rt_bool_t is_raw, const char *log, size_t len) { +#ifdef RT_USING_DEVICE rt_device_t dev = rt_console_get_device(); -#ifdef RT_USING_DEVICE if (dev == RT_NULL) { rt_hw_console_output(log); diff --git a/components/utilities/ulog/ulog.c b/components/utilities/ulog/ulog.c index 9af5fe5b9d..8a8d142eff 100644 --- a/components/utilities/ulog/ulog.c +++ b/components/utilities/ulog/ulog.c @@ -684,7 +684,7 @@ void ulog_hexdump(const char *tag, rt_size_t width, rt_uint8_t *buf, rt_size_t s log_len = 6 + name_len + 2; rt_memset(log_buf, ' ', log_len); } - fmt_result = rt_snprintf(log_buf + log_len, ULOG_LINE_BUF_SIZE, "%04X-%04X: ", i, i + width); + fmt_result = rt_snprintf(log_buf + log_len, ULOG_LINE_BUF_SIZE, "%04X-%04X: ", i, i + width - 1); /* calculate log length */ if ((fmt_result > -1) && (fmt_result <= ULOG_LINE_BUF_SIZE)) { diff --git a/components/utilities/utest/utest.c b/components/utilities/utest/utest.c index f59f97bb64..6500ae2fbe 100644 --- a/components/utilities/utest/utest.c +++ b/components/utilities/utest/utest.c @@ -63,20 +63,20 @@ void utest_log_lv_set(rt_uint8_t lv) int utest_init(void) { /* initialize the utest commands table.*/ -#if defined(__CC_ARM) /* ARM C Compiler */ +#if defined(__CC_ARM) || defined(__CLANG_ARM) /* ARM C Compiler */ extern const int UtestTcTab$$Base; extern const int UtestTcTab$$Limit; tc_table = (utest_tc_export_t)&UtestTcTab$$Base; tc_num = (utest_tc_export_t)&UtestTcTab$$Limit - tc_table; -#elif defined (__ICCARM__) || defined(__ICCRX__) /* for IAR Compiler */ +#elif defined (__ICCARM__) || defined(__ICCRX__) /* for IAR Compiler */ tc_table = (utest_tc_export_t)__section_begin("UtestTcTab"); tc_num = (utest_tc_export_t)__section_end("UtestTcTab") - tc_table; -#elif defined (__GNUC__) /* for GCC Compiler */ +#elif defined (__GNUC__) /* for GCC Compiler */ extern const int __rt_utest_tc_tab_start; extern const int __rt_utest_tc_tab_end; tc_table = (utest_tc_export_t)&__rt_utest_tc_tab_start; tc_num = (utest_tc_export_t) &__rt_utest_tc_tab_end - tc_table; -#endif /* defined(__CC_ARM) */ +#endif LOG_I("utest is initialize success."); LOG_I("total utest testcase num: (%d)", tc_num); @@ -215,7 +215,7 @@ static void utest_run(const char *utest_name) i++; } - if (i == tc_num && is_find == RT_FALSE) + if (i == tc_num && is_find == RT_FALSE && utest_name != RT_NULL) { LOG_I("[==========] [ utest ] Not find (%s)", utest_name); LOG_I("[==========] [ utest ] finished"); diff --git a/components/utilities/utest/utest.h b/components/utilities/utest/utest.h index 386d177a77..2c91bfe0e1 100644 --- a/components/utilities/utest/utest.h +++ b/components/utilities/utest/utest.h @@ -15,6 +15,10 @@ #include "utest_log.h" #include "utest_assert.h" +#ifdef __cplusplus +extern "C" { +#endif + /** * utest_error * @@ -157,4 +161,8 @@ utest_t utest_handle_get(void); utest_unit_run(test_unit_func, #test_unit_func); \ if(utest_handle_get()->failed_num != 0) return; +#ifdef __cplusplus +} +#endif + #endif /* __UTEST_H__ */ diff --git a/components/utilities/utest/utest_assert.h b/components/utilities/utest/utest_assert.h index 9c620c689d..d83279272e 100644 --- a/components/utilities/utest/utest_assert.h +++ b/components/utilities/utest/utest_assert.h @@ -14,6 +14,10 @@ #include "utest.h" #include <rtthread.h> +#ifdef __cplusplus +extern "C" { +#endif + /* No need for the user to use this function directly */ void utest_assert(int value, const char *file, int line, const char *func, const char *msg); @@ -61,4 +65,8 @@ void utest_assert_buf(const char *a, const char *b, rt_size_t sz, rt_bool_t equa #define uassert_in_range(value, min, max) __utest_assert(((value >= min) && (value <= max)), "(" #value ") not in range("#min","#max")") #define uassert_not_in_range(value, min, max) __utest_assert(!((value >= min) && (value <= max)), "(" #value ") in range("#min","#max")") +#ifdef __cplusplus +} +#endif + #endif /* __UTEST_ASSERT_H__ */ diff --git a/components/utilities/ymodem/ry_sy.c b/components/utilities/ymodem/ry_sy.c new file mode 100644 index 0000000000..fa57b8553a --- /dev/null +++ b/components/utilities/ymodem/ry_sy.c @@ -0,0 +1,237 @@ +/* + * Copyright (c) 2019 Fuzhou Rockchip Electronics Co., Ltd + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-12-09 Steven Liu the first version + */ + +#include <rtthread.h> +#include <ymodem.h> +#include <dfs_posix.h> +#include <stdlib.h> +#include <board.h> +#include <string.h> + +struct custom_ctx +{ + struct rym_ctx parent; + int fd; + int flen; + char fpath[DFS_PATH_MAX]; +}; + +static enum rym_code _rym_recv_begin( + struct rym_ctx *ctx, + rt_uint8_t *buf, + rt_size_t len) +{ + struct custom_ctx *cctx = (struct custom_ctx *)ctx; + + cctx->fpath[0] = '/'; + rt_strncpy(&(cctx->fpath[1]), (const char *)buf, len - 1); + cctx->fd = open(cctx->fpath, O_CREAT | O_WRONLY | O_TRUNC, 0); + if (cctx->fd < 0) + { + rt_err_t err = rt_get_errno(); + rt_kprintf("error creating file: %d\n", err); + return RYM_CODE_CAN; + } + cctx->flen = atoi((const char *)buf + rt_strnlen((const char *)buf, len - 1)); + if (cctx->flen == 0) + cctx->flen = -1; + + return RYM_CODE_ACK; +} + +static enum rym_code _rym_recv_data( + struct rym_ctx *ctx, + rt_uint8_t *buf, + rt_size_t len) +{ + struct custom_ctx *cctx = (struct custom_ctx *)ctx; + + RT_ASSERT(cctx->fd >= 0); + if (cctx->flen == -1) + { + write(cctx->fd, buf, len); + } + else + { + int wlen = len > cctx->flen ? cctx->flen : len; + write(cctx->fd, buf, wlen); + cctx->flen -= wlen; + } + + return RYM_CODE_ACK; +} + +static enum rym_code _rym_recv_end( + struct rym_ctx *ctx, + rt_uint8_t *buf, + rt_size_t len) +{ + struct custom_ctx *cctx = (struct custom_ctx *)ctx; + + RT_ASSERT(cctx->fd >= 0); + close(cctx->fd); + cctx->fd = -1; + + return RYM_CODE_ACK; +} + +static enum rym_code _rym_send_begin( + struct rym_ctx *ctx, + rt_uint8_t *buf, + rt_size_t len) +{ + struct custom_ctx *cctx = (struct custom_ctx *)ctx; + struct stat file_buf; + char insert_0 = '\0'; + rt_err_t err; + + cctx->fd = open(cctx->fpath, O_RDONLY); + if (cctx->fd < 0) + { + err = rt_get_errno(); + rt_kprintf("error open file: %d\n", err); + return RYM_ERR_FILE; + } + rt_memset(buf, 0, len); + err = stat(cctx->fpath, &file_buf); + if (err != RT_EOK) + { + rt_kprintf("error open file.\n"); + return RYM_ERR_FILE; + } + sprintf((char *)buf, "%s%c%ld", (char *) & (cctx->fpath[1]), insert_0, file_buf.st_size); + + return RYM_CODE_SOH; +} + +static enum rym_code _rym_send_data( + struct rym_ctx *ctx, + rt_uint8_t *buf, + rt_size_t len) +{ + struct custom_ctx *cctx = (struct custom_ctx *)ctx; + rt_size_t read_size; + int retry_read; + + read_size = 0; + for (retry_read = 0; retry_read < 10; retry_read++) + { + read_size += read(cctx->fd, buf + read_size, len - read_size); + if (read_size == len) + break; + } + + if (read_size < len) + { + rt_memset(buf + read_size, 0x1A, len - read_size); + /* stage = RYM_STAGE_FINISHING */ + ctx->stage = 4; + } + + return RYM_CODE_SOH; +} + +static enum rym_code _rym_send_end( + struct rym_ctx *ctx, + rt_uint8_t *buf, + rt_size_t len) +{ + rt_memset(buf, 0, len); + + return RYM_CODE_SOH; +} + +static rt_err_t rym_download_file(rt_device_t idev) +{ + rt_err_t res; + struct custom_ctx *ctx = rt_calloc(1, sizeof(*ctx)); + + if (!ctx) + { + rt_kprintf("rt_malloc failed\n"); + return RT_ENOMEM; + } + ctx->fd = -1; + RT_ASSERT(idev); + res = rym_recv_on_device(&ctx->parent, idev, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_INT_RX, + _rym_recv_begin, _rym_recv_data, _rym_recv_end, 1000); + rt_free(ctx); + + return res; +} + +static rt_err_t rym_upload_file(rt_device_t idev, const char *file_path) +{ + rt_err_t res = 0; + + struct custom_ctx *ctx = rt_calloc(1, sizeof(*ctx)); + if (!ctx) + { + rt_kprintf("rt_malloc failed\n"); + return RT_ENOMEM; + } + ctx->fd = -1; + rt_strncpy(ctx->fpath, file_path, DFS_PATH_MAX); + RT_ASSERT(idev); + res = rym_send_on_device(&ctx->parent, idev, + RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_INT_RX, + _rym_send_begin, _rym_send_data, _rym_send_end, 1000); + rt_free(ctx); + + return res; +} + +#ifdef RT_USING_FINSH +#include <finsh.h> + +static rt_err_t ry(uint8_t argc, char **argv) +{ + rt_err_t res; + rt_device_t dev; + + if (argc > 1) + dev = rt_device_find(argv[1]); + else + dev = rt_console_get_device(); + if (!dev) + { + rt_kprintf("could not find device.\n"); + return -RT_ERROR; + } + res = rym_download_file(dev); + + return res; +} +MSH_CMD_EXPORT(ry, YMODEM Receive e.g: ry [uart0] default by console.); + +static rt_err_t sy(uint8_t argc, char **argv) +{ + rt_err_t res; + /* temporarily support 1 file*/ + const char *file_path; + rt_device_t dev; + + if (argc > 2) + dev = rt_device_find(argv[2]); + else + dev = rt_console_get_device(); + if (!dev) + { + rt_kprintf("could not find device.\n"); + return -RT_ERROR; + } + file_path = argv[1]; + res = rym_upload_file(dev, file_path); + + return res; +} +MSH_CMD_EXPORT(sy, YMODEM Send e.g: sy file_path [uart0] default by console.); + +#endif /* RT_USING_FINSH */ diff --git a/components/utilities/ymodem/ymodem.c b/components/utilities/ymodem/ymodem.c index 716c702328..0214845303 100644 --- a/components/utilities/ymodem/ymodem.c +++ b/components/utilities/ymodem/ymodem.c @@ -7,12 +7,15 @@ * Change Logs: * Date Author Notes * 2013-04-14 Grissiom initial implementation + * 2019-12-09 Steven Liu add YMODEM send protocol */ #include <rthw.h> #include "ymodem.h" -static const rt_uint16_t ccitt_table[256] = { +#ifndef YMODEM_DISABLE_CRC_TABLE +static const rt_uint16_t ccitt_table[256] = +{ 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7, 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF, 0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6, @@ -46,7 +49,7 @@ static const rt_uint16_t ccitt_table[256] = { 0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8, 0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0 }; -rt_uint16_t CRC16(unsigned char *q, int len) +static rt_uint16_t CRC16(unsigned char *q, int len) { rt_uint16_t crc = 0; @@ -54,6 +57,30 @@ rt_uint16_t CRC16(unsigned char *q, int len) crc = (crc << 8) ^ ccitt_table[((crc >> 8) ^ *q++) & 0xff]; return crc; } +#else +static rt_uint16_t CRC16(unsigned char *q, int len) +{ + rt_uint16_t crc; + char i; + + crc = 0; + while (--len >= 0) + { + crc = crc ^ (int) * q++ << 8; + i = 8; + do + { + if (crc & 0x8000) + crc = crc << 1 ^ 0x1021; + else + crc = crc << 1; + } + while (--i); + } + + return (crc); +} +#endif // we could only use global varible because we could not use // rt_device_t->user_data(it is used by the serial driver)... @@ -69,15 +96,16 @@ static rt_err_t _rym_rx_ind(rt_device_t dev, rt_size_t size) #define _RYM_STX_PKG_SZ (1+2+1024+2) static enum rym_code _rym_read_code( - struct rym_ctx *ctx, - rt_tick_t timeout) + struct rym_ctx *ctx, + rt_tick_t timeout) { /* Fast path */ if (rt_device_read(ctx->dev, 0, ctx->buf, 1) == 1) return (enum rym_code)(*ctx->buf); /* Slow path */ - do { + do + { rt_size_t rsz; /* No data yet, wait for one */ @@ -88,13 +116,14 @@ static enum rym_code _rym_read_code( rsz = rt_device_read(ctx->dev, 0, ctx->buf, 1); if (rsz == 1) return (enum rym_code)(*ctx->buf); - } while (1); + } + while (1); } /* the caller should at least alloc _RYM_STX_PKG_SZ buffer */ static rt_size_t _rym_read_data( - struct rym_ctx *ctx, - rt_size_t len) + struct rym_ctx *ctx, + rt_size_t len) { /* we should already have had the code */ rt_uint8_t *buf = ctx->buf + 1; @@ -103,23 +132,61 @@ static rt_size_t _rym_read_data( do { readlen += rt_device_read(ctx->dev, - 0, buf+readlen, len-readlen); + 0, buf + readlen, len - readlen); if (readlen >= len) return readlen; - } while (rt_sem_take(&ctx->sem, RYM_WAIT_CHR_TICK) == RT_EOK); + } + while (rt_sem_take(&ctx->sem, RYM_WAIT_CHR_TICK) == RT_EOK); return readlen; } +static rt_err_t _rym_send_packet( + struct rym_ctx *ctx, + enum rym_code code, + rt_uint8_t index) +{ + rt_uint16_t send_crc; + rt_uint8_t index_inv = ~index; + rt_size_t writelen = 0; + + send_crc = CRC16(ctx->buf + 3, _RYM_SOH_PKG_SZ - 5); + ctx->buf[0] = code; + ctx->buf[1] = index; + ctx->buf[2] = index_inv; + ctx->buf[131] = (rt_uint8_t)(send_crc >> 8); + ctx->buf[132] = (rt_uint8_t)send_crc & 0xff; + + do + { + writelen += rt_device_write(ctx->dev, 0, ctx->buf + writelen, + _RYM_SOH_PKG_SZ - writelen); + } + while (writelen < _RYM_SOH_PKG_SZ); + + return RT_EOK; +} + static rt_size_t _rym_putchar(struct rym_ctx *ctx, rt_uint8_t code) { rt_device_write(ctx->dev, 0, &code, sizeof(code)); return 1; } +static rt_size_t _rym_getchar(struct rym_ctx *ctx) +{ + rt_uint8_t getc_ack; + + while (rt_device_read(ctx->dev, 0, &getc_ack, 1) != 1) + { + rt_sem_take(&ctx->sem, RT_WAITING_FOREVER); + } + return getc_ack; +} + static rt_err_t _rym_do_handshake( - struct rym_ctx *ctx, - int tm_sec) + struct rym_ctx *ctx, + int tm_sec) { enum rym_code code; rt_size_t i; @@ -133,13 +200,13 @@ static rt_err_t _rym_do_handshake( { _rym_putchar(ctx, RYM_CODE_C); code = _rym_read_code(ctx, - RYM_CHD_INTV_TICK); + RYM_CHD_INTV_TICK); if (code == RYM_CODE_SOH) { data_sz = _RYM_SOH_PKG_SZ; break; } - else if(code == RYM_CODE_STX) + else if (code == RYM_CODE_STX) { data_sz = _RYM_STX_PKG_SZ; break; @@ -154,7 +221,7 @@ static rt_err_t _rym_do_handshake( i = 0; /* automatic exit after receiving specified length data, timeout: 100ms */ tick = rt_tick_get(); - while (rt_tick_get() <= (tick + rt_tick_from_millisecond(100)) && i < (data_sz-1)) + while (rt_tick_get() <= (tick + rt_tick_from_millisecond(100)) && i < (data_sz - 1)) { i += _rym_read_data(ctx, data_sz - 1); rt_thread_mdelay(5); @@ -167,24 +234,79 @@ static rt_err_t _rym_do_handshake( if (ctx->buf[1] != 0 || ctx->buf[2] != 0xFF) return -RYM_ERR_SEQ; - recv_crc = (rt_uint16_t)(*(ctx->buf+data_sz-2) << 8) | *(ctx->buf+data_sz-1); - cal_crc = CRC16(ctx->buf+3, data_sz-5); + recv_crc = (rt_uint16_t)(*(ctx->buf + data_sz - 2) << 8) | *(ctx->buf + data_sz - 1); + cal_crc = CRC16(ctx->buf + 3, data_sz - 5); if (recv_crc != cal_crc) return -RYM_ERR_CRC; /* congratulations, check passed. */ - if (ctx->on_begin && ctx->on_begin(ctx, ctx->buf+3, data_sz-5) != RYM_CODE_ACK) + if (ctx->on_begin && ctx->on_begin(ctx, ctx->buf + 3, data_sz - 5) != RYM_CODE_ACK) return -RYM_ERR_CAN; return RT_EOK; } +static rt_err_t _rym_do_send_handshake( + struct rym_ctx *ctx, + int tm_sec) +{ + enum rym_code code; + rt_size_t i; + rt_size_t data_sz; + rt_uint8_t index = 0; + rt_uint8_t getc_ack; + + ctx->stage = RYM_STAGE_ESTABLISHING; + data_sz = _RYM_SOH_PKG_SZ; + + /* receive C every second */ + for (i = 0; i < tm_sec; i++) + { + code = _rym_read_code(ctx, + RYM_CHD_INTV_TICK); + if (code == RYM_CODE_C) + { + break; + } + } + if (i == tm_sec) + { + return -RYM_ERR_TMO; + } + + /* congratulations, check passed. */ + if (ctx->on_begin && ctx->on_begin(ctx, ctx->buf + 3, data_sz - 5) != RYM_CODE_SOH) + return -RYM_ERR_CODE; + + code = RYM_CODE_SOH; + _rym_send_packet(ctx, code, index); + + rt_device_set_rx_indicate(ctx->dev, _rym_rx_ind); + getc_ack = _rym_getchar(ctx); + + if (getc_ack != RYM_CODE_ACK) + { + return -RYM_ERR_ACK; + } + + getc_ack = _rym_getchar(ctx); + + if (getc_ack != RYM_CODE_C) + { + return -RYM_ERR_ACK; + } + + ctx->stage = RYM_STAGE_ESTABLISHED; + + return RT_EOK; +} + static rt_err_t _rym_trans_data( - struct rym_ctx *ctx, - rt_size_t data_sz, - enum rym_code *code) + struct rym_ctx *ctx, + rt_size_t data_sz, + enum rym_code *code) { - const rt_size_t tsz = 2+data_sz+2; + const rt_size_t tsz = 2 + data_sz + 2; rt_uint16_t recv_crc; /* seq + data + crc */ @@ -210,13 +332,13 @@ static rt_err_t _rym_trans_data( ctx->stage = RYM_STAGE_TRANSMITTING; /* sanity check */ - recv_crc = (rt_uint16_t)(*(ctx->buf+tsz-1) << 8) | *(ctx->buf+tsz); - if (recv_crc != CRC16(ctx->buf+3, data_sz)) + recv_crc = (rt_uint16_t)(*(ctx->buf + tsz - 1) << 8) | *(ctx->buf + tsz); + if (recv_crc != CRC16(ctx->buf + 3, data_sz)) return -RYM_ERR_CRC; /* congratulations, check passed. */ if (ctx->on_data) - *code = ctx->on_data(ctx, ctx->buf+3, data_sz); + *code = ctx->on_data(ctx, ctx->buf + 3, data_sz); else *code = RYM_CODE_ACK; return RT_EOK; @@ -235,7 +357,7 @@ static rt_err_t _rym_do_trans(struct rym_ctx *ctx) rt_size_t data_sz, i; code = _rym_read_code(ctx, - RYM_WAIT_PKG_TICK); + RYM_WAIT_PKG_TICK); switch (code) { case RYM_CODE_SOH: @@ -257,7 +379,8 @@ static rt_err_t _rym_do_trans(struct rym_ctx *ctx) { case RYM_CODE_CAN: /* the spec require multiple CAN */ - for (i = 0; i < RYM_END_SESSION_SEND_CAN_NUM; i++) { + for (i = 0; i < RYM_END_SESSION_SEND_CAN_NUM; i++) + { _rym_putchar(ctx, RYM_CODE_CAN); } return -RYM_ERR_CAN; @@ -271,6 +394,41 @@ static rt_err_t _rym_do_trans(struct rym_ctx *ctx) } } +static rt_err_t _rym_do_send_trans(struct rym_ctx *ctx) +{ + ctx->stage = RYM_STAGE_TRANSMITTING; + enum rym_code code; + rt_size_t data_sz; + rt_uint32_t index = 1; + rt_uint8_t getc_ack; + + data_sz = _RYM_SOH_PKG_SZ; + + while (1) + { + if (ctx->on_data && ctx->on_data(ctx, ctx->buf + 3, data_sz - 5) != RYM_CODE_SOH) + return -RYM_ERR_CODE; + + code = RYM_CODE_SOH; + + _rym_send_packet(ctx, code, index); + index++; + rt_device_set_rx_indicate(ctx->dev, _rym_rx_ind); + + getc_ack = _rym_getchar(ctx); + + if (getc_ack != RYM_CODE_ACK) + { + return -RYM_ERR_ACK; + } + + if (ctx->stage == RYM_STAGE_FINISHING) + break; + } + + return RT_EOK; +} + static rt_err_t _rym_do_fin(struct rym_ctx *ctx) { enum rym_code code; @@ -282,7 +440,7 @@ static rt_err_t _rym_do_fin(struct rym_ctx *ctx) /* we already got one EOT in the caller. invoke the callback if there is * one. */ if (ctx->on_end) - ctx->on_end(ctx, ctx->buf+3, 128); + ctx->on_end(ctx, ctx->buf + 3, 128); _rym_putchar(ctx, RYM_CODE_NAK); code = _rym_read_code(ctx, RYM_WAIT_PKG_TICK); @@ -297,15 +455,15 @@ static rt_err_t _rym_do_fin(struct rym_ctx *ctx) { data_sz = _RYM_SOH_PKG_SZ; } - else if(code == RYM_CODE_STX) + else if (code == RYM_CODE_STX) { data_sz = _RYM_STX_PKG_SZ; } else return -RYM_ERR_CODE; - i = _rym_read_data(ctx, _RYM_SOH_PKG_SZ-1); - if (i != (_RYM_SOH_PKG_SZ-1)) + i = _rym_read_data(ctx, _RYM_SOH_PKG_SZ - 1); + if (i != (_RYM_SOH_PKG_SZ - 1)) return -RYM_ERR_DSZ; /* sanity check @@ -313,14 +471,14 @@ static rt_err_t _rym_do_fin(struct rym_ctx *ctx) if (ctx->buf[1] != 0 || ctx->buf[2] != 0xFF) return -RYM_ERR_SEQ; - recv_crc = (rt_uint16_t)(*(ctx->buf+_RYM_SOH_PKG_SZ-2) << 8) | *(ctx->buf+_RYM_SOH_PKG_SZ-1); - if (recv_crc != CRC16(ctx->buf+3, _RYM_SOH_PKG_SZ-5)) + recv_crc = (rt_uint16_t)(*(ctx->buf + _RYM_SOH_PKG_SZ - 2) << 8) | *(ctx->buf + _RYM_SOH_PKG_SZ - 1); + if (recv_crc != CRC16(ctx->buf + 3, _RYM_SOH_PKG_SZ - 5)) return -RYM_ERR_CRC; /*next file transmission*/ if (ctx->buf[3] != 0) { - if (ctx->on_begin && ctx->on_begin(ctx, ctx->buf+3, data_sz-5) != RYM_CODE_ACK) + if (ctx->on_begin && ctx->on_begin(ctx, ctx->buf + 3, data_sz - 5) != RYM_CODE_ACK) return -RYM_ERR_CAN; return RT_EOK; } @@ -334,9 +492,54 @@ static rt_err_t _rym_do_fin(struct rym_ctx *ctx) return RT_EOK; } +static rt_err_t _rym_do_send_fin(struct rym_ctx *ctx) +{ + enum rym_code code; + rt_size_t data_sz; + rt_uint8_t index = 0; + rt_uint8_t getc_ack; + + data_sz = _RYM_SOH_PKG_SZ; + rt_device_set_rx_indicate(ctx->dev, _rym_rx_ind); + + _rym_putchar(ctx, RYM_CODE_EOT); + getc_ack = _rym_getchar(ctx); + + if (getc_ack != RYM_CODE_NAK) + { + return -RYM_ERR_ACK; + } + + _rym_putchar(ctx, RYM_CODE_EOT); + getc_ack = _rym_getchar(ctx); + + if (getc_ack != RYM_CODE_ACK) + { + return -RYM_ERR_ACK; + } + + getc_ack = _rym_getchar(ctx); + + if (getc_ack != RYM_CODE_C) + { + return -RYM_ERR_ACK; + } + + if (ctx->on_end && ctx->on_end(ctx, ctx->buf + 3, data_sz - 5) != RYM_CODE_SOH) + return -RYM_ERR_CODE; + + code = RYM_CODE_SOH; + + _rym_send_packet(ctx, code, index); + + ctx->stage = RYM_STAGE_FINISHED; + + return RT_EOK; +} + static rt_err_t _rym_do_recv( - struct rym_ctx *ctx, - int handshake_timeout) + struct rym_ctx *ctx, + int handshake_timeout) { rt_err_t err; @@ -348,30 +551,78 @@ static rt_err_t _rym_do_recv( err = _rym_do_handshake(ctx, handshake_timeout); if (err != RT_EOK) + { + rt_free(ctx->buf); return err; + } while (1) { err = _rym_do_trans(ctx); if (err != RT_EOK) + { + rt_free(ctx->buf); return err; + } err = _rym_do_fin(ctx); if (err != RT_EOK) + { + rt_free(ctx->buf); return err; + } + if (ctx->stage == RYM_STAGE_FINISHED) break; } + rt_free(ctx->buf); + return err; +} + +static rt_err_t _rym_do_send( + struct rym_ctx *ctx, + int handshake_timeout) +{ + rt_err_t err; + + ctx->stage = RYM_STAGE_NONE; + + ctx->buf = rt_malloc(_RYM_STX_PKG_SZ); + if (ctx->buf == RT_NULL) + return -RT_ENOMEM; + + err = _rym_do_send_handshake(ctx, handshake_timeout); + if (err != RT_EOK) + { + rt_free(ctx->buf); + return err; + } + + err = _rym_do_send_trans(ctx); + if (err != RT_EOK) + { + rt_free(ctx->buf); + return err; + } + + err = _rym_do_send_fin(ctx); + if (err != RT_EOK) + { + rt_free(ctx->buf); + return err; + } + + rt_free(ctx->buf); return err; } rt_err_t rym_recv_on_device( - struct rym_ctx *ctx, - rt_device_t dev, - rt_uint16_t oflag, - rym_callback on_begin, - rym_callback on_data, - rym_callback on_end, - int handshake_timeout) + struct rym_ctx *ctx, + rt_device_t dev, + rt_uint16_t oflag, + rym_callback on_begin, + rym_callback on_data, + rym_callback on_end, + int handshake_timeout) { rt_err_t res; rt_err_t (*odev_rx_ind)(rt_device_t dev, rt_size_t size); @@ -393,9 +644,9 @@ rt_err_t rym_recv_on_device( int_lvl = rt_hw_interrupt_disable(); rt_device_set_rx_indicate(dev, _rym_rx_ind); - odev_flag = dev->flag; + odev_flag = dev->open_flag; /* make sure the device don't change the content. */ - dev->flag &= ~RT_DEVICE_FLAG_STREAM; + dev->open_flag &= ~RT_DEVICE_FLAG_STREAM; rt_hw_interrupt_enable(int_lvl); res = rt_device_open(dev, oflag); @@ -412,12 +663,68 @@ __exit: int_lvl = rt_hw_interrupt_disable(); rt_sem_detach(&ctx->sem); - dev->flag = odev_flag; + dev->open_flag = odev_flag; + rt_device_set_rx_indicate(dev, odev_rx_ind); + rt_hw_interrupt_enable(int_lvl); + + _rym_the_ctx = RT_NULL; + + return res; +} + +rt_err_t rym_send_on_device( + struct rym_ctx *ctx, + rt_device_t dev, + rt_uint16_t oflag, + rym_callback on_begin, + rym_callback on_data, + rym_callback on_end, + int handshake_timeout) +{ + rt_err_t res = 0; + rt_err_t (*odev_rx_ind)(rt_device_t dev, rt_size_t size); + rt_uint16_t odev_flag; + int int_lvl; + + RT_ASSERT(_rym_the_ctx == 0); + _rym_the_ctx = ctx; + + ctx->on_begin = on_begin; + ctx->on_data = on_data; + ctx->on_end = on_end; + ctx->dev = dev; + rt_sem_init(&ctx->sem, "rymsem", 0, RT_IPC_FLAG_FIFO); + + odev_rx_ind = dev->rx_indicate; + /* no data should be received before the device has been fully setted up. + */ + int_lvl = rt_hw_interrupt_disable(); + rt_device_set_rx_indicate(dev, _rym_rx_ind); + + odev_flag = dev->open_flag; + /* make sure the device don't change the content. */ + dev->open_flag &= ~RT_DEVICE_FLAG_STREAM; + rt_hw_interrupt_enable(int_lvl); + + res = rt_device_open(dev, oflag); + if (res != RT_EOK) + goto __exit; + + res = _rym_do_send(ctx, handshake_timeout); + + rt_device_close(dev); + +__exit: + + int_lvl = rt_hw_interrupt_disable(); + rt_sem_detach(&ctx->sem); + + dev->open_flag = odev_flag; rt_device_set_rx_indicate(dev, odev_rx_ind); rt_hw_interrupt_enable(int_lvl); - rt_free(ctx->buf); _rym_the_ctx = RT_NULL; return res; } + diff --git a/components/utilities/ymodem/ymodem.h b/components/utilities/ymodem/ymodem.h index 45e8f2272e..8419290e13 100644 --- a/components/utilities/ymodem/ymodem.h +++ b/components/utilities/ymodem/ymodem.h @@ -7,16 +7,19 @@ * Change Logs: * Date Author Notes * 2013-04-14 Grissiom initial implementation + * 2019-12-09 Steven Liu add YMODEM send protocol */ #ifndef __YMODEM_H__ #define __YMODEM_H__ #include "rtthread.h" +#include <string.h> /* The word "RYM" is stand for "Real-YModem". */ -enum rym_code { +enum rym_code +{ RYM_CODE_NONE = 0x00, RYM_CODE_SOH = 0x01, RYM_CODE_STX = 0x02, @@ -44,6 +47,10 @@ enum rym_code { #define RYM_ERR_DSZ 0x74 /* the transmission is aborted by user */ #define RYM_ERR_CAN 0x75 +/* wrong answer, wrong ACK or C */ +#define RYM_ERR_ACK 0x76 +/* transmit file invalid */ +#define RYM_ERR_FILE 0x77 /* how many ticks wait for chars between packet. */ #ifndef RYM_WAIT_CHR_TICK @@ -63,7 +70,8 @@ enum rym_code { #define RYM_END_SESSION_SEND_CAN_NUM 0x07 #endif -enum rym_stage { +enum rym_stage +{ RYM_STAGE_NONE, /* set when C is send */ RYM_STAGE_ESTABLISHING, @@ -80,16 +88,15 @@ enum rym_stage { }; struct rym_ctx; -/* when receiving files, the buf will be the data received from ymodem protocol +/* When receiving files, the buf will be the data received from ymodem protocol * and the len is the data size. * - * TODO: * When sending files, the len is the buf size in RYM. The callback need to * fill the buf with data to send. Returning RYM_CODE_EOT will terminate the * transfer and the buf will be discarded. Any other return values will cause * the transfer continue. */ -typedef enum rym_code (*rym_callback)(struct rym_ctx *ctx, rt_uint8_t *buf, rt_size_t len); +typedef enum rym_code(*rym_callback)(struct rym_ctx *ctx, rt_uint8_t *buf, rt_size_t len); /* Currently RYM only support one transfer session(ctx) for simplicity. * @@ -112,7 +119,7 @@ struct rym_ctx rt_device_t dev; }; -/** recv a file on device dev with ymodem session ctx. +/* recv a file on device dev with ymodem session ctx. * * If an error happens, you can get where it is failed from ctx->stage. * @@ -138,7 +145,30 @@ struct rym_ctx * second. */ rt_err_t rym_recv_on_device(struct rym_ctx *ctx, rt_device_t dev, rt_uint16_t oflag, - rym_callback on_begin, rym_callback on_data, rym_callback on_end, - int handshake_timeout); + rym_callback on_begin, rym_callback on_data, rym_callback on_end, + int handshake_timeout); + +/* send a file on device dev with ymodem session ctx. + * + * If an error happens, you can get where it is failed from ctx->stage. + * + * @param on_begin The callback will be invoked when the first packet is sent. + * This packet often contain file names and the size of the file. It is the + * on_begin's responsibility to parse the basic information of the file. The + * on_begin can not be NULL. + * + * @param on_data The callback will be invoked when the data packets is sent. + * The callback should read file system and prepare the data packets. The + * on_data can not be NULL. + * + * @param on_end The callback will be invoked when one transmission is + * finished. The data should be 128 bytes of NULL. The on_end can not be NULL. + * + * @param handshake_timeout the timeout when hand shaking. The unit is in + * second. + */ +rt_err_t rym_send_on_device(struct rym_ctx *ctx, rt_device_t dev, rt_uint16_t oflag, + rym_callback on_begin, rym_callback on_data, rym_callback on_end, + int handshake_timeout); #endif |
