본문 바로가기

Firmware/stm32

STM32 FREERTOS Mail Queue 구현

MailQueue 기본 Function 구현 (CMSIS-RTOS-V1)

 

MailQueue는 Task끼리 데이터를 주고받기 위해 사용하는 자료구조이다.

 

 

동작:

STM32F407Discvery로 구현 하였다.

Task의 우선순위는 똑같이 Normal

 

1. sendMailTask는 val1, val2, val3에 0x01, 0x02, 0x03을 쓴다.

2. Mailput을 호출하여 전송 후 osDelay를 호출하여 Context Switching을 한다.

3. recvMailTask은 Block 상태에서 해제되어 val1, val2, val3 이 0x01,0x02,0x03이 맞는지 확인한다.

4. 맞으면 RED LED를 Blink 하고 틀리면 Blue LED를 Set 한다.

(DEBUG 모드에서 PRINTF(SWV) 사용 시 TASK Switching이 깨져 BLUE LED를 띄운다.)

(RELEASE에서 정상동작 확인)

 

 

MailQueue API

 

osMailQId 

= osMailQId를 가지고 Mail을 Get 했을 때 일치하는 ID를 가지고 있는 Task 만이 Wakeup을 할 수 있다.

(osMailGet을 호출하고 있다고 무조건 Wakeup을 하지 않는다. 일치할 경우만 Wakeup)

 

ex) osMailQId ToErrorTask;

 

osMailQDef(이름, 크기, 타입)

= 메일 이름과 크기 그리고 데이터 타입을 정해준다.

 

ex) osMailQDef(mail, 1 ,vMail_TypeDef); //메일의 이름은 메일, 크기는 1, 데이터 타입은 메일 구조체

 

osThreadCreate(Define 된 메일 이름, 스레드ID or NULL)

= 메일을 만든다

 

ex) mailId = osMailCreate(osMailQ(mail), NULL);

 

osMailAlloc(메일 아이디, TimeOUT)

= 메모리를 할당한다 위 그림의 alloc에 해당한다.

 

ex) pTMail = osMailAlloc(mailId, osWaitForever);

 

osMailFree(메일 아이디, 메일 데이터타입  포인터)

= 할당된 메모리를 Free한다 위 그림의 Free에 해당한다.

 

ex) osMailFree(mailId, recvTMail);

 

osMailGet(메일 아이디, 타임아웃)

= 메일를 받는다.(이 함수에 진입되면 Blocked 상태에 있다가 ID와 일치하는 Mail이 들어오면 Wakeup 한다.)

   Return 값이 에러인지 메시지인디 타입아웃인지 등 확인할 수 있다.

 

ososMailPut(메일아이디, 메일 데이터타입 포인터)

= 메일를 보낸다.

 

메일에 사용하는 데이터 타입 및 ID

typedef struct
{
	int val1;
	int val2;
	int val3;
	int *ptr;

}vMail_TypeDef;

osMailQId mailId;

 

메일을 보내는 Task

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
void sendMailTask(void const * argument)
{
  /* init code for USB_HOST */
  MX_USB_HOST_Init();
  printf("HELLOW WORLD\n");
  /* USER CODE BEGIN startOranageTask */
  vMail_TypeDef *pTMail;
 
 
 
  /* Infinite loop */
  for(;;)
  {
      pTMail = osMailAlloc(mailId, osWaitForever);
      /* ORange LED */
      pTMail->val1 = 0x1;
      pTMail->val2 = 0x2;
      pTMail->val3 = 0x3;
      pTMail->ptr = &(pTMail->val1);
 
      osMailPut(mailId, pTMail);
 
      HAL_GPIO_WritePin(GPIOD, LD3_Pin, GPIO_PIN_SET);
      HAL_Delay(100);
      HAL_GPIO_WritePin(GPIOD, LD3_Pin, GPIO_PIN_RESET);
      osDelay(100);
 
  }
  /* USER CODE END startOranageTask */
}
cs

 

메일을 수신하는 Task

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
void recvMailTask(void const * argument)
{
  /* USER CODE BEGIN startRedTask */
    osEvent event;
    osStatus retStatus;
    vMail_TypeDef *recvTMail;
    /* Infinite loop */
  for(;;)
  {
      /* RED LED */
      event = osMailGet(mailId, osWaitForever);
 
      if(event.status ==osEventMail)
      {
        recvTMail = event.value.p;
//        printf("mail value1: 0x%x \r", recvTMail->val1);
//        printf("mail value2: 0x%x \r", recvTMail->val2);
//        printf("mail value3: 0x%x \r", recvTMail->val3);
//        printf("mail ptr4: 0x%x \r", (int)recvTMail->ptr);
 
        if(recvTMail->val1 == 0x01 && recvTMail->val2 == 0x02 && recvTMail->val3 ==0x03)
        {
            retStatus = osMailFree(mailId, recvTMail);
            if(retStatus == osOK)
            {
                HAL_GPIO_WritePin(GPIOD, LD5_Pin, GPIO_PIN_SET);
                HAL_Delay(100);
                HAL_GPIO_WritePin(GPIOD, LD5_Pin, GPIO_PIN_RESET);
                HAL_Delay(100);
            }
            else
            {
                HAL_GPIO_WritePin(GPIOD, LD6_Pin, GPIO_PIN_SET);
            }
        }
        else
        {
            HAL_GPIO_WritePin(GPIOD, LD6_Pin, GPIO_PIN_SET);
 
        }
      }
 
  }
  /* USER CODE END startRedTask */
}
cs