RT-Thread 邮箱与消息队列

邮箱 RT-Thread 操作系统的邮箱用于线程间通信,特点是开销比较低,效率较高。邮箱中的每一封邮件只能容纳固定的 4 字节内容(针对 32 位处理系统,指针的大小即为 4 个字节,所以一封邮件恰好能够容纳一个指针)。典型的邮箱也称作交换消息。 邮件发送不具有加急(插队)的功能。 静态邮箱初始化 初始化前资源要静态地创建。 rt_err_t rt_mb_init(rt_mailbox_t mb, const char *name, void *msgpool, rt_size_t size, rt_uint8_t flag) 静态邮箱脱管 把静态初始化的邮箱对象从内核对象管理器中脱离。 rt_err_t rt_mb_detach(rt_mailbox_t mb) 创建邮箱 动态地创建邮箱并初始化。 rt_mailbox_t rt_mb_create(const char *name, rt_size_t size, rt_uint8_t flag) 删除邮箱 脱管邮箱并释放动态资源,与 rt_mb_create 配合使用。 rt_err_t rt_mb_delete(rt_mailbox_t mb) 发送邮件 rt_err_t rt_mb_send (rt_mailbox_t mb, rt_uint32_t value) 函数调用了rt_mb_send_wait,timeout = 0 以等待方式发送邮件 邮箱满时等待。 rt_err_t rt_mb_send_wait(rt_mailbox_t mb, rt_uint32_t value, rt_int32_t timeout) 接收邮件 支持空等待。 rt_err_t rt_mb_recv(rt_mailbox_t mb, rt_uint32_t *value, rt_int32_t timeout) 邮箱控制 不常用。 rt_err_t rt_mb_control(rt_mailbox_t mb, rt_uint8_t cmd, void *arg) 2.1.0 版 支持的命令 RT_IPC_CMD_RESET(复位邮箱) timeout 支持以下宏: #define RT_WAITING_FOREVER -1 /**< Block forever until get resource. */ #define RT_WAITING_NO 0 /**< Non-block. */ 消息队列 消息队列能够接收来自线程或中断服务例程中不固定长度的消息,并把消息缓存在自己的内存空间中。其他线程也能够从消息队列中读取相应的消息,而当消息队列是空的时候,可以挂起读取线程。当有新的消息到达时,挂起的线程将被唤醒以接收并处理消息。消息队列是一种异步的通信方式。 很遗憾的是消息队列不支持发送阻塞模式(像邮箱那样的发送等待)。 消息队列初始化 静态创建。 rt_err_t rt_mq_init(rt_mq_t mq, const char *name, void *msgpool, rt_size_t msg_size, rt_size_t pool_size, rt_uint8_t flag) 消息队列脱管 rt_err_t rt_mq_detach(rt_mq_t mq) 动态创建消息队列 rt_mq_t rt_mq_create(const char *name, rt_size_t msg_size, rt_size_t max_msgs, rt_uint8_t flag) 删除消息队列 rt_err_t rt_mq_delete(rt_mq_t mq) 发送消息到队列 线程或者中断服务程序都可以给消息队列发送消息。当发送消息时,消息队列对象先从空闲消息链表上取下一个空闲消息块,把线程或者中断服务程序发送的消息内容复制到消息块上,然后把该消息块挂到消息队列的尾部。当且仅当空闲消息链表上有可用的空闲消息块时,发送者才能成功发送消息;当空闲消息链表上无可用消息块,说明消息队列已满,此时,发送消息的的线程或者中断程序会收到一个错误码(-RT_EFULL)。 rt_err_t rt_mq_send(rt_mq_t mq, void *buffer, rt_size_t size) 发送紧急消息到队列 发送紧急消息的过程与发送消息几乎一样,唯一的不同是,当发送紧急消息时,从空闲消息链表上取下来的消息块不是挂到消息队列的队尾,而是挂到队首,这样,接收者就能够优先接收到紧急消息,从而及时进行消息处理。 rt_err_t rt_mq_urgent(rt_mq_t mq, void *buffer, rt_size_t size) 接收消息 当消息队列中有消息时,接收者才能接收消息,否则接收者会根据超时时间设置,或挂起在消息队列的等待线程队列上,或直接返回。 rt_err_t rt_mq_recv(rt_mq_t mq, void *buffer, rt_size_t size, rt_int32_t timeout) 消息队列控制 rt_err_t rt_mq_control(rt_mq_t mq, rt_uint8_t cmd, void *arg) 支持的命令有:RT_IPC_CMD_RESET(复位) 区别 邮箱只能传4字节的值,消息队列可以传递更长的值; 邮箱有发送等待功能,消息队列没有; 消息队列有紧急消息功能,邮箱没有紧急邮件的功能...

u-boot 通过 tftp 下载 uImage

使用 tftp 下载镜像文件 setenv serverip 172.16.9.52 saveenv # 保存 tftp 0x80800000 uImage # 从服务器下载 uImage 放在 RAM 的 0x80800000 地址(不写地址默认是 0x80200000) bootm 0x80800000 # 从该地址加载内核镜像启动 Linux 系统(掉电后镜像会丢失) 怎样掉电不丢失呢,直接写 flash,替换原有镜像。 查看 nand flash 分区: mtdparts device nand0 <omap2-nand.0>, # parts = 8 #: name size offset mask_flags 0: SPL 0x00020000 0x00000000 0 1: SPL.backup1 0x00020000 0x00020000 0 2: SPL.backup2 0x00020000 0x00040000 0 3: SPL.backup3 0x00020000 0x00060000 0 4: u-boot 0x001e0000 0x00080000 0 5: u-boot-env 0x00020000 0x00260000 0 6: kernel 0x00500000 0x00280000 0 7: rootfs 0x07880000 0x00780000 0 active partition: nand0,0 - (SPL) 0x00020000 @ 0x00000000 defaults: mtdids : nand0=omap2-nand.0 mtdparts: mtdparts=omap2-nand.0:128k(SPL),128k(SPL.backup1),128k(SPL.backup2),128k(SPL.backup3),1920k(u-boot),128k(u-boot-env),5m(kernel),-(rootfs) 擦除原镜像: nand erase 0x00280000 0x00500000 将内存中的镜像文件写入 nand flash: nand write 0x80800000 0x00280000 ${filesize} U-Boot 中的环境命令可以使用 $(filesize) 来确定刚下载(传输)得到的文件大小,printenv filesize 可查看其...

STM8S 使用笔记

1、GPIO 关于 SWIM 用作普通 GPIO 脚 即使 CFG_GCR 的 SWD 脚不置为 1,事实上 PD1 脚也可正常执行输入输出功能,只不过在同时使用 SWIM 调试时,即使设置 DDR 为输出,ODR 总保持为 1。关开 SWIM 连线,复位 MCU 后输出功能可正常执行。SWD 位看似没有什么作用,不过还是按手册所说的方式来做吧。另外也不必担心 SWIM 功能因为该配置而被禁用。 关于开漏输出脚 手册上打 T 标记的是真正的开漏脚,不具备推挽输出的功能,也没有内部上拉功能。使用时需要特别注意。 2、读 TIMx_CNTR 要分别读 TIMx_CNTRH 和 TIMx_CNTRL(分别读 TIMx_CNTRL 和 TIMx_CNTRH 也没错),因为发现直接读 16 位的 TIMx_CNTR 可能出现错误: 明明 TIMx_CNTR 的值是 829,偏偏赋值给一个变量后变量的值是 789。但也不总是有问题,运行几次就好了,复位后现象依旧,但分别读 TIMx_CNTRH 和 TIMx_CNTRL 并赋值给变量就正常,连续读两次 TIMx_CNTR 也是正常的。 3、关于 COSMIC 编译器 编译器有三个自用的变量 c_x、c_y、c_lreg,当与中断函数关联时: (1)当中断函数直接使用(编译器自动产生汇编代码)他们时,会被自动保存和恢复; (2)当终端函数调用使用了 c_x、c_y 的函数时,c_x、c_y 会被自动保存和恢复,但是 c_lreg 不会被这样自动保存和恢复; 这就要特别注意:如果中断中调用了使用 longs 或者 floats 的函数时就要在中断函数的定义中加修饰词 @svlreg! 不太好判断是否使用了 c_lreg(需要反汇编才能看),例如 c_lgadc(长整数加无符号单字节)就没有用到这三个变量,所以在不影响性能的是否加上无妨,除非你的应用很在意那几个 pushw、popw。 4、一个配置字初始化引起的问题 同样的软件延时程序在不同的板子上一个验时是 4ms,一个是 3ms,如果用硬件定时器来实现验时则一致。 读出配置字为 000000F0F000FFFE00,而正常情况下应该读出的是全 0。置 1 的那些位是保留位,具体作用不清除,将其都清零以后延时都是 3ms 了。 可能保留的配置字影响了指令执行等待时间等参数。通过这个问题来看,如果烧写程序时(尤其是 debug 程序时)不烧写正常的配置字进去,可能会造成程序的异常执行。 5、stm8 cosmic 用 sp 索引变量,如果用 push cc 保存寄存器至栈会造成由于编译器不能识别嵌入式汇编而造成的后续代码的变量使用的错误,所以要用 push cc 然后 pop a 的方式获取 cc 的值并返回,不能保存在栈里: uint8 EnterCritical(void) {     #asm     push cc     sim     pop a     #endasm } 6、关于 STVD 开发环境 如果出现编辑界面或仿真界面布局变乱,可以删除 .wed 文件(存储开发界面信息)或 .wdb 文件(存储仿真界面信息),以初始化界面。 7、关于 memcpy cosmic 的 memcpy 是从后往前拷贝,这样当 src 与 dst 重叠时,比如 memcpy(buf, buf + 5, 10) 结果就不是我们预想的,可以使用 memmove 来代替,它会检查是否重叠。当 dst 大于等于 src 时,从前往后拷贝(常规顺序)。 8、stm8 终端向量表 由操作码 0x82(INT)与三字节的地址组成,执行过程是将三字节地址赋给 PC,程序将跳转到该地址处执...

AM335X 内核编译

内核编译: sudo apt-get install u-boot-tools #uImage 生成时依赖的 mkimage 工具 make mrproper make am335x_evm_defconfig make menuconfig make -j4 ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- uImage 模块编译: make modules make modules_install INSTALL_MOD_PATH=./module...

以动态模块 ko 的形式使用 nfs 客户端

ARM 设备的的内核中没有编进去 NFS,所以打算采用 ko 的方式加载进内核。 编译内核源程序,产生 Makefile。 make menuconfig 配置内核: [*] Network File Systems ---> <M> NFS client support [*] NFS client support for NFS version 3 把 NFS client support 选做模块(M)。 make modules 生成 nfs.ko、sunrpc.ko、lockd.ko 拷贝到 /lib/modules/$(uname -r) 执行 depmod 执行 modprobe nfs [ 207.024183] RPC: Registered named UNIX socket transport module. [ 207.030461] RPC: Registered udp transport module. [ 207.035397] RPC: Registered tcp transport module. [ 207.040317] RPC: Registered tcp NFSv4.1 backchannel transport module...

RS-232 接口标准

RS-232 是美国电子工业联盟 EIA(Electronic Industry Association)制定的串行数据通信的物理接口标准,原始编号全称是 EIA-RS-232(简称 RS232, 232),目前的版本是 C(RS-232-C)。 标准的全名是“数据终端设备(DTE)和数据通讯设备(DCE)之间串行二进制数据交换接口技术标准”。该标准规定采用一个 25 脚的 DB-25 连接器,对连接器的每个引脚的信号内容加以规定,还对各种信号的电平加以规定。后来 IBM 的 PC 机将 RS-232 简化成了 DB-9 连接器,从而成为事实标准。而现在通常只使用 RXD、TXD、GND 三条...

ARM DS-5(ARM Development Studio 5)

ARM DS-5 是 ARM 公司 2009 年推出的一款可扩展多功能,可调试裸板、Linux、Android 系统,支持所有 ARM 内核的软件开发工具。 自 2007 年 ARM 公司停止对 ADS 的维护更新后,ARM 在基于 eclipse 集成环境的基础上,相继推出了 RVDS(RealView Development Suite)和 DS-5 两款重量级开发软件。其中 DS-5 以同时集成 ARM Compiler 和 GCC 可轻松调试 Linux 系统而占优势。 ARM DS-5 开发工具链帮助工程师为 ARM 应用处理器(如 Cortex™-A 系列,Cortex-R 实时处理器和其他 ARM 嵌入式处理器)开发强大且高度优化的嵌入式软件 。 DS-5 工具链包括一流的 ARM C / C ++ 编译器,强大的 Linux / Android™/ RTOS 调试器,ARM Streamline™ 系统性能分析器和实时系统仿真模型, 所有这些都方便地封装在基于 Eclipse 的用户友好的集成开发环境(IDE)中。 DS-5 有三个不同的版本,它们是通过同一安装包进行许可证管理。 DS-5 Ultimate Edition 支持最新的 ARM 处理器和技术,如 ARMv8。 DS-5 专业版支持所有 ARM 处理器,包括 ARMv7,提供卓越的调试和跟踪功能以及 ARM 编译器。 DS-5 社区版是免费的,可以使用 DS-5 调试器和 Streamline 的有限功能集。功能包括裸机和 Linux 应用程序调试。 应用程序处理器支持: ARMv5: ARM926EJ-S ARMv6: ARM1136JF-S ARM1176JZ-S ARMv7: Cortex-A5 Cortex-A8 Cortex-A9 Cortex-A15 价格(20171108 Digi-Key): Ultimate 相比 Professional 多 ARMv8 processors、Compiler Safety Package Ultimate DS5UE-KD-40001 floating 1year 56,113.46HKD Ultimate DS5UE-KD-30001 node-locked 1year 44,635.76HKD Professional DS5PE-KD-40001 floating 1year 35,070.92HKD Professional DS5PE-KD-30001 node-locked 1year 28,056.77HKD Professional DS5PE-KD-40000 floating 永久 70,141.84HKD Professional DS5PE-KD-30000 node-locked 永久 56,113.46HKD 仿真器: DS-5 官方推荐的仿真器 DSTREAM,售价大约在 2 万 3 千人民币(201711)。 DS-5 vs MDK KEIL MDK-ARM 是用于满足开发者基于ARM7/9, ARM Cortex-M 处理器的开发需求,包括它自带的 RTX 实时操作系统和中间库,都是属于 MCU 应用领域的。 DS-5 是用于创建 Linux/Andriod 的复杂嵌入式系统应用和系统平台驱动接口,DS-5 支持设备添加,包括多核调试和支持,主要针对复杂的多核调试,片上系统开发而推出...

半导体

半导体(Semiconductor) 半导体是电阻率介于导体和绝缘体之间并有负的电阻温度系数的物质。在室温时,半导体的电阻率约在 $10^{-5}~10^7$ Ω·m(欧·米)之间,温度升高时电阻率指数则减小。半导体导带和价带距离适中,即禁带宽度适中,因此价带中的电子在常见能量级别的激励下,例如光、热和电压,即可进入导带,导致半导体电阻率变化。 本征半导体(Intrinsic Semiconductor) 本征半导体是完全不含杂质且无晶格缺陷的纯净半导体。主要常见代表有硅、锗这两种元素的单晶体结构。 单晶硅的每个硅原子和其周围的硅原子组成 8 电子稳定结构。一般情况下,电子-空穴对较少,具有较大的电阻率。在温度和光照的作用下,电子会变得更加活跃,载流子增多,电阻率下降。 N 型半导体(N-type semiconductors) 在本征半导体中掺入少量杂 Ⅴ 族质元元素(磷、砷、锑等),由于半导体原子(如硅原子)被杂质原子取代,杂质原子外层的五个外层电子的其中四个与周围的半导体原子形成共价键,多出的一个电子几乎不受束缚,较为容易地成为自由电子。于是,N 型半导体就成为了含电子浓度较高的半导体,其导电性主要是因为自由电子导电。该类杂质原子称为施主。多数载流子为电子。 P 型半导体 P 型半导体则通常是由在锗、硅类半导体材料中掺杂适量三价元素(Ⅲ 族元素)硼、铟、镓等而形成。由于半导体原子(如硅原子)被杂质原子取代,杂质原子外层的三个外层电子与周围的半导体原子形成共价键的时候,会产生一个“空穴”。因为三价元素的原子与周围的四价原子还差一个电子才能形成稳定的结构,所以容易“勾引”别的电子以达到稳定结构。多数载流子为空穴。 PN 结 采用不同的掺杂工艺,通过扩散作用,将 P 型半导体与 N 型半导体制作在同一块半导体(通常是硅或锗)基片上,在它们的交界面就形成空间电荷区称为 PN 结(PN junction)。PN 结中的内电场阻止了空穴向 N 区扩散,也阻止了电子向 P 区扩散,至此,扩散过程达到平衡。要想让 PN 结导通形成电流,必须消除其空间电荷区的内部电场的阻力。很显然,给它加一个反方向的更大的电场,即 P 区接外加电源的正极,N 区结负极,就可以抵消其内部自建电场,使载流子可以继续运动,从而形成线性的正向电流。而外加反向电压则相当于内建电场的阻力更大,PN 结不能导通,仅有极微弱的反向电流(由少数载流子的漂移运动形成,因少子数量有限,电流饱和)。当反向电压增大至某一数值时,因少子的数量和能量都增大,会碰撞破坏内部的共价键,使原来被束缚的电子和空穴被释放出来,不断增大电流,最终 PN 结将被击穿(变为导体)损坏,反向电流急剧增大。 PN 结特性 单向导电性 PN 结加正向电压时导通(存在导通电压,抵消 PN 结内电场),PN 结加反向电压时截止(PN 结呈现高阻性,存在反向饱和电流)。 反向击穿性 电容特性...

晶体三极管

晶体三极管(Transistor),也称为晶体管、三极管、半导体三极管、双极型晶体管。是在一块半导体基片上制作两个相距很近的 PN 结,两个 PN 结把整块半导体分成三部分,中间部分是基区,两侧部分是发射区和集电区,排列方式有 PNP 和 NPN 两种。发射区与基区之间形成的 PN 结称为发射结,而集电区与基区形成的 PN 结称为集电结,三条引线分别称为发射极 E(Emitter)、基极 B(Base)和集电极 C (Collector)。 在三极管符号中有一个箭头,箭头画在发射极 E,总是指向 N 区(N 型半导体),这是用来区分电路符号是 NPN(从基极指向射极)还是 PNP(从射极指向基极)的。 晶体三极管是电流型控制器件,而场效应晶体管则是电压型控制器件。 以上图的 NPN 三极管为例来讲。在制造三极管时,有意识地使发射区的多数载流子浓度大于基区的,同时基区做得很薄,而且,要严格控制杂质含量,这样,一旦接通电源后,由于发射结正偏,发射区的多数载流子(电子)及基区的多数载流子(空穴)很容易地越过发射结互相向对方扩散,但因前者的浓度基大于后者,所以通过发射结的电流基本上是电子流,这股电子流称为发射极电流子。由于基区很薄,加上集电结的反偏,注入基区的电子大部分越过集电结进入集电区而形成集电极电流 Ic,只剩下很少的电子在基区的空穴进行复合,被复合掉的基区空穴由基极电源 Eb 重新补给,从而形成了基极电流 Ib。根据电流连续性原理得:Ie = Ib + Ic。这就是说,在基极补充一个很小的 Ib,就可以在集电极上得到一个较大的 Ic,这就是所谓电流放大作用,Ic 与 Ib 是维持一定的比例关系,即:β = Ic / Ib。三极管的电流放大作用实际上是利用基极电流的微小变化去控制集电极电流的巨大变化。 放大原理 发射区向基区发射电子 电源 Ub 经过电阻 Rb 加在发射结上,发射结正偏,发射区的多数载流子(自由电子)不断地越过发射结进入基区,形成发射极电流 Ie。同时基区多数载流子也向发射区扩散,但由于多数载流子浓度远低于发射区载流子浓度,可以不考虑这个电流,因此可以认为发射结主要是电子流。 基区中电子的扩散与复合 电子进入基区后,先在靠近发射结的附近密集,渐渐形成电子浓度差,在浓度差的作用下,促使电子流在基区中向集电结扩散,被集电结电场拉入集电区形成集电极电流 Ic。也有很小一部分电子(因为基区很薄)与基区的空穴复合,扩散的电子流与复合电子流之比例决定了三极管的放大能力。 集电区收集电子 由于集电结外加反向电压很大,这个反向电压产生的电场力将阻止集电区电子向基区扩散,同时将扩散到集电结附近的电子拉入集电区从而形成集电极主电流 Icn。另外集电区的少数载流子(空穴)也会产生漂移运动,流向基区形成反向饱和电流,用 Icbo 来表示,其数值很小,但对温度却异常敏感。 晶体三极管在结构设计上的要点: 基区足够薄,以使发射区发来的载流子能够更容易地越过基区到达集电区; 基区掺杂浓度较小,使得在基区因空穴与电子复合而消耗掉发射区发射的载流子足够地少。 可见,晶体三极管简单地比作两个二极管的组合连接是不恰当的,三极管之所能够工作,与其结构设计是密不可分...

TM1638 按键数码管驱动芯片

TM1638 是一种带键盘扫描接口的 LED 驱动控制 IC,内部集成有 MCU 数字接口、数据锁存器、LED 驱动、键盘扫描等电路。 产品特性: 采用 CMOS 工艺 显示模式 10 段 × 8 位 键扫描(8 × 3 bit) 辉度调节电路(占空比 8 级可调) 串行接口(CLK,STB,DIO) 振荡方式:RC 振荡 内置上电复位电路 封装形式:SOP28 SEG1~SEG8 P 管开漏,只能接 LED 阳极,输出电流。 GRID1~GRID8 N 管开漏,只能接 LED 阴极,吸收电流。 由于是各 8 个脚,所以既可以驱动 8 位共阴极 LED 也可以驱动 8 位共阳极 LED。引脚接法与 RAM 中点亮 LED 的写法不同。 共阴极时可以支持 10 段,8 位。RAM 中写入一组数据(2 字节),可以控制一位的完整显示。 共阳极时可以支持 8 段,10 位。RAM 中写入一组数据(2 字节),可以控制 10 位的同一个段的显示。也就是说,如果控制一个位的显示,至少写 8 个低位字节(按一个位 8 段来说)。 这个表的含义更浅显的解释为:当某位为 1 时表示使 SEGx 输出电流且 GRIDy 输入电...