STM32F407移植OpenHarmony笔记6

继上一篇笔记,编译好STM32的裸机程序,能点亮LED灯了。
下一步就是启动liteos_m内核了。


 不过为了更好的调试代码,需要先把printf重定向到串口,基于gcc的printf重定向和Keil不一样。
直接新建printf.c,在里面重写printf函数即可。

int printf(char const *fmt, ...)
{
    char buf[256];
    va_list ap;
    va_start(ap, fmt);
    int len = vsnprintf_s(buf, sizeof(buf), sizeof(buf) - 1, fmt, ap);
    UartWrite(buf, len);
    va_end(ap);
    return len;
}

UartWrite是写串口的函数,基于HAL库写串口驱动我就不介绍了。
记得在printf之前要初始化UART和相关的GPIO。
这里有2个细节需要注意:
1.写串口没有临界区保护,多线程printf会有竞争风险,等kernel跑起来了,到时候加上mutex。
2.格式化字符串的buf长度256,是在stack上开辟的,注意调用线程的stack空间要给够。


liteos_m内核已经完成了ARM cortex-m4的适配,理论上所有基于cortex-m4的MCU都能快速使用。
我们只需要在main函数调用LOS_KernelInit()和LOS_Start()可以了。
启动之前自己创建一个线程,用来闪灯。

static void LED_Blink(void)
{
	GPIO_InitTypeDef GPIO_InitStruct = {0};
	__HAL_RCC_GPIOA_CLK_ENABLE();
	GPIO_InitStruct.Pin = GPIO_PIN_4;
	GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
	GPIO_InitStruct.Pull = GPIO_PULLUP;
	GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
	GPIO_InitStruct.Alternate = 0;
	HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    printf("enter led blink.\n");
	while(1)
	{
		HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);
		LOS_TaskDelay(250);
		HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);
		LOS_TaskDelay(250);
	}
}

static void InitTask(void)
{
    UINT32 taskID = 0;
    TSK_INIT_PARAM_S stTask = {0};
    stTask.pfnTaskEntry = (TSK_ENTRY_FUNC)LED_Blink;
    stTask.uwStackSize = 1024;
    stTask.pcName = "led";
    stTask.usTaskPrio = 1;
    LOS_TaskCreate(&taskID, &stTask);
    printf("task id=%d\n", taskID);
}

int main(void)
{
	HAL_Init();
	SystemClock_Config();
	UartInit();
	printf("init...\n");
	LOS_KernelInit();
	InitTask();
	LOS_Start();
    printf("BUG!!!\n");
	while(1);
}

运气好的话,编译下去,可以看到串口打印,同时LED也会闪烁。

init...
entering kernel init...
task id=2
Entering scheduler
enter led blink.

如果没有跑起来的话,可以检查一下:

1. 进入kernel/liteos_m目录,执行make menuconfig
试试修改相关配置项。

2. 检查LOSCFG_PLATFORM_HWI有没有定义为1
liteos_m有接管中断向量表的功能,需要开启这个宏。
这样一来我们就不用修改startup.s里面的中断向量函数。

3.检查printf函数能不能正常工作
printf不正常好像也会影响程序运行。


内核跑起来之后,我们可以开启shell控制台。
这个控制台是liteos_m提供的,需要手动开启,里面有几个基本命令。

STM32F407移植OpenHarmony笔记6_第1张图片

开启配置后,在main函数里面调用shell初始化:

LosShellInit();
OsShellInit();
//注册自定义的命令reboot使实现重启功能
osCmdReg(CMD_TYPE_EX, "reboot", 0,(CMD_CBK_FUNC)cmd_reboot); 

static void cmd_reboot(UINT32 argc, const CHAR **argv)
{
    printf("reboot...\n");
    HAL_NVIC_SystemReset();
}

初始化完了还不能用,还要提供一个串口读取字符串的函数:uint8_t UartGetc(void)
这个函数从串口返回1个字符,没有收到数据时返回0。

光是这样还不行,它还需要我们在串口中断里面发送一个信号:
LOS_EventWrite(&g_shellInputEvent, 0x1);
g_shellInputEvent是在shell代码里面定义的全局变量,用来阻塞shell线程。
当收到g_shellInputEvent事件后,shell线程调用UartGetc来接收输入。

由于liteos_m接管了中断向量表,所以我们UART的中断函数要用:
LOS_HwiCreate(USART1_IRQn, 0, 1, (HWI_PROC_FUNC)uart_irq, 0);
这个函数来注册。

好了,终于写好代码,我们编译下载,不出意外可以看到串口打印.
输入help可以看到命令列表。

init...
entering kernel init...
task id=3
Entering scheduler
enter led blink.
OHOS # 
OHOS # 
OHOS # help
*******************shell commands:*************************

cat      cd       cp       date     free     help     ls       memusage 
mkdir    pwd      reboot   rm       rmdir    task     touch    
OHOS # 
OHOS # reboot
reboot...
init...
entering kernel init...
task id=3
Entering scheduler
enter led blink.
OHOS # 

试了下mkdir、ping等命令都不能用,下一步要实现文件系统和网络,让这几个命令正常工作。 

你可能感兴趣的:(学习笔记,MCU,stm32,OpenHarmony)