FreeRTOS
RTOS(real time Operating System)는 프로세스와 주변 자원을 공유하거나 동작 여부를 보장해주는 방법들의 집단입니다. 여기에는 thread를 기본으로 task를 구성하는 방법과, 자원을 공유하는 뮤텍스 세마포어등이 기본으로 들어갑니다.
향후에 이에 관한 세부 내용을 정리하겠습니다.
이글에서는 RTOS 중에서 마이크로프로세서에 많이 사용되는 FreeRTOS를 이용해서 Arduin 에서 시리얼 통신을 구현하는 방법을 알아보겠습니다.
Arduino의 FreeRTOS
Arduino에서 FreeRTOS를 이용해서 시리얼 수신하는 방법을 알아보겠습니다. 우선 다른 글에서 다루었던 Queue 생성 내용을 먼저 참조해야 합니다.
먼저 아두이노에서 라이브러리 매니저에서 FreeRTOS를 선택해서 설치합니다.
그리고 다음과 같이 필요한 헤더를 포함합니다.
#include <Arduino.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <Arduino_FreeRTOS.h>
#include <semphr.h>
//- queue
#include "myQueue.h"
#define STACK_SIZE (configMINIMAL_STACK_SIZE+256)
//- 수신 제어를 위한 세마포어
SemaphoreHandle_t rx0_sem;
//- 수신 문장을 전송
void Task_Rx0(void *par);
수신용 queue를 버퍼를 만듭니다.
//- uart1d의 수신용 queue 객체 , 312 이상의 버퍼를 사용하면 문제가 발생함
myQueue rx0_msg_buff = myQueue(312);
시리얼 통신에서 송신을 위해서 _printf를 사용하면 편리합니다. 이에 관한 내용은 아래 내용을 참조해서 코드를 추가해 주면 좋습니다.
https://studymake.tistory.com/696
다음과 같이 setup()과 loop()을 설정합니다.
void setup() {
//-- uart
//- serial 통신 속도
Serial.begin(9600);
_printf(uart0,"\r\nDasp88Neo Start..\r\n");
//- semaphore 생성
rx0_sem = xSemaphoreCreateCounting(8,0);
//- thread 생성
xTaskCreate(Task_Rx0,"Rx0_Handler",STACK_SIZE, NULL,2,NULL);
//- thread 실행
vTaskStartScheduler();
//- 아래 문장이 실행되면 thread가 실행되지 않음을 의미
for(;;){
}
}
/*
rtos를 사용하면, loop에 아무런 내용도 없어야한다.
*/
void loop() {
}
시리얼 수신 이벤트
시리얼 통신 수신 이벤트에 Queue를 이용해서 수신 데이터를 기록하고, 원하는 문자(RX_LF)를 정의한 다음에 이 문자가 수신되면 세마포어를 이용해서 이를 해독하는 함수가 진행되로 독 유도합니다.
/******************************************************************************
* uart0 receive interrupt
* 수신용 queue와 세마포아를 사용함
*/
void serialEvent(){
char c;
//- 높은 순위의 task 여부 확인용
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
//- 수신 문자가 있을 때 까지 무한 대기
while(Serial.available()){
//- 수신 기록용 버퍼의 용량을 제한
if(rx0_msg_buff.count()<rx0_msg_buff.size()){
//- 한개의 문자를 수신
c = Serial.read();
//- 문자를 queue에 기록
rx0_msg_buff.push(c);
//- 수신 문자가 메세지 완료이면 해석을 시작, Tx0_Rx를 시행하도록 유도
if(c == RX_LF){
xSemaphoreGiveFromISR(rx0_sem,&xHigherPriorityTaskWoken);
}
//- 높은 우선 순위의 task에 대응
if(xHigherPriorityTaskWoken==pdTRUE){
taskYIELD();
}
}
}
}
스레드가 세마포어 상태를 수신해서, 기록된 queue의 버퍼 내용을 수신하고 해석하는 함수 Rx_Receive()를 동작합니다. Rx_Receive()는 사용자가 설정해야 합니다.
/******************************************************************************
* thread로 동작한다.
* uart0로 수신된 내용을 처리한다.
* uart_info 객체에 수신 명령어를 기록
*
* par: 의미 없음, thread를위한 함수 형태임
*/
void Task_Rx0(void *par){
//- 세마포의 실행 대기 시간, 충분히 긴 사간을 사용해도 된다.
const TickType_t block_time = pdMS_TO_TICKS(200);
//- task를 무한히 실행
for(;;){
//- 세마포어의 수신 대기
if(xSemaphoreTake(rx0_sem,block_time)==pdTRUE){
//- queue에 있는 수신 문장을 Rx_Receive()에 한 문자씩 전송
while(rx0_msg_buff.count()>0){
Rx_Receive((char)rx0_msg_buff.pop());
}
}
}
}
광고좀 꾹 눌러주시면 고맙겠습니다.
위의 내용을 참조용으로만 사용해주세요. 무단 도용이나 무단 복제는 불허합니다.
기타 문의 사항은 gigasound@naver.com에 남겨 주시면 고맙겠습니다.
'Embedded' 카테고리의 다른 글
Arduino, FreeRTOS, semaphore, mutex 개요 (0) | 2021.10.23 |
---|---|
Arduino, FreeRTOS, LED Toggle (0) | 2021.10.23 |
라즈베리파이에서 UART 사용 (0) | 2021.10.10 |
시리얼 통신을 위한 Queue의 생성 (0) | 2021.08.17 |
RaspberryPi-온도에 따라 제어되는 FAN 구성 (0) | 2021.08.14 |