Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Лабораторная 6

.docx
Скачиваний:
0
Добавлен:
17.12.2025
Размер:
455.9 Кб
Скачать

Министерство науки и высшего образования Российской Федерации

Федеральное государственное автономное образовательное учреждение высшего образования

ТОМСКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ СИСТЕМ УПРАВЛЕНИЯ И РАДИОЭЛЕКТРОННИКИ (ТУСУР)

Кафедра комплексной информационной безопасности электронно-вычислительных систем (КИБЭВС)

МЕЖПРОЦЕССНОЕ ВЗАИМОДЕЙСТВИЕ В 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++);

}

}