使用Platformio平台的libopencm3开发框架来开发STM32G0,以下为FreeRTOS和CLI组件使用。

1 新建项目

  • 建立freertos_cli项目

在PIO的Home页面新建项目,项目名称freertos_cli,选择开发板为 MonkeyPi_STM32_G070RB,开发框架选择libopencm3;

  • 项目建立完成后在src目录下新建main.c主程序文件;
  • 修改下载和调试方式,这里开发板使用的是DAPLink仿真器,因此修改platformio.ini文件如下:
1
2
upload_protocol = cmsis-dap
debug_tool = cmsis-dap

2 编写程序

直接在之前的文章-FreeRTOS基本使用基础上进行添加,在项目中添加好FreeRTOS源码后,再将FreeRTOS源码中的 FreeRTOS-Plus\Source\FreeRTOS-Plus-CLI 目录放置到项目lib目录下,目录如下:

2.1 串口设置
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
void uart_setup(void)
{

//uart pin
rcc_periph_clock_enable(RCC_USART1);
rcc_periph_clock_enable(RCC_GPIOB);

gpio_mode_setup(GPIOB,GPIO_MODE_AF,GPIO_PUPD_NONE,GPIO6|GPIO7);
gpio_set_af(GPIOB,GPIO_AF0,GPIO6|GPIO7);

usart_set_baudrate(USART1,115200);
usart_set_databits(USART1,8);
usart_set_stopbits(USART1,USART_STOPBITS_1);
usart_set_parity(USART1,USART_PARITY_NONE);
usart_set_flow_control(USART1,USART_FLOWCONTROL_NONE);
usart_set_mode(USART1,USART_MODE_TX_RX);

//uart isr
nvic_enable_irq(NVIC_USART1_IRQ);

usart_enable(USART1);

usart_enable_rx_interrupt(USART1);
}

/**
* @brief uart1 isr function
*
*/
void usart1_isr(void)
{
//receive interrupt
if (((USART_CR1(USART1) & USART_CR1_RXNEIE) != 0) &&
((USART_ISR(USART1) & USART_ISR_RXNE) != 0)) {

char c = usart_recv(USART1);

xQueueSendFromISR(uart_queue, &c, NULL);
}
}

开启出口中断,并在串口接收到数据时候发送到队列;

2.2 命令程序

编写执行命令后要进行的动作函数,这里为了简单直接打印一个信息:

1
2
3
4
5
6
7
8
9
10
11
static BaseType_t prvHelloCommand( 
int8_t *pcWriteBuffer,
size_t xWriteBufferLen,
const int8_t *pcCommandString )
{

sprintf(pcWriteBuffer, "hello world command");

/* Execution of this command is complete, so return pdFALSE. */
return pdFALSE;
}
  • pcWriteBuffer 参数为要写入的信息;
  • xWriteBufferLen 参数为写入的缓冲大小;
  • pcCommandString 为整个命令字符串指针,可以使用 FreeRTOS_CLIGetParameter 来获取命令的参数;
2.3 命令和函数进行映射
1
2
3
4
5
6
7
static const CLI_Command_Definition_t xHelloCommand = 
{
"hello",
"\r\nhello:\r\n This is a hello command for testing\r\n",
prvHelloCommand,
0
};
  • 第一个参数为命令名字;
  • 第二个参数为命令描述;
  • 第三个参数为命令所需要的参数个数;
2.4 注册命令
1
2
//register cli command
FreeRTOS_CLIRegisterCommand(&xHelloCommand);
2.5 命令任务

建立一个任务,用于处理CLI输入输出:

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
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102

static void hello_cli_task(void *args)
{
//register cli command
FreeRTOS_CLIRegisterCommand(&xHelloCommand);

char *outbuff;
static int8_t inbuff[64];
static int8_t lastinbuff[64];
uint8_t index = 0;
BaseType_t ret;

outbuff = FreeRTOS_CLIGetOutputBuffer();

printf(">");//command prompt
fflush(stdout);
// printf("\r\n");

char c;

while(1){

if( xQueueReceive(uart_queue, &c, 5) == pdPASS) {
printf("%c",c);//echo
fflush(stdout);

/* Was it the end of the line? */
if( c == '\n' || c == '\r' )
{
printf("\r\n");
fflush(stdout);

/* See if the command is empty, indicating that the last command is to be executed again. */
if( index == 0 )
{
/* Copy the last command back into the input string. */
strcpy( inbuff, lastinbuff );
}

/* Pass the received command to the command interpreter. The
command interpreter is called repeatedly until it returns
pdFALSE (indicating there is no more output) as it might
generate more than one string. */
do
{
/* Get the next output string from the command interpreter. */
ret = FreeRTOS_CLIProcessCommand( inbuff, outbuff, configCOMMAND_INT_MAX_OUTPUT_SIZE );

/* Write the generated string to the UART. */
printf("%s",outbuff);
fflush(stdout);

} while( ret != pdFALSE );

/* All the strings generated by the input command have been
sent. Clear the input string ready to receive the next command.
Remember the command that was just processed first in case it is
to be processed again. */
strcpy( lastinbuff, inbuff );
index = 0;
memset( inbuff, 0x00, 64 );

printf("\r\n>");
fflush(stdout);

}
else
{
if( c == '\r' )
{
/* Ignore the character. */
}
else if( ( c == '\b' ) || ( c == 0x7f ) )//del
{
/* Backspace was pressed. Erase the last character in the
string - if any. */
if( index > 0 )
{
index--;
inbuff[ index ] = '\0';
}
}
else
{
/* A character was entered. Add it to the string entered so
far. When a \n is entered the complete string will be
passed to the command interpreter. */
if( ( c >= ' ' ) && ( c <= '~' ) )
{
if( index < 64 )
{
inbuff[ index ] = c;
index++;
}
}
}
}

}
}

}

输入这里直接从之前串口中断获取的数据队列中得到;

输出使用串口打印输出即可;

3 烧写测试

将程序烧写到开发板,连接好串口后,执行命令测试: