电子说
前言
动态驱动模块的调试可以减少烧录过程,对于调试来说是一件很快乐的事情。
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工作是否正常。正常说明驱动加载运行正常。
全部0条评论
快来发表一下你的评论吧 !