【BLE】-CC2541 OSAL操作系统抽象层应用程序接口API介绍

参考源source

简介

目的

本文档的目的是定义OS抽象层(OSAL)的API。这个API适用于TI协议栈软件组的产品,例如Z-堆栈™,RemoTI™和BLE。

适用范围

该文件列举了由OSAL提供的所有函数调用。详细地说明了所有函数调用,方便码农们快速调用。

缩略语

API 应用程序接口
BLE 蓝牙低功耗
NV 非易失
OSAL 操作系统(OS)抽象层
RF4CE 射频消费电子
RemoTI 德州仪器(TI)的RF4CE协议栈
Z-Stack Z-Stack德州仪器ZigBee协议栈

API概述

概述

操作系统抽象层用来屏蔽指定TI栈软件组件的环境的细节处理。它以独立于处理环境的方式,包括以下的功能。

1.消息管理
2.任务同步
3.时间管理
4.中断管理
5.任务管理
6.内存管理
7.电源管理
8.非易失性闪存管理
9.简单的非易失性闪存管理
10.时钟管理
11.其他常用

消息管理

简介

消息管理API提供了一种机制用于交换具有不同处理环境的任务或处理元件之间的消息(例如,中断服务程序在一个控制环中被调用)。功能主要包括为任务分配消息缓存、释放消息缓存、接收消息和发送消息等API函数。

osal_msg_allocate()

这个函数通过被一个任务调用来分配消息缓冲区,该任务(函数)将填充到消息列表中并调用osal_msg_send()将消息发送给另一个任务。如果缓冲器不能分配出消息缓冲区的话,msg_ptr指针将被设置为NULL。
注意:不要搞混osal_mem_alloc(),这个函数是用来分配一个缓冲区,而任务之间发送消息使用osal_msg_send()。使用osal_mem_alloc()分配的是内存块。
函数原型

uint8 * osal_msg_allocate( uint16 len )
{
  osal_msg_hdr_t *hdr;

  if ( len == 0 )
    return ( NULL );

  hdr = (osal_msg_hdr_t *) osal_mem_alloc( (short)(len + sizeof( osal_msg_hdr_t )) );
  if ( hdr )
  {
    hdr->next = NULL;
    hdr->len = len;
    hdr->dest_id = TASK_NO_TASK;
    return ( (uint8 *) (hdr + 1) );
  }
  else
    return ( NULL );
}

参数:len消息的长度
返回值:返回分配一个指向消息缓冲区的指针,返回空代表分配消息缓冲区失败。

osal_msg_deallocate( )

此功能用于解除分配的消息缓冲器。这个功能是由一个任务(或处理元件)称为后处理完接收到的消息。
函数原型

uint8 osal_msg_deallocate( uint8 *msg_ptr )
{
  uint8 *x;

  if ( msg_ptr == NULL )
    return ( INVALID_MSG_POINTER );

  // don't deallocate queued buffer
  if ( OSAL_MSG_ID( msg_ptr ) != TASK_NO_TASK )
    return ( MSG_BUFFER_NOT_AVAIL );

  x = (uint8 *)((uint8 *)msg_ptr - sizeof( osal_msg_hdr_t ));

  osal_mem_free( (void *)x );

  return ( SUCCESS );
}

参数: msg_ptr指针是指向需要被解除分配的消息缓冲器。
返回值:msg_ptr指针是指向需要被解除分配的消息缓冲器。

返回值解释
SUCCESS成功
INVALID_MSG_POINTER无效的消息指针
MSG_BUFFER_NOT_AVAIL缓冲区排队

osal_msg_send( )

所述osal_msg_send函数通过被一个任务调用发送一个命令或数据消息到另一任务或处理元件。该destination_task标识符字段必须指向一个有效的系统任务。osal_msg_send()函数同样也设置目标任务事件列表中的SYS_EVENT_MSG事件。
函数原型

uint8 osal_msg_send( uint8 destination_task, uint8 *msg_ptr )
{
  return ( osal_msg_enqueue_push( destination_task, msg_ptr, FALSE ) );
}

参数
destination_task是任务的ID来接收该消息。
msg_ptr是指向包含消息的缓冲器。Msg_ptr必须是一个指针()通过osal_msg_allocate分配的一个有效的消息缓冲区。
返回值:
返回值是1字节字段,指示该操作的结果。

返回值解释
SUCCESS成功
INVALID_MSG_POINTER无效的消息指针
MSG_BUFFER_NOT_AVAIL缓冲区排队

osal_msg_receive( )

该功能称为由任务来检索接收的命令消息。使用osal_msg_deallocate()调用处理消息后,调用任务必须取消分配的消息缓冲区。
函数原型

uint8 *osal_msg_receive( uint8 task_id )
{
  osal_msg_hdr_t *listHdr;
  osal_msg_hdr_t *prevHdr = NULL;
  osal_msg_hdr_t *foundHdr = NULL;
  halIntState_t   intState;

  // Hold off interrupts
  HAL_ENTER_CRITICAL_SECTION(intState);

  // Point to the top of the queue
  listHdr = osal_qHead;

  // Look through the queue for a message that belongs to the asking task
  while ( listHdr != NULL )
  {
    if ( (listHdr - 1)->dest_id == task_id )
    {
      if ( foundHdr == NULL )
      {
        // Save the first one
        foundHdr = listHdr;
      }
      else
      {
        // Second msg found, stop looking
        break;
      }
    }
    if ( foundHdr == NULL )
    {
      prevHdr = listHdr;
    }
    listHdr = OSAL_MSG_NEXT( listHdr );
  }

  // Is there more than one?
  if ( listHdr != NULL )
  {
    // Yes, Signal the task that a message is waiting
    osal_set_event( task_id, SYS_EVENT_MSG );
  }
  else
  {
    // No more
    osal_clear_event( task_id, SYS_EVENT_MSG );
  }

  // Did we find a message?
  if ( foundHdr != NULL )
  {
    // Take out of the link list
    osal_msg_extract( &osal_qHead, foundHdr, prevHdr );
  }

  // Release interrupts
  HAL_EXIT_CRITICAL_SECTION(intState);

  return ( (uint8*) foundHdr );
}

参数
TASK_ID是调用任务(该消息注定)的标识。
返回值
返回值是一个指针,指向包含该消息或NULL,如果没有接收到的消息的缓冲器。

osal_msg_find( )

此功能搜索现有的OSAL信息匹配TASK_ID和事件的参数。
函数原型:

osal_event_hdr_t *osal_msg_find(uint8 task_id, uint8 event)
{
  osal_msg_hdr_t *pHdr;
  halIntState_t intState;

  HAL_ENTER_CRITICAL_SECTION(intState);  // Hold off interrupts.

  pHdr = osal_qHead;  // Point to the top of the queue.

  // Look through the queue for a message that matches the task_id and event parameters.
  while (pHdr != NULL)
  {
    if (((pHdr-1)->dest_id == task_id) && (((osal_event_hdr_t *)pHdr)->event == event))
    {
      break;
    }

    pHdr = OSAL_MSG_NEXT(pHdr);
  }

  HAL_EXIT_CRITICAL_SECTION(intState);  // Release interrupts.

  return (osal_event_hdr_t *)pHdr;
}

参数:
TASK_ID是标识符的入队OSAL信息必须匹配。
事件是OSAL事件ID的入队OSAL信息必须匹配。
返回值
返回值是一个指向上的成功或NULL失败匹配的OSAL信息。

任务同步

简介

此API允许一个任务等待事件处理,再进行返回控制。该API中的函数可以被用来设置为任务的事件,并通知任务一旦任何事件被设置。

osal_set_event()

这个函数被调用来设置事件标志的任务。
函数原型

uint8 osal_set_event( uint8 task_id, uint16 event_flag )
{
  if ( task_id < tasksCnt )
  {
    halIntState_t   intState;
    HAL_ENTER_CRITICAL_SECTION(intState);    // Hold off interrupts
    tasksEvents[task_id] |= event_flag;  // Stuff the event bit(s)
    HAL_EXIT_CRITICAL_SECTION(intState);     // Release interrupts
    return ( SUCCESS );
  }
   else
  {
    return ( INVALID_TASK );
  }
}

参数
TASK_ID是该事件是要设置的任务的标识符。
event_flag是一个2字节的比特映射表,每个比特指定一个事件。只有一个系统事件(SYS_EVENT_MSG),事件的其余/位由接收任务定义。
返回值
返回值指示该操作的结果。

返回值解释
SUCCESS成功
INVALID_TASK无效的任务

时间管理

简介

该API允许通过内部(TI堆栈)的任务和外部的(应用层)任务使用定时器。该API提供的功能来启动和停止计时器。该定时器可在1millisecond的增量进行设置。

osal_start_timerEx()

这个函数被调用,以启动一个定时器。当计时器到期时,给定的事件位将被设置。本次活动将针对TaskID定义任务设置。该定时器是一个单次定时器,这意味着当定时器期满它不重新加载。
函数原型

uint8 osal_start_timerEx( uint8 taskID, uint16 event_id, uint32 timeout_value )
{
    halIntState_t intState;// type:uint16
    osalTimerRec_t *newTimer;//
    //关闭总的中断
    HAL_ENTER_CRITICAL_SECTION( intState );  // Hold off interrupts.
    // Add timer//添加定时器
    newTimer = osalAddTimer( taskID, event_id, timeout_value );
    //打开总的中断
    HAL_EXIT_CRITICAL_SECTION( intState );   // Re-enable interrupts.

    return ( (newTimer != NULL) ? SUCCESS : NO_TIMER_AVAIL );
}

参数
TaskID: 当定时器到期时,获得该事件的任务的任务ID。
EVENT_ID: 是用户定义的事件比特位。当定时器到期时,被调用的任务将被通知(事件)。
timeout_value: 是时间的量(以毫秒为单位)的计时器事件被设置之前。
返回值

返回值解释
SUCCESS成功
NO_TIMER_AVAIL无法启动定时器

osal_start_reload_timer()

设置一个定时时间,定时时间到后,相应任务的相应事件被设置,这一点跟“osal_start_timerEx()”功能一样,但是本接口还多了一个功能:就是定时时间到后相应事件被执行,并重新加载定时器,也就是又重新设置了定时器,继续进行定时工作,除非调用“osal_stop_timerEx()”接口,否则一直循环定时操作。
函数原型

uint8 osal_start_reload_timer( uint8 taskID, uint16 event_id, uint32 timeout_value )
{
  halIntState_t intState;
  osalTimerRec_t *newTimer;

  HAL_ENTER_CRITICAL_SECTION( intState );  // Hold off interrupts.

  // Add timer
  newTimer = osalAddTimer( taskID, event_id, timeout_value );
  if ( newTimer )
  {
    // Load the reload timeout value
    newTimer->reloadTimeout = timeout_value;
  }

  HAL_EXIT_CRITICAL_SECTION( intState );   // Re-enable interrupts.

  return ( (newTimer != NULL) ? SUCCESS : NO_TIMER_AVAIL );
}

参数
TaskID:当定时器到期时,获得该事件的任务的任务ID。
EVENT_ID:是用户定义的事件比特位。当定时器到期时,被调用的任务将被通知(事件)。
timeout_value:是时间的量(以毫秒为单位)的计时器事件被设置之前。此值加载到定时器,当定时器超时。
返回值
返回值指示该操作的结果。

返回值解释
SUCCESS成功
NO_TIMER_AVAIL无法启动定时器

osal_stop_timerEx()

这个函数被调用来停止已启动的计时器。如果成功,该函数将取消定时器,并防止与计时器相关联的事件。
函数原型

uint8 osal_stop_timerEx( uint8 task_id, uint16 event_id )
{
  halIntState_t intState;
  osalTimerRec_t *foundTimer;

  HAL_ENTER_CRITICAL_SECTION( intState );  // Hold off interrupts.

  // Find the timer to stop
  foundTimer = osalFindTimer( task_id, event_id );
  if ( foundTimer )
  {
    osalDeleteTimer( foundTimer );
  }

  HAL_EXIT_CRITICAL_SECTION( intState );   // Re-enable interrupts.

  return ( (foundTimer != NULL) ? SUCCESS : INVALID_EVENT_ID );
}

参数
task_ID是要为其停止定时器的任务。
event_id的是要被停止的定时器的标识符。
返回值
返回值指示该操作的结果。

返回值解释
SUCCESS成功
NO_TIMER_AVAIL无法启动定时器

osal_GetSystemClock()

这个函数被调用,以读取系统时钟
函数原型

uint32 osal_GetSystemClock( void )
{
  return ( osal_systemClock );
}

参数 无参数
返回值 无返回值

中断管理

简介

这部分的API可以控制一个任务以外部中断的方式交互。 API中的函数允许一个任务到一个特定的服务程序与每个中断相关联。中断可以启用或禁用。里面的服务程序,事件可能会被用于其他任务设置。

osal_int_enable

这个函数被调用,以允许中断。一旦启用,中断相关的服务程序被调用发生中断。
函数原型

uint8 osal_int_enable( uint8 interrupt_id )
{

  if ( interrupt_id == INTS_ALL )
  {
    HAL_ENABLE_INTERRUPTS();
    return ( SUCCESS );
  }
  else
  {
    return ( INVALID_INTERRUPT_ID );
  }
}

参数
interrupt_id标识要启用中断。
返回值
返回值指示该操作的结果。

返回值解释
SUCCESS成功
INVALID_INTERRUPT_ID无效中断

osal_int_disable()

这个函数被调用来禁止中断。当禁用中断时,与该中断相关的服务例程不被调用
函数原型

uint8 osal_int_disable( uint8 interrupt_id )
{

  if ( interrupt_id == INTS_ALL )
  {
    HAL_DISABLE_INTERRUPTS();
    return ( SUCCESS );
  }
  else
  {
    return ( INVALID_INTERRUPT_ID );
  }
}

参数
interrupt_id标识要禁用中断。
返回值
返回值指示该操作的结果。

返回值解释
SUCCESS成功
INVALID_INTERRUPT_ID无效中断

任务管理

简介

这部分API是用来添加和管理在OSAL系统层的任务。每个任务是由一个初始化函数和一个事件处理函数组成。OSAL调用osalInitTasks()提供的应用程序初始化任务,OSAL使用任务表(const的pTaskEventHandlerFn tasksArr []),呼吁每个任务(也提供应用程序)的事件处理器。
任务列表实例:

const pTaskEventHandlerFn tasksArr[] =
{
  LL_ProcessEvent,
  Hal_ProcessEvent,
  HCI_ProcessEvent,
#if defined ( OSAL_CBTIMER_NUM_TASKS )
  OSAL_CBTIMER_PROCESS_EVENT( osal_CbTimerProcessEvent ),
#endif
  L2CAP_ProcessEvent,
  GAP_ProcessEvent,
  GATT_ProcessEvent,
  SM_ProcessEvent,
  GAPRole_ProcessEvent,
  GAPBondMgr_ProcessEvent,
  GATTServApp_ProcessEvent,
  HeartRate_ProcessEvent
};
const uint8 tasksCnt = sizeof( tasksArr ) / sizeof( tasksArr[0]);

任务列表初始化实例

void osalInitTasks( void )
{
  uint8 taskID = 0;

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

  /* LL Task */
  LL_Init( taskID++ );

  /* Hal Task */
  Hal_Init( taskID++ );

  /* HCI Task */
  HCI_Init( taskID++ );

#if defined ( OSAL_CBTIMER_NUM_TASKS )
  /* Callback Timer Tasks */
  osal_CbTimerInit( taskID );
  taskID += OSAL_CBTIMER_NUM_TASKS;
#endif

  /* L2CAP Task */
  L2CAP_Init( taskID++ );

  /* GAP Task */
  GAP_Init( taskID++ );

  /* GATT Task */
  GATT_Init( taskID++ );

  /* SM Task */
  SM_Init( taskID++ );

  /* Profiles */
  GAPRole_Init( taskID++ );
  GAPBondMgr_Init( taskID++ );

  GATTServApp_Init( taskID++ );

  /* Application */
  HeartRate_Init( taskID );
}

osal_init_system()

初始化OSAL,该函数是第一个被调用的OSAL函数。
函数原型

uint8 osal_init_system( void )
{
  // Initialize the Memory Allocation System
  osal_mem_init();

  // Initialize the message queue
  osal_qHead = NULL;

  // Initialize the timers
  osalTimerInit();

  // Initialize the Power Management System
  osal_pwrmgr_init();

  // Initialize the system tasks.
  osalInitTasks();

  // Setup efficient search for the first free block of heap.
  osal_mem_kick();

  return ( SUCCESS );
}

参数: NULL
返回值:
返回值指示该操作的结果。

返回值解释
SUCCESS成功

osal_start_system

该函数包含一个无限循环,反复调用执行osal_run_system()函数。此函数没有返回值。
函数原型

void osal_start_system( void )
{
#if !defined ( ZBIT ) && !defined ( UBIT )
  for(;;)  // Forever Loop
#endif
  {
    osal_run_system();
  }
}

参数: NULL
返回值: NULL

osal_run_system

查询所有的任务事件,如果有事件发生,则调用相应的事件处理函数,处理完该事件后将没有处理的事件返回,到主循环中继续检测是否有事件发生,如果开启了休眠模式,则没有事件发生时,该函数将使处理器进入休眠模式,以降低系统功耗。
函数原型

void osal_run_system( void )
{
  uint8 idx = 0;

  #if defined (WDT_USED)
  WD_KICK();
  #endif


#ifndef HAL_BOARD_CC2538
  osalTimeUpdate();
#endif


  Hal_ProcessPoll();

  do {
    if (tasksEvents[idx])  // Task is highest priority that is ready.
    {
      break;
    }
  } while (++idx < tasksCnt);

  if (idx < tasksCnt)
  {
    uint16 events;
    halIntState_t intState;

    HAL_ENTER_CRITICAL_SECTION(intState);
    events = tasksEvents[idx];
    tasksEvents[idx] = 0;  // Clear the Events for this task.
    HAL_EXIT_CRITICAL_SECTION(intState);

    activeTaskID = idx;
    events = (tasksArr[idx])( idx, events );
    activeTaskID = TASK_NO_TASK;

    HAL_ENTER_CRITICAL_SECTION(intState);
    tasksEvents[idx] |= events;  // Add back unprocessed events to the current task.
    HAL_EXIT_CRITICAL_SECTION(intState);
  }
#if defined( POWER_SAVING )
  else  // Complete pass through all task events with no activity?
  {
    //if (gapProfileState != GAPROLE_CONNECTED )
    //||( lcd_sleep_flag == 1))
    //if( lcd_sleep_flag == 1)
    osal_pwrmgr_powerconserve();  // Put the processor/system into sleep
  }
#endif

  /* Yield in case cooperative scheduling is being used. */
#if defined (configUSE_PREEMPTION) && (configUSE_PREEMPTION == 0)
  {
    osal_task_yield();
  }
#endif
}

参数 NULL
返回值 NULL

osal_self( )

返回当前正在执行事件处理的任务的ID,如果没有,则返回TASK_NO_TASK。
函数原型

uint8 osal_self( void )
{
  return ( activeTaskID );
}

参数 NULL
返回值
返回当前有效OSAL任务的ID。

返回值解释
0x00-0xFE有效OSAL任务的ID
0xFF(TASK_NO_TASK)无有效的OSAL任务的ID

内存管理

简介

此部分的API提供了简单的内存分配系统。这部分允许动态的进行内存分配。

osal_mem_alloc()

在堆上分配指定大小的缓冲区。这里需要注意一定要与函数 osal_mem_free( )要成对使用,防止产生内存泄露。
函数原型

#define osal_mem_alloc(_size ) osal_mem_alloc_dbg(_size, __FILE__, __LINE__)

参数
想要分配的buffer的大小。
返回值
一个void型的指针指向分配buffer的首地址(应该强转成指定的类型)。如果没有足够的内存可以分配的话,返回值NULL空指针。

osal_mem_free()

释放使用osal_mem_alloc()分配的缓冲区。
函数原型

#define osal_mem_free(_ptr ) osal_mem_free_dbg(_ptr, __FILE__, __LINE__)

参数
_ptr - 指向osal_mem_alloc分配的缓冲区被释放。
返回值 NULL

电源管理

简介

该部分描述了OSAL的电源管理系统。该系统提供了为应用程序/任务通知OSAL何时可以安全关闭接收器和外部硬件,并使处理器进入睡眠模式的方式。
一共有两个函数控制电源管理。第一个函数,osal_pwrmgr_device()用来设置设备的level模式(有低功耗功能和无低功耗功能)。第二个函数,任务的功耗状态,osal_pwrmgr_task_state(PWRMGR_HOLD),不允许该任务进入低功耗功能,osal_pwrmgr_task_state(PWRMGR_CONSERVE),允许该任务进入低功耗功能。
默认状态下,当所有的任务被初始化,初始化的任务状态是PWRMGR_CONSERVE,如果一个任务不想要功耗保护(维持不变)就不需要调用osal_pwrmgr_task_state()。
此外,在默认情况下,电池供电的设备将在PWRMGR_ALWAYS_ON状态,直到它加入了系统进程中,那么这将改变其状态PWRMGR_BATTERY。这意味着,如果设备无法找到设备的加入也不会进入节电状态。如果你想改变这种行为,在应用程序的任务初始化函数中添加osal_pwrmgr_device(PWRMGR_BATTERY),或者当您的应用程序停止/暂停连接过程。
在进入电源保护状态时,电源管理器监听设备状态和电源状态

osal_pwrmgr_init

此功能将初始化所使用的电源管理系统的变量。重要提示:不要调用这个函数,它已经称为osal_init_system()。
函数原型

void osal_pwrmgr_init( void )
{
  pwrmgr_attribute.pwrmgr_device = PWRMGR_ALWAYS_ON; // Default to no power conservation.

  pwrmgr_attribute.pwrmgr_task_state = 0;            // Cleared.  All set to conserve
}

参数 NULL
返回值 NULL

osal_pwrmgr_powerconserve()

这个函数被调用来进入掉电模式。重要提示:不需要调用此函数,因为此函数已经在osal_start_system()循环中被调用了。
函数原型

void osal_pwrmgr_powerconserve( void )
{
  uint32        next;
  halIntState_t intState;

  // Should we even look into power conservation
  //首先检查是否允许进入低功耗的处理
  if ( pwrmgr_attribute.pwrmgr_device != PWRMGR_ALWAYS_ON )
  {
    // Are all tasks in agreement to conserve
    //是否所有的任务支持低功耗功能
    if ( pwrmgr_attribute.pwrmgr_task_state == 0 )
    {
      // Hold off interrupts.
      HAL_ENTER_CRITICAL_SECTION( intState );

      // Get next time-out
      //查询软件定时器链表的最后最大的时间间隔
      next = osal_next_timeout();

      // Re-enable interrupts.
      HAL_EXIT_CRITICAL_SECTION( intState );

      // Put the processor into sleep mode
      OSAL_SET_CPU_INTO_SLEEP( next );
    }
  }
}

参数 NULL
返回值 NULL

osal_pwrmgr_device()

设置电源管理的特性方式,主要有两种方式:“PWRMGR_ALWAYS_ON”和“PWRMGR_BATTERY”。如果是“PWRMGR_ALWAYS_ON”方式,电源持续供电,不会进入休眠模式;如果是“PWRMGR_BATTERY”方式,系统将在没有事件要处理的时候进入休眠模式,降低功耗。
函数

void osal_pwrmgr_device( uint8 pwrmgr_device )
{
  pwrmgr_attribute.pwrmgr_device = pwrmgr_device;
}

参数
pwrmgr_device :改变或设置power savings模式。

类型描述
PWRMGR_ALWAYS_ON关闭PowerSaving功能,系统一直运行
PWRMGR_BATTERY打开PowerSaving功能

返回值 NULL

osal_pwrmgr_task_state

该函数是用来表示该任务是否想要进入低功耗。
函数

uint8 osal_pwrmgr_task_state( uint8 task_id, uint8 state )
{
  if ( task_id >= tasksCnt )
    return ( INVALID_TASK );

  if ( state == PWRMGR_CONSERVE )
  {
    // Clear the task state flag
    pwrmgr_attribute.pwrmgr_task_state &= ~(1 << task_id );
  }
  else
  {
    // Set the task state flag
    pwrmgr_attribute.pwrmgr_task_state |= (1 << task_id);
  }

  return ( SUCCESS );
}

参数

类型描述
PWRMGR_CONSERVE所有的PowerSaving打开,必须所有task同意。
PWRMGR_HOLD关闭PowerSaving功能

返回值
返回操作结果

返回值描述
SUCCESS成功
INVALID_TASK无效的任务

非易失性闪存管理

简介

这部分描述了OSAL非易失性内存系统。该系统提供了一套为应用程序把所有的信息永久的保存到设备内存中。适用于由堆栈对ZigBee所规范的某些项目的持久存储。NV函数的读写适用于用户自定义的任意类型的结构体和数组。用户可以通过适当的偏移或者长度读写整个item的或者item的某一个部分。该API是独立于NV存储的介质,可以被应用到善存或者E2PROM。
每一个NV的item有一个独立的ID。应用程序有特定的ID值范围,一些ID值被预留给栈或平台使用。如果你的应用程序创建自己的NV项目时,必须选择从应用程序的价值范围内的ID。请参阅下表:

VALUEUSER
0x0000Reserved
0x0001–0x0020OSAL
0x0021–0x0040NWK
0x0041–0x0060APS
0x0061–0x0080Security
0x0081–0x00B0ZDO
0x0081–0x00B0Commissioning SAS
0x00E1–0x0100Reserved
0x0101–0x01FFTrust Center Link Keys
0x0101–0x01FFZigBee-Pro: APS Links Key ZigBee-RF4CE: network layer
0x0301–0x0400ZigBee-Pro: Master Keys ZigBee-RF4CE: app framework
0x0401 – 0x0FFF0x0401 – 0x0FFF
0x1000 -0xFFFF0x1000 -0xFFFF

注意事项:
1.这些堵塞函数的调用以及一个操作可能需要数十毫秒才能完成。NV写操作尤其如此。所以,中断可能被禁止了几个毫秒。最好是在时间执行这些功能时,他们不与其他时序关键的操作发生冲突。举例,一个好的时间去写NV的items在接收器被关闭。
2.尽量少进行NV的写操作。它既花时间有耗功耗。所以说大多数的flash设备都有有限的擦写次数。
3.如果NV的items有一个或者多个结构体发生改变,尤其是TI的软件的协议栈的版本更新到另一个,所以有必要擦除或者重新初始化NV内存。否则的话,NV的items发生改变会导致读写操作在发生错误或者产生错误的结果。

osal_nv_item_init()

初始化NV项目。此功能检查中的某个项目NV的存在。如果它不存在,则创建并用,传递给函数的数据。
该功能必须在调用osal_nv_read()或osal_nv_write()之前被调用。
函数原型

 uint8 osal_nv_item_init( uint16 id, uint16 len, void *buf );

参数
id:用户定义的item 的ID
len:item的字节长度
*buf:指针指向item初始化的数据。如果没有初始化,设置为NULL。
返回值
返回操作的结果

返回值描述
SUCCESS成功
NV_ITEM_UNINIT成功,但是item不存在
NV_OPER_FAILED操作失败

osal_nv_read()

阅读来自NV的数据。这个函数可用于通过索引入项目具有偏移来读取从NV整个项目或项目的一个元素。读取数据复制到* buf中。
函数原型

uint8 osal_nv_read( uint16 id, uint16 offset, uint16 len, void *buf );

参数
id:用户定义的item的id
offset:内存在item中字节偏移量
len:item的字节长度
*buf:数据会被读到buf中
返回值
返回操作的结果

返回值描述
SUCCESS成功
NV_OPER_FAILED操作失败

osal_nv_write()

将数据写入NV。这个函数可用于通过索引入项目具有偏移来写整个项NV或一个项目的一个元素。
函数原型

uint8 osal_nv_write( uint16 id, uint16 offset, uint16 len, void *buf );

参数
id:用户定义的item的id
offset:内存在item中字节偏移量
len:item的字节长度
*buf:需要被写的数据
返回值
返回操作的结果

返回值描述
SUCCESS成功
NV_ITEM_UNINITitem没有被初始化
NV_OPER_FAILED操作失败

osal_nv_delete()

从NV中删除某个item。此函数会检测NV的存在。如果items存在以及它的长度匹配的长度提供了功能的调用,该item就是从NV中删除。
函数类型

 uint8 osal_nv_delete( uint16 id, uint16 len );

参数
id:用户定义的item的id
len:item的字节长度
返回值
返回操作的结果

返回值描述
SUCCESS成功
NV_ITEM_UNINITitem没有被初始化
NV_BAD_ITEM_LEN不正确长度的参数
NV_OPER_FAILED操作失败

osal_nv_item_len()

获取NV项目的长度。如果有这个函数返回一个NV项目的长度,否则返回零。
函数原型

uint16 osal_nv_item_len( uint16 id );

参数
id: 用户定义的item的ID
返回值
返回操作的结果

返回值描述
0NV item没有被发现
1-NNV item的长度

osal_offsetof()

该宏计算存储器中的结构中的一个元素的字节偏移。它可以用于计算所使用的NV API函数的偏移参数。
函数原型

#define osal_offsetof(type, member) ((uint16) &(((type *) 0)->member))

参数
type :结构体类型
member:结构体的长度
返回值 NULL

简单的易挥发性内存的API

简介

本节介绍OSAL简单的非挥发性内存系统。像OSAL NV存储器系统,简单NV存储系统提供了一种方法,应用到持久存储信息到设备内存。另一方面,在OSAL NV存储器系统不同,简单NV存储器系统提供更简单的API来驱动应用程序代码大小和堆栈代码大小向下以及OSAL简单的NV系统实现的代码大小。用户可以读或写整个项目,但它不能部分读取或写入的项目。
就像NV存储器系统,每个NV项具有一个唯一的ID。有特定的ID值范围为应用程序,同时一些ID值预留或使用的栈或平台。如果你的应用程序创建自己的NV项目,它必须选择从应用程序的价值范围内的ID。请参阅下表:

VALUEUSER
0x00Reserved
0x01–0x6FReserved for ZigBee RF4CE network layer
0x70–0x7FReserved for ZigBee RF4CE application framework (RTI)
0x80 – 0xFEApplication
0xFF0xFF

注意事项
1.这些堵塞函数的调用以及一个操作可能需要数十毫秒才能完成。NV写操作尤其如此。所以,中断可能被禁止了几个毫秒。最好是在时间执行这些功能时,他们不与其他时序关键的操作发生冲突。举例,一个好的时间去写NV的items在接收器被关闭。
2.此外,这些函数不可以在中断服务程序中调用。
3.量少进行NV的写操作。它既花时间有耗功耗。所以说大多数的flash设备都有有限的擦写次数。
4如果NV的items有一个或者多个结构体发生改变,尤其是TI的软件的协议栈的版本更新到另一个,所以有必要擦除或者重新初始化NV内存。否则的话,NV的items发生改变会导致读写操作在发生错误或者产生错误的结果。

osal_snv_read()

读来自NV的数据。此功能可被用于读取来自NV整个item。读取的数据被复制到*pbuf。
函数原型

uint8 osal_snv_read( osalSnvId_t id, osalSnvLen_t len, void *pBuf )
{
  uint16 offset = findItem(activePg, pgOff, id);

  if (offset != 0)
  {
    HalFlashRead(activePg, offset, pBuf, len);
    return SUCCESS;
  }
  return NV_OPER_FAILED;
}

参数
id:用户定义的item的id
offset:内存在item中字节偏移量
len:item的字节长度
*buf:数据会被读到buf中
返回值
返回操作结果。

返回值描述
SUCCESS成功
NV_OPER_FAILED操作失败

osal_snv_write()

将数据写入NV。该功能可用于编写整个项目NV。
函数原型

uint8 osal_snv_write( osalSnvId_t id, osalSnvLen_t len, void *pBuf )
{
  uint16 alignedLen;

  {
    uint16 offset = findItem(activePg, pgOff, id);

    if (offset > 0)
    {
      uint8 tmp;
      osalSnvLen_t i;

      for (i = 0; i < len; i++)
      {
        HalFlashRead(activePg, offset, &tmp, 1);
        if (tmp != ((uint8 *)pBuf)[i])
        {
          break;
        }
        offset++;
      }

      if (i == len)
      {
        // Changed value is the same value as before.
        // Return here instead of re-writing the same value to NV.
        return SUCCESS;
      }
    }
  }

  alignedLen = ((len + OSAL_NV_WORD_SIZE - 1) / OSAL_NV_WORD_SIZE) * OSAL_NV_WORD_SIZE;

  if ( pgOff + alignedLen + OSAL_NV_WORD_SIZE > OSAL_NV_PAGE_SIZE )
  {
    setXferPage();
    compactPage(activePg);
  }

  // pBuf shall be referenced beyond its valid length to save code size.
  writeItem(activePg, pgOff, id, alignedLen, pBuf);
  if (failF)
  {
    return NV_OPER_FAILED;
  }

  pgOff += alignedLen + OSAL_NV_WORD_SIZE;

  return SUCCESS;
}

参数
id:用户定义的item的id
len:item的字节长度
*buf:需要被写的数据
返回值
返回操作结果。

返回值描述
SUCCESS成功
NV_OPER_FAILED操作失败

时钟管理

简介

本节介绍了OSAL时钟系统。该系统提供了一种方法,按照日期和时间的格式。该系统将保留的秒数,从秒2000年1月1日0时0分0秒。以下两种数据类型/结构被用于在该系统中(在OSAL_Clock.h定义):

// number of seconds since 0 hrs, 0 minutes, 0 seconds, on the 
// 1st of January 2000 UTC 
typedef uint32 UTCTime; 
// To be used with 
typedef struct 
{ 
uint8 seconds; // 0-59 
uint8 minutes; // 0-59 
uint8 hour; // 0-23 
uint8 day; // 0-30 
uint8 month; // 0-11 
uint16 year; // 2000+ 
} UTCTimeStruct; 

您必须启用OSAL_CLOCK编译器标志使用此功能。另外,此功能在睡眠状态不能够维持。

osalTimeUpdate()

更新系统时钟。
函数原型

void osalTimeUpdate( void )
{
  uint16 tmp;
  uint16 ticks625us;
  uint16 elapsedMSec = 0;

  // Get the free-running count of 625us timer ticks
  tmp = ll_McuPrecisionCount();

  if ( tmp != previousLLTimerTick )
  {
    // Calculate the elapsed ticks of the free-running timer.
    ticks625us = 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 ( ticks625us > 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
    if ( elapsedMSec )
    {
      osalClockUpdate( elapsedMSec );
      osalTimerUpdate( elapsedMSec );
    }
  }
}

参数 NULL
返回值 NULL

osal_setClock()

调用此函数初始化设备的时间。
函数原型

void osal_setClock( UTCTime newTime )
{
  OSAL_timeSeconds = newTime;
}

参数
newTime:从0小时0分0秒,于2000年1月1日UTC以秒为单位的新时间
返回值 NULL

osal_getClock()

调用此函数来获取设备的当前时间。
函数原型

UTCTime osal_getClock( void )
{
  return ( OSAL_timeSeconds );
}

参数 NULL
返回值
当前时间,以秒为单位自零小时,0分0秒,于2000年1月1日UTC。

osal_ConvertUTCTime()

调用此函数UTCTime转换为UTCTimeStruct。
函数原型

void osal_ConvertUTCTime( UTCTimeStruct *tm, UTCTime secTime )
{
  // calculate the time less than a day - hours, minutes, seconds
  {
    uint32 day = secTime % DAY;
    tm->seconds = day % 60UL;
    tm->minutes = (day % 3600UL) / 60UL;
    tm->hour = day / 3600UL;
  }

  // Fill in the calendar - day, month, year
  {
    uint16 numDays = secTime / DAY;
    tm->year = BEGYEAR;
    while ( numDays >= YearLength( tm->year ) )
    {
      numDays -= YearLength( tm->year );
      tm->year++;
    }

    tm->month = 0;
    while ( numDays >= monthLength( IsLeapYear( tm->year ), tm->month ) )
    {
      numDays -= monthLength( IsLeapYear( tm->year ), tm->month );
      tm->month++;
    }

    tm->day = numDays;
  }
}

参数
*tm:UTCTimeStruct结构体
secTime:UTCTime时间
返回值 NULL

osal_ConvertUTCSecs()

调用此函数UTCTimeStruct转换为UTCTime。
函数原型

UTCTime osal_ConvertUTCSecs( UTCTimeStruct *tm )
{
  uint32 seconds;

  /* Seconds for the partial day */
  seconds = (((tm->hour * 60UL) + tm->minutes) * 60UL) + tm->seconds;

  /* Account for previous complete days */
  {
    /* Start with complete days in current month */
    uint16 days = tm->day;

    /* Next, complete months in current year */
    {
      int8 month = tm->month;
      while ( --month >= 0 )
      {
        days += monthLength( IsLeapYear( tm->year ), month );
      }
    }

    /* Next, complete years before current year */
    {
      uint16 year = tm->year;
      while ( --year >= BEGYEAR )
      {
        days += YearLength( year );
      }
    }

    /* Add total seconds before partial day */
    seconds += (days * DAY);
  }

  return ( seconds );
}

参数
*tm :UTCTimeStruct的指针
返回值
返回UTCTime秒值。

其他

简介

本节介绍不适合以前的OSAL分类杂项OSAL功能

osal_rand()

此函数返回一个16位的随机数。
函数原型

uint16 osal_rand( void )
{
  return ( Onboard_rand() );
}

参数 NULL
返回值
返回一个随机数。

osal_memcmp()

比较内存部分。
函数原型

uint8 osal_memcmp( const void GENERIC *src1, const void GENERIC *src2, unsigned int len )
{
  const uint8 GENERIC *pSrc1;
  const uint8 GENERIC *pSrc2;

  pSrc1 = src1;
  pSrc2 = src2;

  while ( len-- )
  {
    if( *pSrc1++ != *pSrc2++ )
      return FALSE;
  }
  return TRUE;
}

参数
src1: 内存比较位置1。
src2 : 内存比较位置2。
len: 比较长度。
返回值
返回比较结果

返回值解析
TRUE相同
FALSE不同

osal_memset()

设置一个缓冲器为特定值。
函数原型

void *osal_memset( void *dest, uint8 value, int len )
{
  return memset( dest, value, len );
}

参数
*dest:内存地址
value : 设置的值
len:长度
返回值
返回设置到的停止的位置的地址。

osal_memcpy()

复制一个缓冲到另一个缓冲区。
函数原型

void *osal_memcpy( void *dst, const void GENERIC *src, unsigned int len )
{
  uint8 *pDst;
  const uint8 GENERIC *pSrc;

  pSrc = src;
  pDst = dst;

  while ( len-- )
    *pDst++ = *pSrc++;

  return ( pDst );
}

参数
dst - 目标缓冲区。
src - 原缓冲区。
len - 长度。
返回值
指针最终的目标缓冲区。

  • 3
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值