--> --> >-->

FreeRTOS笔记

前言 基于ESP32S+ESP-IDF的FreeRTOS笔记。 FreeRTOS 里函数名前缀通常表示返回值类型或返回值含义,属于一种命名约定,常见如下: 前缀 典型返回类型 含义 v void 无返回值 x BaseType_t 基础有符号类型,常用于返回状态、布尔值或错误码 ux UBaseType_t 无符号基础类型,常用于返回数量、索引、优先级等 ul uint32_t / unsigned long 32 位无符号整数 us uint16_t / unsigned short 16 位无符号整数 uc uint8_t / unsigned char 8 位无符号整数 c char 字符类型 pc char * 指向字符的指针,常用于字符串 puc uint8_t * 指向无符号 8 位数据的指针 pv void * 通用指针 px 指向某种结构体的指针 常用于 FreeRTOS 内部结构体指针 e 枚举类型 返回枚举值 prv 通常是 static 私有函数 FreeRTOS 内部私有函数,不强调返回值类型 系统启动流程 flowchart LR entry["ENTRY(call_start_cpu0)<br/><small>esp_system/sections....

June 5, 2026 · 8 min

嵌入式Linux-应用开发笔记

进程 常用命令 pstree # 查看进程树状图 ps -aux # 查看所有用户的进程,-ux查看当前用户进程 进程状态 状态 说明 R 运行状态。严格来说,应该是"可运行状态",即表示进程在运行队列中,处于正在执行或即将运行状态,只有在该状态的进程才可能在 CPU 上运行,而同一时刻可能有多个进程处于可运行状态。 S 可中断的睡眠状态。处于这个状态的进程因为等待某种事件的发生而被挂起,比如进程在等待信号。 D 不可中断的睡眠状态。通常是在等待输入或输出(I/O)完成,处于这种状态的进程不能响应异步信号。 T 停止状态。通常是被shell的工作信号控制,或因为它被追踪,进程正处于调试器的控制之下。 Z 退出状态。进程成为僵尸进程。 X 退出状态。进程即将被回收。 s 进程是会话其首进程。 l 进程是多线程的。 + 进程属于前台进程组。 < 高优先级任务。 创建进程 所有进程都基于一个父进程分叉出来,最初始的父进程为init。 system() system()用于在程序中调用 shell 执行一条命令,内部通常会通过 fork() 创建子进程,再由子进程调用 exec() 执行 /bin/sh -c command。调用者会等待命令执行结束,并获得其退出状态。 #include <sys/types.h> #include <unistd.h> #include <stdio.h> #include <stdlib.h> int main(void) { pid_t result; printf("This is a system demo!\n\n"); /*调用 system()函数*/ result = system("ls -l"); printf("Done!...

June 2, 2026 · 24 min

移植FreeRTOS到我的SoC(一)基本移植

硬件准备 一、实现一个mtime外设作为RISC-V标准机器定时器中断源 src/rtl/peripheral/mtime_mmio.sv `include "../lib/soc_pkg.sv" `include "../lib/bus_if.sv" module mtime_mmio ( input logic clk, input logic rst_n, output logic timer_irq, simple_bus_if.slave bus ); import soc_pkg::*; logic sel_mtime_lo, sel_mtime_hi, sel_mtimecmp_lo, sel_mtimecmp_hi; always_comb begin sel_mtime_lo = (align_word(bus.addr) == IO_MTIME_LO_ADDR); sel_mtime_hi = (align_word(bus.addr) == IO_MTIME_HI_ADDR); sel_mtimecmp_lo = (align_word(bus.addr) == IO_MTIMECMP_LO_ADDR); sel_mtimecmp_hi = (align_word(bus.addr) == IO_MTIMECMP_HI_ADDR); end logic [63:0] mtime; logic [63:0] mtimecmp; always_ff @(posedge clk or negedge rst_n) begin if (!rst_n) begin mtime <= 64'd0; mtimecmp <= 64'hFFFF_FFFF_FFFF_FFFF; end else begin mtime <= mtime + 64'd1; if (bus....

March 25, 2026 · 5 min

MSP430之时钟频率设置

写完这篇文章过了两天我才知道原来把官方例程下载下来可以用图形界面设置时钟。我是🐷 简介 MSP430有三个时钟,分别是MCLK、SMCLK、ACLK。 MCLK:主系统时钟。MCLK是CPU的运行时钟,MCLK频率越高,CPU运行越快,同时功耗越高。 SMCLK:子系统时钟。SMCLK可以提供给需要高速时钟的外设(如ADC、定时器。 ACLK:辅助时钟。辅助时钟的频率一般很低,功耗小,可以一直开启。 这三个时钟可由五个时钟源经过分频后提供,分别是XT1CLK、XT2CLK、VLOCLK、REFCLK、DCOCL。 XT1CLK(低频/高频时钟源):XT1CLK可以作为内部FLL模块的参考时钟,且它是FLL模块(频锁环模块)的默认参考时钟。FLL时钟除锁频之外还可以对时钟进行倍频或分频。 XT2CLK(高频时钟源):XT2CLK可以作为FLL的内部参考时钟。 VLOCLK(低频内部时钟源) REFCLK(低频时钟源,内部的参考时钟源):可以作为内部FLL的参考时钟。 DCOCLK(片内数字控制时钟源):通过内部FLL模块稳定,一般为1MHz。 其中XT1CLK、XT2CLK可由外部晶振提供。片内时钟源受温度影响大,频率一般不会很准确。 设置MSP430F5529的时钟 目的是将MCLK、SMCLK设置为XT2CLK(外部晶振 4Mhz)经过倍频后得到的24Mhz时钟;将ACLK设置为XT1CLK(外部晶振 32.768Khz)。 芯片的默认电压低,不足以支持高速的时钟频率,所以首先提升电压: PMM_setVCore(PMM_CORE_LEVEL_3); 设置XT1CLK与XT2CLK引脚为复用功能: GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P5,GPIO_PIN4 + GPIO_PIN5); GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P5,GPIO_PIN2 + GPIO_PIN3); 设置XT1CLK与XT2CLK外接晶振的频率: UCS_setExternalClockSource(32768,4000000); 开启XT1CLK与XT2CLK: UCS_turnOnLFXT1WithTimeout(UCS_XT1_DRIVE_0,UCS_XCAP_3,50000); UCS_turnOnXT2WithTimeout(UCS_XT2_DRIVE_4MHZ_8MHZ,50000); 将XT1CLK作为ACLK时钟源,XT2CLK作为FLL参考时钟源: UCS_initClockSignal(UCS_ACLK,UCS_XT1CLK_SELECT,UCS_CLOCK_DIVIDER_1) UCS_initClockSignal(UCS_FLLREF,UCS_XT2CLK_SELECT,UCS_CLOCK_DIVIDER_1); 提升MCLK的频率: UCS_initFLLSettle(24000, 6); // 6*4Mhz = 24Mhz 最后开启时钟源中断: SFR_clearInterrupt(SFR_OSCILLATOR_FAULT_INTERRUPT); SFR_enableInterrupt(SFR_OSCILLATOR_FAULT_INTERRUPT); 但我还有一个疑问,就是为什么不用使用UCS_initClockSignal函数将XT2CLK作为MCLK和SMCLK的时钟源,或者说将FLL参考时钟源设置为MCLK和SMCLK的时钟。我不这么做MCLK和SMCLK照样会被设置为XT2CLK倍频后的时钟。如果有大神知道原因,希望能留评论告诉我。 完整代码 clock.h #ifndef __CLOCK_H__ #define __CLOCK_H__ #include "driverlib.h" #define UCS_XT1_TIMEOUT 50000 #define UCS_XT2_TIMEOUT 50000 #define UCS_XT1_CRYSTAL_FREQUENCY 32768 #define UCS_XT2_CRYSTAL_FREQUENCY 4000000 #define UCS_MCLK_DESIRED_FREQUENCY_IN_KHZ 24000 #define UCS_MCLK_FLLREF_RATIO 6 void Clock_Init(void); #endif clock....

July 12, 2024 · 1 min

PCA9685舵机驱动板的使用方法

简介 PCA9685驱动板支持控制16路舵机,采用i2c通信协议。 VCC:PCA9685芯片的电源 V+:舵机的电源 舵机数量较少时电源可以通过V+引脚输入,较多时通过绿色电源输入端输入 Arduino驱动示例 #include <Wire.h> #include <Adafruit_PWMServoDriverh> #define SERVO_45 187 Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(); void setup() { pwm.begin(); pwm.setPWMFreq(50); pwm.setPWM(0,0,SERVO_45); } 本示例使用了Adafruit PWM Servo Driver Library。 该程序可以使连接在PCA9685舵机驱动板上0号位的舵机转动45°。 setPWMFreq()设置了IIC通信的更新频率(50HZ对应脉冲周期20ms),setPWM()`的三个参数依次为舵机编号、脉冲起始时间、脉冲结束时间,其中脉冲时间要以寄存器的值来表示(187对应1.0ms)。 舵机控制逻辑 上述示例使用舵机型号为SG90,运动范围0°-180°,舵机的控制周期信号为20ms,工作脉冲在0.5ms-2.5ms之间,舵机的转动角度由PCA9685的12位寄存器中的值来决定,而寄存器的值由脉冲时间决定。故可以得到脉冲时间-寄存器值-转动角度的关系如下: '0.5ms-0°':0.5*204=102 '1.0ms-45°':1*204=204 '1.5ms-90°':1.5*204=306 '2.0ms-135°':2*204=408 '2.5ms-180°':2.5*204=510 然而在实际使用时会有误差出现,故除了0°与180°的情况,要将寄存器值乘以0.915的系数。 '0.5ms-0°':0.5*204=102 '1.0ms-45°':1*204=204*0.915=187 '1.5ms-90°':1.5*204=306*0.915=280 '2.0ms-135°':2*204=408*0.915=373 '2.5ms-180°':2.5*204

September 28, 2023 · 1 min