【Contiki学习】01.Contiki-stm32系统下实现serial-shell功能_contiki stm32-程序员宅基地

技术标签: contiki  STM32  ContikiOS  

一,背景介绍

之前通过网上收集资料(资料后期整理之后会在博客分享),在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("Initialising\r\n");
  
  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 running\r\n");
  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 <command>: stop a specific command",
	      &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 <command>: command name must be given", "");
  }


  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初始化的时候一并初始化即可


其他的内容,在后续的学习中将陆续记录。

ps.我还只是个初级入门的菜鸟,有些地方写的有问题也请大家指点啊。

贴上我的源码:(仅供参考)

点击打开链接

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/u014572382/article/details/54863484

智能推荐

linux下编译GDAL外加扩展格式支持(五)--完-程序员宅基地

文章浏览阅读229次。接1、2、3、4篇。10、安装mysql支持安装fedora15或者16系统时若选择安装mysql数据库,则必须自行安装mysql开发包。因为自带默认数据库不会安装这个包。否则会遇到mysql错误:ogr_mysql.h:34:23: fatal error: my_global.h: No such file or directory#问题原因:找不到mysql头文件..._linux gdal netcdf5

Linux tc qdisc 模拟网络丢包延时-程序员宅基地

文章浏览阅读1.2k次。Linux tc qdisc 模拟网络丢包延时_tc qdisc

linux64bit 安装 jdk 1.7-程序员宅基地

文章浏览阅读336次。linux64bit 安装 jdk 1.7下载地址 : https://edelivery.oracle.com/otn-pub/java/jdk/7u21-b11/jdk-7u21-linux-x64.rpm0. 卸载rpm版的jdk: #rpm -qa|grep jdk 显示:jdk-1.6.0_10-fcs 卸载:#rpm -e --nodep..._liunx64位得jdk1.7

【Linux笔记】-----Nginx/LVS/HAProxy负载均衡的优缺点_中间件应用场景nginx lvs proxy-程序员宅基地

文章浏览阅读552次。开始听到负载均衡的时候,我第一反应想到的是链路负载均衡,在此之前主要是在学习网络方面知识,像在NA、NP阶段实验做链路负载均衡时常会遇到,后来还接触到SLB负载分担技术,这都是在链路基础上实现的。 其实负载均衡可以分为硬件实现负载均衡和软件实现负载均衡。 硬件实现负载均衡:常见F5和Array负载均衡器,配套专业维护服务,但是成本昂贵。 软件实现负载均衡:常见开源免费的负载均衡软件有Ngin..._中间件应用场景nginx lvs proxy

多维时序 | MATLAB实现CNN-LSTM多变量时序预测_cnn可以进行多步预测-程序员宅基地

文章浏览阅读4.7k次。多维时序 | MATLAB实现CNN-LSTM多变量时序预测目录多维时序 | MATLAB实现CNN-LSTM多变量多步预测基本介绍模型特点程序设计学习总结参考资料基本介绍本次运行测试环境MATLAB2020b,MATLAB实现CNN-LSTM多变量多步预测。模型特点深度学习使用分布式的分层特征表示方法自动提取数据中的从最低层到最高层固有的抽象特征和隐藏不变结构. 为了充分利用单个模型的优点并提高预测性能, 现已提出了许多组合模型。CNN 是多层前馈神经网络, 已被证明在提取隐藏_cnn可以进行多步预测

随便推点

【9.3】用户和组的管理、密码_polkitd:input 用户和组-程序员宅基地

文章浏览阅读219次。3.1 用户配置文件和密码配置文件3.2 用户组管理3.3 用户管理3.4 usermod命令3.5 用户密码管理3.6 mkpasswd命令_polkitd:input 用户和组

pca算法python代码_三种方法实现PCA算法(Python)-程序员宅基地

文章浏览阅读670次。主成分分析,即Principal Component Analysis(PCA),是多元统计中的重要内容,也广泛应用于机器学习和其它领域。它的主要作用是对高维数据进行降维。PCA把原先的n个特征用数目更少的k个特征取代,新特征是旧特征的线性组合,这些线性组合最大化样本方差,尽量使新的k个特征互不相关。关于PCA的更多介绍,请参考:https://en.wikipedia.org/wiki/Prin..._inprementation python code of pca

内存地址Linux下内存分配与映射之一-程序员宅基地

文章浏览阅读35次。发一下牢骚和主题无关:地址类型:32位的cpu,共4G间空,其中0-3G属于用户间空地址,3G-4G是内核间空地址。用户虚拟地址:用户间空程序的地址物理地址:cpu与内存之间的用使地址总线地址:外围总线和内存之间的用使地址内核逻辑地址:内存的分部或全体射映,大多数情况下,它与物理地址仅差一个偏移量。如Kmalloc分..._linux 内存条与内存地址

自动化测试介绍_自动化测试中baw库指的什么-程序员宅基地

文章浏览阅读1.3k次,点赞2次,收藏16次。什么是自动化测试?   做测试好几年了,真正学习和实践自动化测试一年,自我感觉这一个年中收获许多。一直想动笔写一篇文章分享自动化测试实践中的一些经验。终于决定花点时间来做这件事儿。  首先理清自动化测试的概念,广义上来讲,自动化包括一切通过工具(程序)的方式来代替或辅助手工测试的行为都可以看做自动化,包括性能测试工具(loadrunner、jmeter),或自己所写的一段程序,用于_自动化测试中baw库指的什么

a0图框标题栏尺寸_a0图纸尺寸(a0图纸标题栏尺寸标准国标)-程序员宅基地

文章浏览阅读1.6w次。A0纸指的是一平方米大小的白银比例长方形纸(长为1189mm宽为841mm)。A0=1189mm*841mm A1=841mm*594mm 相当于1/2张A0纸 A2=594mm*420mm 相当于1/4.A1图纸大小尺寸:841mm*594mm 即长为841mm,宽为594mm 过去是以多少"开"(例如8开或16开等)来表示纸张的大小,我国采用国际标准,规定以 A0、A1、A2、.GB/T 14..._a0图纸尺寸

TreeTable的简单实现_treetable canvas-程序员宅基地

文章浏览阅读966次。最终效果图:UI说明:针对table本身进行增强的tree table组件。 tree的数据来源是单元格内a元素的自定义属性:level和type。具体代码如下:Java代码 DepartmentEmployeeIDposi_treetable canvas