OSAL移植到STM8

发布者:SereneWanderer最新更新时间:2020-02-13 来源: eefocus关键字:OSAL  移植  STM8 手机看文章 扫描二维码
随时随地手机看文章

最近需要用STM8S105做驱动控制器,涉及到使用485与上位机通讯,上位机的蓝牙模块中使用CC2541。这是个新产品,没有可借鉴的代码,涉及到的协议解算和逻辑结构又比较多,规划了一下架构并尝试写了几行代码,发现在编程幼稚园中学的状态机式编程实在难以胜任,于是打算上一个操作系统。


考虑到ucos代码量比较大,不适用于这种小片子,一时难以抉择。忽然想到已经在BLE上耕耘了大半年了,使用OSAL非常得心应手,于是想把CC2541中的OSAL移植过来。


严格意义上来讲,OSAL不是真正的嵌入式实时操作系统,它的本质是状态机式的伪操作系统,它和Contiki有点像,和uCOS的架构则完全不同(因为uCOS底层是真正要做任务切换的,会把寄存器压入任务栈)。OSAL是把状态机伪装成嵌入式操作系统的接口方式,用起来很方便,每个事件任务处单独处理,并实现了轻量级。而这对于我就够了,因为我只是不想靠脑子去理清那么复杂的下一步、下一步应该到哪,那种感觉我一想起来都觉得不寒而栗。


系统具体原理和使用方法这里就不多讲了,TI官方有OSAL手册。接下来直接切入正题,实现移植。


把OSAL从CC2541工程移植到STM8上需要复制以下这些系统文件:

接下来要创建三个文件,如下图,接下来详述:

首先创建是的时钟文件,这里我起名为app_timer.c , 它配置和使用timer4,负责提供系统调度的时基,文件中代码如下:


/**

  ******************************************************************************

  Timer 文件,产生1ms时基

  ******************************************************************************

  */

 

/* Includes ------------------------------------------------------------------*/

#include "stm8s.h"

#include "stm8s_eval.h"

#include "app_uart.h"

#include "app_bsp.h"

#include "OSAL_Clock.h"

 

#define TIM4_PERIOD 124

 

volatile uint32_t sysTick;  /*系统时间计数器*/

 

void TIM4_TimeBase_Init(void)

{

  /* TIM4 configuration:

   - TIM4CLK is set to 16 MHz, the TIM4 Prescaler is equal to 128 so the TIM1 counter

   clock used is 16 MHz / 128 = 125 000 Hz

  - With 125 000 Hz we can generate time base:

      max time base is 2.048 ms if TIM4_PERIOD = 255 --> (255 + 1) / 125000 = 2.048 ms

      min time base is 0.016 ms if TIM4_PERIOD = 1   --> (  1 + 1) / 125000 = 0.016 ms

  - In this example we need to generate a time base equal to 1 ms

   so TIM4_PERIOD = (0.001 * 125000 - 1) = 124 */

  sysTick = 0;  /*初始化系统时间计数器*/

  TIM4_DeInit();

  /* Time base configuration */

  TIM4_TimeBaseInit(TIM4_PRESCALER_128, TIM4_PERIOD);  /*1ms中断*/

  /* Clear TIM4 update flag */

  TIM4_ClearFlag(TIM4_FLAG_UPDATE);

  /* Enable update interrupt */

  TIM4_ITConfig(TIM4_IT_UPDATE, ENABLE);

  /* enable interrupts */

  //enableInterrupts();

  /* Enable TIM4 */

  TIM4_Cmd(ENABLE);

  //TIM4->CR1 |= TIM4_CR1_CEN;  /* Enable TIM4 同上,二选一*/

}

 

void TIM4_TimeBase_Interrupt(void)  /*1ms中断*/

{

  /* Cleat Interrupt Pending bit */

  TIM4_ClearITPendingBit(TIM4_IT_UPDATE);

  /*User Hook Function*/

  TimerBase_UART_Hook();

  /*系统时间*/

  sysTick++;

  osalTimeUpdate(); /*1ms更新OS时基*/

}

 

uint32_t getMcuTickCount(void)

{

  return sysTick;

}

 

/******************************End File*****************************/

接下来新建一个app_OSAL.c文件,该文件用于初始化用户任务:


/**************************************************************************************************

 *                                            INCLUDES

 **************************************************************************************************/

#include "hal_types.h"

#include "OSAL.h"

#include "OSAL_Tasks.h"

#include "app.h"

/* HAL */

#include "hal_drivers.h"

 

/*********************************************************************

 * GLOBAL VARIABLES

 */

 

// The order in this table must be identical to the task initialization calls below in osalInitTask.

const pTaskEventHandlerFn tasksArr[] =

{

  Hal_ProcessEvent,                                 // task 0

  App_ProcessEvent                                  // task 1

 

};

 

const uint8 tasksCnt = sizeof( tasksArr ) / sizeof( tasksArr[0] );

uint16 *tasksEvents;

 

/*********************************************************************

 * FUNCTIONS

 *********************************************************************/

 

/*********************************************************************

 * @fn      osalInitTasks

 *

 * @brief   This function invokes the initialization function for each task.

 *

 * @param   void

 *

 * @return  none

 */

void osalInitTasks( void )

{

  uint8 taskID = 0;

 

  tasksEvents = (uint16 *)osal_mem_alloc( sizeof( uint16 ) * tasksCnt);

  osal_memset( tasksEvents, 0, (sizeof( uint16 ) * tasksCnt));

 

  /* Hal Task */

  Hal_Init( taskID++ );

  /* Application */

  App_Init( taskID );

 

}

 

/*********************************************************************

*********************************************************************/

接下来要修改OSAL文件中的OSAL_ClockBLE.c文件,里面osalTimeUpdate这个函数是用于刷新系统驱动时钟的,因为原来它是借助于BLE的时隙时钟为625us,做了比较复杂的换算成1ms,但是因为上面我自己改造了时钟函数,可以产生1ms时基,所以这里注释掉换算代码,直接用自己的时基:


 


//extern volatile uint32_t sysTick;  /*系统时间计数器*/

void osalTimeUpdate( void )

{

//  uint32 tmp;

//  uint32 ticks1ms;

//  uint16 elapsedMSec = 0;

//  static uint32 test =0 ;

//

//  // Get the free-running count of 625us timer ticks

//  //tmp = ll_McuPrecisionCount();

//  tmp = getMcuTickCount();

//  //tmp = sysTick;

//

//  if ( tmp != previousLLTimerTick )

//  {

//    // Calculate the elapsed ticks of the free-running timer.

//    ticks1ms = tmp - previousLLTimerTick;

//

//    // Store the LL Timer tick count for the next time through this function.

//    previousLLTimerTick = tmp;

//

//    /* It is necessary to loop to convert the usecs to msecs in increments so as

//     * not to overflow the 16-bit variables.

//     */

////    while ( ticks1ms > MAXCALCTICKS )

////    {

////      ticks625us -= MAXCALCTICKS;

////      elapsedMSec += MAXCALCTICKS * 5 / 8;

////      remUsTicks += MAXCALCTICKS * 5 % 8;

////    }

////

////    // update converted number with remaining ticks from loop and the

////    // accumulated remainder from loop

////    tmp = (ticks625us * 5) + remUsTicks;

////

////    // Convert the 625 us ticks into milliseconds and a remainder

////    elapsedMSec += tmp / 8;

////    remUsTicks = tmp % 8;

//

//    // Update OSAL Clock and Timers

//    elapsedMSec = ticks1ms;

//    if ( elapsedMSec )

//    {

//      osalClockUpdate( elapsedMSec );

//      osalTimerUpdate( elapsedMSec );

//    }

//  }

      osalClockUpdate( 1 );

      osalTimerUpdate( 1 );

}

 


最后一步,在main.c文件中增加OSAL相关语句,我工程中的main.c文件内容如下:


void main()

{

  /* system_clock / div = 1 */

  CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1);

 

  BSP_Init(&Board_Address);

#if !defined(__DEBUG) && !defined(__DEBUG_MODBUS) && !defined(__DEBUG_UART) && !defined(__DEBUG_I2C)

  UART_APP_Init(); /*APP mode*/

#else

  UART_Debug_Init();  /*Use debug mode, don't init app uart*/

#endif

  /* Output a message on Hyperterminal using printf function */

  DEBUG("Start done! Version:%s n",__DATE__);

//  I2C_APP_Init();

  ModbusInit(Board_Address);

  TIM4_TimeBase_Init();

  ADC_APP_Init();

  /* Initialize the operating system */

  osal_init_system();

  /* Enable interrupts */

  HAL_ENABLE_INTERRUPTS();

  osal_set_event( App_TaskID, SBP_I2C_INIT_EVT ); /*初始化I2C和9930的任务*/

  /* Start OSAL */

  osal_start_system(); // No Return from here

}

 


最后一句启动了OSAL后,由系统托管了应用程序,再也不会在main中编写代码了。Bye Bye, main! ^-^


用户任务代码都放在app.c文件中,新建该文件,示例用法概要如下:


/*********************************************************************

 * @fn      App_Init

 */

void App_Init( uint8 task_id )

{

  App_TaskID = task_id;

 

/*用户新增功能初始化*/

  UserAppInit();

 

  // Setup a delayed profile startup

  osal_set_event( App_TaskID, SBP_START_DEVICE_EVT );

 

}

 

 

/*********************************************************************

 * @fn      App_ProcessEvent

 *

 * @brief   Simple BLE Peripheral Application Task event processor.  This function

 *          is called to process all events for the task.  Events

 *          include timers, messages and any other user defined events.

 */

uint16 App_ProcessEvent( uint8 task_id, uint16 events )

{

 

  VOID task_id; // OSAL required parameter that isn't used in this function

  //static uint8 cnt = 0;

  if ( events & SYS_EVENT_MSG )

  {

    uint8 *pMsg;

 

    if ( (pMsg = osal_msg_receive( App_TaskID )) != NULL )

    {

      app_ProcessOSALMsg( (osal_event_hdr_t *)pMsg );

 

      // Release the OSAL message

      VOID osal_msg_deallocate( pMsg );

    }

 

    // return unprocessed events

    return (events ^ SYS_EVENT_MSG);

  }

 

  if ( events & SBP_START_DEVICE_EVT )

  {

    // Set timer for first periodic event

    osal_start_timerEx( App_TaskID, SBP_PERIODIC_EVT, SBP_PERIODIC_EVT_PERIOD );

//    osal_start_timerEx( eye_TaskID, SBP_REPORT_TEMP_EVT, SBP_REPORT_TEMP_EVT_PERIOD );

//    osal_start_reload_timer( App_TaskID, SBP_RUNTIME_CNT_EVT, SBP_RUNTIME_CNT_EVT_PERIOD );

    //osal_set_event( eye_TaskID, SBP_SW_LIGHT_EVT );

    return ( events ^ SBP_START_DEVICE_EVT );

  }

……

继续处理其他事件

……

  // Discard unknown events

  return 0;

}

 


至于接下来用户怎样使用OSAL,还是请参考TI官方手册,毕竟系统是人家写的,不服不行。

关键字:OSAL  移植  STM8 引用地址:OSAL移植到STM8

上一篇:STM8s103F3p 16位定时器 STM2
下一篇:STM8S103F3实现串口中断接,中断发功能

推荐阅读最新更新时间:2024-11-16 23:15

STM8 时钟安全系统寄存器
STM8时钟安全系统寄存器(CLK_CSSR) 地址偏移值:0x08 复位值:0x00 位7:4 保留。始终为0。 位3 CSSD:时钟安全系统监测 由硬件置位或软件写0清除。 0:CSS关或未检测到HSE失效 1:检测到HSE失效 位2 CSSDIE:时钟安全系统监测中断使能 由软件置位或清除 0:时钟安全系统监测中断禁用 1:时钟安全系统监测中断使能 位1 AUX:辅助振荡器连接至主时钟 由硬件置位或清除。 0:辅助振荡器关 1:辅助振荡器(HSI/8)开,并做为当前的主时钟源 位0 CSSEN:时钟安全系统使能 可读,但只能由软件写一次。 0:时钟安全系统关。 1:时钟安全系统开。
[单片机]
<font color='red'>STM8</font> 时钟安全系统寄存器
STM32开发笔记44:RTC驱动程序的移植
单片机型号:STM32F070F6P6 本文介绍,将RTC驱动程序移植到自己的工程项目中的方法。本项目仅使用了RTC的实时时钟功能,没有启动定时报警等功能。 1、在STM32CubeMX中对RTC进行配置,如下图所示,激活了时钟源和日历功能。 2、配置RTC的时钟,如下图所示,STM32F070F6P6不能接外部的32.768K的晶振,所以只能使用HSE或LSI RC供给,考虑LSI RC精度比较差,所以使用HSE作为RTC的时钟源,我现在接的HSE时钟为12MHz,由于其频率比较高,所以选择最大的分频系数,这里是32,则供给给RTC的频率为375KHz。 3、对RTC进行设置,如下图所示,这里只考虑S
[单片机]
STM32开发笔记44:RTC驱动程序的<font color='red'>移植</font>
STM8除法运算的时间及注意事项
STM8单片机在乘除法上的时间大为缩短了!除法运算也只需要2.75us @ 8MHz。 需要注意的是,不要在中断程序中做乘除法运算,会出错。 论坛上的解释是:这是因为做乘法运算时,编译器实际上调用了一个函数,而这个函数用到了几个编译器自定义的全局变量,如果不按照2楼说的去做,在进入中断时不会保存这几个全局变量,而造成这个乘法运算函数为不可重入,导致错误。
[单片机]
<font color='red'>STM8</font>除法运算的时间及注意事项
stm32之nRF24L01无线模块(1):SPI2到SPI1的移植
本来要接着写滴答定时器的,但是趁热打铁写下SPI2到SPI1的移植。 为什么SPI2到SPI1的移植要放在nRF24L01模块里写呢,因为无线模块最重要的数据传输就是通过SPI实现的。为什么需要移植呢,因为即使是一个厂家的板子,不同型号之间它的无线模块引脚也有可能是不同的,顺便稿下移植,加深下理解。SPI2移植到SPI1呢,自己做的时候遇到了一些问题,就从遇到的问题顺便讲下初始化。 1.引脚问题 看stm32的手册,不知道为什么,无论在GPIO还是在SPI里都没有看到这个引脚的问题(初学者有可能移植的时候可能纳闷为什么是这些引脚),只有在引脚复用AFIO那里才提了一下,如下图 这样才知道SPI1的引脚,但是
[单片机]
stm32之nRF24L01无线模块(1):SPI2到SPI1的<font color='red'>移植</font>
将STemWin移植到在STM32F103RCT6上的FreeRTOS上
1、版本信息 STM32固件库V3.5.0 FreeRTOS V8.2.3 STemWin 5.26 Keil 4 2、移植步骤 将FreeRTOS移植到STM32F103RCT6上,这个前面的博客有提到,课参考; 添加LCD屏的驱动代码,在这个实验中使用的正点原子的MINI板,使用的ILI9341的驱动芯片,添加好并在裸机下测试可用; 将STemWin 5.26相关文件添加到工程中,如下图 将涉及到的头文件路径加到工程的头文件路径中去 修改GUIConf.c文件中的一处地方,这个地方根据芯片来改,太大了编译会不通过,提示内存不足。如下图 在FreeRTOS创建一个任务来显示,效果如图 至此,就
[单片机]
将STemWin<font color='red'>移植</font>到在STM32F103RCT6上的FreeRTOS上
为STM32移植FATFS,读取SD卡上FAT12/16/32文件系统
给stm32移植fatfs文件系统,今天终于取得阶段性胜利。只需要提供这样几个函数即可 DSTATUS disk_initialize (BYTE); DSTATUS disk_status (BYTE); DRESULT disk_read (BYTE, BYTE*, DWORD, BYTE); DRESULT disk_write (BYTE, const BYTE*, DWORD, BYTE); // 如果实现只读的文件系统就不需要了。 DRESULT disk_ioctl (BYTE, BYTE, void*); 移植成功后,可以用如下方式读取SD卡了,实在太方便了,和PC机上编程差不了多少。 unsigned in
[单片机]
u-boot-在2440上的移植详解(三)
嵌入式Linux之我行,主要讲述和总结了本人在学习嵌入式linux中的每个步骤。一为总结经验,二希望能给想入门嵌入式Linux的朋友提供方便。如有错误之处,谢请指正。 共享资源,欢迎转载: http://hbhuanggang.cublog.cn 一、移植环境 主 机:VMWare--Fedora 9 开发板:Mini2440--64MB Nand, Kernel:2.6.30.4 编译器: arm-linux-gcc-4.3.2.tgz u-boot: u-boot-2009.08.tar.bz2 二、移植步骤 上接: u-boot-2009.08在2440上的移植详解(二) 5)准备进入u-boot的第
[单片机]
u-boot-在2440上的<font color='red'>移植</font>详解(三)
在ARM处理器上移植uCOS II的中断处理
uCOS II是一个源码公开、可移植、可固化、可剪裁和抢占式的实时多任务操作系统,其大部分源码是用ANSI C编写,与处理器硬件相关的部分使用汇编语言编写。总量约200行的汇编语言部分被压缩到最低限度,以便于移植到任何一种其它的CPU上。 uCOS II最多可支持56个任务,其内核为占先式,总是执行就绪态的优先级最高的任务,并支持Semaphore (信号量)、Mailbox (邮箱)、MessageQueue(消息队列)等多种常用的进程间通信机制。与大多商用RTOS不同的是,uCOS II公开所有的源代码.并可以免费获得,只对商业应用收取少量License费用。 uCOS II移植跟OS_CUP_C.C、OS_CPU_A.
[单片机]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved