本帖最后由 DKENNY 于 2024-8-7 18:29 编辑
#申请原创# @21小跑堂
## 前言 最近在学习操作系统,发现了OSAL这个玩意儿,网上查了一下,OSAL的主要目的是提供一个统一的接口,使得上层应用程序能够独立于底层操作系统的具体实现,从而简化多平台开发的复杂性。目前已经有大佬已经完成了OSAL的移植框架,下面简单讲讲怎么将这个玩意儿移植到APM32F407。
## 什么是OSAL? OSAL 是“操作系统抽象层”(Operating SystemAbstraction Layer)的缩写。简单来说,OSAL 是一种帮助软件开发者与不同操作系统进行交互的工具或接口。它的主要作用是提供一个统一的平台,使得开发者可以在编写代码时不必过多关心具体操作系统的细节,使得软件能够更容易地在不同的操作系统上运行。
## 为什么需要 OSAL? 1. 兼容性:不同的操作系统(如Windows、Linux、MacOS 等)有各自的系统调用和管理方式。OSAL 可以隐藏这些差异,让开发者只需要使用统一的接口就能达到相同的效果。 2. 可移植性:使用OSAL 编写的程序更容易在不同的环境中运行。这样,开发者不需要为每个操作系统单独编写一套代码,只需编写一次,通过OSAL 就可以在多种平台上使用。 3. 简化开发:OSAL提供了一套简化的开发接口,减少了与底层操作系统交互时的复杂性,开发者可以更专注于应用的功能实现,而不是底层细节。
## OSAL 的组成部分 OSAL 通常包括一些基本的组件和功能,例如: - 线程管理:提供创建、销毁和管理线程的功能。 - 时间管理:提供时间延迟、计时器等功能。 - 内存管理:提供动态内存分配和释放的接口。 - 文件系统访问:提供统一的方式来读写文件。
想象一下,你正在开发一个需要访问文件和网络的应用。如果不使用 OSAL,当你想要在 Windows 上和 Linux 上运行此应用时,你可能需要分别处理这两个系统的文件和网络接口,这会让工作变得复杂而繁琐。而如果你使用了 OSAL,你只需调用 OSAL 提供的统一函数,无需关心实际底层的实现。
## 源码 获取地址:https://github.com/mcuwty/osal,其内部代码结构如下。
## 移植 这份代码原来是在linux上编译运行的,我把它移植到了windows的keil编译环境上。可以直接去geehy官网直接下载一个F4的SDK包,使用里面的模板工程进行移植。
1、将osal整个文件夹复制到工程路径下。
2、添加必要的头文件以及源文件 我这里对OSAL源文件做了一个简单的结构优化,不过总体上不影响使用。
3、修改注释掉apm32f4xx_int.h中的Sys_Handler,重新实现timer.c文件。 /****************************************************************************************
* 文件名 :timer.c
* 描述 :硬件定时器配置文件,为osal操作系统提供系统时钟,移植时需要修改的文件
* 开发平台:
* 库版本 :
***************************************************************************************/
#include "timer.h"
#include "osal_timer.h"
//硬件定时器初始化,设定系统时钟
void OSAL_TIMER_TICKINIT(void)
{
SysTick_Config(SystemCoreClock / 1000);
}
//开启硬件定时器
void OSAL_TIMER_TICKSTART(void )
{
}
//关闭硬件定时器
void OSAL_TIMER_TICKSTOP(void )
{
}
//此处添加硬件定时器中断溢出函数,并调用系统时钟更新函数osal_update_timers()
/**
* [url=home.php?mod=space&uid=247401]@brief[/url] This function handles SysTick Handler.
* @param None
* @retval None
*/
void SysTick_Handler(void)
{
osal_update_timers();
}
4、编写serial_task.c文件/****************************************************************************************
* 文件名 :serial_task.c
* 描述 :系统串口通信任务
* 开发平台:
* 库版本 :
***************************************************************************************/
#include "application.h"
#include <string.h>
#include <stdarg.h>
#include <stdio.h>
#include "Board.h"
uint8 Serial_TaskID; //系统串口通信任务ID
/*********************************************************************
* LOCAL FUNCTION PROTOTYPES
*/
/*********************************************************************
* FUNCTIONS
*********************************************************************/
//串口通信任务初始化
void Serial_Task_Init(uint8 task_id)
{
Serial_TaskID = task_id;
//串口配置初始化
USART_Config_T usartConfig;
usartConfig.baudRate = 115200;
usartConfig.hardwareFlow = USART_HARDWARE_FLOW_NONE;
usartConfig.mode = USART_MODE_TX_RX;
usartConfig.parity = USART_PARITY_NONE;
usartConfig.stopBits = USART_STOP_BIT_1;
usartConfig.wordLength = USART_WORD_LEN_8B;
APM_TINY_COMInit(COM1, &usartConfig);
APM_TINY_LEDInit(LED2);
APM_TINY_LEDInit(LED3);
}
//串口通信任务事件处理
uint16 Serial_Task_EventProcess(uint8 task_id,uint16 task_event)
{
if ( task_event & SYS_EVENT_MSG ) //判断系统消息事件
{
osal_sys_msg_t *MSGpkt; //定义一个指向接受系统消息结构体的指针
//从消息队列获取消息
MSGpkt = (osal_sys_msg_t *)osal_msg_receive( task_id );
while ( MSGpkt )
{
switch ( MSGpkt->hdr.event ) //判断消息事件
{
case OSAL_PRINTF:
break;
default:
break;
}
// Release the memory
osal_msg_deallocate( (uint8 *)MSGpkt );
// Next 获取下一个消息
MSGpkt = (osal_sys_msg_t *)osal_msg_receive( task_id );
}
// return unprocessed events
return (task_event ^ SYS_EVENT_MSG);
}
if(task_event & PRINTF_STR)
{
static int dir = 1;
if(dir)
{
dir = 0;
APM_TINY_LEDOn(LED2);
}
else
{
dir = 1;
APM_TINY_LEDOff(LED2);
}
printf("APM32F407 printf !\r\n");
return task_event ^ PRINTF_STR;
}
return 0;
}
5、编写main函数。 /*!
* [url=home.php?mod=space&uid=288409]@file[/url] main.c
*
* [url=home.php?mod=space&uid=247401]@brief[/url] Main program body
*
* [url=home.php?mod=space&uid=895143]@version[/url] V1.0.3
*
* [url=home.php?mod=space&uid=212281]@date[/url] 2023-07-31
*
* @attention
*
* Copyright (C) 2021-2023 Geehy Semiconductor
*
* You may not use this file except in compliance with the
* GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE).
*
* The program is only for reference, which is distributed in the hope
* that it will be useful and instructional for customers to develop
* their software. Unless required by applicable law or agreed to in
* writing, the program is distributed on an "AS IS" BASIS, WITHOUT
* ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied.
* See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions
* and limitations under the License.
*/
/* Includes */
#include "main.h"
#include "Board.h"
#include "stdio.h"
#include "apm32f4xx_gpio.h"
#include "apm32f4xx_adc.h"
#include "apm32f4xx_misc.h"
#include "apm32f4xx_usart.h"
#include "apm32f4xx_tmr.h"
/** @addtogroup Examples
@{
*/
/** @addtogroup ADC_AnalogWindowWatchdog
@{
*/
/** @defgroup ADC_AnalogWindowWatchdog_Macros Macros
@{
*/
/* printf using USART1 */
#define DEBUG_USART USART1
#define APM_COMInit APM_TINY_COMInit
/**@} end of group ADC_AnalogWindowWatchdog_Macros*/
/** @defgroup ADC_AnalogWindowWatchdog_Functions Functions
@{
*/
#include "application.h"
/*!
* [url=home.php?mod=space&uid=247401]@brief[/url] Main program
*
* @param None
*
* @retval None
*/
int main(void)
{
//系统硬件、外设等初始化
//禁止中断
HAL_DISABLE_INTERRUPTS();
//osal操作系统初始化
osal_init_system();
//添加任务
osal_add_Task(Serial_Task_Init,Serial_Task_EventProcess,1);
//添加的任务统一进行初始化
osal_Task_init();
osal_mem_kick();
//允许中断
HAL_ENABLE_INTERRUPTS();
//设置初始任务事件,上电就需要自动轮询的任务事件可在此添加
osal_start_reload_timer( Serial_TaskID, PRINTF_STR, 1000);
//启动osal系统,不会再返回
osal_start_system();
}
#if defined (__CC_ARM) || defined (__ICCARM__) || (defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050))
/*!
* [url=home.php?mod=space&uid=247401]@brief[/url] Redirect C Library function printf to serial port.
* After Redirection, you can use printf function.
*
* @param ch: The characters that need to be send.
*
* @param *f: pointer to a FILE that can recording all information
* needed to control a stream
*
* @retval The characters that need to be send.
*
* @note
*/
int fputc(int ch, FILE* f)
{
/* send a byte of data to the serial port */
USART_TxData(DEBUG_USART, (uint8_t)ch);
/* wait for the data to be send */
while (USART_ReadStatusFlag(DEBUG_USART, USART_FLAG_TXBE) == RESET);
return (ch);
}
#elif defined (__GNUC__)
/*!
* [url=home.php?mod=space&uid=247401]@brief[/url] Redirect C Library function printf to serial port.
* After Redirection, you can use printf function.
*
* @param ch: The characters that need to be send.
*
* @retval The characters that need to be send.
*
* @note
*/
int __io_putchar(int ch)
{
/* send a byte of data to the serial port */
USART_TxData(DEBUG_USART, ch);
/* wait for the data to be send */
while (USART_ReadStatusFlag(DEBUG_USART, USART_FLAG_TXBE) == RESET);
return ch;
}
/*!
* [url=home.php?mod=space&uid=247401]@brief[/url] Redirect C Library function printf to serial port.
* After Redirection, you can use printf function.
*
* @param file: Meaningless in this function.
*
* @param *ptr: Buffer pointer for data to be sent.
*
* @param len: Length of data to be sent.
*
* @retval The characters that need to be send.
*
* @note
*/
int _write(int file, char* ptr, int len)
{
int i;
for (i = 0; i < len; i++)
{
__io_putchar(*ptr++);
}
return len;
}
#else
#warning Not supported compiler type
#endif
/**@} end of group ADC_AnalogWindowWatchdog_Functions */
/**@} end of group ADC_AnalogWindowWatchdog */
/**@} end of group Examples */
## 现象
## 总结
OSAL 是一种能够帮助开发者编写更灵活、可移植代码的工具。通过抽象化操作系统的底层细节,OSAL使得在不同环境中开发和运行软件变得更简单。 针对OSAL跟RTOS的区别,我做了一份简单的表格。 特性 | | | | OSAL 是一种软件层,提供对不同操作系统的抽象,以便于在不同平台上进行可移植和可重用的代码开发。 | RTOS 是一种操作系统,设计用于实时应用程序中,确保任务在严格的时间约束内执行。 | | 实现代码的可移植性,简化对不同操作系统的适配过程。 | 提供实时任务调度和响应能力,确保时间敏感的操作具备准确性和可靠性。 | | 被用于需要在多个不同操作系统上运行的应用程序中,例如嵌入式系统。 | 被用于对时间要求严格的应用场景,如飞行控制、医疗设备、工业自动化等。 | | | 涉及底层硬件管理,提供任务调度、中断管理、时间管理等基本功能。 | | | | | | | | | |
如果有条件的话,最好选择使用实时操作系统(RTOS),因为它的功能比较丰富。如果不使用RTOS,操作系统抽象层(OSAL)也是一个不错的选择。不过,使用OSAL之前,最好先对它的源码有一定的了解,这样在遇到问题时才能更有效地解决。
附件:
2.
osal源码.zip
(176.79 KB)
|
一文了解OSAL的概念和使用方法,通过OSAL,简化多平台开发的复杂性,但是需注意使用时适当剪裁,避免项目过于臃肿造成系统负担。