You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
232 lines
7.2 KiB
232 lines
7.2 KiB
/*
|
|
* Copyright (c) 2019-2022, Erich Styger
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
|
|
#include "platform.h"
|
|
#include "Shell.h"
|
|
#include "McuShell.h"
|
|
#include "McuRTT.h"
|
|
#include "McuArmTools.h"
|
|
#include "McuShellUart.h"
|
|
#include "McuLog.h"
|
|
#include "McuUtility.h"
|
|
#include "MotOffsetTable.h"
|
|
|
|
|
|
#define SHELL_CMD_ELEM_SIZE (sizeof(Shell_cmd_s))
|
|
|
|
static QueueHandle_t shellCmdQueue;
|
|
|
|
static void vQueueShellCmd(Shell_cmd_s shellCmd){
|
|
if(xQueueSendToBack(shellCmdQueue, &shellCmd, pdMS_TO_TICKS(100)) != pdPASS){
|
|
McuLog_warn("Failed adding shell cmd to queue, maybe full?");
|
|
}
|
|
}
|
|
|
|
static uint8_t ParseCommand(const uint8_t *cmd, bool *handled, McuShell_ConstStdIOType *io){
|
|
if (McuUtility_strcmp((char*)cmd, McuShell_CMD_HELP)==0) {
|
|
McuShell_SendStr((unsigned char*)"\r\n", io->stdOut);
|
|
McuShell_SendStr((unsigned char*)McuShell_DASH_LINE, io->stdOut);
|
|
McuShell_SendStr((unsigned char*)"\r\n", io->stdOut);
|
|
McuShell_SendHelpStr((unsigned char*)"SplitFlap Help", (const unsigned char*)"Group of SplitFlap commands\r\n", io->stdOut);
|
|
McuShell_SendHelpStr((unsigned char*)" help", (const unsigned char*)"Print help this message\r\n", io->stdOut);
|
|
McuShell_SendHelpStr((unsigned char*)SHELL_CMD_IDENTIFY_SF, (const unsigned char*)"<SetupIdentifier> <HardwareIdentifier> (uint8_t) (uint8_t)\r\n", io->stdOut);
|
|
McuShell_SendHelpStr((unsigned char*)SHELL_CMD_POWEROFF_RPI, (const unsigned char*)"power of the raspberry pi\r\n", io->stdOut);
|
|
McuShell_SendHelpStr((unsigned char*)SHELL_CMD_INIT_ALL_SF, (const unsigned char*)"init all Splitflaps\r\n", io->stdOut);
|
|
*handled = TRUE;
|
|
return ERR_OK;
|
|
} else if(McuUtility_strncmp((char*)cmd, SHELL_CMD_IDENTIFY_SF, sizeof(SHELL_CMD_IDENTIFY_SF)-1) == 0){
|
|
int32_t hwId = 0;
|
|
int32_t setupId = 0;
|
|
*handled = TRUE;
|
|
cmd += sizeof(SHELL_CMD_IDENTIFY_SF)-1;
|
|
if(McuUtility_xatoi(&cmd, &setupId) == ERR_OK){
|
|
// validate param
|
|
if(setupId > NUM_FLAPS){
|
|
return ERR_FAILED;
|
|
}
|
|
}else{
|
|
return ERR_FAILED;
|
|
}
|
|
// second param
|
|
cmd++;
|
|
if(McuUtility_xatoi(&cmd, &hwId) == ERR_OK){
|
|
// validate param
|
|
int32_t offset = 0;
|
|
if(MotOffset_Get(hwId, &offset) != ERR_OK){
|
|
return ERR_FAILED;
|
|
}
|
|
}else{
|
|
return ERR_FAILED;
|
|
}
|
|
Shell_cmd_s shellCmd = {.shellCmd = Shell_Identify_SF, .numberOfParams = 2, .params = {hwId,setupId}};
|
|
//Shell_cmd_s shellCmd = {.shellCmd = Shell_Identify_SF, .value1 = setupId, .value2 = hwId};
|
|
vQueueShellCmd(shellCmd);
|
|
} else if(McuUtility_strcmp((char*)cmd,SHELL_CMD_POWEROFF_RPI) == 0){
|
|
// shutown rpi
|
|
*handled = TRUE;
|
|
Shell_cmd_s shellCmd = {.shellCmd = Shell_Powerof_rpi, .numberOfParams = 0};
|
|
vQueueShellCmd(shellCmd);
|
|
}else if(McuUtility_strcmp((char*)cmd, SHELL_CMD_INIT_ALL_SF) == 0){
|
|
*handled = TRUE;
|
|
Shell_cmd_s shellCmd = {.shellCmd = Shell_Init_All_SF, .numberOfParams = 0};
|
|
vQueueShellCmd(shellCmd);
|
|
}else if(McuUtility_strncmp((char*)cmd,SHELL_CMD_DISPLAY_STRING,sizeof(SHELL_CMD_DISPLAY_STRING)-1) == 0){
|
|
*handled = TRUE;
|
|
Shell_cmd_s shellCmd = {.shellCmd = Shell_Display_String_SF, .numberOfParams = NUM_FLAPS, .params = {0}};
|
|
cmd += sizeof(SHELL_CMD_DISPLAY_STRING)-1;
|
|
if(SHELL_stringToInt32ArrayForSFCMD(&cmd, shellCmd.params, NUM_FLAPS) != ERR_OK){
|
|
return ERR_FAILED;
|
|
}
|
|
vQueueShellCmd(shellCmd);
|
|
}
|
|
return ERR_OK;
|
|
|
|
}
|
|
|
|
uint8_t SHELL_stringToInt32ArrayForSFCMD(const unsigned char **str, int32_t* res, int8_t sizeRes){
|
|
uint8_t c = 0;
|
|
while(**str == ' '){
|
|
(*str)++; // skip leading spaces
|
|
}
|
|
c = **str;
|
|
while(c != '\0' && sizeRes>0){
|
|
sizeRes--;
|
|
if(c <= '9' && c >= '0'){
|
|
// its a number
|
|
*res = (int32_t)c;
|
|
res++;
|
|
}else if((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')){
|
|
// its a char
|
|
if(c >= 'a' && c <= 'z'){
|
|
*res = (int32_t)c-0x20;
|
|
}else{
|
|
*res = (int32_t)c;
|
|
}
|
|
res++;
|
|
} else if(c == '!' || c == '?' || c == ':' || c == ' '){
|
|
// special character allowed by SF
|
|
*res = (int32_t)c;
|
|
res++;
|
|
} else{
|
|
return ERR_RANGE;
|
|
}
|
|
c = *(++(*str));
|
|
}
|
|
return ERR_OK;
|
|
}
|
|
|
|
uint8_t SHELL_Int32ArrayToStringForSF(int32_t* intArray, int8_t size, char *str){
|
|
for(uint8_t i = 0; i < size; i++){
|
|
if(intArray[i] > 127 || intArray[i] < 0){
|
|
return ERR_RANGE;
|
|
}
|
|
*str = (char)intArray[i];
|
|
if(!((*str <= '9' && *str >= '0') || (*str >= 'A' && *str <= 'Z') ||
|
|
*str == '!' || *str == '?' || *str == ':' || *str == ' ')){
|
|
return ERR_RANGE;
|
|
}
|
|
str++;
|
|
}
|
|
return ERR_OK;
|
|
}
|
|
|
|
static const McuShell_ParseCommandCallback CmdParserTable[] =
|
|
{
|
|
ParseCommand,
|
|
McuShell_ParseCommand,
|
|
McuRTOS_ParseCommand,
|
|
NULL /* Sentinel */
|
|
};
|
|
|
|
typedef struct {
|
|
McuShell_ConstStdIOType *stdio;
|
|
unsigned char *buf;
|
|
size_t bufSize;
|
|
} SHELL_IODesc;
|
|
|
|
static const SHELL_IODesc ios[] =
|
|
{
|
|
{&McuShellUart_stdio, McuShellUart_DefaultShellBuffer, sizeof(McuShellUart_DefaultShellBuffer)},
|
|
{&McuRTT_stdio, McuRTT_DefaultShellBuffer, sizeof(McuRTT_DefaultShellBuffer)},
|
|
// {&USB_CdcStdio, USB_CdcDefaultShellBuffer, sizeof(USB_CdcDefaultShellBuffer)},
|
|
};
|
|
|
|
QueueHandle_t SHELL_GetShellCmdQueueHandle() {
|
|
return shellCmdQueue;
|
|
}
|
|
|
|
void SHELL_SendChar(unsigned char ch) {
|
|
for(int i=0;i<sizeof(ios)/sizeof(ios[0]);i++) {
|
|
McuShell_SendCh(ch, ios[i].stdio->stdOut);
|
|
}
|
|
}
|
|
|
|
uint8_t SHELL_ParseCommandIO(const unsigned char *command, McuShell_ConstStdIOType *io, bool silent) {
|
|
if (io==NULL) { /* use a default */
|
|
io = McuShell_GetStdio();
|
|
}
|
|
return McuShell_ParseWithCommandTableExt(command, io, CmdParserTable, silent);
|
|
}
|
|
|
|
void SHELL_SendString(const unsigned char *str) {
|
|
for(int i=0;i<sizeof(ios)/sizeof(ios[0]);i++) {
|
|
McuShell_SendStr(str, ios[i].stdio->stdOut);
|
|
}
|
|
}
|
|
|
|
static void ShellTask(void *pv) {
|
|
int i;
|
|
|
|
McuLog_info("Shell task started");
|
|
for(i=0;i<sizeof(ios)/sizeof(ios[0]);i++) {
|
|
ios[i].buf[0] = '\0';
|
|
}
|
|
for(;;) {
|
|
/* process all I/Os */
|
|
for(i=0;i<sizeof(ios)/sizeof(ios[0]);i++) {
|
|
(void)McuShell_ReadAndParseWithCommandTable(ios[i].buf, ios[i].bufSize, ios[i].stdio, CmdParserTable);
|
|
}
|
|
vTaskDelay(pdMS_TO_TICKS(20));
|
|
}
|
|
}
|
|
|
|
void SHELL_Init(void) {
|
|
if (xTaskCreate(
|
|
ShellTask, /* pointer to the task */
|
|
"Shell", /* task name for kernel awareness debugging */
|
|
800/sizeof(StackType_t), /* task stack size */
|
|
(void*)NULL, /* optional task startup argument */
|
|
tskIDLE_PRIORITY+2, /* initial priority */
|
|
(TaskHandle_t*)NULL /* optional task handle to create */
|
|
) != pdPASS)
|
|
{
|
|
McuLog_fatal("failed creating Shell task");
|
|
for(;;){} /* error! probably out of memory */
|
|
}
|
|
// McuShell_SetStdio(McuRTT_GetStdio()); /* use RTT as the default */
|
|
if(McuShell_SetStdio(&McuShellUart_stdio) != ERR_OK){
|
|
// couldnt set uart as stdio, try set RTT
|
|
McuLog_warn("Failed to choose UART for shell, try RTT");
|
|
if(McuShell_SetStdio(McuRTT_GetStdio())!= ERR_OK){ /* use RTT as the default */
|
|
//couldnt set rtt!!
|
|
McuLog_fatal("failed to set rtt as default for shell");
|
|
for(;;){}
|
|
}else{
|
|
McuLog_info("RTT set for shell");
|
|
}
|
|
}else{
|
|
McuLog_info("UART set for shell");
|
|
}
|
|
shellCmdQueue = xQueueCreate(SHELL_CMD_QUEUE_LENGTH,SHELL_CMD_ELEM_SIZE);
|
|
if(shellCmdQueue == NULL){
|
|
McuLog_fatal("failed to create shell cmd queue!");
|
|
for(;;){}
|
|
}
|
|
vQueueAddToRegistry(shellCmdQueue, "Shell CMD Queue");
|
|
}
|
|
|
|
void SHELL_Deinit(void) {}
|
|
|
|
|