前言
動(dòng)態(tài)驅(qū)動(dòng)模塊的調(diào)試可以減少燒錄過程,對(duì)于調(diào)試來說是一件很快樂的事情。
rtt中有動(dòng)態(tài)模塊概念,而且和linux中的命名類似為分為mo和so,其中mo在筆者淺顯的理解即類似于linux中的elf,即可執(zhí)行文件。同時(shí)linux中的ko也是elf文件一種,所以想rtt中的mo和linux中的ko是否可以實(shí)現(xiàn)同樣的功能。以下以uart串口驅(qū)動(dòng)模塊的動(dòng)態(tài)加載調(diào)試作為示例講解整個(gè)操作流程。
正文
準(zhǔn)備步驟
首先是準(zhǔn)備步驟:搭建環(huán)境,編譯生成mo。這里可以參考RT_Thread編程指南中的28節(jié) 動(dòng)態(tài)模塊章節(jié),使用過程中注意linux環(huán)境中也需要設(shè)置環(huán)境變量(RTT_ROOT、BSP_ROOT)。
我這里使用的是github倉(cāng)庫(kù)中的hello模塊。編譯生成hello.mo,在msh中執(zhí)行hello,輸出hello,這一步工作完成。
編譯驅(qū)動(dòng)mo
接下來是編譯生成uart的設(shè)備驅(qū)動(dòng),并且注冊(cè)到rtt的設(shè)備驅(qū)動(dòng)管理框架中。
以下是hello.c中的代碼,代碼比較多,截取了主要部分,因?yàn)獒槍?duì)于不同平臺(tái)的串口初始化函數(shù)是不一樣的。
在main中調(diào)用rt_hw_uart_init();實(shí)現(xiàn)對(duì)串口驅(qū)動(dòng)的注冊(cè)。
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;
}
這里會(huì)出現(xiàn)兩個(gè)問題:
問題一:動(dòng)態(tài)模塊加載缺少函數(shù)符號(hào)問題
問題二:動(dòng)態(tài)驅(qū)動(dòng)模塊加載報(bào)錯(cuò)【rt_object_init】是否存在bug?
以上是針對(duì)兩個(gè)問題的解決方式。
針對(duì)問題二做一下補(bǔ)充說明
#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)比較的設(shè)備是uart1,如果你的hello.c中的注冊(cè)設(shè)備是其他記得修改
這里,同時(shí)這里也是一個(gè)極其不合理的存在。正在思考如何修改
編譯執(zhí)行完后,在msh執(zhí)行hello.c,使用指令list_device可以觀察到存在uart1設(shè)備,說明運(yùn)行成功。
測(cè)試驅(qū)動(dòng)是否正常
編寫串口測(cè)試程序
/*
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,驅(qū)動(dòng)打開,初始化正常。觀察uart1工作是否正常。正常說明驅(qū)動(dòng)加載運(yùn)行正常。
-
調(diào)試器
+關(guān)注
關(guān)注
1文章
300瀏覽量
23692 -
串口驅(qū)動(dòng)
+關(guān)注
關(guān)注
2文章
82瀏覽量
18624 -
LINUX內(nèi)核
+關(guān)注
關(guān)注
1文章
316瀏覽量
21619 -
RT-Thread
+關(guān)注
關(guān)注
31文章
1274瀏覽量
39938 -
Uart串口
+關(guān)注
關(guān)注
0文章
29瀏覽量
6799
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論