历史上的今天
今天是:2025年04月07日(星期一)
2020年04月07日 | 【Contiki学习】01.Contiki-stm32系统下实现serial-shell功能
2020-04-07 来源:eefocus
一,背景介绍
之前通过网上收集资料(资料后期整理之后会在博客分享),在stm32上面跑通了,就是实现了简单的点灯程序,以及串口输出。
但是后期开发使用肯定需要用到shell,经过一番折腾后小有收获。
在这说一下开发环境:IAR+stm32vet6(ST官方库3.5+contiki3.0)
二,准备工作
1,在contiki源码中按照目录提取以下文件:


ps. stm32_shell.c是自行添加的代码
三,源码分析
1,先看一下main函数:
int main()
{
dbg_setup_uart();
led_init();
printf("Initialisingrn");
clock_init();
process_init();
//shell serial_line 初始化
uart1_set_input(serial_line_input_byte);
serial_line_init();
//
process_start(&etimer_process, NULL);
autostart_start(autostart_processes);
printf("Processes runningrn");
while(1) {
do
{
}
while(process_run() > 0);
idle_count++;
/* Idle! */
/* Stop processor clock */
/* asm("wfi"::); */
}
return 0;
}
需要注意的是:
//shell serial_line 初始化
uart1_set_input(serial_line_input_byte);
serial_line_init();
//
2,usrt1_set_input定义在串口底层驱动里面
static int (* uart1_input_handler)(unsigned char c);
void uart1_set_input(int (* input)(unsigned char c))
{
uart1_input_handler = input;
}
先建立一个函数指针:
static int (* uart1_input_handler)(unsigned char c);
再通过
uart1_set_input(serial_line_input_byte);
将(*uart1_input_handler)指向 serial_line_input_byte()函数,
这样就可以通过调用uart1_input_handler();将串口接到的数据导入serial_line中,从而可以通过serial_line_process进程进行命令分析做出相应处理。
uart1_input_handler();的调用写在串口中断中即可:
void USART1_IRQHandler(void)
{
ENERGEST_ON(ENERGEST_TYPE_IRQ);
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
{
if(uart1_input_handler != NULL)
{
/* Read one byte from the receive data register */
uint8_t buf = USART_ReceiveData(USART1);
uart1_input_handler(buf);
}
}
ENERGEST_OFF(ENERGEST_TYPE_IRQ);
}
3,通过上面的处理已经把串口接收到的数据导入serial_line中了,当然串口配置初始化在这就不用多说了,接下来就是要把shell进程加入系统了:
调用serial_shell_init()函数即可
定义:
void
serial_shell_init(void)
{
process_start(&serial_shell_process, NULL);
}
就是开启serial_shell_process进程,但是我这边新建立一个进程,用于后续其他自定义的shell命令的初始化:
#include "contiki.h"
#include "shell.h"
#include "serial-shell.h"
PROCESS(stm32_shell_process, "STM32 Contiki Shell");
PROCESS_THREAD(stm32_shell_process, ev, data)
{
PROCESS_BEGIN();
serial_shell_init();//初始化shell
PROCESS_END();
}
然后再将改进程加入main函数即可,
到这边就已经完成了shell的功能,可以通过串口看见

发送 help(加回车)

这是一些默认的命令,你也可以自己定义一些命令,通过阅读shell部分的源码进一步了解原理。
4,在shell.c中可以看见关于上面打印出来的命令的定义,其实每个shell命令对应一个process,
PROCESS(help_command_process, "help");
SHELL_COMMAND(help_command, "help", "help: shows this help",
&help_command_process);
SHELL_COMMAND(question_command, "?", "?: shows this help",
&help_command_process);
PROCESS(shell_killall_process, "killall");
SHELL_COMMAND(killall_command, "killall", "killall: stop all running commands",
&shell_killall_process);
PROCESS(shell_kill_process, "kill");
SHELL_COMMAND(kill_command, "kill", "kill &shell_kill_process); PROCESS(shell_null_process, "null"); SHELL_COMMAND(null_command, "null", "null: discard input", &shell_null_process); PROCESS(shell_exit_process, "exit"); SHELL_COMMAND(exit_command, "exit", "exit: exit shell", &shell_exit_process); SHELL_COMMAND(quit_command, "quit", "quit: exit shell", &shell_exit_process); PROCESS_THREAD(shell_kill_process, ev, data) { struct shell_command *c; char *name; PROCESS_BEGIN(); name = data; if(name == NULL || strlen(name) == 0) { shell_output_str(&kill_command, "kill } for(c = list_head(commands); c != NULL; c = c->next) { if(strcmp(name, c->command) == 0 && c != &kill_command && process_is_running(c->process)) { command_kill(c); PROCESS_EXIT(); } } shell_output_str(&kill_command, "Command not found: ", name); PROCESS_END(); } 5,添加自定义命令通过一下方式即可: #include "contiki.h" #include "shell.h" #include "stdio.h" #include "string.h" #include "stm32f10x.h" PROCESS(shell_blink_process, "shell blink"); SHELL_COMMAND(blink_command, "blink", "blink on/off : led on/off", &shell_blink_process); static void led_init() { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOF,ENABLE); GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7; GPIO_Init(GPIOF, &GPIO_InitStructure); } /** * brief * param * */ static void led_on() { GPIO_SetBits(GPIOF, GPIO_Pin_7); } static void led_off() { GPIO_ResetBits(GPIOF, GPIO_Pin_7); } PROCESS_THREAD(shell_blink_process, ev, data) { PROCESS_BEGIN(); if(data != NULL) { if(strcmp(data, "on")) { led_on(); } else if(strcmp(data, "off")) { led_off(); } else { printf("Invalid param!n"); } } PROCESS_END(); } void shell_blink_init(void) { led_init(); shell_register_command(&blink_command); } a,通过SHELL_COMMAND(blink_command, "blink", "blink on/off : led on/off", &shell_blink_process);定义shell命令; b,通过shell_register_command(&blink_command);在shell初始化的时候一并初始化即可
史海拾趣
|
随着微电子技术和超大规模集成电路技术的发展,单片微型计算机以其体积小、性价比 高、功能强、可靠性高等独有的特点, 在各个领域(如工业控制、家电产品、汽车电子、通信、智能仪器仪表)得到了广泛的应 用。学习、使用单片机的人越来越多, 而生 ...… 查看全部问答> |
|
业界主要高端ASIC原型校验产品列表 这个表格验证了前面的初步判断,在高端领域,不论是FPGA芯片的数量,还是目标验证芯片的规模,赛灵思占有着绝对的市场地位。其中: l 在1片FPGA数量的板卡规模产品上,大部分公司既可以开发基于Altera FPGA的 ...… 查看全部问答> |
|
留个QQ号,大家在使用过程中遇到问题,可以交流!我们的群号是85824260 [ 本帖最后由 jxb01033016 于 2009-9-16 10:01 编辑 ]… 查看全部问答> |
|
在Vxworks下虚拟ftp客户端问题登陆到windowsFTP服务器上,通过ftpCommand(ctrlSock, \"HELP\",0, 0, 0, 0, 0, 0),或LIST、PWD等命令,请问命令执行的结果回显到哪里了? 通过这种方式发送的命令都会执行,比如MKD就可以看到创建的目录,但就是不 ...… 查看全部问答> |
|
我开发了一套控制程序。该控制程序是用C写的,并在仿真和实验室环境都验证过了。在实际的工业应用中,该程序需要运行在基于DSP的数字控制硬件系统上。根据被控对象的不同特点,用户需要能够修改参数。所以我希望能详细了解程序的封装技术,即如何能 ...… 查看全部问答> |
|
晶振是11.0592 我想得到一秒的时间 TMOD=0x01; //定时时间50ms TH0= -46080/256; TL0= -46080%256;   ...… 查看全部问答> |
|
stm8编译后生成的.map看不懂了。 “.const”因该是rom吧,那“.text"又是什么? “.ubsct”、“.data, initialized”、“.data, from”、“.bss”因该是ram吧,但他们有什么区别? 更奇怪的是“.debug”,它怎么从地址0开始了?它因该不会 ...… 查看全部问答> |
|
工信部 7月4日发布的数据显示,5月我国电子信息制造业内销、出口交货值增速比4月分别提高3和0.7个百分点 ,电子信息制造业有望逐步企稳回升。 1-5月,规模以上电子制造业增加值同比增长13.1%;实现销售产值31724亿元,同比增长11.2%。其中,5月 ...… 查看全部问答> |




