PSoC 6 듀얼 코어로 Hello World (2)
13016 단어 PSoC6Cortex-M0Cortex-M4메시지HelloWorld
마지막 회의
마지막 기사 에서는, 메세지 기능을 사용해 Cortex-M4로부터 Cortex-M0+에 캐릭터 라인을 보내, UART로부터 출력을 얻고 있었습니다.
이번에는 Cortex-M4 측에 복수의 태스크를 갖게 해, 태스크간에 UART의 사용권을 서로 빼앗는, 멀티 태스크와 같은 구조를 도입해 보았습니다.
멀티태스킹이란?
하나의 CPU에 복수의 일을 시키는 것은, 하나의 CPU를 실행할 수 있는 것은 하나의 프로그램 뿐이므로, 보통은 불가능한 과제입니다. 그러나 여러 작업을 세분화하여 하나의 CPU로 문지르면서 실행할 수 있으면 밖에서 CPU의 동작을 보았을 때 여러 작업이 동시에 실행되고 있는 것처럼 보입니다. 이것이 단일 CPU를 통한 멀티 태스킹 아이디어입니다.
이 프로젝트에서 목표로하는 목표
이 프로젝트에서는 Cortex-M4 측에 멀티 태스킹과 같은 메커니즘을 도입하여 각 태스크에서 Cortex-M0 + 측에 메시지를 보내 UART의 출력을 요청합니다.
Cortex-M0+ 측 프로그램
Cortex-M0+ 측의 프로그램은 마지막 기사 의 것이 그대로 사용할 수 있습니다. 변경 부분은 0입니다. 송신측의 태스크의 수가 아무리 증가해도, 수신측은 도착한 데이터를 딱딱함과 UART로부터 흘릴 뿐입니다.
Cortex-M4 측 프로그램
Cortex-M4 측의 프로그램에서는 먼저 문자열을 전송하는 작업을 상태 머신으로 분해하여 초기화 루틴과 디스패치 루틴으로 분리했습니다.
main_cm4.c
#include <stdio.h>
#include "project.h"
#define IPC_CHANNEL_UARTTX (8) /* メッセージ送受信用の IPC チャネル番号 */
/* IPC チャネルのハンドル */
IPC_STRUCT_Type *ipcHandle;
/* Task1の定義 */
enum Task1State {
ST_CREATE,
ST_SEND
};
struct Task1Context {
enum Task1State state; /* ステートマシンの状態 */
uint32_t count; /* メッセージ番号 */
uint32_t side; /* 使用中バッファ面 */
const char_t *name; /* タスクの名前 */
char_t buffer[2][128]; /* ダブルバッファ */
};
void task1_init(struct Task1Context *context, const char_t *name) {
/* タスクの初期化 */
context->name = name;
context->count = 0;
context->side = 0;
context->state = ST_CREATE;
}
void task1_dispatch(struct Task1Context *context) {
switch (context->state) {
case ST_CREATE:
/* 送信するメッセージを作成する */
(void)sprintf(
context->buffer[context->side],
"%s: HELLO WORLD %lu\r\n",
context->name, context->count++
);
context->state = ST_SEND;
break;
case ST_SEND:
/* メッセージを送る */
if (
Cy_IPC_Drv_SendMsgPtr(
ipcHandle,
CY_IPC_NO_NOTIFICATION,
context->buffer[context->side]
) == CY_IPC_DRV_SUCCESS
) {
/* バッファを切り替える */
context->side = (context->side)?(0):(1);
context->state = ST_CREATE;
}
break;
default:
CY_ASSERT(false);
}
}
Task1은 자신의 이름과 일련 번호가 포함된 문자열을 Cortex-M0+ 쪽으로 보냅니다. 상태 머신에는 두 가지 상태가 있습니다. ST_CREATE 상태에서는 다음에 전송할 문자열을 준비하고 ST_SEND 상태로 전환합니다. ST_SEND 상태에서는 Cortex-M0+에 메시지를 보내지만 성공한 경우에만 ST_CREATE 상태로 돌아갑니다. 이렇게 하면 작성한 문자열이 전송될 때까지 ST_SEND 상태에 머무르므로 모든 문자열을 빠짐없이 전달할 수 있습니다.
Task1에서 사용되는 태스크에 고유한 저장 영역은
struct Task1Context
라는 구조체에 있습니다. 이 구조체에 대한 포인터를 task1_init()
함수 또는 task1_dispatch()
함수의 첫 번째 인수로 전달하여 독립적인 작업을 처리할 수 있습니다.main_cm4.c
int main(void) {
struct Task1Context context1_0;
struct Task1Context context1_1;
struct Task1Context context1_2;
__enable_irq(); /* 全体の割り込みを許可する */
/* メッセージ交換のためのハンドルを獲得する */
ipcHandle = Cy_IPC_Drv_GetIpcBaseAddress(IPC_CHANNEL_UARTTX);
/* タスクの初期化 */
task1_init(&context1_0, "M4-1-0");
task1_init(&context1_1, "M4-1-1");
task1_init(&context1_2, "M4-1-2");
for (;;) {
/* Task1 のディスパッチャ */
task1_dispatch(&context1_0);
task1_dispatch(&context1_1);
task1_dispatch(&context1_2);
}
}
Task1을 벗어난
main()
함수에는 초기화와 디스패처 호출 만 남았습니다. 여기에서는 세 가지 작업을 정의하고 무한 루프 내에서 단순히 순서대로 디스패처를 호출합니다.실행해보면
실행을 시작하면 세 가지 작업이 처리되는 방식을 알 수 있습니다.
실행 순서와 실행 빈도는 작업에 따라 다릅니다. 이것은, 태스크의 스케줄은 커녕 메시지의 큐등도 받아들이고 있지 않기 때문입니다. 이 때문에 잠시 움직이면
이와 같이 타이밍에 따라서는, 하나의 태스크만이 연장되어 실행되어 가는 모습도 관측되었습니다. 가장 큰 원인은 Cortex-M4가 부담없이 요청을 연발하고 있다는 것입니다. 요구측의 타이밍을 만들어야 합니다.
관련 문헌
AN215656 – PSoC 6 MCU Dual-Core CPU System Design
AN217666 - PSoC 6 MCU 인터럽트
CE216795 - PSoC(R) 6 MCU Dual-Core Basics
PSoC 6 MCU: PSoC 63 with BLE Architecture Technical Reference Manual
관련 기사
PSoC 6 듀얼 코어 L 치카 (1)
PSoC 6 듀얼 코어 L 치카 (2)
PSoC 6 듀얼 코어 L 치카 (3)
PSoC 6 듀얼 코어 L 치카 (4)
PSoC 6 듀얼 코어 L 치카 (5)
PSoC 6 듀얼 코어 L 치카 (6)
PSoC 6 듀얼 코어 L 치카 (7)
PSoC 6 듀얼 코어로 Hello World (1)
Reference
이 문제에 관하여(PSoC 6 듀얼 코어로 Hello World (2)), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/noritan_org/items/c3878bc05a53247b641d텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)