diff --git "a/2025/\347\254\2542\347\273\204(RA8D1-Vision-Board)/\345\202\205\345\215\216\351\235\231/\347\254\224\350\256\260/58e9da5c022f1989fa48a51dddc5b3f.png" "b/2025/\347\254\2542\347\273\204(RA8D1-Vision-Board)/\345\202\205\345\215\216\351\235\231/\347\254\224\350\256\260/58e9da5c022f1989fa48a51dddc5b3f.png" new file mode 100644 index 0000000000000000000000000000000000000000..8b2c898851e382b03dd77b2ac3830b5eb8c9b2e4 Binary files /dev/null and "b/2025/\347\254\2542\347\273\204(RA8D1-Vision-Board)/\345\202\205\345\215\216\351\235\231/\347\254\224\350\256\260/58e9da5c022f1989fa48a51dddc5b3f.png" differ diff --git "a/2025/\347\254\2542\347\273\204(RA8D1-Vision-Board)/\345\202\205\345\215\216\351\235\231/\347\254\224\350\256\260/DAY1.md" "b/2025/\347\254\2542\347\273\204(RA8D1-Vision-Board)/\345\202\205\345\215\216\351\235\231/\347\254\224\350\256\260/DAY1.md" new file mode 100644 index 0000000000000000000000000000000000000000..30ffd6065104c8ac4fb9c7cba9e421b6f7446719 --- /dev/null +++ "b/2025/\347\254\2542\347\273\204(RA8D1-Vision-Board)/\345\202\205\345\215\216\351\235\231/\347\254\224\350\256\260/DAY1.md" @@ -0,0 +1,53 @@ +# # DAY1:创建环境 + +## env的使用 + +pkgs --upgrade 升级软件包 + +pkgs - -update 更新软件包 + +scons 编译文件 +menuconfig 打开配置菜单 记得保存后再退出 + + + + + +## git的使用 + +**git的四大组成区域:**工作区 暂存区 本地仓库 远端仓库 + +**关系流程图**:工作区 → (git add) → 暂存区 → (git commit) → 本地仓库 → (git push) → 远端仓库 + +git init 初始化新仓库 +git clone 克隆远程仓库到本地 +git status 查看工作区/暂存区状态 + +git commit 提交 + +git branch 查看分支(`-a` 查看所有分支) +git checkout -b 创建新分支 + +git checkout 切换的指定分支上 + +git merge 合并指定分支到当前分支 + +git branch -d 删除本地分支 + +git branch -D 强制删除一个分支 + +git remote -v 查看远程仓库地址 +git remote add 添加远程仓库 + +git push 推送 +git pull 拉取 +git fetch 仅获取远程更新(不自动合并) + +git log 查看提交历史 + +git reflog 查看git命令的所有操作记录 +git diff 比较工作区与暂存区差异 + +git reset --hard HEAD~ 硬重置 +git reset --soft HEAD~ 软重置 + diff --git "a/2025/\347\254\2542\347\273\204(RA8D1-Vision-Board)/\345\202\205\345\215\216\351\235\231/\347\254\224\350\256\260/DAY2.md" "b/2025/\347\254\2542\347\273\204(RA8D1-Vision-Board)/\345\202\205\345\215\216\351\235\231/\347\254\224\350\256\260/DAY2.md" new file mode 100644 index 0000000000000000000000000000000000000000..8965bd0a86e4a33f9abfa9f70702e9625e22cb79 --- /dev/null +++ "b/2025/\347\254\2542\347\273\204(RA8D1-Vision-Board)/\345\202\205\345\215\216\351\235\231/\347\254\224\350\256\260/DAY2.md" @@ -0,0 +1,122 @@ +#include + +#define THREAD_PRIORITY 25 +#define THREAD_STACK_SIZE 512 +#define THREAD_TIMESLICE 10 + + +static rt_thread_t tid1 = RT_NULL; +static rt_thread_t tid2 = RT_NULL; +static rt_thread_t tid3 = RT_NULL; + + +static void thread1_entry(void *parameter) +{ + rt_uint32_t count = 0; + while (1) + { + rt_kprintf("Thread1 (Low Priority) running: %d\n", count++); + rt_thread_mdelay(500); + } +} + +static void thread2_entry(void *parameter) +{ + rt_uint32_t count = 0; + while (1) + { + rt_kprintf("Thread2 (Medium Priority)抢占运行: %d\n", count++); + rt_thread_mdelay(1000); + } +} + + +static void thread3_entry(void *parameter) +{ + rt_uint32_t count = 0; + while (1) + { + rt_kprintf("Thread3 (High Priority)抢占运行: %d\n", count++); + rt_thread_mdelay(2000); + } +} + +int main(void) +{ + + tid1 = rt_thread_create("thread1", + thread1_entry, RT_NULL, + THREAD_STACK_SIZE, + THREAD_PRIORITY + 2, THREAD_TIMESLICE); + if (tid1 != RT_NULL) rt_thread_startup(tid1); + + + tid2 = rt_thread_create("thread2", + thread2_entry, RT_NULL, + THREAD_STACK_SIZE, + THREAD_PRIORITY + 1, THREAD_TIMESLICE); + if (tid2 != RT_NULL) rt_thread_startup(tid2); + + + tid3 = rt_thread_create("thread3", + thread3_entry, RT_NULL, + THREAD_STACK_SIZE, + THREAD_PRIORITY, THREAD_TIMESLICE); + if (tid3 != RT_NULL) rt_thread_startup(tid3); + + return 0; +} + + + +DAY2:课堂笔记 +![alt text](58e9da5c022f1989fa48a51dddc5b3f.png) + + rt_thread_init   为静态线程 +在编译阶段,代码编好后为线程分配空间 仅为这个线程使用 有安全要求 + rt_thread_detach 删除一个已经创建的线程 + + rt_thread_create  为动态线程   + 内存有限,但是需要的功能多,对安全没有太大的要求 + rt_thread_delete  删除一个已经创建的线程 + + rt_thread_self   用于获取当前正在执行的线程句柄 + + rt_thread_startup  将线程从初始状态转换到就绪状态,使其能够被操作系统调度执行 + + rt_thread_yield  用于主动让出 CPU 使用权,允许其他具有相同优先级的就绪线程获得执行机会 该函数在线程需要暂时放弃 CPU 资源时非常有用 + + rt_thread_find   用于通过线程名称查找对应的线程句柄 在线程间通信或需要操作其他线程时非常有用 + + rt_thread_delay   是 RT-Thread 实时操作系统中用于使当前线程暂停执行的函数 通过指定延时时间,线程可以主动释放 CPU 资源,让其他就绪线程有机会执行 + +时间线的单位是tick +优先级大小:数字越小,优先级越大 + + +参数: +name 线程的名称 +entry 线程的入口函数参数 +stack_size 线程栈的大小 +priority 线程的优先级 +tick 线程的时间片大小 + + +返回: +RE_EOK  线程创建成功 +-RE_ERROR  线程创建失败 + +无循环线程被执行完毕后,系统会自动回收资源,与需手动删除 + +循环线程需要有让出cpu的动作 +主动让出:使用系统延时 +被动让出:等待ipc + + +调度器的主要工作: +1.决定任务运行顺序 +2.执行任务切换 + +调度规则: +1.优先级抢占 +2.时间片轮转 \ No newline at end of file diff --git "a/2025/\347\254\2542\347\273\204(RA8D1-Vision-Board)/\345\202\205\345\215\216\351\235\231/\347\254\224\350\256\260/DAY3/event_sample.c" "b/2025/\347\254\2542\347\273\204(RA8D1-Vision-Board)/\345\202\205\345\215\216\351\235\231/\347\254\224\350\256\260/DAY3/event_sample.c" new file mode 100644 index 0000000000000000000000000000000000000000..60f047887f9f51e347191f2b9b85707beace4a26 --- /dev/null +++ "b/2025/\347\254\2542\347\273\204(RA8D1-Vision-Board)/\345\202\205\345\215\216\351\235\231/\347\254\224\350\256\260/DAY3/event_sample.c" @@ -0,0 +1,79 @@ +#include + +#define THREAD_PRIORITY 25 +#define THREAD_STACK_SIZE 512 +#define THREAD_TIMESLICE 5 + +#define EVENT_FLAG3 (1 << 3) +#define EVENT_FLAG5 (1 << 5) + +static rt_event_t event = RT_NULL; + +static void thread1_entry(void *parameter) +{ + rt_uint32_t recv_set = 0; + + while (1) + { + if (rt_event_recv(event, + EVENT_FLAG3 | EVENT_FLAG5, + RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, + RT_WAITING_FOREVER, &recv_set) == RT_EOK) + { + rt_kprintf("thread1 received event 0x%x\n", recv_set); + } + } +} + +static void thread2_entry(void *parameter) +{ + rt_uint8_t count = 0; + + while (1) + { + count++; + if (count % 2 == 0) + { + rt_event_send(event, EVENT_FLAG3); + rt_kprintf("thread2 send event 0x%x\n", EVENT_FLAG3); + } + else + { + rt_event_send(event, EVENT_FLAG5); + rt_kprintf("thread2 send event 0x%x\n", EVENT_FLAG5); + } + + rt_thread_mdelay(800); + } +} + +int event_sample(void) +{ + event = rt_event_create("event", RT_IPC_FLAG_FIFO); + if (event == RT_NULL) + { + rt_kprintf("create event failed\n"); + return -1; + } + + rt_thread_t thread1 = rt_thread_create("thread1", + thread1_entry, RT_NULL, + THREAD_STACK_SIZE, + THREAD_PRIORITY - 1, + THREAD_TIMESLICE); + if (thread1 != RT_NULL) + rt_thread_startup(thread1); + + + rt_thread_t thread2 = rt_thread_create("thread2", + thread2_entry, RT_NULL, + THREAD_STACK_SIZE, + THREAD_PRIORITY, + THREAD_TIMESLICE); + if (thread2 != RT_NULL) + rt_thread_startup(thread2); + + return 0; +} + +MSH_CMD_EXPORT(event_sample, "event sample"); \ No newline at end of file diff --git "a/2025/\347\254\2542\347\273\204(RA8D1-Vision-Board)/\345\202\205\345\215\216\351\235\231/\347\254\224\350\256\260/DAY3/mailbox_sample.c" "b/2025/\347\254\2542\347\273\204(RA8D1-Vision-Board)/\345\202\205\345\215\216\351\235\231/\347\254\224\350\256\260/DAY3/mailbox_sample.c" new file mode 100644 index 0000000000000000000000000000000000000000..15d4d2465fd6ea65f38444d06f58340636b88ccb --- /dev/null +++ "b/2025/\347\254\2542\347\273\204(RA8D1-Vision-Board)/\345\202\205\345\215\216\351\235\231/\347\254\224\350\256\260/DAY3/mailbox_sample.c" @@ -0,0 +1,72 @@ +#include + +#define THREAD_PRIORITY 25 +#define THREAD_STACK_SIZE 512 +#define THREAD_TIMESLICE 5 + +static rt_mailbox_t mb = RT_NULL; +static char mb_pool[128]; + +static void thread1_entry(void *parameter) +{ + rt_uint32_t count = 0; + char buf[32]; + + while (1) + { + rt_sprintf(buf, "mail %d", count++); + + if (rt_mb_send(mb, (rt_uint32_t)buf) == RT_EOK) + { + rt_kprintf("thread1 send mail: %s\n", buf); + } + else + { + rt_kprintf("thread1 send mail failed\n"); + } + + rt_thread_mdelay(1000); + } +} + +static void thread2_entry(void *parameter) +{ + rt_uint32_t *str; + + while (1) + { + if (rt_mb_recv(mb, (rt_uint32_t *)&str, RT_WAITING_FOREVER) == RT_EOK) + { + rt_kprintf("thread2 received mail: %s\n", (char *)str); + } + } +} + +int mailbox_sample(void) +{ + mb = rt_mb_create("mbt", sizeof(mb_pool)/4, RT_IPC_FLAG_FIFO); + if (mb == RT_NULL) + { + rt_kprintf("create mailbox failed\n"); + return -1; + } + rt_thread_t thread1 = rt_thread_create("thread1", + thread1_entry, RT_NULL, + THREAD_STACK_SIZE, + THREAD_PRIORITY, + THREAD_TIMESLICE); + if (thread1 != RT_NULL) + rt_thread_startup(thread1); + + rt_thread_t thread2 = rt_thread_create("thread2", + thread2_entry, RT_NULL, + THREAD_STACK_SIZE, + THREAD_PRIORITY - 1, + THREAD_TIMESLICE); + if (thread2 != RT_NULL) + rt_thread_startup(thread2); + + return 0; +} + +MSH_CMD_EXPORT(mailbox_sample, "mailbox sample"); \ No newline at end of file diff --git "a/2025/\347\254\2542\347\273\204(RA8D1-Vision-Board)/\345\202\205\345\215\216\351\235\231/\347\254\224\350\256\260/DAY3/message_queue_sample.c" "b/2025/\347\254\2542\347\273\204(RA8D1-Vision-Board)/\345\202\205\345\215\216\351\235\231/\347\254\224\350\256\260/DAY3/message_queue_sample.c" new file mode 100644 index 0000000000000000000000000000000000000000..43e1a361c74f8c08189b624207d36d6c221deeb4 --- /dev/null +++ "b/2025/\347\254\2542\347\273\204(RA8D1-Vision-Board)/\345\202\205\345\215\216\351\235\231/\347\254\224\350\256\260/DAY3/message_queue_sample.c" @@ -0,0 +1,75 @@ +#include + +#define THREAD_PRIORITY 25 +#define THREAD_STACK_SIZE 512 +#define THREAD_TIMESLICE 5 + +static rt_mq_t mq = RT_NULL; + +struct message +{ + rt_uint8_t type; + rt_uint8_t data[32]; +}; + +static void thread1_entry(void *parameter) +{ + struct message msg; + rt_uint8_t count = 0; + + while (1) + { + msg.type = count % 3; + rt_sprintf((char *)msg.data, "message %d", count++); + + if (rt_mq_send(mq, &msg, sizeof(msg)) == RT_EOK) + { + rt_kprintf("thread1 send message: type=%d, data=%s\n", msg.type, msg.data); + } + + rt_thread_mdelay(1000); + } +} + +static void thread2_entry(void *parameter) +{ + struct message msg; + + while (1) + { + if (rt_mq_recv(mq, &msg, sizeof(msg), RT_WAITING_FOREVER) == RT_EOK) + { + rt_kprintf("thread2 received message: type=%d, data=%s\n", msg.type, msg.data); + } + } +} + +int message_queue_sample(void) +{ + mq = rt_mq_create("mqt", sizeof(struct message), 5, RT_IPC_FLAG_FIFO); + if (mq == RT_NULL) + { + rt_kprintf("create message queue failed\n"); + return -1; + } + + rt_thread_t thread1 = rt_thread_create("thread1", + thread1_entry, RT_NULL, + THREAD_STACK_SIZE, + THREAD_PRIORITY, + THREAD_TIMESLICE); + if (thread1 != RT_NULL) + rt_thread_startup(thread1); + + rt_thread_t thread2 = rt_thread_create("thread2", + thread2_entry, RT_NULL, + THREAD_STACK_SIZE, + THREAD_PRIORITY - 1, + THREAD_TIMESLICE); + if (thread2 != RT_NULL) + rt_thread_startup(thread2); + + return 0; +} + +MSH_CMD_EXPORT(message_queue_sample, "message queue sample"); \ No newline at end of file diff --git "a/2025/\347\254\2542\347\273\204(RA8D1-Vision-Board)/\345\202\205\345\215\216\351\235\231/\347\254\224\350\256\260/DAY3/mutex_sample.c" "b/2025/\347\254\2542\347\273\204(RA8D1-Vision-Board)/\345\202\205\345\215\216\351\235\231/\347\254\224\350\256\260/DAY3/mutex_sample.c" new file mode 100644 index 0000000000000000000000000000000000000000..6510a7466b62f4db6ed11a63098a595d2ad4ff71 --- /dev/null +++ "b/2025/\347\254\2542\347\273\204(RA8D1-Vision-Board)/\345\202\205\345\215\216\351\235\231/\347\254\224\350\256\260/DAY3/mutex_sample.c" @@ -0,0 +1,69 @@ +#include + +static rt_mutex_t mutex = RT_NULL; +static rt_uint8_t number1 = 0, number2 = 0; + +static void thread1_entry(void *parameter) +{ + while (1) + { + rt_mutex_take(mutex, RT_WAITING_FOREVER); + + number1++; + rt_thread_mdelay(10); + number2++; + + if (number1 != number2) + { + rt_kprintf("not protect, number1 = %d, number2 = %d\n", number1, number2); + } + else + { + rt_kprintf("mutex protect, number1 = number2 = %d\n", number1); + } + + rt_mutex_release(mutex); + + rt_thread_mdelay(100); + } +} + +static void thread2_entry(void *parameter) +{ + while (1) + { + rt_mutex_take(mutex, RT_WAITING_FOREVER); + + number1++; + number2++; + rt_mutex_release(mutex); + + rt_thread_mdelay(150); + } +} + +int mutex_sample(void) +{ + mutex = rt_mutex_create("mutex", RT_IPC_FLAG_FIFO); + if (mutex == RT_NULL) + { + rt_kprintf("create mutex failed\n"); + return -1; + } + + rt_thread_t thread1 = rt_thread_create("thread1", + thread1_entry, RT_NULL, + 1024, 10, 20); + if (thread1 != RT_NULL) + rt_thread_startup(thread1); + + rt_thread_t thread2 = rt_thread_create("thread2", + thread2_entry, RT_NULL, + 1024, 10, 20); + if (thread2 != RT_NULL) + rt_thread_startup(thread2); + + return 0; +} + +MSH_CMD_EXPORT(mutex_sample, "mutex sample"); \ No newline at end of file diff --git "a/2025/\347\254\2542\347\273\204(RA8D1-Vision-Board)/\345\202\205\345\215\216\351\235\231/\347\254\224\350\256\260/DAY3/semaphore_sample.c" "b/2025/\347\254\2542\347\273\204(RA8D1-Vision-Board)/\345\202\205\345\215\216\351\235\231/\347\254\224\350\256\260/DAY3/semaphore_sample.c" new file mode 100644 index 0000000000000000000000000000000000000000..576b5ce14ab9466fae8d80adf1db2d0cd3bcbf8a --- /dev/null +++ "b/2025/\347\254\2542\347\273\204(RA8D1-Vision-Board)/\345\202\205\345\215\216\351\235\231/\347\254\224\350\256\260/DAY3/semaphore_sample.c" @@ -0,0 +1,60 @@ +#include + +#define THREAD_PRIORITY 25 +#define THREAD_TIMESLICE 5 + +static rt_thread_t tid1 = RT_NULL; +static rt_thread_t tid2 = RT_NULL; +static rt_sem_t sem = RT_NULL; + +static void thread1_entry(void *parameter) +{ + rt_uint32_t count = 0; + + while (1) + { + rt_sem_take(sem, RT_WAITING_FOREVER); + + rt_kprintf("thread1 take semaphore, count = %d\n", ++count); + + rt_thread_mdelay(500); + } +} + +static void thread2_entry(void *parameter) +{ + while (1) + { + rt_sem_release(sem); + + rt_kprintf("thread2 release semaphore\n"); + + rt_thread_mdelay(1000); + } +} + +int semaphore_sample(void) +{ + sem = rt_sem_create("sem", 0, RT_IPC_FLAG_FIFO); + if (sem == RT_NULL) + { + rt_kprintf("create semaphore failed\n"); + return -1; + } + + tid1 = rt_thread_create("thread1", + thread1_entry, RT_NULL, + 1024, THREAD_PRIORITY, THREAD_TIMESLICE); + if (tid1 != RT_NULL) + rt_thread_startup(tid1); + + tid2 = rt_thread_create("thread2", + thread2_entry, RT_NULL, + 1024, THREAD_PRIORITY - 1, THREAD_TIMESLICE); + if (tid2 != RT_NULL) + rt_thread_startup(tid2); + + return 0; +} + +MSH_CMD_EXPORT(semaphore_sample, "semaphore sample"); \ No newline at end of file diff --git "a/2025/\347\254\2542\347\273\204(RA8D1-Vision-Board)/\345\202\205\345\215\216\351\235\231/\347\254\224\350\256\260/DAY3/signal_sample.c" "b/2025/\347\254\2542\347\273\204(RA8D1-Vision-Board)/\345\202\205\345\215\216\351\235\231/\347\254\224\350\256\260/DAY3/signal_sample.c" new file mode 100644 index 0000000000000000000000000000000000000000..eb3da7fa6b6e20777e5b3d92ee8beb387bfdc936 --- /dev/null +++ "b/2025/\347\254\2542\347\273\204(RA8D1-Vision-Board)/\345\202\205\345\215\216\351\235\231/\347\254\224\350\256\260/DAY3/signal_sample.c" @@ -0,0 +1,65 @@ +#include + +#define THREAD_PRIORITY 25 +#define THREAD_STACK_SIZE 512 +#define THREAD_TIMESLICE 5 + +static rt_thread_t tid1 = RT_NULL; +static rt_thread_t tid2 = RT_NULL; + +static void signal_handler(int sig) +{ + rt_kprintf("thread1 received signal %d\n", sig); +} + +static void thread1_entry(void *parameter) +{ + rt_signal_install(SIGUSR1, signal_handler); + + rt_signal_unmask(SIGUSR1); + + while (1) + { + rt_thread_mdelay(500); + } +} + +static void thread2_entry(void *parameter) +{ + rt_uint8_t count = 0; + + while (1) + { + count++; + if (count % 2 == 0) + { + rt_thread_kill(tid1, SIGUSR1); + rt_kprintf("thread2 send signal to thread1\n"); + } + + rt_thread_mdelay(1000); + } +} + +int signal_sample(void) +{ + tid1 = rt_thread_create("thread1", + thread1_entry, RT_NULL, + THREAD_STACK_SIZE, + THREAD_PRIORITY, + THREAD_TIMESLICE); + if (tid1 != RT_NULL) + rt_thread_startup(tid1); + + tid2 = rt_thread_create("thread2", + thread2_entry, RT_NULL, + THREAD_STACK_SIZE, + THREAD_PRIORITY - 1, + THREAD_TIMESLICE); + if (tid2 != RT_NULL) + rt_thread_startup(tid2); + + return 0; +} + +MSH_CMD_EXPORT(signal_sample, "signal sample"); \ No newline at end of file diff --git "a/2025/\347\254\2542\347\273\204(RA8D1-Vision-Board)/\345\202\205\345\215\216\351\235\231/\347\254\224\350\256\260/DAY3/\347\254\224\350\256\260.md" "b/2025/\347\254\2542\347\273\204(RA8D1-Vision-Board)/\345\202\205\345\215\216\351\235\231/\347\254\224\350\256\260/DAY3/\347\254\224\350\256\260.md" new file mode 100644 index 0000000000000000000000000000000000000000..395fd53671ed5fd4223eb092037cf34e2941e5f8 --- /dev/null +++ "b/2025/\347\254\2542\347\273\204(RA8D1-Vision-Board)/\345\202\205\345\215\216\351\235\231/\347\254\224\350\256\260/DAY3/\347\254\224\350\256\260.md" @@ -0,0 +1,115 @@ + + ### 信号量 + +信号量一般分为三种: +1.互斥信号量 用于解决互斥问题 它比较特殊,可能会引起优先级反转问题 +2.二值信号量 用于解决同步问题 + +3.计数信号量 用于解决资源计数问题 + +1.创建信号量:rt_sem_t rt_sem_create(const char *name, + rt_uint32_t value, + +​ rt_uint8_t flag); + +2.删除信号量:rt_err_t rt_sem_delete(rt_sem_t sem); + 系统不再使用信号量时,可通过删除信号量以释放系统资源。 + +3.初始化信号量:rt_err_t rt_sem_init(rt_sem_t sem, + const char *name, + rt_uint32_t value, + rt_uint8_t flag) +当调用这个函数时,系统将对这个 semaphore 对象进行初始化,然后初始化IPC 对象以及与semaphore +相关的部分。信号量标志可用上面创建信号量函数里提到的标志。 + +4.脱离信号量:rt err_t rt_sem_detach(rt_sem_t sem) 脱离信号量就是让信号量对象从内核对象管理器中`脱离`,适用于静态初始化的信号量。 + 使用该函数后,内核先唤醒所有挂在该信号量等待队列上的线程,然后将该信号量从内核对象管理器中脱离。原来挂起在信号量上的等待线程将获得`-RTERROR `的返回值。 + + 5.获取信号量:rt_err_t rt_sem_take(rt_sem_t sem,rt_int32_t time), + 线程通过获取信号量来获得信号量资源实例,当信号量值大于零时,线程将获得信号量,并且相应的信号量值会减 1。 + 在调用这个函数时,如果信号量的值等于零,那么说明当前信号量资源实例不可用,申请该信号量的线程将根据 time 参数的情况选择`直接返回、或挂起等待一段时间、或永久等待,直到其他线程或中断释放该信号量。如果在参数 time 指定的时间内依然得不到信号量,线程将超时返回,返回值是-RT ETIMEOUT + +6. 无等待获取信号量:rt_err_t rt_sem_trytake(rt_sem_t sem) 当用户不想在申请的信号量上挂起线程进行等待时,可以使用无等待方式获取信号量。 + +7.释放信号量:rt_err_t rt_sem_release(rt_sem_t sem) 释放信号量可以唤醒挂起在该信号量上的线程 + + + +### 互斥量 + + 互斥量`又叫相互排斥的信号量,是一种特殊的二值信号量。它和信号量不同的是,它支持: + +1. 互斥量所有权:互斥量具有线程所有权,只有加锁的线程才能解锁,否则可能导致未定义行为(如死锁) + 2.递归访问: + 3.防止优先级反转的特性 + + ### 优先级反转(Prioritylnversion): + + 所谓优先级翻转,即当一个高优先级线程试图通过信号量机制访问共享资源时,如果该信号量已被一低优先级线程持有,而这个低优先级线程在运行过程中可能又被其它一些中等优先级的线程抢占,因此造成高优先级线程被许多具有较低优先级的线程阻塞,实时性难以得到保证。 + + ### 事件集 + + 事件集是一个32bit 的数 每个事件用一个bit位代表 + + 触发方式有 与触发、或触发 + + 发送:可以从中断或者线程中进行发送 + 接收:线程接收,条件检查(逻辑与方式、逻辑或方式) + + ### 消息邮箱 + + RT-Thread 操作系统的邮箱用于线程间通信,特点是 开销比较低,效率较高 。邮箱中的每一封邮件只能容纳固定的 4 字节内容(针对 32 位处理系统,指针的大小即为4个字节,所以一封邮件恰好能够容纳一个指针)。典型的邮箱也称作 “交换消息”, + + 非阻塞方式的邮件发送过程能够安全的应用于中断服务中,是线程、中断服务、定时器向线程发送消息的有效手段。 + +1.删除邮箱:rt_err_t rt_mb_delete(rt_mailbox_t mb); + 当用 rt_mb create()创建的邮箱不再被使用时,应该删除它来释放相应的系统资源,一旦操作完成,邮箱将被永久性的删除。 + 2.发送邮件:rt_err_t rt_mb_send(rt_mailbox_t mb, rt_uint32_t value);线程或者中断服务程序可以通过邮箱给其他线程发送邮件。 + 发送的邮件可以是 32 位任意格式的数据,一个整型值或者一个指向缓冲区的指针。当邮箱中的邮件已经满时,发送邮件的线程或者中断程序会收到-RTEFULL 的返回值。 + +3.等待方式发送邮件:rt_err_t rt_mb_send_wait(rt_mailbox_t mb, + rt_uint32_t value, + +​ rt int32_t timeout); + + rt mb send wait()与 rt mb send()的区别在于有等待时间,如果邮箱已经满了,那么发送线程将根据设定的 timeout 参数等待邮箱中因为收取邮件而空出空间。如果设置的超时时间到达依然没有空出空间,这时发送线程将被唤醒并返回错误码。 + +4. 接受邮件:rt_err_t rt_mb_recv (rt_mailbox_t mb, rt _uint32_t* value, rt_int32_t timeout); + 只有当接收者接收的邮箱中有邮件时,接收者才能立即取到邮件并返回 RTEOK 的返回值,否则接收线程会根据超时时间设置,或挂起在邮箱的等待线程队列上,或直接返回。 + +### 消息队列 + + 消息队列,也就是将多条消息排成的队列形式,是一种常用的线程间通信方式,可以应用在多种场合,线程间的消息交换,使用串口接收不定长数据等。线程可以将一条或多条消息放到消息队列中,同样一个或多个线程可以从消息队列中获得消息;同时消息队列提供异步处理机制可以起到缓冲消息的作用. + 使用消息队列实现线程间的异步通信工作,具有以下特性: + +1. 支持等待方式发送消息 +2. 支持读消息超时机制 +3. 允许不同长度(不超过队列节点最大值)任意类型消息 +4. 支持发送紧急消息 + + 线程先得到的是先进入消息队列的消息,即先进先出 + +​ 创建消息队列时先从对象管理器中分配一个消息队列对象,然后给消息队列对象分配一块内存空间,组织成空闲消息链表,这块内存的大小 =[消息大小 + 消息头(用于链表连接)的大小]*消息队列最大个数`,接着再初始化消息队列;接口返回RTEOK表示动态消息队列创建成功。 + /* *消息队列句柄*/ + rt ert mg tmg=RT NULL: + +/* 创建消息队列对象,返回消息队列句柄*/ + mg=rt mg_create("mg",4,10,RT IPC FLAG FIFO); //名称,消息长度,消息个数,等待方式 + + + ### 信号(又称为软中断信号) + +在软件层次上是对中断机制的一种模拟,在原理上,一个线程收到一个信号与处理器收到一个中断请求可以说是类似的。 + +信号在 RT-Thread 中用作异步通信,POSIX 标准定义了 sigset t 类型来定义一个信号集,然而sigset_t 类型在不同的系统可能有不同的定义方式,在 RT-Thread 中,将 sigset_t 定义成了unsigned long型,并命名为rt_sigset t,应用程序能够使用的信号为 SIGUSR1(10)和SIGUSR2(12)。 + + 信号本质是软中断,用来通知线程发生了异步事件,用做线程之间的异常通知、应急处理。一个线程不必通过任何操作来等待信号的到达,事实上,线程也不知道信号到底什么时候到达,线程之间可以互相通过调用rtthread kill()发送软中断信号 + +#### API:接收消息 + + 当消息队列中有消息时,接收者才能接收消息,否则接收者会根据超时时间设置,或挂起在消息队列的等待线程队列上,或直接返回。接收消息函数接口如下 : + rt_err_trt_mg recv(rt_mg_t mq, //消息队列对象的句柄 + void* buffer, // 消息内容 + rt size_t_size, // 消息大小 + +​ rt_int32_ttimeout); //指定的超时时间 \ No newline at end of file diff --git "a/2025/\347\254\2542\347\273\204(RA8D1-Vision-Board)/\345\202\205\345\215\216\351\235\231/\347\254\224\350\256\260/DAY4.md/\344\275\234\344\270\232.md" "b/2025/\347\254\2542\347\273\204(RA8D1-Vision-Board)/\345\202\205\345\215\216\351\235\231/\347\254\224\350\256\260/DAY4.md/\344\275\234\344\270\232.md" new file mode 100644 index 0000000000000000000000000000000000000000..a8f7d9665988c725c1c3e93ae8467de9e4b6b699 --- /dev/null +++ "b/2025/\347\254\2542\347\273\204(RA8D1-Vision-Board)/\345\202\205\345\215\216\351\235\231/\347\254\224\350\256\260/DAY4.md/\344\275\234\344\270\232.md" @@ -0,0 +1,196 @@ +#ifndef __VDEV_SIMPLE_H__ +#define __VDEV_SIMPLE_H__ + +#include + +struct virtual_device +{ + char name[16]; // 设备名称 + rt_uint8_t type; // 设备类型:1-LED, 2-Button + rt_uint8_t status; // 设备状态 + rt_err_t (*init)(void); // 初始化函数 + rt_err_t (*read)(rt_uint8_t *value); // 读函数 + rt_err_t (*write)(rt_uint8_t value); // 写函数 +}; + +/* 注册虚拟设备 */ +rt_err_t vdev_register(struct virtual_device *dev); + +/* 查找虚拟设备 */ +struct virtual_device *vdev_find(const char *name); + +#endif + +#include "vdev_simple.h" + +static rt_list_t device_list = RT_LIST_OBJECT_INIT(device_list); + +/* 设备注册 */ +rt_err_t vdev_register(struct virtual_device *dev) +{ + if (dev == RT_NULL || dev->name[0] == '\0') { + return -RT_ERROR; + } + + /* 检查是否已注册 */ + struct virtual_device *d; + rt_list_for_each_entry(d, &device_list, list) { + if (rt_strcmp(d->name, dev->name) == 0) { + return -RT_ERROR; + } + } + + /* 执行设备初始化 */ + if (dev->init) { + dev->init(); + } + + /* 添加到设备列表 */ + rt_list_insert_after(&device_list, &dev->list); + rt_kprintf("Register virtual device: %s\n", dev->name); + + return RT_EOK; +} + +/* 查找设备 */ +struct virtual_device *vdev_find(const char *name) +{ + struct virtual_device *dev; + rt_list_for_each_entry(dev, &device_list, list) { + if (rt_strcmp(dev->name, name) == 0) { + return dev; + } + } + return RT_NULL; +} + +#include "vdev_simple.h" + +static rt_uint8_t led_status = 0; + +/* LED初始化 */ +static rt_err_t led_init(void) +{ + led_status = 0; // 默认关闭 + return RT_EOK; +} + +/* 读取LED状态 */ +static rt_err_t led_read(rt_uint8_t *value) +{ + *value = led_status; + return RT_EOK; +} + +/* 控制LED开关 */ +static rt_err_t led_write(rt_uint8_t value) +{ + led_status = value ? 1 : 0; + rt_kprintf("LED set to %s\n", led_status ? "ON" : "OFF"); + return RT_EOK; +} + +/* 声明LED设备 */ +struct virtual_device vled = { + .name = "vled0", + .type = 1, // LED类型 + .init = led_init, + .read = led_read, + .write = led_write +}; + +/* 注册LED设备 */ +int vdev_led_init(void) +{ + return vdev_register(&vled); +} +INIT_APP_EXPORT(vdev_led_init); // 自动初始化 + +#include "vdev_simple.h" + + + +/* 按钮状态 */ +static rt_uint8_t button_status = 0; + +/* 按钮初始化 */ +static rt_err_t button_init(void) +{ + button_status = 0; // 默认未按下 + return RT_EOK; +} + +/* 读取按钮状态 */ +static rt_err_t button_read(rt_uint8_t *value) +{ + *value = button_status; + return RT_EOK; +} + +/* 模拟按钮按下/释放 */ +static rt_err_t button_write(rt_uint8_t value) +{ + button_status = value ? 1 : 0; + rt_kprintf("Button %s\n", button_status ? "PRESSED" : "RELEASED"); + return RT_EOK; +} + +/* 声明按钮设备 */ +struct virtual_device vbutton = { + .name = "vbtn0", + .type = 2, // 按钮类型 + .init = button_init, + .read = button_read, + .write = button_write +}; + +/* 注册按钮设备 */ +int vdev_button_init(void) +{ + return vdev_register(&vbutton); +} +INIT_APP_EXPORT(vdev_button_init); + +#include "vdev_simple.h" + +/* 控制LED闪烁 */ +static void led_blink(void) +{ + struct virtual_device *led = vdev_find("vled0"); + if (led) { + for (int i = 0; i < 5; i++) { + led->write(1); // 开 + rt_thread_mdelay(500); + led->write(0); // 关 + rt_thread_mdelay(500); + } + } +} + +/* 模拟按钮按下 */ +static void button_press(void) +{ + struct virtual_device *btn = vdev_find("vbtn0"); + if (btn) { + btn->write(1); // 按下 + rt_thread_mdelay(1000); + btn->write(0); // 释放 + } +} + +/* MSH命令示例 */ +static void vdev_test(int argc, char *argv[]) +{ + if (argc < 2) { + rt_kprintf("Usage: vdev_test [led|btn]\n"); + return; + } + + if (rt_strcmp(argv[1], "led") == 0) { + led_blink(); + } + else if (rt_strcmp(argv[1], "btn") == 0) { + button_press(); + } +} +MSH_CMD_EXPORT(vdev_test, "virtual device test"); \ No newline at end of file diff --git "a/2025/\347\254\2542\347\273\204(RA8D1-Vision-Board)/\345\202\205\345\215\216\351\235\231/\347\254\224\350\256\260/DAY4.md/\347\254\224\350\256\260md" "b/2025/\347\254\2542\347\273\204(RA8D1-Vision-Board)/\345\202\205\345\215\216\351\235\231/\347\254\224\350\256\260/DAY4.md/\347\254\224\350\256\260md" new file mode 100644 index 0000000000000000000000000000000000000000..7e97de347042a4d6864a06ca07e73ab29d695a88 --- /dev/null +++ "b/2025/\347\254\2542\347\273\204(RA8D1-Vision-Board)/\345\202\205\345\215\216\351\235\231/\347\254\224\350\256\260/DAY4.md/\347\254\224\350\256\260md" @@ -0,0 +1,67 @@ + + +![image-20250727212821516](C:\Users\Lenovo\AppData\Roaming\Typora\typora-user-images\image-20250727212821516.png) + +![image-20250727212908515](C:\Users\Lenovo\AppData\Roaming\Typora\typora-user-images\image-20250727212908515.png) + +#### 字符设备和块设备的特点与区别: + + **字符设备:**提供连续的数据流,应用程序可以顺序读取,通常不支持随机存取。相反此类设备支持按字节/字符来读写数据。举例来说,键盘、串口、调制解调器都是典型的字符设备 + **块设备:**应用程序可以随机访设备数据,程序可自行确定读取数据的位置。硬盘、软盘、CD-ROM驱动器和闪存都是典型的块设备,应用程序可以寻址磁盘上的任何位置,并由此读取数据。此外,数据的读写只能以块(通常是512B)的倍数进行。与字符设备不同,块设备并不支持基于字符的寻址。 + + 这两种类型的设备的根本区别在于它们是否可以被随机访问。字符设备只能总结一下,顺序读取,块设备可以随机读取。 + +#### 为什么要对设备分类 + + **MSH**可以重定向到任意的字符设备上,例如将lcd模拟成字符设备,就可以将打印输出到LCD上,或者是实现一套空字符设备,将msh重定向到这里。 + **Fatfs文件系统**依赖块设备驱动,我们将SD卡读写实现成块设备,但是也可以用ram来模拟块设备驱动 + + 不同的组件和应用会依赖不同的设备,对设备进行分类,可以做到对一类设备同样的控制 + +#### 访问 I/0 设备 + + 应用程序通过IO设备管理接口来访问硬件设备,当设备驱动实现后,应用程序就可以访问该硬件。I/O设备管理接口与I/0设备的操作方法的映射关系下图所示 + +![image-20250727213509751](C:\Users\Lenovo\AppData\Roaming\Typora\typora-user-images\image-20250727213509751.png) + +#### 数据接收回调 + +当硬件设备收到数据时,可以通过如下函数回调另一个函数来设置数据接收指示,通知上层应用线程有数据到达 + 在应用程序调用rt_device_write()入数据时,如果底层硬件能够支持自动发送,那么上层应用可以设置一个回调函数。这个回调函数会在底层硬件数据发送完成后(例如DMA传送完成或 FIFO已经写入完毕产生完成中断时)调用。 + +![image-20250727214323784](C:\Users\Lenovo\AppData\Roaming\Typora\typora-user-images\image-20250727214323784.png) + +#### GPIO概念与原理 + +芯片上的引脚一般分为4类:电源、时钟、控制与 I/O,I/0 口在使用模式上又分为 General Purpose lnput Output(通用输入/输出),简称GPIO,与功能复用I/O(如SPI/I2C/UART等)。 + + 大多数MCU的引脚都不止一个功能。不同引脚内部结构不一样,拥有的功能也不一样。可以通过不同的配置,切换引脚的实际功能通用 I/O 口主要特性如下: + 可编程控制中断-中断触发模式可配置,一般有下图所示5种中断触发模式: + 上升沿触发:用于检测无抖动的上升沿 + 下降沿触发:用于检测无抖动的下降沿 + 高电平触发:用于检测高电平状态 + 低电平触发:用于检测低电平状态 + 双边沿触发:用于检测无抖动的双边沿 + +#### RT-Thread I2C 使用思路 + +1. 查找I2C总线设备 +2. 构造 msgs 消息 +3. 启动 transfer 传输 +4. 处理结果 + +#### 软件i2c驱动编写 + +• 开启 I2C 框架 +• 选中I2C软件模拟设备功能 +•编写I2C 软件模拟驱动 + +#### RT-Thread SPI 开发模式 + +• 编写SPI BUS驱动 + +• 注册 SPI Device 设备 + +• 打开 SPI Device 设备 +•使用 SPI 框架提供 API 编程发送接收数据 +• 关闭 SPI Device 设备 \ No newline at end of file diff --git "a/2025/\347\254\2542\347\273\204(RA8D1-Vision-Board)/\345\202\205\345\215\216\351\235\231/\347\254\224\350\256\260/DAY5.md/\344\275\234\344\270\232.md" "b/2025/\347\254\2542\347\273\204(RA8D1-Vision-Board)/\345\202\205\345\215\216\351\235\231/\347\254\224\350\256\260/DAY5.md/\344\275\234\344\270\232.md" new file mode 100644 index 0000000000000000000000000000000000000000..2df269f0db494bef28e5d2478d453c03135b6886 --- /dev/null +++ "b/2025/\347\254\2542\347\273\204(RA8D1-Vision-Board)/\345\202\205\345\215\216\351\235\231/\347\254\224\350\256\260/DAY5.md/\344\275\234\344\270\232.md" @@ -0,0 +1,134 @@ +#include +#include +#include + + +#define BROKER_ADDR "mqtt.eclipseprojects.io" +#define BROKER_PORT 1883 +#define CLIENT_ID "rtthread_student" +#define PUB_TOPIC "/study/report" +#define SUB_TOPIC "/study/response" +#define YOUR_NAME "xiaoming" + +static MQTTClient client; + + +static void message_handler(MQTTClient *c, MessageData *msg) +{ + char response[100]; + int len = msg->message->payloadlen < 99 ? msg->message->payloadlen : 99; + rt_memcpy(response, msg->message->payload, len); + response[len] = '\0'; + + rt_kprintf("老师回复: %s\n", response); +} + + +static int mqtt_init(void) +{ + + NetworkInit(&client.network); + MQTTClientInit(&client, &client.network, 1000, rt_malloc, rt_free, rt_tick_get); + + if (NetworkConnect(&client.network, BROKER_ADDR, BROKER_PORT) < 0) { + rt_kprintf("连接MQTT服务器失败!\n"); + return -1; + } + + + MQTTPacket_connectData opts = MQTTPacket_connectData_initializer; + opts.clientID.cstring = CLIENT_ID; + opts.keepAliveInterval = 60; + opts.cleansession = 1; + + if (MQTTConnect(&client, &opts) < 0) { + rt_kprintf("MQTT登录失败!\n"); + return -1; + } + + if (MQTTSubscribe(&client, SUB_TOPIC, 1, message_handler) < 0) { + rt_kprintf("订阅主题失败!\n"); + return -1; + } + + rt_kprintf("MQTT初始化成功!\n"); + return 0; +} + + +static void send_study_report(const char *content) +{ + + cJSON *root = cJSON_CreateObject(); + cJSON_AddStringToObject(root, "name", YOUR_NAME); + cJSON_AddStringToObject(root, "study", content); + + char *json_str = cJSON_PrintUnformatted(root); + + + MQTTMessage msg; + msg.qos = 1; + msg.retained = 0; + msg.payload = json_str; + msg.payloadlen = rt_strlen(json_str); + + if (MQTTPublish(&client, PUB_TOPIC, &msg) == 0) { + rt_kprintf("学习收获已发送!\n"); + } else { + rt_kprintf("发送失败!\n"); + } + + cJSON_Delete(root); + cJSON_free(json_str); +} + + +static void study(int argc, char **argv) +{ + if (argc < 2) { + rt_kprintf("使用方法: study 你今天的学习收获\n"); + rt_kprintf("示例: study \"今天学会了MQTT基础\"\n"); + return; + } + + send_study_report(argv[1]); +} + +static int mqtt_study_init(void) +{ + if (mqtt_init() == 0) { + MSH_CMD_EXPORT(study, "发送学习收获"); + } + return 0; +} +INIT_APP_EXPORT(mqtt_study_init); + +import paho.mqtt.client as mqtt +import json + +def on_connect(client, userdata, flags, rc): + print("连接成功!") + client.subscribe("/study/report") + +def on_message(client, userdata, msg): + try: + data = json.loads(msg.payload.decode()) + print(f"{data['name']}的学习收获: {data['study']}") + + + client.publish("/study/response", "辛苦了,下周的比赛加油!") + + except Exception as e: + print("处理消息出错:", e) + +# 创建客户端 +client = mqtt.Client() +client.on_connect = on_connect +client.on_message = on_message + +# 连接服务器 +client.connect("mqtt.eclipseprojects.io", 1883, 60) + +# 保持连接 +print("等待学生上报学习收获...") +client.loop_forever() \ No newline at end of file diff --git "a/2025/\347\254\2542\347\273\204(RA8D1-Vision-Board)/\345\202\205\345\215\216\351\235\231/\347\254\224\350\256\260/DAY5.md/\347\254\224\350\256\260.md" "b/2025/\347\254\2542\347\273\204(RA8D1-Vision-Board)/\345\202\205\345\215\216\351\235\231/\347\254\224\350\256\260/DAY5.md/\347\254\224\350\256\260.md" new file mode 100644 index 0000000000000000000000000000000000000000..2673ca258d9719d754c5235f7bb900380f12e94e --- /dev/null +++ "b/2025/\347\254\2542\347\273\204(RA8D1-Vision-Board)/\345\202\205\345\215\216\351\235\231/\347\254\224\350\256\260/DAY5.md/\347\254\224\350\256\260.md" @@ -0,0 +1,29 @@ +软件包定义**:运行于 RT-Thread 物联网操作系统平台上,面户不同应用领域的软件组件形成一个个软件包,由软件包描述信息,软件包源代码或库文件组成。 + + 若要制作软件包,需要先对软件包的功能进行准确的定义,确保不要粿合与产品业务逻辑有关的代码,提高软件包的通用性。 + 软件包更新机制 + + + +当 Env 工具无法自动获取最新软件包时,可通过 Git 手动更新。 + + git pull origin master # 更新官方软件包仓库 + + + +**LLM-chat 组件配置要点:** + API 注册:需在阿里云模型市场(https://bailian.console.aliyun.com)完成账号注册并获取 API 密钥。 + CONFIG_LLM_MAX_FRAGMENT_LENGTH=6144 # 调整最大分片长度(字节) + CONFIG_USING_MBEDTLS=y # 启用 MbedTLS 加密库 + CONFIG_USING_EMAC=y # 启用以太网 MAC 驱动 + + + +**配置文件转换流程** +Kconfig(.config) ── scons── rtconfig.h ── 编译器 ── 编译选项 +config:Kconfig 系统生成的中间配置文件,包含所有选项的实际值。 +rtconfig.h:由 SCons 工具根据 .config 生成的 C 语言头文件,定义编译所需的宏。 +Kconfig 文件组织结构 +osource:引用上级目录的 Kconfig 文件。 + +source:引用当前目录的子目录中的 Kconfig 文件。 \ No newline at end of file diff --git "a/2025/\347\254\2542\347\273\204(RA8D1-Vision-Board)/\351\273\204\345\255\220\351\230\263/\347\254\224\350\256\260/Git\344\275\277\347\224\250\350\257\264\346\230\216.md" "b/2025/\347\254\2542\347\273\204(RA8D1-Vision-Board)/\351\273\204\345\255\220\351\230\263/\347\254\224\350\256\260/Git\344\275\277\347\224\250\350\257\264\346\230\216.md" deleted file mode 100644 index 2d1fc4fe90583f03038ddca01c5b6c444651c25e..0000000000000000000000000000000000000000 --- "a/2025/\347\254\2542\347\273\204(RA8D1-Vision-Board)/\351\273\204\345\255\220\351\230\263/\347\254\224\350\256\260/Git\344\275\277\347\224\250\350\257\264\346\230\216.md" +++ /dev/null @@ -1,89 +0,0 @@ -# Git使用说明 - - - -## 远端仓库的fork与clone - - - -**①**在github或gitee中找到你所需要的项目 - -**②**找到fork,将仓库拉取到你的私有账号上 - -**③**配置ssh密钥 - -**④**新建文件夹并命名,在文件夹内打开Git Bash,输入 - -``` -git clone "ssh"/"https" -``` - -等待clone完成 - - - -## 本地仓库的分支创建,内容修改与提交 - -**①**clone完成后,默认处于master或main分支,输入 - -``` -git checkout -b "分支名称" -``` - -创建并切换到新建分支 - - - -``` -git swtich "分支名称" -``` - -切换到你想要的分支 - - - -``` -git status -``` - -获取当前所处分支 - - - -``` -git branch -a -``` - -显示当前所有分支 - - - -**②**向新建分支内添加内容,使用 - -``` -git add . -``` - -将更改内容添加到暂存区 - - - -**③**将暂存区的更新内容推送到私人仓库,使用 - -``` -git commit-m "说明" -``` - -将个人主仓更新 - - - -**④**将个人仓库与远端仓库进行合并,使用 - -``` -git push -u origin "上游分支名称" -``` - - - -**⑤**等待远端仓库管理员审核合并请求 \ No newline at end of file diff --git "a/2025/\347\254\2542\347\273\204(RA8D1-Vision-Board)/\351\273\204\345\255\220\351\230\263/\347\254\224\350\256\260/RT-Thread\347\216\257\345\242\203\351\205\215\347\275\256.md" "b/2025/\347\254\2542\347\273\204(RA8D1-Vision-Board)/\351\273\204\345\255\220\351\230\263/\347\254\224\350\256\260/RT-Thread\347\216\257\345\242\203\351\205\215\347\275\256.md" deleted file mode 100644 index ea058cab64b2f6527f075af59640eb8d87b6acd0..0000000000000000000000000000000000000000 --- "a/2025/\347\254\2542\347\273\204(RA8D1-Vision-Board)/\351\273\204\345\255\220\351\230\263/\347\254\224\350\256\260/RT-Thread\347\216\257\345\242\203\351\205\215\347\275\256.md" +++ /dev/null @@ -1,73 +0,0 @@ -# RT-Thread环境配置 - -## 工具介绍: - -ENV - -Vscode - -GIT - -## 具体步骤: - -**①**使用git将rtthread官方源码fork到私人的github仓库,并复制ssh链接 - -​ rtthread官方gitee代码仓库地址 - -​ https://gitee.com/rtthread/rt-thread.git - - - -**②**创建文件夹,在文件夹内打开git bash,对复制的ssh链接进行clone - -``` -git clone https://gitee.com/rtthread/rt-thread.git -``` - - - -**③**下载env工具软件,在软件右上角的setting里面注册环境变量 - - - -**④**在rtthread任一bsp包下打开env - - - -```c -scons -j4 -``` - -进行编译 - - - -```c -menuconfig -``` - -进入菜单配置页面 - - - -```c -qemu-nographic.bat -``` - -运行rtthread主程序 - - - -**⑥**进入菜单配置页面,使能LVGL图形化界面 - - - -**⑦**在env里进行编译,随后使用 - - - -```c -qemu.bat -``` - -打开qume图形化界面 \ No newline at end of file