发新帖本帖赏金 50.00元(功能说明)我要提问
返回列表
打印
[APM32F4]

你了解OSAL是个什么玩意儿吗?

[复制链接]
881|6
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
DKENNY|  楼主 | 2024-8-7 18:29 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 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使得在不同环境中开发和运行软件变得更简单。
    针对OSALRTOS的区别,我做了一份简单的表格。
  
特性
  
OSAL(操作系统抽象层)
RTOS(实时操作系统)
定义
OSAL 是一种软件层,提供对不同操作系统的抽象,以便于在不同平台上进行可移植和可重用的代码开发。
RTOS 是一种操作系统,设计用于实时应用程序中,确保任务在严格的时间约束内执行。
目标
实现代码的可移植性,简化对不同操作系统的适配过程。
提供实时任务调度和响应能力,确保时间敏感的操作具备准确性和可靠性。
应用场景
被用于需要在多个不同操作系统上运行的应用程序中,例如嵌入式系统。
被用于对时间要求严格的应用场景,如飞行控制、医疗设备、工业自动化等。
抽象层级
提供更高层次的抽象,隐藏底层操作系统的细节。
涉及底层硬件管理,提供任务调度、中断管理、时间管理等基本功能。
复杂性
通常较低,功能较简单,主要关注可移植性。
较高,需处理更多的底层细节和实时性要求。
性能
性能开销较小,主要取决于底层操作系统的表现。
性能要求高,需确保任务在严格时间内执行。
易用性
提供一致的接口,简化开发步骤。
需要对实时调度算法、任务优先级等有深入理解。

    如果有条件的话,最好选择使用实时操作系统(RTOS),因为它的功能比较丰富。如果不使用RTOS,操作系统抽象层(OSAL)也是一个不错的选择。不过,使用OSAL之前,最好先对它的源码有一定的了解,这样在遇到问题时才能更有效地解决。

附件:

1. APM32F4 OSAL.zip (807.36 KB)

2. osal源码.zip (176.79 KB)
   
   

使用特权

评论回复

打赏榜单

21小跑堂 打赏了 50.00 元 2024-08-12
理由:恭喜通过原创审核!期待您更多的原创作品~

评论
21小跑堂 2024-8-12 10:42 回复TA
一文了解OSAL的概念和使用方法,通过OSAL,简化多平台开发的复杂性,但是需注意使用时适当剪裁,避免项目过于臃肿造成系统负担。 
沙发
chenqianqian| | 2024-8-8 07:58 | 只看该作者
相当于在底层驱动和应用层之间又封了一层,实用性并不一定高,特别是在嵌入式应用中,无形中把代码量又搞大了。

使用特权

评论回复
评论
liang9528 2024-8-9 09:40 回复TA
你没必要用完整的osal,适当裁剪,例如一些不要求精度很高的延时,可以用osal timer的软定时器,节约资源。osal中event都是用的bit进行宏定义,程序中一些零散的全局状态变量可以用event替换,程序结构也清晰一些。总的来说,osal提供一种思想,你也可以自己写一个适合的osal,不用拘泥于osal本身 
板凳
WoodData| | 2024-8-8 13:46 | 只看该作者
这个可以提高应用移植方便

使用特权

评论回复
地板
15949699614| | 2024-8-8 14:02 | 只看该作者
好是教dhv

使用特权

评论回复
5
逢dududu必shu| | 2024-8-17 01:13 | 只看该作者
OSAL(Operating System Abstraction Layer)是一个操作系统抽象层,旨在为应用程序提供一个统一的接口,以便在不同的底层操作系统上运行

使用特权

评论回复
发新帖 本帖赏金 50.00元(功能说明)我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

27

主题

50

帖子

5

粉丝