diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000000000000000000000000000000000000..38dfcd7b5f715d58daf6448820f4aff5e1e5be64 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,28 @@ +{ + "tasks": [ + { + "type": "cppbuild", + "label": "C/C++: gcc.exe 生成活动文件", + "command": "C:\\mingw\\mingw64\\bin\\gcc.exe", + "args": [ + "-fdiagnostics-color=always", + "-g", + "${file}", + "-o", + "${fileDirname}\\${fileBasenameNoExtension}.exe" + ], + "options": { + "cwd": "${fileDirname}" + }, + "problemMatcher": [ + "$gcc" + ], + "group": { + "kind": "build", + "isDefault": true + }, + "detail": "调试器生成的任务。" + } + ], + "version": "2.0.0" +} \ No newline at end of file diff --git "a/2025/\347\254\2541\347\273\204(STM32H750-ART-PI)/\345\274\240\344\270\200\346\231\250/\344\275\234\344\270\232/main..c" "b/2025/\347\254\2541\347\273\204(STM32H750-ART-PI)/\345\274\240\344\270\200\346\231\250/\344\275\234\344\270\232/main..c" new file mode 100644 index 0000000000000000000000000000000000000000..4f17332bd02ba4e85cb09c4250c5784f6834dbc9 --- /dev/null +++ "b/2025/\347\254\2541\347\273\204(STM32H750-ART-PI)/\345\274\240\344\270\200\346\231\250/\344\275\234\344\270\232/main..c" @@ -0,0 +1,71 @@ +#include +#include +#include + +#define THREAD_PRIORITY 25 +#define THREAD_STACK_SIZE 1024 +#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 count: %d\n", count++); + rt_thread_mdelay(500); + } +} + +static void thread2_entry(void *parameter) +{ + rt_uint32_t count = 0; + + while (1) + { + rt_kprintf("thread2 count: %d\n", count++); + for (int i = 0; i < 1000000; i++); + } +} + +static void thread3_entry(void *parameter) +{ + rt_uint32_t count = 0; + + while (1) + { + rt_kprintf("THREAD3 COUNT: %d\n", count++); + rt_thread_mdelay(200); + } +} + +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); + } + + while (1) + { + rt_kprintf("main thread running\n"); + rt_thread_mdelay(1000); + } + + return RT_EOK; +} \ No newline at end of file diff --git "a/2025/\347\254\2541\347\273\204(STM32H750-ART-PI)/\345\274\240\344\270\200\346\231\250/\344\275\234\344\270\232/\344\275\234\344\270\232.md" "b/2025/\347\254\2541\347\273\204(STM32H750-ART-PI)/\345\274\240\344\270\200\346\231\250/\344\275\234\344\270\232/\344\275\234\344\270\232.md" new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git "a/2025/\347\254\2541\347\273\204(STM32H750-ART-PI)/\345\274\240\344\270\200\346\231\250/\344\275\234\344\270\232/\347\254\254\344\270\211\345\244\251\344\275\234\344\270\232/event_demo.c" "b/2025/\347\254\2541\347\273\204(STM32H750-ART-PI)/\345\274\240\344\270\200\346\231\250/\344\275\234\344\270\232/\347\254\254\344\270\211\345\244\251\344\275\234\344\270\232/event_demo.c" new file mode 100644 index 0000000000000000000000000000000000000000..e7fc8d451cb07f683da85443397556dc80a10281 --- /dev/null +++ "b/2025/\347\254\2541\347\273\204(STM32H750-ART-PI)/\345\274\240\344\270\200\346\231\250/\344\275\234\344\270\232/\347\254\254\344\270\211\345\244\251\344\275\234\344\270\232/event_demo.c" @@ -0,0 +1,53 @@ +#include + +#define EVENT_FLAG3 (1 << 3) +#define EVENT_FLAG5 (1 << 5) + +static struct rt_event event; + +static void event_thread1(void *parameter) +{ + rt_uint32_t e; + while (1) + { + if (rt_event_recv(&event, (EVENT_FLAG3 | EVENT_FLAG5), + RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, + RT_WAITING_FOREVER, &e) == RT_EOK) + { + rt_kprintf("thread1: OR event received 0x%x\n", e); + } + } +} + +static void event_thread2(void *parameter) +{ + while (1) + { + rt_event_send(&event, EVENT_FLAG3); + rt_kprintf("thread2 send event 0x%x\n", EVENT_FLAG3); + rt_thread_mdelay(200); + + rt_event_send(&event, EVENT_FLAG5); + rt_kprintf("thread2 send event 0x%x\n", EVENT_FLAG5); + rt_thread_mdelay(500); + } +} + +int event_demo(void) +{ + rt_event_init(&event, "event", RT_IPC_FLAG_FIFO); + + rt_thread_t thread1 = rt_thread_create("thread1", + event_thread1, RT_NULL, + 512, 25, 5); + rt_thread_t thread2 = rt_thread_create("thread2", + event_thread2, RT_NULL, + 512, 26, 5); + + if (thread1 != RT_NULL) rt_thread_startup(thread1); + if (thread2 != RT_NULL) rt_thread_startup(thread2); + + return 0; +} + +MSH_CMD_EXPORT(event_demo, event demo); \ No newline at end of file diff --git "a/2025/\347\254\2541\347\273\204(STM32H750-ART-PI)/\345\274\240\344\270\200\346\231\250/\344\275\234\344\270\232/\347\254\254\344\270\211\345\244\251\344\275\234\344\270\232/mailbox_demo.c" "b/2025/\347\254\2541\347\273\204(STM32H750-ART-PI)/\345\274\240\344\270\200\346\231\250/\344\275\234\344\270\232/\347\254\254\344\270\211\345\244\251\344\275\234\344\270\232/mailbox_demo.c" new file mode 100644 index 0000000000000000000000000000000000000000..f9b11207299d38120e1721028f9f2864ac9f481c --- /dev/null +++ "b/2025/\347\254\2541\347\273\204(STM32H750-ART-PI)/\345\274\240\344\270\200\346\231\250/\344\275\234\344\270\232/\347\254\254\344\270\211\345\244\251\344\275\234\344\270\232/mailbox_demo.c" @@ -0,0 +1,52 @@ +#include + +#define THREAD_PRIORITY 25 +#define MB_ENTRY_SIZE sizeof(rt_uint32_t) +#define MB_SIZE 4 + +static struct rt_mailbox mb; + +static void mailbox_send_thread(void *parameter) +{ + rt_uint32_t value = 0; + while (1) + { + value++; + if (rt_mb_send(&mb, (rt_uint32_t)value) == RT_EOK) + { + rt_kprintf("thread1 send mailbox: %d\n", value); + } + rt_thread_mdelay(500); + } +} + +static void mailbox_recv_thread(void *parameter) +{ + rt_uint32_t value; + while (1) + { + if (rt_mb_recv(&mb, (rt_ubase_t *)&value, RT_WAITING_FOREVER) == RT_EOK) + { + rt_kprintf("thread2 recv mailbox: %d\n", value); + } + } +} + +int mailbox_demo(void) +{ + rt_mb_init(&mb, "mbt", &mb[0], MB_SIZE, RT_IPC_FLAG_FIFO); + + rt_thread_t thread1 = rt_thread_create("thread1", + mailbox_send_thread, RT_NULL, + 512, THREAD_PRIORITY, 5); + rt_thread_t thread2 = rt_thread_create("thread2", + mailbox_recv_thread, RT_NULL, + 512, THREAD_PRIORITY, 5); + + if (thread1 != RT_NULL) rt_thread_startup(thread1); + if (thread2 != RT_NULL) rt_thread_startup(thread2); + + return 0; +} + +MSH_CMD_EXPORT(mailbox_demo, mailbox demo); \ No newline at end of file diff --git "a/2025/\347\254\2541\347\273\204(STM32H750-ART-PI)/\345\274\240\344\270\200\346\231\250/\344\275\234\344\270\232/\347\254\254\344\270\211\345\244\251\344\275\234\344\270\232/message_queue_demo.c" "b/2025/\347\254\2541\347\273\204(STM32H750-ART-PI)/\345\274\240\344\270\200\346\231\250/\344\275\234\344\270\232/\347\254\254\344\270\211\345\244\251\344\275\234\344\270\232/message_queue_demo.c" new file mode 100644 index 0000000000000000000000000000000000000000..d27a09603e0b6873530888e353f34b440b42bb53 --- /dev/null +++ "b/2025/\347\254\2541\347\273\204(STM32H750-ART-PI)/\345\274\240\344\270\200\346\231\250/\344\275\234\344\270\232/\347\254\254\344\270\211\345\244\251\344\275\234\344\270\232/message_queue_demo.c" @@ -0,0 +1,63 @@ +#include + +#define THREAD_PRIORITY 25 +#define QUEUE_SIZE 5 +#define MSG_SIZE sizeof(struct msg) + +struct msg { + rt_uint8_t type; + rt_uint8_t data[20]; +}; + +static struct rt_messagequeue mq; + +static void mq_send_thread(void *parameter) +{ + struct msg buf; + buf.type = 0x01; + rt_memcpy(buf.data, "hello", 6); + + while (1) + { + if (rt_mq_send(&mq, &buf, MSG_SIZE) == RT_EOK) + { + rt_kprintf("thread1 send message: %s\n", buf.data); + } + rt_thread_mdelay(800); + } +} + +static void mq_recv_thread(void *parameter) +{ + struct msg buf; + while (1) + { + if (rt_mq_recv(&mq, &buf, MSG_SIZE, RT_WAITING_FOREVER) == RT_EOK) + { + rt_kprintf("thread2 recv message: type=%d data=%s\n", buf.type, buf.data); + } + } +} + +int message_queue_demo(void) +{ + rt_uint8_t msg_pool[QUEUE_SIZE * (MSG_SIZE + 4)]; + + rt_mq_init(&mq, "mqt", msg_pool, + MSG_SIZE, sizeof(msg_pool), + RT_IPC_FLAG_FIFO); + + rt_thread_t thread1 = rt_thread_create("thread1", + mq_send_thread, RT_NULL, + 512, THREAD_PRIORITY, 5); + rt_thread_t thread2 = rt_thread_create("thread2", + mq_recv_thread, RT_NULL, + 512, THREAD_PRIORITY, 5); + + if (thread1 != RT_NULL) rt_thread_startup(thread1); + if (thread2 != RT_NULL) rt_thread_startup(thread2); + + return 0; +} + +MSH_CMD_EXPORT(message_queue_demo, message queue demo); \ No newline at end of file diff --git "a/2025/\347\254\2541\347\273\204(STM32H750-ART-PI)/\345\274\240\344\270\200\346\231\250/\344\275\234\344\270\232/\347\254\254\344\270\211\345\244\251\344\275\234\344\270\232/mutex_demo.c" "b/2025/\347\254\2541\347\273\204(STM32H750-ART-PI)/\345\274\240\344\270\200\346\231\250/\344\275\234\344\270\232/\347\254\254\344\270\211\345\244\251\344\275\234\344\270\232/mutex_demo.c" new file mode 100644 index 0000000000000000000000000000000000000000..9e9b69f69fa31422ba2244f9fc37507faf4677a0 --- /dev/null +++ "b/2025/\347\254\2541\347\273\204(STM32H750-ART-PI)/\345\274\240\344\270\200\346\231\250/\344\275\234\344\270\232/\347\254\254\344\270\211\345\244\251\344\275\234\344\270\232/mutex_demo.c" @@ -0,0 +1,50 @@ +#include + +static rt_mutex_t mutex; +static rt_uint32_t counter; + +static void mutex_thread1(void *parameter) +{ + while (1) + { + rt_mutex_take(mutex, RT_WAITING_FOREVER); + rt_kprintf("thread1: counter = %d\n", ++counter); + rt_mutex_release(mutex); + rt_thread_mdelay(10); + } +} + +static void mutex_thread2(void *parameter) +{ + while (1) + { + rt_mutex_take(mutex, RT_WAITING_FOREVER); + rt_kprintf("thread2: counter = %d\n", ++counter); + rt_mutex_release(mutex); + rt_thread_mdelay(10); + } +} + +int mutex_demo(void) +{ + mutex = rt_mutex_create("mtx", RT_IPC_FLAG_FIFO); + if (mutex == RT_NULL) + { + rt_kprintf("create mutex failed.\n"); + return -1; + } + + rt_thread_t thread1 = rt_thread_create("thread1", + mutex_thread1, RT_NULL, + 512, 25, 5); + rt_thread_t thread2 = rt_thread_create("thread2", + mutex_thread2, RT_NULL, + 512, 25, 5); + + if (thread1 != RT_NULL) rt_thread_startup(thread1); + if (thread2 != RT_NULL) rt_thread_startup(thread2); + + return 0; +} + +MSH_CMD_EXPORT(mutex_demo, mutex demo); \ No newline at end of file diff --git "a/2025/\347\254\2541\347\273\204(STM32H750-ART-PI)/\345\274\240\344\270\200\346\231\250/\344\275\234\344\270\232/\347\254\254\344\270\211\345\244\251\344\275\234\344\270\232/semaphore_demo.c" "b/2025/\347\254\2541\347\273\204(STM32H750-ART-PI)/\345\274\240\344\270\200\346\231\250/\344\275\234\344\270\232/\347\254\254\344\270\211\345\244\251\344\275\234\344\270\232/semaphore_demo.c" new file mode 100644 index 0000000000000000000000000000000000000000..ea7adc051f1ef70b474bba5035deab7b3e95f173 --- /dev/null +++ "b/2025/\347\254\2541\347\273\204(STM32H750-ART-PI)/\345\274\240\344\270\200\346\231\250/\344\275\234\344\270\232/\347\254\254\344\270\211\345\244\251\344\275\234\344\270\232/semaphore_demo.c" @@ -0,0 +1,51 @@ +#include + +#define THREAD_PRIORITY 25 +#define THREAD_TIMESLICE 5 + +static rt_sem_t dynamic_sem; + +static void semaphore_thread1(void *parameter) +{ + while (1) + { + rt_kprintf("thread1 try to take semaphore...\n"); + rt_sem_take(dynamic_sem, RT_WAITING_FOREVER); + rt_kprintf("thread1 take semaphore!\n"); + rt_thread_mdelay(500); + } +} + +static void semaphore_thread2(void *parameter) +{ + while (1) + { + rt_kprintf("thread2 release semaphore!\n"); + rt_sem_release(dynamic_sem); + rt_thread_mdelay(1000); + } +} + +int semaphore_demo(void) +{ + dynamic_sem = rt_sem_create("dsem", 0, RT_IPC_FLAG_FIFO); + if (dynamic_sem == RT_NULL) + { + rt_kprintf("create semaphore failed.\n"); + return -1; + } + + rt_thread_t thread1 = rt_thread_create("thread1", + semaphore_thread1, RT_NULL, + 512, THREAD_PRIORITY, THREAD_TIMESLICE); + rt_thread_t thread2 = rt_thread_create("thread2", + semaphore_thread2, RT_NULL, + 512, THREAD_PRIORITY, THREAD_TIMESLICE); + + if (thread1 != RT_NULL) rt_thread_startup(thread1); + if (thread2 != RT_NULL) rt_thread_startup(thread2); + + return 0; +} + +MSH_CMD_EXPORT(semaphore_demo, semaphore demo); \ No newline at end of file diff --git "a/2025/\347\254\2541\347\273\204(STM32H750-ART-PI)/\345\274\240\344\270\200\346\231\250/\344\275\234\344\270\232/\347\254\254\344\270\211\345\244\251\344\275\234\344\270\232/signal_demo.c" "b/2025/\347\254\2541\347\273\204(STM32H750-ART-PI)/\345\274\240\344\270\200\346\231\250/\344\275\234\344\270\232/\347\254\254\344\270\211\345\244\251\344\275\234\344\270\232/signal_demo.c" new file mode 100644 index 0000000000000000000000000000000000000000..5c61739a8ab704db5c2632b4a1553aaecc570c3e --- /dev/null +++ "b/2025/\347\254\2541\347\273\204(STM32H750-ART-PI)/\345\274\240\344\270\200\346\231\250/\344\275\234\344\270\232/\347\254\254\344\270\211\345\244\251\344\275\234\344\270\232/signal_demo.c" @@ -0,0 +1,49 @@ +#include + +static void signal_handler(int sig) +{ + rt_kprintf("Received signal %d\n", sig); +} + +static void signal_thread(void *parameter) +{ + rt_thread_t tid = rt_thread_self(); + rt_signal_install(SIGUSR1, signal_handler); + rt_signal_unmask(SIGUSR1); + + while (1) + { + rt_kprintf("thread1 wait signal...\n"); + rt_thread_mdelay(1000); + } +} + +static void trigger_thread(void *parameter) +{ + rt_thread_t tid = rt_thread_find("thread1"); + if (tid == RT_NULL) return; + + while (1) + { + rt_thread_mdelay(2000); + rt_kprintf("thread2 send signal\n"); + rt_thread_kill(tid, SIGUSR1); + } +} + +int signal_demo(void) +{ + rt_thread_t thread1 = rt_thread_create("thread1", + signal_thread, RT_NULL, + 512, 25, 5); + rt_thread_t thread2 = rt_thread_create("thread2", + trigger_thread, RT_NULL, + 512, 26, 5); + + if (thread1 != RT_NULL) rt_thread_startup(thread1); + if (thread2 != RT_NULL) rt_thread_startup(thread2); + + return 0; +} + +MSH_CMD_EXPORT(signal_demo, signal demo); \ No newline at end of file diff --git "a/2025/\347\254\2541\347\273\204(STM32H750-ART-PI)/\345\274\240\344\270\200\346\231\250/\344\275\234\344\270\232/\347\254\254\345\233\233\345\244\251\344\275\234\344\270\232/main.c" "b/2025/\347\254\2541\347\273\204(STM32H750-ART-PI)/\345\274\240\344\270\200\346\231\250/\344\275\234\344\270\232/\347\254\254\345\233\233\345\244\251\344\275\234\344\270\232/main.c" new file mode 100644 index 0000000000000000000000000000000000000000..2a0094bcdac8d62d4ea2e7a401395f36c185c6ac --- /dev/null +++ "b/2025/\347\254\2541\347\273\204(STM32H750-ART-PI)/\345\274\240\344\270\200\346\231\250/\344\275\234\344\270\232/\347\254\254\345\233\233\345\244\251\344\275\234\344\270\232/main.c" @@ -0,0 +1,331 @@ +#include +#include +#include // 用于rand() + +/* 虚拟传感器控制命令 */ +#define VIR_SENSOR_CTRL_PRINT_INFO 0x20 +#define VIR_SENSOR_CTRL_SET_DATA 0x21 +#define VIR_SENSOR_CTRL_GET_DATA 0x22 +#define VIR_SENSOR_CTRL_START_SIM 0x23 +#define VIR_SENSOR_CTRL_STOP_SIM 0x24 +#define VIR_SENSOR_CTRL_SET_RANGE 0x25 + +/* 虚拟传感器设备结构体 */ +struct vir_sensor_dev +{ + struct rt_device parent; // RT-Thread设备基类 + rt_uint32_t sensor_data; // 当前传感器数据 + const char *info; // 传感器描述信息 + rt_uint32_t min_value; // 数据最小值 + rt_uint32_t max_value; // 数据最大值 + rt_timer_t simulate_timer; // 数据模拟定时器 + rt_uint32_t sim_interval; // 模拟间隔(ms) + rt_int32_t sim_step; // 每次模拟的变化步长 +}; + +/* 设备操作接口实现 */ +static rt_err_t vir_sensor_init(rt_device_t dev) +{ + struct vir_sensor_dev *sensor = (struct vir_sensor_dev *)dev; + rt_kprintf("Virtual sensor [%s] initialized\n", dev->parent.name); + return RT_EOK; +} + +static rt_err_t vir_sensor_open(rt_device_t dev, rt_uint16_t oflag) +{ + rt_kprintf("Virtual sensor [%s] opened\n", dev->parent.name); + return RT_EOK; +} + +static rt_err_t vir_sensor_close(rt_device_t dev) +{ + rt_kprintf("Virtual sensor [%s] closed\n", dev->parent.name); + return RT_EOK; +} + +static rt_size_t vir_sensor_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size) +{ + struct vir_sensor_dev *sensor = (struct vir_sensor_dev *)dev; + + if (buffer == RT_NULL || size < sizeof(rt_uint32_t)) { + return 0; + } + + *(rt_uint32_t *)buffer = sensor->sensor_data; + return sizeof(rt_uint32_t); +} + +static rt_size_t vir_sensor_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size) +{ + struct vir_sensor_dev *sensor = (struct vir_sensor_dev *)dev; + + if (buffer == RT_NULL || size < sizeof(rt_uint32_t)) { + return 0; + } + + rt_uint32_t new_value = *(rt_uint32_t *)buffer; + + // 数据范围检查 + if (new_value < sensor->min_value) new_value = sensor->min_value; + if (new_value > sensor->max_value) new_value = sensor->max_value; + + sensor->sensor_data = new_value; + return sizeof(rt_uint32_t); +} + +/* 定时器回调函数 - 数据模拟 */ +static void sensor_simulate(void *parameter) +{ + struct vir_sensor_dev *sensor = (struct vir_sensor_dev *)parameter; + + // 在[-sim_step, +sim_step]范围内随机变化 + rt_int32_t change = (rt_rand() % (2 * sensor->sim_step + 1)) - sensor->sim_step; + rt_int32_t new_value = (rt_int32_t)sensor->sensor_data + change; + + // 确保数据在范围内 + if (new_value < (rt_int32_t)sensor->min_value) new_value = sensor->min_value; + if (new_value > (rt_int32_t)sensor->max_value) new_value = sensor->max_value; + + sensor->sensor_data = (rt_uint32_t)new_value; + + // 发送数据更新事件(可选) + // rt_device_report_event(&sensor->parent, RT_DEVICE_EVENT_UPDATE, &sensor->sensor_data); +} + +static rt_err_t vir_sensor_control(rt_device_t dev, int cmd, void *args) +{ + struct vir_sensor_dev *sensor = (struct vir_sensor_dev *)dev; + + switch (cmd) { + case VIR_SENSOR_CTRL_PRINT_INFO: + if (args) { + rt_kprintf("[%s] Info: %s - %s\n", dev->parent.name, sensor->info, (char *)args); + } else { + rt_kprintf("[%s] Info: %s\n", dev->parent.name, sensor->info); + } + break; + + case VIR_SENSOR_CTRL_SET_DATA: + if (args) { + rt_uint32_t new_value = *(rt_uint32_t *)args; + // 数据范围检查 + if (new_value < sensor->min_value) new_value = sensor->min_value; + if (new_value > sensor->max_value) new_value = sensor->max_value; + sensor->sensor_data = new_value; + } + break; + + case VIR_SENSOR_CTRL_GET_DATA: + if (args) { + *(rt_uint32_t *)args = sensor->sensor_data; + } + break; + + case VIR_SENSOR_CTRL_START_SIM: + if (sensor->simulate_timer) { + rt_timer_start(sensor->simulate_timer); + rt_kprintf("[%s] Simulation started\n", dev->parent.name); + } + break; + + case VIR_SENSOR_CTRL_STOP_SIM: + if (sensor->simulate_timer) { + rt_timer_stop(sensor->simulate_timer); + rt_kprintf("[%s] Simulation stopped\n", dev->parent.name); + } + break; + + case VIR_SENSOR_CTRL_SET_RANGE: + if (args) { + rt_uint32_t *range = (rt_uint32_t *)args; + if (range[0] <= range[1]) { + sensor->min_value = range[0]; + sensor->max_value = range[1]; + // 确保当前值在新范围内 + if (sensor->sensor_data < sensor->min_value) + sensor->sensor_data = sensor->min_value; + if (sensor->sensor_data > sensor->max_value) + sensor->sensor_data = sensor->max_value; + } + } + break; + + default: + return -RT_ENOSYS; + } + return RT_EOK; +} + +/* 设备注册函数 */ +int rt_hw_vir_sensor_register(struct vir_sensor_dev *sensor, + const char *name, + const char *info, + rt_uint32_t init_value, + rt_uint32_t min_val, + rt_uint32_t max_val, + rt_uint32_t sim_interval, + rt_int32_t sim_step) +{ + RT_ASSERT(sensor != RT_NULL); + + // 初始化设备参数 + rt_memset(sensor, 0, sizeof(struct vir_sensor_dev)); + sensor->sensor_data = init_value; + sensor->info = info; + sensor->min_value = min_val; + sensor->max_value = max_val; + sensor->sim_interval = sim_interval; + sensor->sim_step = sim_step; + + // 设置设备操作接口 + sensor->parent.type = RT_Device_Class_Sensor; + sensor->parent.init = vir_sensor_init; + sensor->parent.open = vir_sensor_open; + sensor->parent.close = vir_sensor_close; + sensor->parent.read = vir_sensor_read; + sensor->parent.write = vir_sensor_write; + sensor->parent.control= vir_sensor_control; + + // 创建模拟定时器 + if (sim_interval > 0 && sim_step != 0) { + char timer_name[RT_NAME_MAX]; + rt_snprintf(timer_name, sizeof(timer_name), "sim_%s", name); + + sensor->simulate_timer = rt_timer_create(timer_name, + sensor_simulate, + sensor, + sim_interval, + RT_TIMER_FLAG_PERIODIC | RT_TIMER_FLAG_SOFT_TIMER); + if (sensor->simulate_timer) { + rt_kprintf("[%s] Simulation timer created (%dms interval)\n", name, sim_interval); + } + } + + // 注册设备到RT-Thread系统 + rt_device_register(&sensor->parent, name, RT_DEVICE_FLAG_RDWR); + + return RT_EOK; +} + +/* 快捷函数接口 */ +void vir_sensor_set(rt_device_t dev, rt_uint32_t data) +{ + rt_device_control(dev, VIR_SENSOR_CTRL_SET_DATA, &data); +} + +void vir_sensor_get(rt_device_t dev, rt_uint32_t *data) +{ + rt_device_control(dev, VIR_SENSOR_CTRL_GET_DATA, data); +} + +void vir_sensor_print(rt_device_t dev, const char *str) +{ + rt_device_control(dev, VIR_SENSOR_CTRL_PRINT_INFO, (void *)str); +} + +void vir_sensor_start_sim(rt_device_t dev) +{ + rt_device_control(dev, VIR_SENSOR_CTRL_START_SIM, RT_NULL); +} + +void vir_sensor_stop_sim(rt_device_t dev) +{ + rt_device_control(dev, VIR_SENSOR_CTRL_STOP_SIM, RT_NULL); +} + +void vir_sensor_set_range(rt_device_t dev, rt_uint32_t min_val, rt_uint32_t max_val) +{ + rt_uint32_t range[2] = {min_val, max_val}; + rt_device_control(dev, VIR_SENSOR_CTRL_SET_RANGE, range); +} + +/* 传感器实例定义和初始化 */ +#ifdef RT_USING_VIR_SENSOR0 +static struct vir_sensor_dev vir_sensor0; + +static int rt_hw_vir_sensor0_init(void) +{ + return rt_hw_vir_sensor_register(&vir_sensor0, + "vs0", + "Virtual Temperature Sensor", + 25, // 初始值 25°C + -40, // 最小值 -40°C + 125, // 最大值 125°C + 1000, // 1秒更新间隔 + 2); // 每次变化±2°C +} +INIT_DEVICE_EXPORT(rt_hw_vir_sensor0_init); +#endif + +#ifdef RT_USING_VIR_SENSOR1 +static struct vir_sensor_dev vir_sensor1; + +static int rt_hw_vir_sensor1_init(void) +{ + return rt_hw_vir_sensor_register(&vir_sensor1, + "vs1", + "Virtual Humidity Sensor", + 50, // 初始值 50% + 0, // 最小值 0% + 100, // 最大值 100% + 2000, // 2秒更新间隔 + 5); // 每次变化±5% +} +INIT_DEVICE_EXPORT(rt_hw_vir_sensor1_init); +#endif + +/* 应用示例 */ +static void sensor_app_thread_entry(void *parameter) +{ + rt_device_t temp_dev = rt_device_find("vs0"); + rt_device_t humi_dev = rt_device_find("vs1"); + + if (!temp_dev || !humi_dev) { + rt_kprintf("Sensor devices not found!\n"); + return; + } + + rt_device_open(temp_dev, RT_DEVICE_FLAG_RDWR); + rt_device_open(humi_dev, RT_DEVICE_FLAG_RDWR); + + // 设置温度范围 + vir_sensor_set_range(temp_dev, -20, 80); + + // 启动模拟 + vir_sensor_start_sim(temp_dev); + vir_sensor_start_sim(humi_dev); + + while (1) { + rt_uint32_t temp, humi; + + // 读取传感器数据 + vir_sensor_get(temp_dev, &temp); + vir_sensor_get(humi_dev, &humi); + + rt_kprintf("Temperature: %d°C, Humidity: %d%%\n", temp, humi); + + // 随机设置湿度值 + if (rt_rand() % 10 == 0) { + rt_uint32_t new_humi = rt_rand() % 100; + vir_sensor_set(humi_dev, new_humi); + rt_kprintf("Set humidity to: %d%%\n", new_humi); + } + + rt_thread_mdelay(3000); + } +} + +static int sensor_app_init(void) +{ + rt_thread_t tid = rt_thread_create("sensor_app", + sensor_app_thread_entry, + RT_NULL, + 2048, + 20, + 10); + if (tid) { + rt_thread_startup(tid); + } + return RT_EOK; +} +INIT_APP_EXPORT(sensor_app_init); \ No newline at end of file diff --git "a/2025/\347\254\2541\347\273\204(STM32H750-ART-PI)/\345\274\240\344\270\200\346\231\250/\347\254\224\350\256\260/\347\254\254\344\270\200\345\244\251\347\254\224\350\256\260.md" "b/2025/\347\254\2541\347\273\204(STM32H750-ART-PI)/\345\274\240\344\270\200\346\231\250/\347\254\224\350\256\260/\347\254\254\344\270\200\345\244\251\347\254\224\350\256\260.md" new file mode 100644 index 0000000000000000000000000000000000000000..f2ddf28888007b7e7de2dbc0b84a835d27afcbb7 --- /dev/null +++ "b/2025/\347\254\2541\347\273\204(STM32H750-ART-PI)/\345\274\240\344\270\200\346\231\250/\347\254\224\350\256\260/\347\254\254\344\270\200\345\244\251\347\254\224\350\256\260.md" @@ -0,0 +1,180 @@ +# 2025 RT-Thread 夏令营第一天笔记 + +## 上午 + +### 一、开发环境配置及示例工程的运行 + +#### 1.1 安装 Git 并抓取源码 +首先在电脑上安装 Git。然后打开命令行,输入以下命令来抓取 RT-Thread 源码和 ENV 环境: +```bash +git clone https://gitee.com/mirrors_RT-Thread/rt-thread.git +git clone --recursive --depth 1 https://gitee.com/mirrors_RT-Thread/env-windows.git +``` + +#### 1.2 配置 ENV 环境 +1. 打开 env-windows 文件夹,并运行 env.bat +2. 使用快捷键 Win + Alt + P 打开设置界面 +3. 在左侧点击 Integration,然后点击 Register 完成对 ENV 环境的配置与注册 +4. 注册完成后,在任意文件夹中右键菜单会出现 ConEmu Here 选项 + +#### 1.3 编译并运行 RT-Thread 示例工程 +1. 进入路径 `\rt-thread\bsp\qemu-vexpress-a9`,右键选择 ConEmu Here 打开终端 +2. 输入以下命令: +```bash +menuconfig +``` +回车后保存并退出,生成 Config 文件 +3. 更新 ENV 环境: +```bash +pkgs --upgrade +``` +4. 编译工程: +```bash +scons -j4 +``` +5. 编译完成后运行: +```bash +qemu-nographic.bat +``` +6. 再次进入 menuconfig,配置并下载 lvgl 软件包 +7. 重新编译后输入: +```bash +qemu +``` +即可成功运行 lvgl 示例工程 + +#### 1.4 安装 VS Code 并进行开发 +1. 下载并安装 Visual Studio Code +2. 使用 VS Code 打开 qemu-vexpress-a9 文件夹 +3. 找到 application 文件夹,编辑主函数 main.c +4. 修改完成后重复 1.3 中的编译和运行步骤,即可在终端看到运行结果 + +## 下午 + +### 二、Git 的学习和使用 + +#### 2.1 使用 Git 抓取代码 +在命令行中使用以下命令从 Gitee 抓取仓库代码: +```bash +git clone [仓库地址] +``` + +#### 2.2 使用 VS Code 和 Git Graph 插件 +1. 在 VS Code 中安装 Git Graph 插件 +2. 该插件可以避免使用命令行,简化 Git 操作,提高效率 +3. 在 Gitee 上 Fork RSOC-RTT 到自己的仓库 +4. 使用 SSH 方式将代码拉取到本地 +5. 创建自己的分支,编写笔记和作业 +6. 最后通过 Pull Request(PR)提交到远端仓库 + +### 三、常用的 Git 指令 + +#### 初始化仓库 +```bash +git init +``` +初始化一个新的 Git 仓库 + +#### 克隆仓库 +```bash +git clone [url] +``` +从远程仓库克隆一个项目到本地 + +#### 查看状态 +```bash +git status +``` +显示工作目录和暂存区的状态 + +#### 添加文件到暂存区 +```bash +git add [file] +``` +将指定文件添加到暂存区 +```bash +git add . +``` +将所有改动添加到暂存区 + +#### 提交更改 +```bash +git commit -m "[message]" +``` +提交暂存区的更改,并附带提交信息 + +#### 查看提交历史 +```bash +git log +``` +显示项目的提交日志 +```bash +git log --oneline +``` +以简洁的一行格式显示提交日志 + +#### 分支操作 +```bash +git branch +``` +列出所有的本地分支 +```bash +git branch [branch-name] +``` +创建新分支 +```bash +git checkout [branch-name] +``` +切换到指定分支 +```bash +git checkout -b [branch-name] +``` +创建并切换到新的分支 + +#### 合并分支 +```bash +git merge [branch] +``` +将指定分支合并到当前分支 + +#### 远程操作 +```bash +git remote add [remote-name] [url] +``` +添加一个新的远程仓库 +```bash +git fetch [remote-name] +``` +从远程仓库获取最新更新而不自动合并 +```bash +git pull [remote-name] [branch] +``` +获取并合并远程仓库的更改到当前分支 +```bash +git push [remote-name] [branch] +``` +推送本地分支的更新到远程仓库 + +#### 查看差异 +```bash +git diff +``` +显示工作目录与暂存区之间的差异 +```bash +git diff --staged +``` +显示暂存区与最近一次提交之间的差异 + +#### 删除操作 +```bash +git reset [file] +``` +将指定文件从暂存区移除,但保留工作目录中的内容 +```bash +git reset [commit] +``` +回滚到特定的提交(请谨慎使用,可能会丢失未提交的更改) +```bash +git rm [file] +``` +从工作目录和暂存区中删除文件 \ No newline at end of file diff --git "a/2025/\347\254\2541\347\273\204(STM32H750-ART-PI)/\345\274\240\344\270\200\346\231\250/\347\254\224\350\256\260/\347\254\254\344\270\211\345\244\251\347\254\224\350\256\260.md" "b/2025/\347\254\2541\347\273\204(STM32H750-ART-PI)/\345\274\240\344\270\200\346\231\250/\347\254\224\350\256\260/\347\254\254\344\270\211\345\244\251\347\254\224\350\256\260.md" new file mode 100644 index 0000000000000000000000000000000000000000..fc3b31bbadb97df816957198e5f240c07ad608a8 --- /dev/null +++ "b/2025/\347\254\2541\347\273\204(STM32H750-ART-PI)/\345\274\240\344\270\200\346\231\250/\347\254\224\350\256\260/\347\254\254\344\270\211\345\244\251\347\254\224\350\256\260.md" @@ -0,0 +1,98 @@ +# 2025 RT-Thread 夏令营第三天笔记 +## 一、线程间的同步 +### 1.1 信号量(Semaphore) +**概念**: +信号量是一种用于控制多个线程对共享资源访问的同步机制。它通常代表可用资源的数量,可以用于线程间的同步或资源管理。信号量有两种类型:二值信号量(只能取0或1)和计数信号量(非负整数)。 +**工作机制**: +- **创建**:初始化一个信号量时,会指定一个初始值(例如,初始资源数量)。 +- **获取(take)**:当一个线程需要访问共享资源时,它会尝试获取信号量。如果信号量的值大于0,则信号量减1,线程继续执行;如果信号量的值为0,则线程会被阻塞,直到信号量的值大于0(表示有资源可用)。 +- **释放(release)**:当线程使用完共享资源后,会释放信号量,信号量的值加1。如果有其他线程正在等待该信号量,则其中一个线程会被唤醒(取决于等待策略,如FIFO或优先级)。 +信号量常用于: +- 限制同时访问共享资源的线程数量(例如,限制同时访问一个硬件的线程数)。 +- 线程同步(例如,一个线程完成任务后通知另一个线程)。 + +**示例代码**:先打开*RT-Studio*,然后创建新的工程,然后在界面左侧栏选择*RT-Thread Settings*,然后在软件包的杂项软件包里选择*samples*然后打开*rt-thread*软件包内核实例,然后依次打开*semaphore*、*mutex*和*event*,然后还可以将注释更改为中文,然后*Ctrl+s*保存文件,然后编译,运行即可看到信号量是如何使用的了。 +### 1.2 互斥量(Mutex) +**概念**: +互斥量是一种特殊的二值信号量,用于实现互斥访问共享资源。与信号量不同,互斥量具有所有权概念,即只有获取互斥量的线程才能释放它。互斥量还支持优先级继承,以防止优先级反转问题。 +**工作机制**: +- **创建**:互斥量初始为可用状态(解锁状态)。 +- **获取(lock)**:线程尝试获取互斥量。如果互斥量当前未被占用,则线程成功获取互斥量(互斥量变为锁定状态),并成为互斥量的所有者。如果互斥量已被其他线程占用,则当前线程被阻塞,直到互斥量被释放。 +- **释放(unlock)**:只有拥有互斥量的线程才能释放它。释放后,互斥量变为解锁状态。如果有其他线程在等待该互斥量,则其中一个线程会被唤醒并获取互斥量。 +互斥量的特点: +- **所有权**:只有持有互斥量的线程才能释放它。 +- **优先级继承**:如果一个高优先级线程等待一个被低优先级线程占有的互斥量,则低优先级线程会暂时提升到高优先级,以防止中优先级线程抢占导致的高优先级线程被阻塞过久(即优先级反转问题)。 +互斥量用于保护共享资源,确保同一时间只有一个线程访问该资源。 + +**示例代码**:与信号量的相同。 +### 1.3 事件集(Event) +**概念**: +事件集是一种用于线程间同步的机制,允许一个线程等待多个事件的发生,并且可以等待多个事件的任意组合(如任意一个事件发生或所有事件发生)。每个事件由一个位表示(通常32位系统支持32个事件)。 +**工作机制**: +- **创建**:事件集被初始化为0(没有任何事件发生)。 +- **发送(send)**:线程可以设置事件集中的某些位(表示事件发生)。发送事件会唤醒正在等待这些事件的线程。 +- **接收(recv)**:线程可以等待事件集中的事件。在等待时,可以指定: + - 等待哪些事件(通过事件掩码)。 + - 等待条件:是等待所有指定事件(逻辑与)还是任意一个事件(逻辑或)。 + - 是否清除事件:在成功接收到事件后,是否清除事件标志(自动清零)。 + **示例代码**:与信号量的相同。 + ## 二、线程间的通信 + ### 2.1邮箱(Mailbox) +**概念**: +邮箱是一种用于线程间通信的机制,它允许线程发送一个固定大小的消息(通常是4字节,在32位系统上为一个指针或一个整数值)给另一个线程。邮箱中每个消息槽只能存放一条消息,当邮箱满时,发送线程可以选择等待或立即返回。 +**工作机制**: +1. **初始化**:创建一个邮箱,并指定邮箱容量(消息数量)和消息大小(RT-Thread中固定为4字节)。 +2. **发送消息**: + - 如果邮箱未满,消息被复制到邮箱的一个槽中,并唤醒等待接收的线程(如果有)。 + - 如果邮箱已满,发送线程可以选择挂起等待(阻塞)直到有空位,或者立即返回错误。 +3. **接收消息**: + - 如果邮箱中有消息,接收线程取出消息(复制到提供的缓冲区),并唤醒等待发送的线程(如果有)。 + - 如果邮箱为空,接收线程可以选择挂起等待(阻塞)直到有消息,或者立即返回错误。 +**关键特性**: +- 消息大小固定(通常为4字节,适合传递指针或整数)。 +- 可以传递一个指向更大数据块的指针,但需要确保数据在接收线程访问时仍然有效(通常需要动态分配内存,并约定释放责任)。 +- 支持超时机制。 +**典型应用**: +- 传递简单的整数值或状态标志。 +- 传递指针,指向动态分配的数据结构(需注意内存管理)。 +- 轻量级的事件通知。 +### 2.2消息队列(Message Queue) +**概念**: +消息队列是邮箱的扩展,允许发送不定长的消息(但每条消息有最大长度限制)。消息队列在内部维护一个消息缓冲区,每个消息由消息头和消息内容组成。发送时消息被复制到队列缓冲区,接收时再从缓冲区复制出来。 +**工作机制**: +1. **初始化**:创建消息队列时,需要指定队列中消息的最大数量、每条消息的最大长度,并分配相应的存储空间(通常是一个连续的内存块)。 +2. **发送消息**: + - 如果队列中有足够的空间存放新消息,则消息被复制到队列的缓冲区中,并唤醒等待接收的线程。 + - 如果队列空间不足,发送线程可以选择挂起等待(阻塞)直到有空间,或者立即返回错误。 +3. **接收消息**: + - 如果队列中有消息,接收线程将消息从队列缓冲区复制到用户提供的缓冲区(需要足够大),并唤醒等待发送的线程(如果有空间释放)。 + - 如果队列为空,接收线程可以选择挂起等待(阻塞)直到有消息,或者立即返回错误。 +**关键特性**: +- 支持可变长度消息(每条消息长度在初始化时设定的最大值内)。 +- 消息在传递过程中被复制,发送方和接收方操作的是不同的内存副本(避免了共享内存的同步问题)。 +- 支持超时机制。 +- 比邮箱更灵活,但开销也更大。 +**典型应用**: +- 传递长度可变的数据(如字符串、结构体等)。 +- 需要传递较大数据块的场景(通过传递指针,但需要注意内存管理)。 +- 多线程之间传递复杂消息。 +### 2.3信号(Signal) +**概念**: +信号是一种异步通信机制,类似于操作系统中的软中断。一个线程可以给另一个线程(或自身)发送信号,接收线程在收到信号后,将中断当前执行流程,转而去执行预先注册的信号处理函数。处理完成后,线程再返回到被中断的地方继续执行。 +**工作机制**: +1. **安装信号处理函数**:线程通过`rt_signal_install()`为特定信号注册处理函数。 +2. **阻塞/解除阻塞信号**:线程可以屏蔽某些信号(`rt_signal_mask()`)或解除屏蔽(`rt_signal_unmask()`)。 +3. **发送信号**:线程通过`rt_thread_kill()`(注意:函数名类似Unix的kill,但只是发送信号)向目标线程发送信号。 +4. **信号处理**: + - 当目标线程被调度运行时,如果收到信号且该信号未被屏蔽,则调用相应的处理函数。 + - 信号处理函数在目标线程的上下文中执行(类似于中断,但属于线程上下文)。 + - 信号处理函数应尽量简短,避免调用可能引起阻塞的函数。 +**关键特性**: +- 异步通知:信号可以在任何时候发送给目标线程。 +- 处理函数执行在目标线程的上下文:因此会中断目标线程的正常执行流程。 +- 支持标准信号(如SIGINT, SIGUSR1等),也可以自定义信号。 +- 线程可以屏蔽信号(暂时不处理)或解除屏蔽。 +**典型应用**: +- 中断线程的正常流程以处理异常情况。 +- 自定义事件通知(如超时提醒、外部事件等)。 +- 实现类似Unix风格的信号处理(如Ctrl+C中断)。 \ No newline at end of file diff --git "a/2025/\347\254\2541\347\273\204(STM32H750-ART-PI)/\345\274\240\344\270\200\346\231\250/\347\254\224\350\256\260/\347\254\254\344\272\214\345\244\251\347\254\224\350\256\260.md" "b/2025/\347\254\2541\347\273\204(STM32H750-ART-PI)/\345\274\240\344\270\200\346\231\250/\347\254\224\350\256\260/\347\254\254\344\272\214\345\244\251\347\254\224\350\256\260.md" new file mode 100644 index 0000000000000000000000000000000000000000..621377b0bf49c67591be2effb1ce273005b94732 --- /dev/null +++ "b/2025/\347\254\2541\347\273\204(STM32H750-ART-PI)/\345\274\240\344\270\200\346\231\250/\347\254\224\350\256\260/\347\254\254\344\272\214\345\244\251\347\254\224\350\256\260.md" @@ -0,0 +1,60 @@ +# 2025 RT-Thread 夏令营第二天笔记 +## 一、RT-Thread STtudio安装与配置 +### 1.1 RT Studio和SDK资源包下载 + 到*RT-Thread*官网*https://www.rt-thread.org/download.html#download-rt-thread-studio*下载*RT Studio*,下载完成后正常安装即可。然后打开*RT Studio*,然后打开SDK资源管理器,然后选择*STM32F407*,选择最新版本后安装。之后再安装最新版本的*QEMU* 。 + ### 1.2新建工程并模拟运行QEMU + 选择基于开发板创建新工程,开发板选择*STM32F407-ATK-EXPLORER*,然后调制器选择*QEMU*,待创建完成之后build工程即可。然后在工具栏选择下载,并选择与之对应的模拟器,然后系统控制台就会自动运行,然后输入*PC*即可查看当前任务状态。 +## 二、裸机和RTOS的区别 +### 2.1裸机的优势 +裸机适用于系统功能单一的情况下使用,并可以提高其运行效率;还可以使用较少的储存实现嵌入式系统的功能。 +### 2.2裸机的劣势 +裸机的代码耦合度较高,复用性较差;而且不适合复杂的嵌入式系统;同时在编写的代码不合理时容易造成系统阻塞。 +### 2.3ROTS的优势 +相较于裸机代码耦合度低,复用性较好;而且可以使用任务划分的方式降低实现复杂嵌入式系统的代码逻辑;RTOS下的延时不会一直占用CPU,延时期间处理其他任务;使用RTOS提供的线程同步与信息传递会提高系统的实时性。 +### 2.3ROTS的劣势 +在小容量的嵌入式系统中,其本身会占据部分内存;而且在单一系统中,系统调度会增加额外的开销。 + ## 三、初识RT-Thread内核 +### 3.1临界区 +定义:访问共享资源的代码段,同一时间仅允许一个线程访问。一但被占用,其他线程就不能够再使用,只能等待。 +### 3.2阻塞式线程和非阻塞式线程 +阻塞式线程对于临界区只能等,期间不能执行其他任务;非阻塞式线程对于临界区,等待期间可以执行其他任务。 +### 3.3RT-Thread系统启动流程 +3.3.1 **启动文件初始化**: + ```assembly + Reset_Handler: + BL SystemInit ; 时钟配置 + BL entry ; 进入RT-Thread + ``` + +3.3.2. **软件初始化**: + ```c + rt_hw_interrupt_disable(); // 关中断 + rt_hw_board_init(); // 板级外设 + rt_show_version(); // 打印版本 + rt_system_timer_init(); // 硬件定时器 + rt_system_scheduler_init(); // 调度器 + ``` +3.3.3. **线程创建**: + ```c + rt_application_init(); // 主线程 + rt_thread_idle_init(); // 空闲线程(优先级最低) + ``` +3.3.4 **启动调度**: + ```c + rt_system_scheduler_start(); // 开始线程调度 + ``` +### 3.4 空闲线程 +- 优先级最低(通常31) +- 永不挂起 +- 功能: + - CPU使用率统计 + - 低功耗模式管理 + - 僵尸线程资源回收 +### 3.5 线程调度机制 +1. **优先级抢占**: + - 高优先级线程可抢占低优先级线程 + - 示例:中断服务程序唤醒高优先级线程 + +2. **时间片轮转**: + - 相同优先级线程轮流执行 + - 时间片用完触发切换 \ No newline at end of file diff --git "a/2025/\347\254\2541\347\273\204(STM32H750-ART-PI)/\345\274\240\344\270\200\346\231\250/\347\254\224\350\256\260/\347\254\254\345\233\233\345\244\251\347\254\224\350\256\260.md" "b/2025/\347\254\2541\347\273\204(STM32H750-ART-PI)/\345\274\240\344\270\200\346\231\250/\347\254\224\350\256\260/\347\254\254\345\233\233\345\244\251\347\254\224\350\256\260.md" new file mode 100644 index 0000000000000000000000000000000000000000..1d90c7f04b6f0cba5b99ad27e036c9ba1d525e31 --- /dev/null +++ "b/2025/\347\254\2541\347\273\204(STM32H750-ART-PI)/\345\274\240\344\270\200\346\231\250/\347\254\224\350\256\260/\347\254\254\345\233\233\345\244\251\347\254\224\350\256\260.md" @@ -0,0 +1,14 @@ +# 2025 RT-Thread 夏令营第四天笔记 +## 一、IO设备模型介绍 +RT-Thread的IO设备模型是RT-Thread内核的核心组件之一,它为上层应用程序提供了一套统一的设备操作接口(API),使得应用程序可以以相同的方式访问不同类型的硬件设备,而不必关心底层硬件的具体差异。 +#### 1.1 核心概念 +- **设备(Device)**:在RT-Thread中,设备被抽象为一种内核对象,每个设备都有一个名称,并通过设备驱动与硬件关联。 +- **设备驱动(Driver)**:设备驱动是底层硬件操作的实现,负责将标准的设备操作(如读、写、控制)映射到具体的硬件操作。 +- **设备类型(Device Class)**:设备按照其功能特性进行分类,如字符设备、块设备、网络设备、传感器设备等。设备类型决定了设备支持的操作集合。 +- **设备操作接口(Operations)**:设备驱动通过一组预定义的操作函数(如init, open, read, write, control等)来提供服务。 +## 二、设备驱动框架介绍 +### 2.1核心定义 +设备驱动框架是操作系统内核中**标准化硬件交互**的软件层,提供: +- 应用层通过标准API访问硬件(如 `read()`/`write()`) +- 驱动开发者复用通用逻辑,专注硬件差异 +- 操作系统统一管理硬件资源 diff --git "a/2025/\347\254\2544\347\273\204(FRDM-MCXA156)/\350\202\226\346\231\257\345\263\260/\344\275\234\344\270\232/main.c" "b/2025/\347\254\2544\347\273\204(FRDM-MCXA156)/\350\202\226\346\231\257\345\263\260/\344\275\234\344\270\232/main.c" new file mode 100644 index 0000000000000000000000000000000000000000..939336066cd9e6a17bb65fc51185ee65880e92e1 --- /dev/null +++ "b/2025/\347\254\2544\347\273\204(FRDM-MCXA156)/\350\202\226\346\231\257\345\263\260/\344\275\234\344\270\232/main.c" @@ -0,0 +1,67 @@ +#include +#include +#include + +#define thread_size 512 +#define thread_pri 15 +#define thread_tick 5 + + +#define THREAD1_TICK 10 +#define THREAD2_TICK 20 +#define THREAD3_TICK 30 + +uint16_t sum1, sum2; + + +void thread1_entry() +{ + while(1) + { + rt_kprintf("sum1=%d\n", sum1++); + rt_thread_mdelay(500); + } +} + +void thread2_entry() +{ + while(1) + { + rt_kprintf("sum2=%d\n", sum2++); + rt_thread_mdelay(500); + } +} + +void thread3_entry() +{ + while(1) + { + rt_kprintf("ing......\n"); + rt_thread_mdelay(300); + } +} + + +int main(void) +{ + rt_thread_t thread1 = RT_NULL; + rt_thread_t thread2 = RT_NULL; + rt_thread_t thread3 = RT_NULL; + + thread3 = rt_thread_create("thread3", thread3_entry, RT_NULL, + thread_size, thread_pri, THREAD3_TICK); + thread1 = rt_thread_create("thread1", thread1_entry, RT_NULL, + thread_size, thread_pri, THREAD1_TICK); + + thread2 = rt_thread_create("thread2", thread2_entry, RT_NULL, + thread_size, thread_pri, THREAD2_TICK); + + if(thread3) + rt_thread_startup(thread3); + if(thread1) + rt_thread_startup(thread1); + if(thread2) + rt_thread_startup(thread2); + + return RT_EOK; +} diff --git "a/2025/\347\254\2544\347\273\204(FRDM-MCXA156)/\350\202\226\346\231\257\345\263\260/\347\254\224\350\256\260/Day1\347\254\224\350\256\260.md" "b/2025/\347\254\2544\347\273\204(FRDM-MCXA156)/\350\202\226\346\231\257\345\263\260/\347\254\224\350\256\260/Day1\347\254\224\350\256\260.md" new file mode 100644 index 0000000000000000000000000000000000000000..49c7f297a22b291471718e85e2bb5f5c27a1bcfc --- /dev/null +++ "b/2025/\347\254\2544\347\273\204(FRDM-MCXA156)/\350\202\226\346\231\257\345\263\260/\347\254\224\350\256\260/Day1\347\254\224\350\256\260.md" @@ -0,0 +1,30 @@ +# ENV工具使用 +```c +scons -4j//对文件进行编译 +pkgs --upgrade//升级软件包 +menuconfig//打开图形化配置界面 +``` +其中使用pkgs --upgrade时可能会报错如下 +![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20250722/e7d05ce56c526fcc60c8346d89eff8d0.png.webp) +此时需要进入ENV的这个目录:E:\env\tools\scripts\cmds,注意ENV安装的目录 +在这个目录下打开ENV工具,运行menuconfig,保存 + +vsc进行代码编写,在env工具进行编译后使用qemu-nographic.bat 运行编译好的文件 +![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20250722/6a1eb985c8edab33fe71d2828a403a0a.png.webp) + +![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20250722/63fc6d6d9f8b2a94616f28f942f7caae.png.webp) +使用qemu.bat运行lvgl的demo + +![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20250722/e8553b927d181517f5217ea3022c0554.png.webp) +#git使用 + +```c +git add 暂存 +git commit 提交 +git log 查看历史 +git checkout/git reset 回退 +git branch 创建分支 +git merge 合并分支 +git push/pull 推送/拉取 +git status 查看文件状态 +``` \ No newline at end of file diff --git "a/2025/\347\254\2544\347\273\204(FRDM-MCXA156)/\350\202\226\346\231\257\345\263\260/\347\254\224\350\256\260/Day2\347\254\224\350\256\260.md" "b/2025/\347\254\2544\347\273\204(FRDM-MCXA156)/\350\202\226\346\231\257\345\263\260/\347\254\224\350\256\260/Day2\347\254\224\350\256\260.md" new file mode 100644 index 0000000000000000000000000000000000000000..0cd1925c9970769b1d54756f5ed1df65aa8d3a70 --- /dev/null +++ "b/2025/\347\254\2544\347\273\204(FRDM-MCXA156)/\350\202\226\346\231\257\345\263\260/\347\254\224\350\256\260/Day2\347\254\224\350\256\260.md" @@ -0,0 +1,111 @@ +# RTT Studio使用 +**1.资源包下载** + 安装STM32F407探索者和qemu的资源包 +**2.新建RTT项目** +**3.打开RT-Thread Settings下载示例** +# 基本知识 +**临界区**:每个进程中访问临界资源的那段程序称之为临界区 +**信号量**:表示可用资源的数量,即线程可访问 +**阻塞**:当程序执行某个操作时,若条件未满足,则主动挂起等待,直到条件满足后才继续执行。 +**非阻塞**:执行操作时无论是否满足条件都立即返回。 +# 创建线程以及应用 +**动态**: + +```c +rt_thread_create(1.线程名字 + 2.入口函数 + 3.入口函数参数 + 4.栈大小 + 5.线程优先级 + 6.线程时间片大小) +``` +**静态**: + +```c +rt_thread_init(1.线程控制块的地址 + 2.线程名字 + 3.入口函数 + 4.入口函数参数 + 5.线程栈起始地址 + 6.栈大小 + 7.线程优先级 + 8.线程时间片大小) +``` +两者区别在于静态的需要提前分配内存,在某些需要保证安全的情况下更合适使用 +**初始化线程**: + +```c +rt_thread_startup(线程名) +``` +**作业**: + +```c +#include +#include +#include + +#define thread_size 512 +#define thread_pri 15 +#define thread_tick 5 + + +#define THREAD1_TICK 10 +#define THREAD2_TICK 20 +#define THREAD3_TICK 30 + +uint16_t sum1, sum2; + + +void thread1_entry() +{ + while(1) + { + rt_kprintf("sum1=%d\n", sum1++); + rt_thread_mdelay(500); + } +} + +void thread2_entry() +{ + while(1) + { + rt_kprintf("sum2=%d\n", sum2++); + rt_thread_mdelay(500); + } +} + +void thread3_entry() +{ + while(1) + { + rt_kprintf("ing......\n"); + rt_thread_mdelay(300); + } +} + + +int main(void) +{ + rt_thread_t thread1 = RT_NULL; + rt_thread_t thread2 = RT_NULL; + rt_thread_t thread3 = RT_NULL; + + thread3 = rt_thread_create("thread3", thread3_entry, RT_NULL, + thread_size, thread_pri, THREAD3_TICK); + thread1 = rt_thread_create("thread1", thread1_entry, RT_NULL, + thread_size, thread_pri, THREAD1_TICK); + + thread2 = rt_thread_create("thread2", thread2_entry, RT_NULL, + thread_size, thread_pri, THREAD2_TICK); + + if(thread3) + rt_thread_startup(thread3); + if(thread1) + rt_thread_startup(thread1); + if(thread2) + rt_thread_startup(thread2); + + return RT_EOK; +} + +``` \ No newline at end of file