单片机控制台第一次使用是在RTthread上的Finsh组件,当时感觉挺好,但也一直没移植到其他单片机芯片平台,主要是一直搞Linux的开发,最近看了下刚准备搞,发现有个开源的做的不赖。 LetterShell开源项目地址
效果
移植方法
目前3.06版本的IAR测试存在问题,定位到指定段(shellCommand
),需要增加编译器关键字__root
修改如下:
shell.h文件
替换其中的宏定义
#ifndef SECTION
#ifdef __CC_ARM /* ARM Compiler */
#define SECTION(x) __attribute__((section(x)))
#define USED __attribute__((used))
#elif defined (__IAR_SYSTEMS_ICC__) /* for IAR Compiler */
#define SECTION(x) @ x
#define USED __root
#elif defined (__GNUC__) /* GNU GCC Compiler */
#define SECTION(x) __attribute__((section(x)))
#define USED __attribute__((used))
#else
#error not supported tool chain
#endif /* __CC_ARM */
#endif
文件中所有定位到shellCommand段的常量全部增加USED
宏即(__root
)
USED const ShellCommand \
shellCommand##_name SECTION("shellCommand")
shell.c文件
有一个需要修改
以上修改好即可。
IAR指定段的起始地址设置,修改icf文件(非必须)
/*###ICF### Section handled by ICF editor, don't touch! ****/
/*-Editor annotation file-*/
/* IcfEditorFile="$TOOLKIT_DIR$\config\ide\IcfEditor\cortex_v1_0.xml" */
/*-Specials-*/
define symbol __ICFEDIT_intvec_start__ = 0x08000000;
define symbol __ICFEDIT_const_data_start__ = 0x08008000;
/*-Memory Regions-*/
define symbol __ICFEDIT_region_ROM_start__ = 0x08000000;
define symbol __ICFEDIT_region_ROM_end__ = 0x081FFFFF;
define symbol __ICFEDIT_region_RAM_start__ = 0x20000000;
define symbol __ICFEDIT_region_RAM_end__ = 0x2001FFFF;
define symbol __ICFEDIT_region_ITCMRAM_start__ = 0x00000000;
define symbol __ICFEDIT_region_ITCMRAM_end__ = 0x0000FFFF;
/*-Sizes-*/
define symbol __ICFEDIT_size_cstack__ = 0x0000A000;
define symbol __ICFEDIT_size_heap__ = 0x0000C000;
/**** End of ICF editor section. ###ICF###*/
define memory mem with size = 4G;
define region ROM_region = mem:[from __ICFEDIT_region_ROM_start__ to __ICFEDIT_region_ROM_end__];
define region RAM_region = mem:[from __ICFEDIT_region_RAM_start__ to __ICFEDIT_region_RAM_end__];
define region ITCMRAM_region = mem:[from __ICFEDIT_region_ITCMRAM_start__ to __ICFEDIT_region_ITCMRAM_end__];
define block CSTACK with alignment = 8, size = __ICFEDIT_size_cstack__ { };
define block HEAP with alignment = 8, size = __ICFEDIT_size_heap__ { };
initialize by copy { readwrite };
do not initialize { section .noinit };
place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec };
place at address mem:__ICFEDIT_const_data_start__ { readonly section shellCommand };
place in ROM_region { readonly };
place in RAM_region { readwrite,
block CSTACK, block HEAP };
加入文件到工程
1、复制源码
2、加入到工程
3、加入头文件路径到工程
完善接口
4、在Shell_Port.c
中根据需要完善读、写、初始化接口
以下模板使用的STM32串口操作库文件和环形队列库文件
/**
* @brief shell写
*
* @param data 数据
*/
static void Shell_Port_Write(char data)
{
/*底层接口最好是阻塞式发送*/
Uart_Port_Transmit_Data(Uart_Dev_Handle, (uint8_t *)&data, 1);
}
/**
* @brief shell读
*
* @param data 数据
* @return char 状态
*/
static signed char Shell_Port_Read(char *data)
{
uint32_t len = CQ_getLength(Uart_Dev_Handle->cb);
if(len == 0)
{
return -1;
}
CQ_getData(Uart_Dev_Handle->cb, (uint8_t *)data, 1);
return 0;
}
/**
* @brief shell初始化
*
* @param data 数据
* @return char 状态
*/
void Shell_Port_Init(void)
{
Uart_Dev_Handle = Uart_Port_Get_Handle(UART_NUM_1);
if(Uart_Dev_Handle == NULL)
{
return;
}
shell.write = Shell_Port_Write;
shell.read = Shell_Port_Read;
shellInit(&shell, shellBuffer, 512);
}
如需使用串口操作库文件则需要移植它,并修改如下接口为阻塞式发送
/************************************************************
* @brief 串口数据发送
* @param [in]uart_opt_handle 串口句柄.
* @param [in]data 数据.
* @param [in]size 数据大小.
* @return true 发送成功.
* @author aron566
* @date 2020/3/15
* @version v1.0
* @note @@
***********************************************************/
bool Uart_Port_Transmit_Data(Uart_Dev_Handle_t *uart_opt_handle, uint8_t *data, uint16_t size)
{
if(uart_opt_handle == NULL)
{
return false;
}
if(HAL_UART_Transmit(uart_opt_handle->phuart, data, size, 0xFF) != HAL_OK)
{
return false;
}
return true;
}
测试代码
int func(int argc, char *argv[])
{
printf("%dparameter(s)\r\n", argc);
for (char i = 1; i < argc; i++)
{
printf("%s\r\n", argv[i]);
}
return 0;
}
/** Public application code --------------------------------------------------*/
/*******************************************************************************
*
* Public code
*
********************************************************************************
*/
/**
******************************************************************
* @brief 引导任务启动
* @param [in]None
* @return None.
* @author aron566
* @version v1.0
* @date 2021/2/1
******************************************************************
*/
int main(void)
{
/*初始化硬件,串口。。。*/
/*TODO*/
/*其他初始化*/
User_Main_Init();
for(;;)
{
/*启动shell*/
Shell_Port_Start();
}
}
/**
******************************************************************
* @brief 初始化任务
* @param [in]None
* @return None.
* @author aron566
* @version v1.0
* @date 2021/2/1
******************************************************************
*/
void User_Main_Init(void)
{
/*初始化串口设备*/
Uart_Port_Init();
/*Flash操作初始化*/
Flash_Port_Init();
/*Shell初始化*/
Shell_Port_Init();
}
/*导出功能函数*/
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN), func, func, test);