RT 您所在的位置:网站首页 关于签证面试的知识有哪些 RT

RT

2024-06-15 22:55| 来源: 网络整理| 查看: 265

RT-Thread— 知识点总结 内核

RO: 只读数据段,存放程序中定义的常量 RO Size: code + RO Data ----> 占用flash大小

RW:读写数据段,存放非0全局变量 RW Size: RW Data + ZI Data ----> 运行时占用RAM大小

​ ROM Size: code + RO Data + RW Data ----> 烧写占用flash大小

ZI: 0 数据段,存放未初始化全局变量 + 初始化为0变量

flash相当于后台仓库,程序和数据存在这里,上电RAM就走向前台,从flash取各种东西

例:const static int data = 0x00000FE ------> RO段

​ int sensor_data; ------> ZI 段

​ bool sensor_data = true; ------> RW段

线程

线程五种状态:初始------->就绪------>运行------>挂起------>关闭

空闲线程:优先级最低,永远为就绪态,不被挂起。 用处:回收被删除线程资源(回收僵尸线程)

当线程优先级相同时,采用时间片轮转方式调度,单位一个时钟节拍

比如:A:10,B:5,那么A线程执行10个节拍,B线程执行5个节拍

rt_thread_yield():当前线程被换出,相同优先级的下一个就绪线程将被执行。

rt_schedule():当前线程并不一定被换出,而是在系统中选取就绪的优先级最高的线程执行。

创建线程(静态)-----占用RAM空间(RW/ZI 空间),用户分配栈空间和线程句柄:

好处:运行时不需要动态分配内存,运行时效率较高,实时性较好,但内存不能被释放,

只能使用 rt_thread_detach() 函数将该线程控制块从对象管理器中脱离。

static rt_uint8_t thread2_stack[512]; //线程栈 static struct rt_thread thread2; //线程控制块 rt_thread_init(&thread2, //线程handle "thread2", //线程名称 thread2_entry, //线程入口函数 RT_NULL, //线程入口参数 &thread2_stack[0], //线程栈地址 sizeof(thread2_stack), //线程栈大小 15, //线程优先级 5); //线程时间片 rt_thread_startup(&thread2); //线程进入就绪态

创建线程(动态)-------依赖与内存堆管理器,系统自动从动态内存堆分配栈空间:

好处:运行时需要动态分配内存,效率没有静态方式高,调用 rt_thread_delete() 函数就会将这段申请的内存空间重新释放到内存堆中。

static rt_thread_t sht30_thread_id = RT_NULL; sht30_thread_id = rt_thread_create("sht30_th", //名称 sht30_entry, //线程代码 RT_NULL, //参数 1024, //栈大小 15, //优先级 20); //时间片 if (sht30_thread_id != RT_NULL) rt_thread_startup(sht30_thread_id); //线程进入就绪态 else rt_kprintf("sht30_thread create failure\n"); return RT_EOK; 定时器

动态定时器:

static rt_timer_t timer; /* 定时器超时函数 */ static void timeout(void *parameter) { rt_kprintf("one shot timer is timeout\n"); } /* 创建定时器单次定时器 */ timer = rt_timer_create("timer", timer, RT_NULL, 30, RT_TIMER_FLAG_ONE_SHOT); /* 启动定时器*/, if (timer != RT_NULL) rt_timer_start(timer);

静态定时器:

/* 定时器的控制块 */ static struct rt_timer timer1; static void timeout1(void* parameter) { rt_kprintf("one shot timer is timeout\n"); } /* 初始化定时器 */ rt_timer_init(&timer1, "timer1", /* 定时器名字是 timer1 */ timeout1, /* 超时时回调的处理函数 */ RT_NULL, /* 超时函数的入口参数 */ 10, /* 定时长度,以 OS Tick 为单位*/ RT_TIMER_FLAG_PERIODIC); /* 周期性定时器 */ /* 启动定时器 */ rt_timer_start(&timer1); 线程间同步——信号量

LED闪烁–信号量控制

#define LED_PIN GET_PIN(F, 9) static rt_thread_t tid1 = RT_NULL; static rt_thread_t tid2 = RT_NULL; static rt_sem_t led_sem = RT_NULL; //static struct rt_semaphore led_sem; static void sem_entry(void *parameter) { while(1) { //释放信号量 rt_sem_release(&led_sem); rt_sem_release(led_sem); rt_thread_mdelay(500); } } static void led_entry(void *parameter) { static unsigned char cnt = 0; while(1) { //获取信号量 rt_sem_take(&led_sem, RT_WAITING_FOREVER); rt_sem_take(led_sem, RT_WAITING_FOREVER); if(cnt++ % 2) rt_pin_write(LED_PIN, PIN_HIGH); else rt_pin_write(LED_PIN, PIN_LOW); } } int led_sample(void) { //初始化信号量 rt_sem_init(&led_sem, "led_sem", 0, RT_IPC_FLAG_FIFO); led_sem = rt_sem_creat("led_sem", 1, RT_IPC_FLAG_FIFO) if (led_sem == RT_NULL) { rt_kprintf("creat led sem fail!\n"); return -RT_ERROR; } tid1 = rt_thread_creat("ctl_sem",sem_entry,RT_NULL,512,20,0); if (tid1 != RT_NULL) rt_thread_startup(tid1); tid2 = rt_thread_creat("ctl_sem",led_entry,RT_NULL,512,25,0); if (tid2 != RT_NULL) rt_thread_startup(tid2); } INIT_APP_EXPORT(led_sample, led dample) 线程间通讯——邮箱/队列

**消息邮箱:**开销低,效率高,不可以在中断中接收邮件,不可以在中断中等待方式发送邮件

/* 邮箱控制块 */ static struct rt_mailbox mb; /* 用于放邮件的内存池 */ static char mb_pool[128]; /* 线程 1 入口 */ static void thread1_entry(void *parameter) { char *str; while (1) { /* 从邮箱中收取邮件 */ if (rt_mb_recv(&mb, (rt_uint32_t *)&str, RT_WAITING_FOREVER) == RT_EOK) { rt_kprintf("thread1: get a mail from mailbox, the content:%s\n", str); } } /* 执行邮箱对象脱离 */ rt_mb_detach(&mb); } /* 线程 2 入口 */ static void thread2_entry(void *parameter) { rt_uint8_t count = 0; while (count rt_err_t result; /* 初始化一个 mailbox */ result = rt_mb_init(&mb, "mbt", /* 名称是 mbt */ &mb_pool[0], /* 邮箱用到的内存池是 mb_pool */ sizeof(mb_pool) / 4, /* 邮箱中的邮件数目,因为一封邮件占 4 字节 */ RT_IPC_FLAG_FIFO); /* 采用 FIFO 方式进行线程等待 */ if (result != RT_EOK) { rt_kprintf("init mailbox failed.\n"); return -1; } } MSH_CMD_EXPORT(mailbox_sample, mailbox sample);

**消息队列:**发送不定长数据,线程之间的数据交换,不可以在中断中接收队列消息

/* 消息队列控制块 */ static struct rt_messagequeue mq; /* 消息队列中用到的放置消息的内存池 */ static rt_uint8_t msg_pool[2048]; static void thread1_entry(void *parameter) { char buf = 0; while (1) { /* 从消息队列中接收消息 */ if (rt_mq_recv(&mq, &buf, sizeof(buf), RT_WAITING_FOREVER) == RT_EOK) { rt_kprintf("thread1: recv msg from msg queue, the content:%c\n", buf); } } rt_mq_detach(&mq); } static void thread2_entry(void *parameter) { int result; char buf = 'A'; while (1) { /* 发送紧急消息到消息队列中 */ result = rt_mq_urgent(&mq, &buf, 1); /* 发送消息到消息队列中 */ result = rt_mq_send(&mq, &buf, 1); if (result != RT_EOK) { rt_kprintf("rt_mq_send ERR\n"); } } } /* 消息队列示例的初始化 */ int msgq_sample(void) { rt_err_t result; /* 初始化消息队列 */ result = rt_mq_init(&mq, "mqt", &msg_pool[0], /* 内存池指向 msg_pool */ 1, /* 每个消息的大小是 1 字节 */ sizeof(msg_pool), /* 内存池的大小是 msg_pool 的大小 */ RT_IPC_FLAG_FIFO); /* 如果有多个线程等待,按照先来先得到的方法分配消息 */ if (result != RT_EOK) { rt_kprintf("init message queue failed.\n"); return -1; } return 0; } 外设接口

SPI: 高速,全双工,同步通信总线

MOSI: 主机输出/从机输入 (MASTER OUTPUT / SLAVE INPUT)

MISO: 主机输入/从机输出 (MASTER INPUT/ SLAVE OUTPUT)

SCLK: 串行时钟线, 主设备输出时钟信号到从设备

CS: 从设备选择线, 主设备输出片选信号到从设备

工作方式: 主从方式, 一个主设备和一个/多个从设备. 主设备发起, 通过CS选择从设备, 通过SCLK提供时钟信号,

数据通过MOSI输出给从设备. MISO接收从设备发送的数据. 每个从设备的CS引脚是独立的.

任何时刻, SPI主设备上只有一个CS引脚是有效的.

IIC: 半双工、双向二线制同步串行总线

不同于 SPI 一主多从的结构,它允许同时有多个主设备存在,每个连接到总线上的器件都有唯一的地址,主设备启动数据传输并产生时钟信号,

从设备被主设备寻址,同一时刻只允许有一个主设备。

当总线空闲时,SDA 和 SCL 都处于高电平状态

开始条件: SCL 为高电平时,主机将 SDA 拉低,表示数据传输即将开始。

虚拟文件系统

有一系列文件如:1.txt, 12.txt, 123.txt,从中找出1.txt,并将文件内容输出出来。

static void findfile_sample(void) { DIR *dirp; struct dirrnt *d; char *f; char buffer[100]; /*打开根目录*/ dirp = opendir("/"); if (dirp == RT_NULL) { rt_kprintf("open directory error\n"); } else { /*读取目录*/ while ((d = readdir(dirp) != RT_NULL)) { //读取文件名称 f = d->d_name; if(!strcmp(f, "1.txt")) { fd = open("1.txt", O_RDONLY); if (fd >= 0) { read(fd, buffer, sizeof(buffer)); rt_kprintf("file 1.txt was found, the content is %s", buffer) close(fd); } } } closedir(dirp); } } MSH_CMD_EXPORT(findfile_sample, find file)

读写文件:

#include #include /* 当需要使用文件操作时,需要包含这个头文件 */ static void readwrite_sample(void) { int fd, size; char s[] = "hello world\n", buffer[80]; /* 以创建和读写模式打开 /text.txt 文件,如果该文件不存在则创建该文件 */ fd = open("/text.txt", O_WRONLY | O_CREAT); if (fd >= 0) { write(fd, s, sizeof(s)); close(fd); } /* 以只读模式打开 /text.txt 文件 */ fd = open("/text.txt", O_RDONLY); if (fd>= 0) { //读取内容 read(int fd, void *buf, size_t len); size = read(fd, buffer, sizeof(buffer)); close(fd); rt_kprintf("Read from file test.txt : %s \n", buffer); if (size char c; double d; int i; }

#prama pack(n):指定c编译器按照n个字节对齐

#pragma pack(4):

#pragma pack(8):

为表示关系x≥y≥z,应使用C语言表达式

(x;=y);(y;=z) (x;=y)AND(y;=z) (x;=y;=z) (x;=y);;(y;=z)

操作系统

进程与程序不是一一对应的,一个程序可以启动多个进程

执行一个作业可能会运行多个进程

进程是动态的

倘若一款存储器的数据线条数为 16 条, 地址线条数为 20 条, 那么此存储器的容量有多少?

2^20 * 16=16MB

计算机在一个指令周期的过程中,为从内存读取指令操作码,首先要将( C )的内容送到地址总线上

A.指令寄存器(IR)

B.通用寄存器(GR)

C.程序计数器(PC)

D.状态寄存器(PSW)

下面代码有什么错误?

#include void main() { char *s = "AAA"; s[0] = 'B'; printf("%s", s); }

(1)"AAA"是字符串常量(定义在只读区域),s是指针,指向这个字符串常量,所以声明s的时候就有问题,应该是cosnt char* s=“AAA”。

(2)然后又因为是常量,所以对是s[0]的赋值操作是不合法的。

若修改:char s[] = “AAA”; char* str2 = s; str2[0] = ‘B’; 这样"AAA"就存到了栈区中,可以修改

下面代码运行后会是什么现象?

#include #define N 500 void main() { unsigned char count; for(count = 0; count int i; char c = 0x80; i = c; if(i > 0) return 1; return 2; }

返回值为2

因为0x80 == 128,超出了char类型变量c的表示范围(-128~127),所以c == -128,进而i == -128,i < 0

判断下列表达式正确与否?

char str[2][3] = {“a”, “b”}; // 正确,str是一个可存放两个字符串的字符串数组 char str[2][3] = {{1, 2}, {3, 4}, {5, 6}}; // 错误,行列不匹配 char str[] = {“a”, “b”}; // 错误,字符数组不能存放两个字符串 char str[] = {'a', 'b'}; / char str[] = "ab"; char str[2] = {“a”, “b”}; // 错误,字符数组不能存放两个字符串 char str[] = {'a', 'b'};

在C语言中字符用’ '括起来,而字符串用” ”括起来。

ARM

CPU的内部结构

控制单元(指令寄存器、指令译码器、操作控制器)

运算单元(算术逻辑单元)

存储单元(专用寄存器和通用寄存器)

时钟

中断的优缺点

优点:实现CPU和I/O设备的并行,提高CPU的利用率和系统的性能

缺点:中断处理过程需要保护现场、恢复现场,整个过程需要一定的时间和空间开销。如果中断的频率太高,会降低系统的性能

SRAM、DRAM、SDRAM的区别

SRAM:静态的随机存储器,加电情况下,不需要刷新,数据不会丢失,CPU的缓存就是SRAMDRAM:动态随机存储器,加电情况下,也需要不断刷新,才能保存数据,最为常见的系统内存SDRAM:同步动态随机存储器,即数据的读取需要时钟来同步,也可用作内存

GPIO的输入输出模式有哪些

输入模式:浮空输入、带上拉输入、带下拉输入、模拟输入

输出模式:开漏输出、推挽输出、开漏复用输出、推挽复用输出

UART、SPI 是全双工类型

IIC、USB 是半双工类型

UART和TTL、RS-232、RS-485的关系

TTL(晶体管-晶体管逻辑电平)规定+5V(或>=2.4V)等于逻辑“1”,0V(或


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有