RT-Thread动态模块mo调试设备驱动小结

电子说

1.2w人已加入

描述

前言
动态驱动模块的调试可以减少烧录过程,对于调试来说是一件很快乐的事情。
rtt中有动态模块概念,而且和linux中的命名类似为分为mo和so,其中mo在笔者浅显的理解即类似于linux中的elf,即可执行文件。同时linux中的ko也是elf文件一种,所以想rtt中的mo和linux中的ko是否可以实现同样的功能。以下以uart串口驱动模块的动态加载调试作为示例讲解整个操作流程。

正文
准备步骤
首先是准备步骤:搭建环境,编译生成mo。这里可以参考RT_Thread编程指南中的28节 动态模块章节,使用过程中注意linux环境中也需要设置环境变量(RTT_ROOT、BSP_ROOT)。
我这里使用的是github仓库中的hello模块。编译生成hello.mo,在msh中执行hello,输出hello,这一步工作完成。

编译驱动mo
接下来是编译生成uart的设备驱动,并且注册到rtt的设备驱动管理框架中。
以下是hello.c中的代码,代码比较多,截取了主要部分,因为针对于不同平台的串口初始化函数是不一样的。
在main中调用rt_hw_uart_init();实现对串口驱动的注册。

int rt_hw_uart_init(void)
{
struct rt_serial_device *serial;
struct device_uart *uart;
struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
static struct rt_serial_device serial1;
static struct device_uart uart1;
serial = &serial1;
uart = &uart1;
serial->ops = &_uart_ops;
serial->config = config;
serial->config.baud_rate = 115200;
rt_hw_serial_register(serial,
"uart1",
RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
uart);
return 0;
}
int main(int argc, char *argv[])
{
printf("hello world from RTT::dynamic modulen");
rt_hw_uart_init();
return 0;
}
这里会出现两个问题:

问题一:动态模块加载缺少函数符号问题

问题二:动态驱动模块加载报错【rt_object_init】是否存在bug?

以上是针对两个问题的解决方式。

针对问题二做一下补充说明

#ifdef RT_USING_MODULE
if (module)
{
if(rt_strcmp(object->name,"uart1") == 0)
{
rt_list_insert_after(&(information->object_list), &(object->list));
object->module_id = (void *)module;
}
else
{
rt_list_insert_after(&(module->object_list), &(object->list));
object->module_id = (void )module;
}
}
else
#endif /
RT_USING_MODULE /
{
/
insert object into information object list */
rt_list_insert_after(&(information->object_list), &(object->list));
}

这里 if(rt_strcmp(object->name,”uart1”) == 0)比较的设备是uart1,如果你的hello.c中的注册设备是其他记得修改

这里,同时这里也是一个极其不合理的存在。正在思考如何修改

编译执行完后,在msh执行hello.c,使用指令list_device可以观察到存在uart1设备,说明运行成功。

调试器

测试驱动是否正常
编写串口测试程序

/*

Program list: This is a uart device usage routine
The routine exports the uart_sample command to the control terminal
Format of command: uart_sample uart2
Command explanation: the second parameter of the command is the name of the uart device. If it is null, the default uart device wil be used
Program function: output the string "hello RT-Thread!" through the serial port, and then malposition the input character
/
#include
#define SAMPLE_UART_NAME "uart1"
/
Semaphore used to receive messages /
static struct rt_semaphore rx_sem;
static rt_device_t serial;
/
Receive data callback function /
static rt_err_t uart_input(rt_device_t dev, rt_size_t size)
{
/
After the uart device receives the data, it generates an interrupt, calls this callback function, and then sends the received semaphore. */
rt_sem_release(&rx_sem);
return RT_EOK;
}
static void serial_thread_entry(void parameter)
{
char ch;
while (1)
{
/
Read a byte of data from the serial port and wait for the receiving semaphore if it is not read /
while (rt_device_read(serial, -1, &ch, 1) != 1)
{
/
Being Suspended and waiting for the semaphore /
rt_sem_take(&rx_sem, RT_WAITING_FOREVER);
}
/
Read the data from the serial port and output through dislocation */
ch = ch + 1;
rt_device_write(serial, 0, &ch, 1);
}
}
static int uart_sample(int argc, char argv[])
{
rt_err_t ret = RT_EOK;
char uart_name[RT_NAME_MAX];
char str[] = "hello RT-Thread!rn";
if (argc == 2)
{
rt_strncpy(uart_name, argv[1], RT_NAME_MAX);
}
else
{
rt_strncpy(uart_name, SAMPLE_UART_NAME, RT_NAME_MAX);
}
/
Find uart devices in the system /
serial = rt_device_find(uart_name);
if (!serial)
{
rt_kprintf("find %s failed!n", uart_name);
return RT_ERROR;
}
/
Initialize the semaphore /
rt_sem_init(&rx_sem, "rx_sem", 0, RT_IPC_FLAG_FIFO);
/
Open the uart device in interrupt receive and polling send mode /
rt_device_open(serial, RT_DEVICE_FLAG_INT_RX);
/
Set the receive callback function /
rt_device_set_rx_indicate(serial, uart_input);
/
Send string /
rt_device_write(serial, 0, str, (sizeof(str) - 1));
/
Create a serial thread /
rt_thread_t thread = rt_thread_create("serial", serial_thread_entry, RT_NULL, 1024, 25, 10);
/
Start the thread successfully /
if (thread != RT_NULL)
{
rt_thread_startup(thread);
}
else
{
ret = RT_ERROR;
}
return ret;
}
/
Export to the msh command list */
MSH_CMD_EXPORT(uart_sample, uart device sample);

在msh中输入uart_sample,驱动打开,初始化正常。观察uart1工作是否正常。正常说明驱动加载运行正常。

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分