c语言上下文的快速切换
前言我们通常认为,在中断中,不能执行耗时的操作,否则会影响系统的稳定性,尤其对于嵌入式编程。对于带操作系统的程序而言,可以通过操作系统的调度,将中断处理分成两个部分,耗时的操作可以放到线程中去执行,但是对于没有操作系统的情况,又应该如何处理呢
比较常见的,我们可能会定义一些全局变量,作为flag,然后在mainloop中不停的判断这些flag,再在中断中修改这些flag,最后在mainloop中执行具体的逻辑,但是这样,无疑会增加耦合,增加程序维护成本
cpostcpost正是应用在这种情况下的一个简单但又十分方便的工具,它可以特别方便的进行上下文的切换,减少模块耦合
cpost借鉴的Android的handler机制,通过在mainloop中跑一个任务,然后在其他地方,可以是中断,也可以是模块逻辑中,直接抛出需要执行的函数,使其脱离调用处的上下文,运行在mainloop中。cpost还支持延迟处理,可以指定函数在抛出后多久执行
使用cpost的使用十分简单,这里以使用在嵌入式无操作系统中为例,主要用作中断延迟处理的情况
配置系统tick
配置cpost.h中的宏CPOST_GET ...
C语言模块化编程的完美解耦
前言对于模块化编程来说,如何实现各模块间的解耦一直是一个比较令人头疼的问题,特别是对于嵌入式编程,由于控制逻辑复杂,并且对程序体积有控制,经常容易写出各独立模块之间相互调用的问题。由此,cpost中的cevent组件,通过模仿Android系统中的广播机制,提供了一种非常简单的模块间解耦实现
原理cevent借鉴的是Android系统的广播机制,一方面,各模块在工作的时候,都会有多个具体的事件点,在高耦合的编程中,可能会在这些地方调用其他模块的功能,比如说,在通信模块接收到指令的时候,需要闪烁一下指示灯
使用cevent,我们可以在这些地方抛出一个事件,当前模块不需要关心在这各地方需要执行哪些其他模块的逻辑,由其他模块,或者用户定义一个事件监听,当具体的事件发生时,执行相应的动作
使用cevent使用注册的方式监听事件,会依赖于编译环境,目前支持keil,iar,和gcc,对于gcc,需要修改链接文件(.ld),在只读数据区添加:
123_cevent_start = .;KEEP (*(cEvent))_cevent_end = .;
初始化cevent
系统初始化时,调用ce ...
Android 音频框架分析
初始化
系统开机启动时,加载init.rc,启动mediaserver,在Android7.0之后,启动mediaserver的脚本被分离在了audioserver.rc文件中
12345service media /system/bin/mediaserver class main user media group audio camera inet net_bt net_bt_admin net_bw_acct drmrpc mediadrm ioprio rt 4
mediaserver源码位置为frameworks/av/media/mediaserver,mediaserver目录中主要只有main_mediaserver.cpp一个文件,用于启动AudioFlinger, AudioPolicyService, RadioService等服务,其中与音频相关的主要是AudioFlinger和AudioPolicyService
1234567891011121314151617181920int main(int argc __unused, ch ...
STM32从原理入门(一)-点灯(上篇)
前言有了基本概念之后,下一步要做的,就是搭建好适合自己的开发环境。STM32可以选择的开发环境很多,这个我在上一篇文章里面也提到过,对于初学者,这里就直接选择keil吧,同时搭配STM32Cube MX做工程配置。当然,一开始的工程肯定不能使用STM32Cube MX生成,我们需要手动创建工程,只有这样才能对工程的结构有深入的了解
准备工作
安装开发环境
在编写程序之前,请确认已经安装好keil软件,并安装芯片对应的包,这部分网上教程很多,请自行查找
准备好开发板
嵌入式开发离不开硬件,请确保至少要有一块开发板或者自己制作PCB,本篇文章的内容,至少需要用到一个LED资源
准备好文档
芯片手册和开发板原理图是必须要的,本篇文章所使用的芯片是STM32F407系列的,所以我准备了STM32F4xx参考手册,具体手册可以到ST官网下载(学会查找资料也是一个重要的技能)
建立工程打开keil软件,通过project选项卡新建工程,选择工程目录和工程名,选择对应的芯片,创建工程,此时,keil可能会弹出一下的窗口
这是keil本身支持的组件管理工具,我们可以在这里直接添加一些包 ...
STM32从原理入门(零)-起点
前言我从毕业工作到现在,已经整整两年了,和STM32打交道也已经有三年了,这期间,碰到的问题不少,解决的问题也很多,而且也体会到了使用STM32实实在在做产品开发,同时也有了自己的开源项目,要我自己评价的话,那就是对于STM32,对于嵌入式软件开发,算是入门了
网上针对STM32的教程很多,非常优秀的教程也不少,但是,大多数教程,都只是在告诉你要怎么做,很少有教程会详细分析,为什么要这么做,我个人认为,知道为什么,要比只知道怎么做重要的太多,毕竟,你不可能永远都只用一种芯片,一套工具或者一套外设
所以我希望通过自己的几篇文章,和大家分享一下自己这几年攒下来的知识,希望可以有效地帮助想学习相关知识的朋友,当然,文章中免不了会有一些错误,大家可以直接指出,一起交流
单片机、MCU、STM32?一开始学过51单片机的朋友可能会混淆一些概念,认为所谓的单片机就是指51,简单来说,一块包含处理器(CPU),存储器(RAM和ROM),包含IO和各种外设的芯片就可以叫做单片机,所以STM32也是单片机的一种,而MCU其实就是指的单片机
STM32是意法半导体推出的基于arm cortex-m内核的M ...
letter-shell代理函数解析
前言letter shell默认支持整形,字符,字符串参数的自动解析,我一直以为,浮点型的参数也是可以支持的,结果前几天发现,浮点型参数只在某些特定情况下可以使用(仅当浮点型参数为函数的最后一个参数时),为此,我尝试了一种新的方式,从而引出了代理函数和代理参数解析的概念,可以实现任意类型参数的解析
原理如果你需要导出一个命令到shell,但是函数又有shell原生不支持的数据类型,比如说void test(int a, float b, int c, float d),那么要怎么办呢
最简单的,你可能会重新定义一个函数void testWarpper(int a, int b, int c, int d),在这个函数里面对参数进行转换,调用test,然后导出testWarpper作为命令
这就是所谓代理函数的概念,letter shell的代理函数就是基于此,只不过通过宏,简化了代理函数的定义,代理函数宏定义如下:
123456789101112131415/** * @brief shell 代理函数名 */#define SHELL_AGENCY_FUNC_NAME(_fu ...
Letter shell 3.0 全新出发
前言从我一开始写letter shell已经一年多了,从1.x版本shell只能做命令解析,到2.x版本加入快捷键等功能,letter shell功能慢慢变多,但是体积也越来越大,似乎违背了我一开始只是想做一个超小型调试工具的想法,因此,我重新实现了letter shell 3.0,作为一个功能更加强大的版本,原先的2.x版本保留原有功能,继续维护。
3.0改变了什么letter shell 3.0保留了2.x版本的所有功能,此次新增加了用户管理,权限管理,加入了对main函数形式和普通C函数命令的同时支持,加强了快捷键功能,此外,后续还会增加文件系统支持等其他功能
移植letter shell 3.0在一直这一块基本保留了2.x的结构,原先使用2.x版本的如果想迁移,只需要简单的修改即可
定义shell
首先定义shell对象,3.0版本修改了结构体命名,从2.x版本迁移的话需要注意
新建一个shell_port.c文件,定义shell
1Shell shell;
申请内存
letter shell需要申请一片内存作为数据缓冲,申请内存大小取决于你希望命令行输入的最大长度 ...
Android 技巧总结
ADB
隐藏虚拟键及顶部状态栏:
adb shell settings put global policy_control immersive.full=*
隐藏顶部状态栏(底部虚拟键会显示):
adb shell settings put global policy_control immersive.status=*
隐藏虚拟键(顶部状态栏会显示):
adb shell settings put global policy_control immersive.navigation=*
恢复原来的设置:
adb shell settings put global policy_control null
在C语言上优雅地使用json
前言json是目前最为流行的文本数据传输格式,特别是在网络通信上广泛应用,随着物联网的兴起,在嵌入式设备上,也需要开始使用json进行数据传输,那么,如何快速简洁地用C语言进行json的序列化和反序列化呢
当前,应用最广泛的C语言json解析库当属cJSON,但是,使用cJSON读json进行序列化和反序列化,需要根据key一个一个进行处理,会导致代码冗余,逻辑性不强,哪有没有更好的方法呢
思路在Android平台,一般会使用gson等工具解析json,这些工具将json直接映射成对象,在C语言上使用对象的概念,我们需要借助结构体,然而,最大的问题在于,C语言没有高级语言具有的反射机制,直接从json映射到结构体对象几乎是不可能的
怎么解决呢,既然C语言没有反射机制,那么我们可以自己定义一套类似于反射的机制,这里我将其称之为结构体数据模型,在数据模型中,我们需要准确地描述结构体的特征,包括结构体各成员的名称,类型,在结构体中的偏移,有了这些,我们可以在解析josn的时候,将解析得到的数据直接写入到对应的内存里面去,或者是在序列化的时候,直接从对应的内存中读取数据,进行处理
实现CS ...
Android 自定义颜色选择器的实现
前言某日,突然产生想法,给我自己做的纪念日的APP加一个主题色的功能,那自然就需要用到颜色选择器了,在网上搜索了一圈,没找到自己想要的,于是干脆就自己做一个吧。刚好最近也在研究Kotlin,于是就拿Kotlin写了一个简单的颜色选择器
先上效果图:
颜色盘颜色选择器最基本的元素就是单个的颜色控件了,简单的颜色控件设计只需要一个单色的圆加上边框就行,就直接用View画了
首先定义好ColorPane所需要的自定义属性,包括颜色属性,边框颜色和边框宽度
12345<declare-styleable name = "ColorPane"> <attr name="color" format="color" /> <attr name="strokeColor" format="color" /> <attr name="strokeWidth" format="dimension" /& ...