前言
恩智浦“FRDM-MCXN947”評(píng)測活動(dòng)由安富利和與非網(wǎng)協(xié)同舉辦。本篇內(nèi)容由與非網(wǎng)用戶發(fā)布,已獲轉(zhuǎn)載許可。原文可在與非網(wǎng)(eefocus)工程師社區(qū)查看。
背景
此次任務(wù)通過串口命令行控制RGB LED,相比較與上一次任務(wù)通過單個(gè)字符控制增加了FreeRTOS-CLI組件,支持更復(fù)雜的、帶參數(shù)的命令。
1. 搭建VSCode開發(fā)環(huán)境
2. 添加FreeRTOS組件,創(chuàng)建任務(wù)
3. 添加FreeRTOS-CLI組件,打通適配層
4. 添加FreeRTOS-CLI自定義命令,控制RGB LED
搭建VS Code開發(fā)環(huán)境
無論是使用MCUXpresso IDE還是VS Code開發(fā)環(huán)境,都必須要:
1. 安裝MCUXpresso IDE,因?yàn)镮DE里有NXP支持的GCC工具鏈
2. 下載mcux_sdk_frdm_mcxn947 SDK
3. VS Code安裝插件MCUXPresso for VS Code
4. VS Code配置插件MCUXpresso for VS Code
前幾個(gè)步驟都好說,這里簡短演示下VS Code配置插件MCUXpresso for VS Code。
01 配置MCUXpresso for VS Code

1. 在VS Code側(cè)邊欄單擊MCUXpresso圖標(biāo)展開右側(cè)視圖
2. 單擊(2)處展開右側(cè)視圖。這里建議單擊Import Example from Repository,因?yàn)樗壬厦娴?strong>Import Repository有更多的配置選型,可以直接從這里創(chuàng)建示例工程
3. 單擊(3)處選擇本地的SDK路徑,例如這里選擇已經(jīng)下載并解壓縮的mcux_sdk_frdm_mcxn947
4. 單擊(4)處選擇MCUXpresso IDE的GCC工具鏈
5. 單擊(5)處選擇開發(fā)板,一個(gè)SDK可以支持同類型的幾個(gè)開發(fā)板,根據(jù)需要選擇對(duì)應(yīng)的開發(fā)板
6. 單擊(6)處選擇示例工程模版,也可以輸入關(guān)鍵詞搜索
7. 編輯(7)處輸入框輸入新建的工程名字
8. 單擊(8)處選擇工程保存路徑
9. 最后點(diǎn)擊Create即可以創(chuàng)建工程
02 工程結(jié)構(gòu)
.vscode/包含一些配置選項(xiàng)、調(diào)試啟動(dòng)文件
repo/是一個(gè)鏈接文件,執(zhí)行SDK所在文件夾
app/包含應(yīng)用代碼
armgcc包含CMakeLists.txt目錄程序以及一些bat、shell編譯腳本,如果新增了源文件和頭文件,需要修改此處的CMakeLists.txt文件
board/包含管腳、時(shí)鐘、外設(shè)初始化代碼,是MCUXpresso Config Tools自動(dòng)生成的文件夾
iar/是IAR IDE工程文件和鏈接腳本
mdk/是MDK IDE工程文件和鏈接腳本
后綴名為*.mex是MCUXpresso Config Tools的輸入文件
readme.md是示例工程的說明文檔
03 編譯、下載、調(diào)試
采用CMake+GCC編譯此工程,圖簡便的話直接點(diǎn)擊MCUXpresso for VS Code中的圖標(biāo),如下圖所示。

04 添加FreeRTOS組件
嘗試過MCUXpresso IDE添加FreeRTOS組件,雖然把源碼拷貝過來添加到工程里,但是port層的源文件和頭文件缺失了,需要從例程拷貝復(fù)制,太麻煩了。
而VS Code中添加組件的方式特別簡單,如下添加FreeRTOS組件,簡直不要太爽了。
1. 鼠標(biāo)右鍵單擊工程名
2. 在彈出的菜單中選擇(2)配置工程
3. 然后選擇(3)管理組件
4. 在(4)處編輯框輸入kernel過濾組件
5. 在(5)處選擇合適的FreeRTOS類型
6. 在(6)處點(diǎn)擊確認(rèn)即可


添加FreeRTOS所做的更改體現(xiàn)在armgcc/config.cmake文件,如下圖所示文件中增加了幾處和freertos相關(guān)的配置選項(xiàng)。當(dāng)然FreeRTOS源碼不會(huì)拷貝過來,它依然存在于SDK路徑中,但是需要拷貝一份FreeRTOSConfig.h過來,自行修改其中的參數(shù)。

05 新建FreeRTOS任務(wù)
新建一個(gè)最簡單的FreeRTOS任務(wù),每隔兩秒鐘打印一次信息。
(滑動(dòng)查看)
int main(void)
{
// 管腳復(fù)用和配置
BOARD_InitBootClocks();
BOARD_InitBootPeripherals();
BOARD_InitBootPins();
BOARD_InitSWD_DEBUGPins();
// 調(diào)試串口打印日志
BOARD_InitDebugConsole();
PRINTF("
");
PRINTF("
Build: %s %s
", __DATE__, __TIME__);
if (xTaskCreate(zygote_task, "zygote_task", ZYGOTE_TASK_STACK_SIZE, NULL, ZYGOTE_TASK_PRIORITY, NULL) !=
pdPASS)
{
PRINTF("Task creation failed!.
");
while (1)
;
}
vTaskStartScheduler();
for (;;)
;
}
static void zygote_task(void *pvParameters)
{
uint32_t zygote_loop_cnt = 0;
for (;;) {
zygote_loop_cnt++;
PRINTF("zygote loop cnt: %u
", zygote_loop_cnt);
vTaskDelay(pdMS_TO_TICKS(2000));
}
}

FreeRTOS-CLI組件
01 組件介紹
FreeRTOS-CLI是FreeRTOS官方的組件,支持注冊(cè)多參數(shù)命令,命令接口可以是串口、網(wǎng)絡(luò)套接字等。
當(dāng)前使用的版本是FreeRTOS+CLI V1.0.4,適配層使用串口,注冊(cè)兩個(gè)多參數(shù)的命令,控制開發(fā)板上的RGB LED亮滅。
02 添加FreeRTOS-CLI組件
在源碼頂層目錄新建3rdparty目錄并拷貝FreeRTOS_Plus_CLI組件到此,目錄結(jié)構(gòu)如下:
FreeRTOS_Plus_CLI/
port/
serial.c
serial.h
src/
FreeRTOS_CLI.c
FreeRTOS_CLI.h
我們只需要關(guān)心port/目錄即可,適配UART層在這里。
03 適配層
重點(diǎn)在以下幾個(gè)函數(shù)的適配:
xSerialPortInitMinimal()
xSerialPortInit()
vSerialPutString()
xSerialGetChar()
xSerialPutChar()
因?yàn)楣苣_初始化已經(jīng)由MCUXpresso Config Tools圖形化配置完成,通過Debug UART進(jìn)行輸入輸出,所以前兩個(gè)串口初始化函數(shù)可以留空,重點(diǎn)在于xSerialGetChar()和xSerialPutChar()的實(shí)現(xiàn),這里簡單實(shí)現(xiàn)一下,通過Debug UART進(jìn)行輸入輸出即可。
(滑動(dòng)查看)
signed portBASE_TYPE xSerialGetChar(xComPortHandle pxPort,
signed char *pcRxedChar,
TickType_t xBlockTime)
{
#ifndef DEBUG_CONSOLE_TRANSFER_NON_BLOCKING
*pcRxedChar = GETCHAR();
return pdPASS;
#else
char data = 0;
while (xBlockTime-- > 0) {
if (kStatus_Success == DbgConsole_TryGetchar(&data)) {
*pcRxedChar = data;
return pdPASS;
} else {
vTaskDelay(pdMS_TO_TICKS(1));
}
}
return pdFAIL;
#endif
}
signed portBASE_TYPE xSerialPutChar(xComPortHandle pxPort, signed char cOutChar,
TickType_t xBlockTime)
{
signed portBASE_TYPE ch = 0;
ch = PUTCHAR(cOutChar);
return ch;
}
04 RGB LED控制命令
為了點(diǎn)亮、熄滅RGB LED,需要實(shí)現(xiàn)如下這樣的命令:
ledset r on點(diǎn)亮紅色LED,同理ledset g/b on點(diǎn)亮綠色、藍(lán)色LED
ledset r off熄滅紅色LED,同理ledset g/b off熄滅綠色、藍(lán)色LED
ledget r獲取紅色LED狀態(tài),如LEDR:OFF表示熄滅,LEDR:ON表示點(diǎn)亮
05 點(diǎn)亮、熄滅 LED命令的實(shí)現(xiàn)
(滑動(dòng)查看)
// TODO: ledset r/g/b on/off
// 作用:設(shè)置燈的狀態(tài)
// 命令: ledset
// 參數(shù)1:編號(hào),這里以 r/g/b 縮寫分別表示 "RED/GREE/BLUE" 三個(gè)燈
// 參數(shù)2:開關(guān),這里以字符串 on/off 分別表示 "開燈/關(guān)燈"
/**
* @brief
*
* @param pcWriteBuffer
* @param xWriteBufferLen
* @param pcCommandString
* @return BaseType_t
*/
static BaseType_t prvLedSetCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString )
{
configASSERT(pcWriteBuffer);
/* param1: r/g/b */
const char *paramLedId = NULL;
BaseType_t paramLedIdLength = 0;
led_id_e mLedId = LED_ID_INVALID;
/* param2: on/off */
const char *paramLedStatus = NULL;
BaseType_t paramLedStatusLength = 0;
led_status_e mLedStatus;
// 首先清除輸出緩沖區(qū)舊的內(nèi)容
memset(pcWriteBuffer, 0, xWriteBufferLen);
// TODO: 根據(jù)兩個(gè)參數(shù)打印返回的字符串
paramLedId = FreeRTOS_CLIGetParameter(pcCommandString, 1, ¶mLedIdLength);
paramLedStatus = FreeRTOS_CLIGetParameter(pcCommandString, 2, ¶mLedStatusLength);
if (strncmp("r", paramLedId, 1) == 0) {
mLedId = LED_ID_RED;
} else if (strncmp("g", paramLedId, 1) == 0) {
mLedId = LED_ID_GREEN;
} else if (strncmp("b", paramLedId, 1) == 0) {
mLedId = LED_ID_BLUE;
} else {
mLedId = LED_ID_INVALID;
}
if (strncmp("on", paramLedStatus, 2) == 0) {
mLedStatus = LED_ON;
} else if (strncmp("off", paramLedStatus, 3) == 0) {
mLedStatus = LED_OFF;
}
led_set_status(mLedId, mLedStatus);
/* There is no more data to return after this single string, so return pdFALSE. */
return pdFALSE;
}
06 獲取LED狀態(tài)命令的實(shí)現(xiàn)
(滑動(dòng)查看)
// TODO: ledget r/g/b
// 作用:獲取燈的狀態(tài)
// 命令: ledget
// 參數(shù)1:編號(hào)
/**
* @brief
*
* @param pcWriteBuffer
* @param xWriteBufferLen
* @param pcCommandString
* @return BaseType_t
*/
static BaseType_t prvLedGetCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString )
{
configASSERT(pcWriteBuffer);
/* param1: r/g/b */
const char *paramLedId = NULL;
BaseType_t paramLedIdLength = 0;
led_id_e mLedId = LED_ID_INVALID;
led_status_e mLedStatus;
// 首先清除輸出緩沖區(qū)舊的內(nèi)容
memset(pcWriteBuffer, 0, xWriteBufferLen);
paramLedId = FreeRTOS_CLIGetParameter(pcCommandString, 1, ¶mLedIdLength);
if (strncmp("r", paramLedId, 1) == 0) {
mLedId = LED_ID_RED;
} else if (strncmp("g", paramLedId, 1) == 0) {
mLedId = LED_ID_GREEN;
} else if (strncmp("b", paramLedId, 1) == 0) {
mLedId = LED_ID_BLUE;
} else {
mLedId = LED_ID_INVALID;
}
/* 獲取燈的狀態(tài) */
mLedStatus = led_get_status(mLedId);
/* 輸出燈的狀態(tài),輸出到 pcWriteBuffer 緩沖區(qū)中 */
sprintf(pcWriteBuffer, "%s: %s
", led_helper_id_to_string(mLedId), led_helper_status_to_string(mLedStatus));
/* There is no more data to return after this single string, so return pdFALSE. */
return pdFALSE;
}
07 注冊(cè)命令
先定義結(jié)構(gòu)體,把命令字符串和解析函數(shù)關(guān)聯(lián)在一起。
(滑動(dòng)查看)
/* Structure that defines the "ledset" command line command. This generates
a table that gives information on each task in the system. */
static const CLI_Command_Definition_t xLedSet =
{
"ledset", /* The command string to type. */
"
ledset :
set r/g/b led status
example: ledset r on or ledset g off
",
prvLedSetCommand, /* The function to run. */
2 /* 2 parameters are expected. */
};
/* Structure that defines the "ledget" command line command. This generates
a table that gives information on each task in the system. */
static const CLI_Command_Definition_t xLedGet =
{
"ledget", /* The command string to type. */
"
ledget :
get r/g/b led status
example: ledget r or ledget g
",
prvLedGetCommand, /* The function to run. */
1 /* 1 parameters are expected. */
};
再在合適的時(shí)機(jī)注冊(cè)命令,如下所示:
(滑動(dòng)查看)
void vRegisterBspCliCommands(void) { /* Register all the command line commands defined immediately above. */ FreeRTOS_CLIRegisterCommand( &xLedSet ); FreeRTOS_CLIRegisterCommand( &xLedGet ); }
static void zygote_task(void *pvParameters)
{
uint32_t zygote_loop_cnt = 0;
/* FreeRTOS-CLI 任務(wù)創(chuàng)建 */
vUARTCommandConsoleStart();
extern void vRegisterSampleCLICommands(void);
vRegisterSampleCLICommands();
vRegisterBspCliCommands();
for (;;) {
zygote_loop_cnt++;
PRINTF("zygote loop cnt: %u
", zygote_loop_cnt);
vTaskDelay(pdMS_TO_TICKS(2000));
}
}
08 驗(yàn)證
發(fā)送命令ledset r on電量紅色LED
發(fā)送命令ledset r off熄滅紅色LED
發(fā)送命令ledget r獲取紅色LED點(diǎn)亮狀態(tài)
替換r/g/b可以正確執(zhí)行命令


-
恩智浦
+關(guān)注
關(guān)注
14文章
6121瀏覽量
152999 -
RGB
+關(guān)注
關(guān)注
4文章
835瀏覽量
62200 -
命令
+關(guān)注
關(guān)注
5文章
758瀏覽量
23911 -
開發(fā)環(huán)境
+關(guān)注
關(guān)注
1文章
275瀏覽量
17670
原文標(biāo)題:用戶測評(píng)(四):使用NXP MCX-N板卡新增命令控制
文章出處:【微信號(hào):AvnetAsia,微信公眾號(hào):安富利】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
恩智浦 MCX N系列之電源管理(MCX N94/54與MCX N23)
貼片代碼MARKING絲印手冊(cè),新增NXP的
恩智浦全新MCX N微控制器推出!助力實(shí)現(xiàn)高性能、低功耗的邊緣安全智能
貿(mào)澤電子開售適用于智能電機(jī)控制和機(jī)器學(xué)習(xí)應(yīng)用的 NXP Semiconductors MCX微控制器
基于MCX N和MCX A系列微控制器,NXP宣布推出無線多協(xié)議MCX W系列
富昌電子推薦兩款恩智浦的MCX A和MCX N系列微控制器
MCX N系列微控制器適用于安全、智能的電機(jī)控制和機(jī)器學(xué)習(xí)應(yīng)用
NXP MCX N23和MCX N94/54的不同之處
用戶測評(píng)之體驗(yàn)NXP MCX-N板卡的NPU功能
使用NXP MCX-N板卡搭建環(huán)境及點(diǎn)燈
貿(mào)澤開售NXP MCX E系列MCU:專為高要求邊緣應(yīng)用打造的安全可靠新選擇
使用NXP MCX-N板卡新增命令控制
評(píng)論