Лабораторная 6
.docxМинистерство науки и высшего образования Российской Федерации
Федеральное государственное автономное образовательное учреждение высшего образования
ТОМСКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ СИСТЕМ УПРАВЛЕНИЯ И РАДИОЭЛЕКТРОННИКИ (ТУСУР)
Кафедра комплексной информационной безопасности электронно-вычислительных систем (КИБЭВС)
МЕЖПРОЦЕССНОЕ ВЗАИМОДЕЙСТВИЕ В FREERTOS
Отчет по лабораторной работе №6
по дисциплине «Основы программирования микроконтроллеров»
Вариант №1
Студенты гр. 712-2: ___________ Л.С. Болтушкин
___________ Н.А. Рыбин
___________ Д.В. Шабанова __________
Руководитель Старший преподаватель кафедры КИБЭВС
_______ __________ Д.С. Беляков
__________
Томск 2025
Введение
Целью данной лабораторной работы является углубленное изучение архитектуры ARM на примере микроконтроллера STM32F103RBT6, изучение межпроцессного взаимодействия и примитивов синхронизации в OCPB FreeRTOS.
Вариант №1 – Есть два потока, один пишет текст в консоль, второй - ожидает текста из очереди, после приостанавливает первый поток и пересылает текст в консоль. При нажатии на кнопку из обработчика прерывания отправляется текст в очередь.
1 ХОД РАБОТЫ
Для выполнения данной лабораторной работы были использованы файлы, созданные в предыдущей лабораторной работе. Для начала изменен размер кучи в файле конфигурации (рисунок 1.1).
Рисунок 1.1 – Изменение размера кучи
После изменен файл «main.c» для выполнения по индивидуальному варианту работы.
Код программы представлен в приложении А. Результат выполнения работы представлен на рисунке 1.2.
Рисунок 1.2 – Выполнение программы
Заключение
В ходе выполнения данной лабораторной работы было изучено межпроцессное взаимодействие и примитивы синхронизации в OCPB FreeRTOS.
Приложение А
(обязательное)
Листинг файла «main.c»
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "stm32f1xx.h"
#include <stdio.h>
#include <string.h>
extern void init_uart(void);
static QueueHandle_t xQueue = NULL;
static TaskHandle_t xTaskPrintHandle = NULL;
static volatile uint32_t press_counter = 0;
static void LED_Init(void) {
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;
GPIOA->CRL &= ~(GPIO_CRL_CNF5 | GPIO_CRL_MODE5);
GPIOA->CRL |= GPIO_CRL_MODE5_0;
GPIOA->ODR &= ~GPIO_ODR_ODR5;
}
static void Button_Init(void) {
RCC->APB2ENR |= RCC_APB2ENR_IOPCEN | RCC_APB2ENR_AFIOEN;
GPIOC->CRH &= ~(GPIO_CRH_CNF13 | GPIO_CRH_MODE13);
GPIOC->CRH |= GPIO_CRH_CNF13_0;
GPIOC->ODR |= GPIO_ODR_ODR13;
AFIO->EXTICR[3] = (AFIO->EXTICR[3] & ~AFIO_EXTICR4_EXTI13) | AFIO_EXTICR4_EXTI13_PC;
EXTI->IMR |= EXTI_IMR_MR13;
EXTI->FTSR |= EXTI_FTSR_TR13;
NVIC_SetPriority(EXTI15_10_IRQn, 6);
NVIC_EnableIRQ(EXTI15_10_IRQn);
}
static void vTaskPrint(void *pvParameters) {
uint32_t counter = 0;
while(1) {
printf("Задача1: Печать сообщения #%lu\r\n", counter++);
GPIOA->ODR ^= GPIO_ODR_ODR5;
vTaskDelay(pdMS_TO_TICKS(1000));
}
}
static void vTaskQueue(void *pvParameters) {
char received_text[50];
while(1) {
if(xQueueReceive(xQueue, received_text, portMAX_DELAY) == pdPASS) {
printf("\r\n=== АКТИВАЦИЯ ЗАДАЧИ2 ===\r\n");
printf("Приостановка Задачи1...\r\n");
vTaskSuspend(xTaskPrintHandle);
printf("Получено из очереди: %s\r\n", received_text);
printf("Обработка сообщения...\r\n");
for(int i = 0; i < 8; i++) {
GPIOA->ODR ^= GPIO_ODR_ODR5;
vTaskDelay(pdMS_TO_TICKS(125));
}
printf("Возобновление Задачи1...\r\n");
vTaskResume(xTaskPrintHandle);
printf("=== ЗАДАЧА2 ЗАВЕРШЕНА ===\r\n\r\n");
vTaskDelay(pdMS_TO_TICKS(50));
}
}
}
void EXTI15_10_IRQHandler(void) {
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
static uint32_t last_press_time = 0;
if(EXTI->PR & EXTI_PR_PR13) {
EXTI->PR = EXTI_PR_PR13;
uint32_t current_time = xTaskGetTickCountFromISR();
if((current_time - last_press_time) < pdMS_TO_TICKS(200)) {
return;
}
for(volatile int i = 0; i < 5000; i++);
if(!(GPIOC->IDR & GPIO_IDR_IDR13)) {
last_press_time = current_time;
press_counter++;
char message[50];
snprintf(message, sizeof(message), "Кнопка нажата! Счетчик: %lu", press_counter);
if(xQueueSendFromISR(xQueue, message, &xHigherPriorityTaskWoken) != pdPASS) {
}
if(xHigherPriorityTaskWoken) {
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
}
}
}
int main(void) {
init_uart();
LED_Init();
Button_Init();
printf("\r\n");
printf("================================================\r\n");
printf("Лабораторная работа №6 - Вариант 1\r\n");
printf("Задача1: Выводит 'Задача1: Печать сообщения #X' каждую секунду\r\n");
printf("Задача2: Ожидает сообщение от нажатия кнопки\r\n");
printf("Нажмите USER кнопку (синюю) для отправки сообщения в очередь\r\n");
printf("Задача2 приостановит Задачу1 и выведет полученный текст\r\n");
printf("Защита от дребезга: время антидребезга 200мс\r\n");
printf("================================================\r\n\r\n");
xQueue = xQueueCreate(3, 50);
if(xQueue == NULL) {
printf("ОШИБКА: Не удалось создать очередь!\r\n");
while(1);
}
printf("Очередь успешно создана (3 сообщения, по 50 символов)\r\n");
if(xTaskCreate(vTaskPrint, "PrintTask", 256, NULL, 1, &xTaskPrintHandle) != pdPASS) {
printf("ОШИБКА: Не удалось создать Задачу1!\r\n");
while(1);
}
if(xTaskCreate(vTaskQueue, "QueueTask", 256, NULL, 2, NULL) != pdPASS) {
printf("ОШИБКА: Не удалось создать Задачу2!\r\n");
while(1);
}
printf("Задачи успешно созданы\r\n");
printf("Приоритет Задачи1: 1, Приоритет Задачи2: 2\r\n");
printf("Запуск планировщика FreeRTOS...\r\n\r\n");
vTaskStartScheduler();
while(1) {
GPIOA->ODR ^= GPIO_ODR_ODR5;
for(volatile int i = 0; i < 500000; i++);
}
}
void vApplicationStackOverflowHook(TaskHandle_t xTask, char *pcTaskName) {
(void)xTask;
printf("\r\n!!! ПЕРЕПОЛНЕНИЕ СТЕКА в задаче: %s !!!\r\n", pcTaskName);
while(1) {
GPIOA->ODR ^= GPIO_ODR_ODR5;
for(volatile int i = 0; i < 200000; i++);
}
}
void vApplicationMallocFailedHook(void) {
printf("\r\n!!! ОШИБКА ВЫДЕЛЕНИЯ ПАМЯТИ !!!\r\n");
while(1) {
GPIOA->ODR ^= GPIO_ODR_ODR5;
for(volatile int i = 0; i < 400000; i++);
}
}
