使用 RT_USING_POSIX finsh能显示,但不能输入

发布于 2018-03-09 10:48:12
    本帖最后由 moebius.ever 于 2018-3-9 11:28 编辑


有类似的问题,https://www.rt-thread.org/qa/for ... thread&tid=5603
只不过现在RT_USING_DFS宏变成RT_USING_POSIX了,使用的是stm32f405vg的片子,用的stm32f429-apollo模板修改来的。
具体表现为,进入rt_init_thread_entry

[indent]void rt_init_thread_entry(void* parameter)[/indent][indent]{ [/indent][indent] /* initialization RT-Thread Components */[/indent][indent] #ifdef RT_USING_COMPONENTS_INIT[/indent][indent] rt_components_init();[/indent]进入rt_components_init()

void rt_components_init(void)
{
#if RT_DEBUG_INIT
int result;
const struct rt_init_desc *desc;
rt_kprintf("do components intialization.\n");
for (desc = &__rt_init_desc_rti_board_end; desc < &__rt_init_desc_rti_end; desc ++)
{
rt_kprintf("initialize %s", desc->fn_name);
result = desc->fn();
rt_kprintf(":%d done\n", result);

}

通过result = desc->fn();进入,使用的newlib/stdio.c

[indent]int libc_system_init(void)[/indent][indent]{[/indent][indent]#if defined(RT_USING_DFS) & defined(RT_USING_DFS_DEVFS)[/indent][indent] rt_device_t dev_console;
dev_console = rt_console_get_device();[/indent][indent] if (dev_console)[/indent][indent] {[/indent][indent] #if defined(RT_USING_POSIX)[/indent][indent] libc_stdio_set_console(dev_console->parent.name, O_RDWR);[/indent][indent] #else[/indent][indent] libc_stdio_set_console(dev_console->parent.name, O_WRONLY);[/indent][indent] #endif[/indent][indent] }[/indent][indent]#endif[/indent]进入libc_stdio_set_console(dev_console->parent.name, O_RDWR);
[indent]int libc_stdio_set_console(const char* device_name, int mode)[/indent][indent]{[/indent][indent] FILE *fp;[/indent][indent] char name[STDIO_DEVICE_NAME_MAX];[/indent][indent] char *file_mode;
snprintf(name, sizeof(name) - 1, "/dev/%s", device_name);[/indent][indent] name[STDIO_DEVICE_NAME_MAX - 1] = '\0';
if (mode == O_RDWR) file_mode = "r+";[/indent][indent] else if (mode == O_WRONLY) file_mode = "wb";[/indent][indent] else if (mode == O_RDONLY) file_mode = "rb";
fp = fopen(name, file_mode);[/indent][indent] if (fp)[/indent][indent] {[/indent][indent] setvbuf(fp, NULL, _IONBF, 0);[/indent]进入 fopen,然后进入,_fopen_r,这个函数没有c代码,然后进入_open_r, 使用的是newlib/syscall.c
int


[indent]_open_r(struct _reent *ptr, const char *file, int flags, int mode)[/indent][indent]{[/indent][indent]#ifndef RT_USING_DFS[/indent][indent] return 0;[/indent][indent]#else[/indent][indent] int rc;

[/indent][indent] rc = open(file, flags, mode);[/indent][indent] return rc;[/indent][indent]#endif[/indent][indent]}[/indent]进入 open,使用的是dfs_posix.c

[indent]int open(const char *file, int flags, ...)[/indent][indent]{[/indent][indent] int fd, result;[/indent][indent] struct dfs_fd *d;[/indent][indent] /* allocate a fd */[/indent][indent] fd = fd_new();[/indent][indent] if (fd < 0)[/indent][indent] {[/indent][indent] rt_set_errno(-ENOMEM);
return -1;[/indent][indent] }[/indent][indent] d = fd_get(fd);
result = dfs_file_open(d, file, flags);[/indent][indent] if (result < 0)[/indent][indent] {[/indent][indent] /* release the ref-count of fd */[/indent][indent] fd_put(d);[/indent][indent] fd_put(d);
rt_set_errno(result);
return -1;[/indent][indent] }
/* release the ref-count of fd */[/indent][indent] fd_put(d);
return fd;[/indent][indent]}[/indent]进入

int dfs_file_open(struct dfs_fd *fd, const char *path, int flags)
[indent]{[/indent][indent] struct dfs_filesystem *fs;[/indent][indent] char *fullpath;[/indent][indent] int result;[/indent][indent] /* parameter check */[/indent][indent] if (fd == NULL)[/indent][indent] return -EINVAL;
/* make sure we have an absolute path */[/indent][indent] fullpath = dfs_normalize_path(NULL, path);[/indent][indent] if (fullpath == NULL)[/indent][indent] {[/indent][indent] return -ENOMEM;[/indent][indent] }
dbg_log(DBG_LOG, "open file:%s\n", fullpath);
/* Check whether file is already open */[/indent][indent] if (fd_is_open(fullpath) == 0)[/indent][indent] {[/indent][indent] rt_free(fullpath); /* release path */
return -EBUSY;[/indent][indent] }
/* find filesystem */[/indent][indent] fs = dfs_filesystem_lookup(fullpath);[/indent][indent] if (fs == NULL)[/indent][indent] {[/indent][indent] rt_free(fullpath); /* release path */
return -ENOENT;[/indent][indent] }
dbg_log(DBG_LOG, "open in filesystem:%s\n", fs->ops->name);[/indent][indent] fd->fops = fs->ops->fops; /* set file ops */
/* initialize the fd item */[/indent][indent] fd->type = FT_REGULAR;[/indent][indent] fd->flags = flags;[/indent][indent] fd->size = 0;[/indent][indent] fd->pos = 0;[/indent][indent] fd->data = fs;[/indent][indent] if (!(fs->ops->flags & DFS_FS_FLAG_FULLPATH))[/indent][indent] {[/indent][indent] if (dfs_subdir(fs->path, fullpath) == NULL)[/indent][indent] fd->path = rt_strdup("/");[/indent][indent] else[/indent][indent] fd->path = rt_strdup(dfs_subdir(fs->path, fullpath));[/indent][indent] rt_free(fullpath);[/indent][indent] dbg_log(DBG_LOG, "Actual file path: %s\n", fd->path);[/indent][indent] }[/indent][indent] else[/indent][indent] {[/indent][indent] fd->path = fullpath;
}
/* specific file system open routine */[/indent][indent] if (fd->fops->open == NULL)[/indent][indent] {[/indent][indent] /* clear fd */[/indent][indent] rt_free(fd->path);[/indent][indent] fd->path = NULL;
return -ENOSYS;[/indent][indent] }[/indent][indent] if ((result = fd->fops->open(fd)) < 0)[/indent][indent] {[/indent][indent] /* clear fd */[/indent][indent] rt_free(fd->path);[/indent]进入
[indent]static int serial_fops_open(struct dfs_fd *fd)[/indent][indent]{[/indent][indent] rt_err_t ret = 0;[/indent][indent] rt_uint16_t flags = 0;[/indent][indent] rt_device_t device;
device = (rt_device_t)fd->data;[/indent][indent] RT_ASSERT(device != RT_NULL);
switch (fd->flags & O_ACCMODE)[/indent][indent] {[/indent][indent] case O_RDONLY:[/indent][indent] dbg_log(DBG_LOG, "fops open: O_RDONLY!\n");[/indent][indent] flags = RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_RDONLY;[/indent][indent] break;[/indent][indent] case O_WRONLY:[/indent][indent] dbg_log(DBG_LOG, "fops open: O_WRONLY!\n");[/indent][indent] flags = RT_DEVICE_FLAG_WRONLY;[/indent][indent] break;[/indent][indent] case O_RDWR:[/indent][indent] dbg_log(DBG_LOG, "fops open: O_RDWR!\n");[/indent][indent] flags = RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_RDWR;[/indent][indent] break;[/indent][indent] default:[/indent][indent] dbg_log(DBG_ERROR, "fops open: unknown mode - %d!\n", fd->flags & O_ACCMODE);[/indent][indent] break;[/indent][indent] }
if ((fd->flags & O_ACCMODE) != O_WRONLY)[/indent][indent] rt_device_set_rx_indicate(device, serial_fops_rx_ind);[/indent][indent] ret = rt_device_open(device, flags);[/indent][indent] if (ret == RT_EOK) return 0;[/indent][indent] return ret;[/indent][indent]}[/indent]进入
[indent]rt_err_t rt_device_open(rt_device_t dev, rt_uint16_t oflag)[/indent][indent]{[/indent][indent] rt_err_t result = RT_EOK;[/indent][indent] RT_ASSERT(dev != RT_NULL);[/indent][indent] /* if device is not initialized, initialize it. */[/indent][indent] if (!(dev->flag & RT_DEVICE_FLAG_ACTIVATED))[/indent][indent] {[/indent][indent] if (dev->init != RT_NULL)[/indent][indent] {[/indent][indent] result = dev->init(dev);[/indent][indent] if (result != RT_EOK)[/indent][indent] {[/indent][indent] rt_kprintf("To initialize device:%s failed. The error code is %d\n",[/indent][indent] dev->parent.name, result);[/indent][indent] return result;[/indent][indent] }[/indent][indent] }[/indent][indent]
dev->flag |= RT_DEVICE_FLAG_ACTIVATED;[/indent][indent] }[/indent][indent]
/* device is a stand alone device and opened */[/indent][indent] if ((dev->flag & RT_DEVICE_FLAG_STANDALONE) &&[/indent][indent] (dev->open_flag & RT_DEVICE_OFLAG_OPEN))[/indent][indent] {[/indent][indent] return -RT_EBUSY;[/indent][indent] }[/indent][indent] /* call device open interface */[/indent][indent] if (dev->open != RT_NULL)[/indent][indent] {[/indent][indent] result = dev->open(dev, oflag);[/indent]进入


[indent]static rt_err_t rt_serial_open(struct rt_device *dev, rt_uint16_t oflag)[/indent][indent] rt_uint16_t stream_flag = 0;[/indent][indent] struct rt_serial_device *serial;[/indent][indent]
RT_ASSERT(dev != RT_NULL);[/indent][indent] serial = (struct rt_serial_device *)dev;[/indent][indent]
dbg_log(DBG_LOG, "open serial device: 0x%08x with open flag: 0x%04x\n",[/indent][indent] dev, oflag);[/indent][indent] /* check device flag with the open flag */[/indent][indent] if ((oflag & RT_DEVICE_FLAG_DMA_RX) && !(dev->flag & RT_DEVICE_FLAG_DMA_RX))[/indent][indent] return -RT_EIO;[/indent][indent] if ((oflag & RT_DEVICE_FLAG_DMA_TX) && !(dev->flag & RT_DEVICE_FLAG_DMA_TX))[/indent][indent] return -RT_EIO;[/indent][indent] if ((oflag & RT_DEVICE_FLAG_INT_RX) && !(dev->flag & RT_DEVICE_FLAG_INT_RX))[/indent][indent] return -RT_EIO;[/indent][indent] if ((oflag & RT_DEVICE_FLAG_INT_TX) && !(dev->flag & RT_DEVICE_FLAG_INT_TX))[/indent][indent] return -RT_EIO;
/* keep steam flag */[/indent][indent] if ((oflag & RT_DEVICE_FLAG_STREAM) || (dev->open_flag & RT_DEVICE_FLAG_STREAM))[/indent][indent] stream_flag = RT_DEVICE_FLAG_STREAM;[/indent]在此处返回 -RT_EIO, oflag的值为 0x103, dev->flag的值为 0xa13,无论怎么修改libc_stdio_set_console(dev_console->parent.name, O_RDWR);的参数,这一句都执行不过去。感觉是不是个bug啊。





查看更多

关注者
0
被浏览
3.3k
17 个回答
moebius.ever
moebius.ever 2018-03-09
格式化成代码的时候全乱了,不知道为什么,又手工修改了一遍,不太好看
moebius.ever
moebius.ever 2018-03-15
    本帖最后由 moebius.ever 于 2018-3-15 11:16 编辑


使用
rt_hw_serial_register(&serial_uart0,
"rtt",
RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
NULL);

串口初始化的时候使用 RT_DEVICE_FLAG_INT_RX模式可以,使用 RT_DEVICE_FLAG_DMA_RX模式不行
armink
armink 2018-03-15
moebius.ever 发表于 2018-3-15 11:13
使用
rt_hw_serial_register(&serial_uart0,
"rtt",


console 默认使用是中断模式,所以只注册 DMA 模式是不行。如果两个模式都支持,也可以两个模式都注册
    /* register UART1 device */
rt_hw_serial_register(&serial1,
"uart1",
RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_DMA_RX,
uart);


moebius.ever
moebius.ever 2018-03-16
armink 发表于 2018-3-15 12:46
console 默认使用是中断模式,所以只注册 DMA 模式是不行。如果两个模式都支持,也可以两个模式都注册




好的,谢谢了,我是使用的segger rtt,没有中断模式,就自己利用空闲线程模拟了下中断处理
armink
armink 2018-03-16
moebius.ever 发表于 2018-3-16 10:47
好的,谢谢了,我是使用的segger rtt,没有中断模式,就自己利用空闲线程模拟了下中断处理 ...

如果你的驱动就不支持 RT_DEVICE_FLAG_INT_RX ,那你注册设备时候就 不要 填写上这个 Flag 。

这样 console 初始化时,即便你的设备不支持中断模式,也会自动使用轮训模式的。
moebius.ever
moebius.ever 2018-03-17
armink 发表于 2018-3-16 20:29
如果你的驱动就不支持 RT_DEVICE_FLAG_INT_RX ,那你注册设备时候就 不要 填写上这个 Flag 。

这样 conso ...


使用posix接口的时候, int dfs_file_open(struct dfs_fd *fd, const char *path, int flags) 函数在这个部分
case O_RDWR:
dbg_log(DBG_LOG, "fops open: O_RDWR!\n");
flags = RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_RDWR;
break;
会把它置成中断模式, 如果没有使用空闲进程模拟中断的话,rt-thread就接收不到数据
moebius.ever
moebius.ever 2018-03-19
Spunky 发表于 2018-3-19 13:35
我已经解决:
https://www.rt-thread.org/qa/thread-6908-1-1.html


看了,确实能解决,不过我感觉这个问题是配置或者宏定义不正常造成的,getchar是已经移植好的,它通过不断查询缓冲区来输入数据,只是rt-thread中串口初始化时只有中断和DMA两个模式,,假如说像模拟串口这种没有中断或者DMA的就不能正常工作了,它没有办法不经过CPU把数据直接放入系统输入的缓冲区,因为它需要轮询接收数据
Spunky
Spunky 2018-03-19
moebius.ever 发表于 2018-3-19 18:46
看了,确实能解决,不过我感觉这个问题是配置或者宏定义不正常造成的,getchar是已经移植好的,它通过不 ...


getchar()在哪里移植好了的,我没有找到。
armink
armink 2018-03-20
moebius.ever 发表于 2018-3-19 18:46
看了,确实能解决,不过我感觉这个问题是配置或者宏定义不正常造成的,getchar是已经移植好的,它通过不 ...


大概明白你的意思了。

1、你的项目中使用的软件模式中断模式,在流程处理上实际也是按照中断的流程,所以你在中断设备注册时使用中断是没有问题的,只不过是软中断;

2、注入数据,直接使用 rt_hw_serial_isr 来通知就好,软中断是没法规避轮训接收数据的问题。
moebius.ever
moebius.ever 2018-03-21
Spunky 发表于 2018-3-19 23:11
getchar()在哪里移植好了的,我没有找到。


如果使用 gcc编译器, 使用newlib的话,是在rt-thread\components\libc\compilers\newlib里实现的,因为编译器里有一段代码,你从getchar是直接定位不到它调用的函数的,我的单步调试时最终调用的应该是 syscalls.c里的_ssize_t
_read_r(struct _reent *ptr, int fd, void *buf, size_t nbytes),具体没有再试
moebius.ever
moebius.ever 2018-03-21
armink 发表于 2018-3-20 10:13
大概明白你的意思了。

1、你的项目中使用的软件模式中断模式,在流程处理上实际也是按照中断的流程,所 ...


是的,不过我觉着这个应该是现在比较简单的处理方案了,不知道rt-thread有没有处理需要轮询接收数据的方案
armink
armink 2018-03-21
moebius.ever 发表于 2018-3-21 14:21
是的,不过我觉着这个应该是现在比较简单的处理方案了,不知道rt-thread有没有处理需要轮询接收数据的方 ...

你可以增加一个 POLL 读模式,然后 pr 出来哈。
有问题的地方,我可以协助你
moebius.ever
moebius.ever 2018-03-21
armink 发表于 2018-3-21 18:31
你可以增加一个 POLL 读模式,然后 pr 出来哈。
有问题的地方,我可以协助你
...


我试试
tanek
tanek 2018-07-23
我也尝试在不支持中断模式下,使用shell。

是基于IDLE HOOK来做的。在serial的control接口里,有开关中断的配置。

对应的打开中断就是注册hook,关闭中断就是删除hook。需要注意的问题是有可能会重复配置,需要处理一下。

具体实现在这里
moebius.ever
moebius.ever 2018-07-29
tanek 发表于 2018-7-23 11:27
我也尝试在不支持中断模式下,使用shell。

是基于IDLE HOOK来做的。在serial的control接口里,有开关中断 ...


赞一个,我是直接在空闲线程里做的,感觉不优雅
阿吉1234
阿吉1234 2019-09-20
hi,我在risc-v上跑rtt也遇到这个问题。请问这个问题有标准的解决方法吗?

撰写答案

请登录后再发布答案,点击登录

发布
问题

分享
好友