From d7f91ac9bb3a58377e41315a7a1060cd3f65e953 Mon Sep 17 00:00:00 2001 From: Jose Date: Sat, 22 Feb 2025 22:20:57 +0100 Subject: [PATCH] new file: include/OSAL.c new file: include/OSAL.h new file: include/ZComDef.h new file: include/i2c.h --- include/OSAL.c | 1821 +++++++++++++++++++++++++++++++++++++++++++++ include/OSAL.h | 361 +++++++++ include/ZComDef.h | 489 ++++++++++++ include/i2c.h | 181 +++++ 4 files changed, 2852 insertions(+) create mode 100644 include/OSAL.c create mode 100644 include/OSAL.h create mode 100644 include/ZComDef.h create mode 100644 include/i2c.h diff --git a/include/OSAL.c b/include/OSAL.c new file mode 100644 index 0000000..353a756 --- /dev/null +++ b/include/OSAL.c @@ -0,0 +1,1821 @@ +/************************************************************************************************** + Filename: OSAL.c + Revised: $Date: 2014-11-04 15:36:27 -0800 (Tue, 04 Nov 2014) $ + Revision: $Revision: 40989 $ + + Description: This API allows the software components in the Z-stack to be written + independently of the specifics of the operating system, kernel or tasking + environment (including control loops or connect-to-interrupt systems). + + + Copyright 2004-2014 Texas Instruments Incorporated. All rights reserved. + + IMPORTANT: Your use of this Software is limited to those specific rights + granted under the terms of a software license agreement between the user + who downloaded the software, his/her employer (which must be your employer) + and Texas Instruments Incorporated (the "License"). You may not use this + Software unless you agree to abide by the terms of the License. The License + limits your use, and you acknowledge, that the Software may not be modified, + copied or distributed unless embedded on a Texas Instruments microcontroller + or used solely and exclusively in conjunction with a Texas Instruments radio + frequency transceiver, which is integrated into your product. Other than for + the foregoing purpose, you may not use, reproduce, copy, prepare derivative + works of, modify, distribute, perform, display or sell this Software and/or + its documentation for any purpose. + + YOU FURTHER ACKNOWLEDGE AND AGREE THAT THE SOFTWARE AND DOCUMENTATION ARE + PROVIDED “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, + INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY, TITLE, + NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL + TEXAS INSTRUMENTS OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER CONTRACT, + NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR OTHER + LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES + INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE + OR CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT + OF SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES + (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS. + + Should you have any questions regarding your right to use this Software, + contact Texas Instruments Incorporated at www.TI.com. +**************************************************************************************************/ + +/********************************************************************* + * INCLUDES + */ + +#include + +#include "comdef.h" +#include "hal_board.h" +#include "OSAL.h" +#include "OSAL_Tasks.h" +#include "OSAL_Memory.h" +#include "OSAL_PwrMgr.h" +#include "OSAL_Clock.h" + +#include "OnBoard.h" + +/* HAL */ +#include "hal_drivers.h" + +#ifdef IAR_ARMCM3_LM + #include "FreeRTOSConfig.h" + #include "osal_task.h" +#endif + +#ifdef USE_ICALL + #include +#endif /* USE_ICALL */ + +/********************************************************************* + * MACROS + */ + +/********************************************************************* + * CONSTANTS + */ +#ifdef USE_ICALL +// A bit mask to use to indicate a proxy OSAL task ID. +#define OSAL_PROXY_ID_FLAG 0x80 +#endif // USE_ICALL + +/********************************************************************* + * TYPEDEFS + */ + +/********************************************************************* + * GLOBAL VARIABLES + */ + +// Message Pool Definitions +osal_msg_q_t osal_qHead; + +#ifdef USE_ICALL +// OSAL event loop hook function pointer +void (*osal_eventloop_hook)(void) = NULL; +#endif /* USE_ICALL */ + +/********************************************************************* + * EXTERNAL VARIABLES + */ + +/********************************************************************* + * EXTERNAL FUNCTIONS + */ + +/********************************************************************* + * LOCAL VARIABLES + */ + +// Index of active task +static uint8 activeTaskID = TASK_NO_TASK; + +#ifdef USE_ICALL +// Maximum number of proxy tasks +#ifndef OSAL_MAX_NUM_PROXY_TASKS +#define OSAL_MAX_NUM_PROXY_TASKS 2 +#endif // OSAL_MAX_NUM_PROXY_TASKS + +// ICall entity ID value used to indicate invalid value +#define OSAL_INVALID_DISPATCH_ID 0xffu + +// Semaphore associated with OSAL RTOS thread receive queue +ICall_Semaphore osal_semaphore; + +// Entity ID that OSAL RTOS thread has registered with +ICall_EntityID osal_entity; + +// Last read tick count value reflected into the OSAL timer +uint_least32_t osal_last_timestamp; + +// RTOS tick period in microseconds +uint_least32_t osal_tickperiod; + +// Maximum timeout value in milliseconds that can be used with an RTOS timer +uint_least32_t osal_max_msecs; + +// Timer ID for RTOS timer as backend engine for OSAL timer +static ICall_TimerID osal_timerid_msec_timer; + +// Timer callback sequence tracking counter to handle race condition +static unsigned osal_msec_timer_seq = 0; + +// proxy task ID map +static uint8 osal_proxy_tasks[OSAL_MAX_NUM_PROXY_TASKS]; + +// service dispatcher entity IDs corresponding to OSAL tasks +static uint8 *osal_dispatch_entities; + +static uint8 osal_notask_entity; + +#endif // USE_ICALL + +/********************************************************************* + * LOCAL FUNCTION PROTOTYPES + */ + +static uint8 osal_msg_enqueue_push( uint8 destination_task, uint8 *msg_ptr, uint8 urgent ); + +#ifdef USE_ICALL +static uint8 osal_alien2proxy(ICall_EntityID entity); +static ICall_EntityID osal_proxy2alien(uint8 proxyid); +static uint8 osal_dispatch2id(ICall_EntityID entity); +static void osal_msec_timer_cback(void *arg); +#endif // USE_ICALL + +/********************************************************************* + * HELPER FUNCTIONS + */ +/* very ugly stub so Keil can compile */ +#ifdef __KEIL__ +char * itoa ( int value, char * buffer, int radix ) +{ + return(buffer); +} +#endif + +/********************************************************************* + * @fn osal_strlen + * + * @brief + * + * Calculates the length of a string. The string must be null + * terminated. + * + * @param char *pString - pointer to text string + * + * @return int - number of characters + */ +int osal_strlen( char *pString ) +{ + return (int)( strlen( pString ) ); +} + +/********************************************************************* + * @fn osal_memcpy + * + * @brief + * + * Generic memory copy. + * + * Note: This function differs from the standard memcpy(), since + * it returns the pointer to the next destination uint8. The + * standard memcpy() returns the original destination address. + * + * @param dst - destination address + * @param src - source address + * @param len - number of bytes to copy + * + * @return pointer to end of destination buffer + */ +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 ); +} + +/********************************************************************* + * @fn osal_revmemcpy + * + * @brief Generic reverse memory copy. Starts at the end of the + * source buffer, by taking the source address pointer and moving + * pointer ahead "len" bytes, then decrementing the pointer. + * + * Note: This function differs from the standard memcpy(), since + * it returns the pointer to the next destination uint8. The + * standard memcpy() returns the original destination address. + * + * @param dst - destination address + * @param src - source address + * @param len - number of bytes to copy + * + * @return pointer to end of destination buffer + */ +void *osal_revmemcpy( void *dst, const void GENERIC *src, unsigned int len ) +{ + uint8 *pDst; + const uint8 GENERIC *pSrc; + + pSrc = src; + pSrc += (len-1); + pDst = dst; + + while ( len-- ) + *pDst++ = *pSrc--; + + return ( pDst ); +} + +/********************************************************************* + * @fn osal_memdup + * + * @brief Allocates a buffer [with osal_mem_alloc()] and copies + * the src buffer into the newly allocated space. + * + * @param src - source address + * @param len - number of bytes to copy + * + * @return pointer to the new allocated buffer, or NULL if + * allocation problem. + */ +void *osal_memdup( const void GENERIC *src, unsigned int len ) +{ + uint8 *pDst; + + pDst = osal_mem_alloc( len ); + if ( pDst ) + { + VOID osal_memcpy( pDst, src, len ); + } + + return ( (void *)pDst ); +} + +/********************************************************************* + * @fn osal_memcmp + * + * @brief + * + * Generic memory compare. + * + * @param src1 - source 1 addrexx + * @param src2 - source 2 address + * @param len - number of bytes to compare + * + * @return TRUE - same, FALSE - different + */ +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; +} + + +/********************************************************************* + * @fn osal_memset + * + * @brief + * + * Set memory buffer to value. + * + * @param dest - pointer to buffer + * @param value - what to set each uint8 of the message + * @param size - how big + * + * @return pointer to destination buffer + */ +void *osal_memset( void *dest, uint8 value, int len ) +{ + return memset( dest, value, len ); +} + +/********************************************************************* + * @fn osal_build_uint16 + * + * @brief + * + * Build a uint16 out of 2 bytes (0 then 1). + * + * @param swapped - 0 then 1 + * + * @return uint16 + */ +uint16 osal_build_uint16( uint8 *swapped ) +{ + return ( BUILD_UINT16( swapped[0], swapped[1] ) ); +} + +/********************************************************************* + * @fn osal_build_uint32 + * + * @brief + * + * Build a uint32 out of sequential bytes. + * + * @param swapped - sequential bytes + * @param len - number of bytes in the uint8 array + * + * @return uint32 + */ +uint32 osal_build_uint32( uint8 *swapped, uint8 len ) +{ + if ( len == 2 ) + return ( BUILD_UINT32( swapped[0], swapped[1], 0L, 0L ) ); + else if ( len == 3 ) + return ( BUILD_UINT32( swapped[0], swapped[1], swapped[2], 0L ) ); + else if ( len == 4 ) + return ( BUILD_UINT32( swapped[0], swapped[1], swapped[2], swapped[3] ) ); + else + return ( (uint32)swapped[0] ); +} + +#if !defined ( ZBIT ) && !defined ( ZBIT2 ) && !defined (UBIT) +/********************************************************************* + * @fn _ltoa + * + * @brief + * + * convert a long unsigned int to a string. + * + * @param l - long to convert + * @param buf - buffer to convert to + * @param radix - 10 dec, 16 hex + * + * @return pointer to buffer + */ +unsigned char * _ltoa(unsigned long l, unsigned char *buf, unsigned char radix) +{ +#if defined (__TI_COMPILER_VERSION) + return ( (unsigned char*)ltoa( l, (char *)buf ) ); +#elif defined( __GNUC__ ) + return ( (char*)ltoa( l, buf, radix ) ); +#else + unsigned char tmp1[10] = "", tmp2[10] = "", tmp3[10] = ""; + unsigned short num1, num2, num3; + unsigned char i; + + buf[0] = '\0'; + + if ( radix == 10 ) + { + num1 = l % 10000; + num2 = (l / 10000) % 10000; + num3 = (unsigned short)(l / 100000000); + + if (num3) _itoa(num3, tmp3, 10); + if (num2) _itoa(num2, tmp2, 10); + if (num1) _itoa(num1, tmp1, 10); + + if (num3) + { + strcpy((char*)buf, (char const*)tmp3); + for (i = 0; i < 4 - strlen((char const*)tmp2); i++) + strcat((char*)buf, "0"); + } + strcat((char*)buf, (char const*)tmp2); + if (num3 || num2) + { + for (i = 0; i < 4 - strlen((char const*)tmp1); i++) + strcat((char*)buf, "0"); + } + strcat((char*)buf, (char const*)tmp1); + if (!num3 && !num2 && !num1) + strcpy((char*)buf, "0"); + } + else if ( radix == 16 ) + { + num1 = l & 0x0000FFFF; + num2 = l >> 16; + + if (num2) _itoa(num2, tmp2, 16); + if (num1) _itoa(num1, tmp1, 16); + + if (num2) + { + strcpy((char*)buf,(char const*)tmp2); + for (i = 0; i < 4 - strlen((char const*)tmp1); i++) + strcat((char*)buf, "0"); + } + strcat((char*)buf, (char const*)tmp1); + if (!num2 && !num1) + strcpy((char*)buf, "0"); + } + else + return NULL; + + return buf; +#endif +} +#endif // !defined(ZBIT) && !defined(ZBIT2) + +/********************************************************************* + * @fn osal_rand + * + * @brief Random number generator + * + * @param none + * + * @return uint16 - new random number + */ +uint16 osal_rand( void ) +{ + return ( Onboard_rand() ); +} + +/********************************************************************* + * API FUNCTIONS + *********************************************************************/ + +#ifdef USE_ICALL +/********************************************************************* + * @fn osal_prepare_svc_enroll + * + * @brief Initialize data structures that map OSAL task ids to + * ICall entity ids. + * + * @param none + * + * @return none + */ +static void osal_prepare_svc_enroll(void) +{ + osal_dispatch_entities = (uint8 *) osal_mem_alloc(tasksCnt * 2); + osal_memset(osal_dispatch_entities, OSAL_INVALID_DISPATCH_ID, tasksCnt * 2); + osal_memset(osal_proxy_tasks, OSAL_INVALID_DISPATCH_ID, + OSAL_MAX_NUM_PROXY_TASKS); +} + +/********************************************************************* + * @fn osal_enroll_dispatchid + * + * @brief Map a task id to an ICall entity id for messaging in + * both directions (sending and receiving). + * + * @param taskid OSAL task id + * @param dispatchid ICall entity id + * + * @return none + */ +void osal_enroll_dispatchid(uint8 taskid, ICall_EntityID dispatchid) +{ + osal_dispatch_entities[taskid] = dispatchid; + osal_dispatch_entities[tasksCnt + taskid] = dispatchid; +} + +/********************************************************************* + * @fn osal_enroll_senderid + * + * @brief Map a task id to an ICall entity id, which shall be used + * just for sending a message from an OSAL task. + * Note that osal_enroll_dispatchid() must never be called + * with the same OSAL task id used in this function call. + * However, it is OK to call osal_enroll_dispatchid() + * with the same ICall entity id and a different OSAL task id. + * + * @param taskid OSAL task id + * @param dispatchid ICall entity id + * + * @return none + */ +void osal_enroll_senderid(uint8 taskid, ICall_EntityID dispatchid) +{ + osal_dispatch_entities[tasksCnt + taskid] = dispatchid; +} + +/********************************************************************* + * @fn osal_enroll_notasksender + * + * @brief Map no task id to an ICall entity id, which shall be used + * just for sending a message from non-OSAL task. + * + * @param dispatchid ICall entity id + * + * @return none + */ +void osal_enroll_notasksender(ICall_EntityID dispatchid) +{ + osal_notask_entity = dispatchid; +} +#endif /* USE_ICALL */ + +/********************************************************************* + * @fn osal_msg_allocate + * + * @brief + * + * This function is called by a task to allocate a message buffer + * into which the task will encode the particular message it wishes + * to send. This common buffer scheme is used to strictly limit the + * creation of message buffers within the system due to RAM size + * limitations on the microprocessor. Note that all message buffers + * are a fixed size (at least initially). The parameter len is kept + * in case a message pool with varying fixed message sizes is later + * created (for example, a pool of message buffers of size LARGE, + * MEDIUM and SMALL could be maintained and allocated based on request + * from the tasks). + * + * + * @param uint8 len - wanted buffer length + * + * + * @return pointer to allocated buffer or NULL if allocation failed. + */ +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 ); +} + +/********************************************************************* + * @fn osal_msg_deallocate + * + * @brief + * + * This function is used to deallocate a message buffer. This function + * is called by a task (or processing element) after it has finished + * processing a received message. + * + * + * @param uint8 *msg_ptr - pointer to new message buffer + * + * @return SUCCESS, INVALID_MSG_POINTER + */ +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 ); +} + +/********************************************************************* + * @fn osal_msg_send + * + * @brief + * + * This function is called by a task to send a command message to + * another task or processing element. The sending_task field must + * refer to a valid task, since the task ID will be used + * for the response message. This function will also set a message + * ready event in the destination tasks event list. + * + * + * @param uint8 destination_task - Send msg to Task ID + * @param uint8 *msg_ptr - pointer to new message buffer + * + * @return SUCCESS, INVALID_TASK, INVALID_MSG_POINTER + */ +uint8 osal_msg_send( uint8 destination_task, uint8 *msg_ptr ) +{ +#ifdef USE_ICALL + if (destination_task & OSAL_PROXY_ID_FLAG) + { + /* Destination is a proxy task */ + osal_msg_hdr_t *hdr = (osal_msg_hdr_t *)msg_ptr - 1; + ICall_EntityID src, dst; + + uint8 taskid = osal_self(); + if (taskid == TASK_NO_TASK) + { + /* Call must have been made from either an ISR or a user-thread */ + src = osal_notask_entity; + } + else + { + src = (ICall_EntityID) osal_dispatch_entities[taskid + tasksCnt]; + } + if (src == OSAL_INVALID_DISPATCH_ID) + { + /* The source entity is not registered */ + /* abort */ + ICall_abort(); + return FAILURE; + } + dst = osal_proxy2alien(destination_task); + hdr->dest_id = TASK_NO_TASK; + if (ICall_send(src, dst, ICALL_MSG_FORMAT_KEEP, msg_ptr) == + ICALL_ERRNO_SUCCESS) + { + return SUCCESS; + } + osal_msg_deallocate(msg_ptr); + return FAILURE; + } +#endif /* USE_ICALL */ + return ( osal_msg_enqueue_push( destination_task, msg_ptr, FALSE ) ); +} + +/********************************************************************* + * @fn osal_msg_push_front + * + * @brief + * + * This function is called by a task to push a command message + * to the head of the OSAL queue. The destination_task field + * must refer to a valid task, since the task ID will be used to + * send the message to. This function will also set a message + * ready event in the destination task's event list. + * + * @param uint8 destination_task - Send msg to Task ID + * @param uint8 *msg_ptr - pointer to message buffer + * + * @return SUCCESS, INVALID_TASK, INVALID_MSG_POINTER + */ +uint8 osal_msg_push_front( uint8 destination_task, uint8 *msg_ptr ) +{ + return ( osal_msg_enqueue_push( destination_task, msg_ptr, TRUE ) ); +} + +/********************************************************************* + * @fn osal_msg_enqueue_push + * + * @brief + * + * This function is called by a task to either enqueue (append to + * queue) or push (prepend to queue) a command message to the OSAL + * queue. The destination_task field must refer to a valid task, + * since the task ID will be used to send the message to. This + * function will also set a message ready event in the destination + * task's event list. + * + * @param uint8 destination_task - Send msg to Task ID + * @param uint8 *msg_ptr - pointer to message buffer + * @param uint8 push - TRUE to push, otherwise enqueue + * + * @return SUCCESS, INVALID_TASK, INVALID_MSG_POINTER + */ +static uint8 osal_msg_enqueue_push( uint8 destination_task, uint8 *msg_ptr, uint8 push ) +{ + if ( msg_ptr == NULL ) + { + return ( INVALID_MSG_POINTER ); + } + +#ifdef USE_ICALL + if (destination_task & OSAL_PROXY_ID_FLAG) + { + ICall_abort(); + } +#endif /* USE_ICALL */ + + if ( destination_task >= tasksCnt ) + { + osal_msg_deallocate( msg_ptr ); + return ( INVALID_TASK ); + } + + // Check the message header + if ( OSAL_MSG_NEXT( msg_ptr ) != NULL || + OSAL_MSG_ID( msg_ptr ) != TASK_NO_TASK ) + { + osal_msg_deallocate( msg_ptr ); + return ( INVALID_MSG_POINTER ); + } + + OSAL_MSG_ID( msg_ptr ) = destination_task; + + if ( push == TRUE ) + { + // prepend the message + osal_msg_push( &osal_qHead, msg_ptr ); + } + else + { + // append the message + osal_msg_enqueue( &osal_qHead, msg_ptr ); + } + + // Signal the task that a message is waiting + osal_set_event( destination_task, SYS_EVENT_MSG ); + + return ( SUCCESS ); +} + +/********************************************************************* + * @fn osal_msg_receive + * + * @brief + * + * This function is called by a task to retrieve a received command + * message. The calling task must deallocate the message buffer after + * processing the message using the osal_msg_deallocate() call. + * + * @param uint8 task_id - receiving tasks ID + * + * @return *uint8 - message information or NULL if no message + */ +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 ); +} + +/************************************************************************************************** + * @fn osal_msg_find + * + * @brief This function finds in place an OSAL message matching the task_id and event + * parameters. + * + * input parameters + * + * @param task_id - The OSAL task id that the enqueued OSAL message must match. + * @param event - The OSAL event id that the enqueued OSAL message must match. + * + * output parameters + * + * None. + * + * @return NULL if no match, otherwise an in place pointer to the matching OSAL message. + ************************************************************************************************** + */ +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; +} + +/************************************************************************************************** + * @fn osal_msg_count + * + * @brief This function counts the number of messages, in the OSAL message queue with a + * a given task ID and message event type. + * + * input parameters + * + * @param task_id - The OSAL task id that the enqueued OSAL message must match. + * @param event - The OSAL event id that the enqueued OSAL message must match. 0xFF for + * all events. + * + * output parameters + * + * None. + * + * @return The number of OSAL messages that match the task ID and Event. + ************************************************************************************************** + */ +uint8 osal_msg_count( uint8 task_id, uint8 event ) +{ + uint8 count = 0; + 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) + && ((event == 0xFF) || (((osal_event_hdr_t *)pHdr)->event == event)) ) + { + count++; + } + + pHdr = OSAL_MSG_NEXT(pHdr); + } + + HAL_EXIT_CRITICAL_SECTION(intState); // Release interrupts. + + return ( count ); +} + +/********************************************************************* + * @fn osal_msg_enqueue + * + * @brief + * + * This function enqueues an OSAL message into an OSAL queue. + * + * @param osal_msg_q_t *q_ptr - OSAL queue + * @param void *msg_ptr - OSAL message + * + * @return none + */ +void osal_msg_enqueue( osal_msg_q_t *q_ptr, void *msg_ptr ) +{ + void *list; + halIntState_t intState; + + // Hold off interrupts + HAL_ENTER_CRITICAL_SECTION(intState); + + OSAL_MSG_NEXT( msg_ptr ) = NULL; + // If first message in queue + if ( *q_ptr == NULL ) + { + *q_ptr = msg_ptr; + } + else + { + // Find end of queue + for ( list = *q_ptr; OSAL_MSG_NEXT( list ) != NULL; list = OSAL_MSG_NEXT( list ) ); + + // Add message to end of queue + OSAL_MSG_NEXT( list ) = msg_ptr; + } + + // Re-enable interrupts + HAL_EXIT_CRITICAL_SECTION(intState); +} + +/********************************************************************* + * @fn osal_msg_dequeue + * + * @brief + * + * This function dequeues an OSAL message from an OSAL queue. + * + * @param osal_msg_q_t *q_ptr - OSAL queue + * + * @return void * - pointer to OSAL message or NULL of queue is empty. + */ +void *osal_msg_dequeue( osal_msg_q_t *q_ptr ) +{ + void *msg_ptr = NULL; + halIntState_t intState; + + // Hold off interrupts + HAL_ENTER_CRITICAL_SECTION(intState); + + if ( *q_ptr != NULL ) + { + // Dequeue message + msg_ptr = *q_ptr; + *q_ptr = OSAL_MSG_NEXT( msg_ptr ); + OSAL_MSG_NEXT( msg_ptr ) = NULL; + OSAL_MSG_ID( msg_ptr ) = TASK_NO_TASK; + } + + // Re-enable interrupts + HAL_EXIT_CRITICAL_SECTION(intState); + + return msg_ptr; +} + +/********************************************************************* + * @fn osal_msg_push + * + * @brief + * + * This function pushes an OSAL message to the head of an OSAL + * queue. + * + * @param osal_msg_q_t *q_ptr - OSAL queue + * @param void *msg_ptr - OSAL message + * + * @return none + */ +void osal_msg_push( osal_msg_q_t *q_ptr, void *msg_ptr ) +{ + halIntState_t intState; + + // Hold off interrupts + HAL_ENTER_CRITICAL_SECTION(intState); + + // Push message to head of queue + OSAL_MSG_NEXT( msg_ptr ) = *q_ptr; + *q_ptr = msg_ptr; + + // Re-enable interrupts + HAL_EXIT_CRITICAL_SECTION(intState); +} + +/********************************************************************* + * @fn osal_msg_extract + * + * @brief + * + * This function extracts and removes an OSAL message from the + * middle of an OSAL queue. + * + * @param osal_msg_q_t *q_ptr - OSAL queue + * @param void *msg_ptr - OSAL message to be extracted + * @param void *prev_ptr - OSAL message before msg_ptr in queue + * + * @return none + */ +void osal_msg_extract( osal_msg_q_t *q_ptr, void *msg_ptr, void *prev_ptr ) +{ + halIntState_t intState; + + // Hold off interrupts + HAL_ENTER_CRITICAL_SECTION(intState); + + if ( msg_ptr == *q_ptr ) + { + // remove from first + *q_ptr = OSAL_MSG_NEXT( msg_ptr ); + } + else + { + // remove from middle + OSAL_MSG_NEXT( prev_ptr ) = OSAL_MSG_NEXT( msg_ptr ); + } + OSAL_MSG_NEXT( msg_ptr ) = NULL; + OSAL_MSG_ID( msg_ptr ) = TASK_NO_TASK; + + // Re-enable interrupts + HAL_EXIT_CRITICAL_SECTION(intState); +} + +/********************************************************************* + * @fn osal_msg_enqueue_max + * + * @brief + * + * This function enqueues an OSAL message into an OSAL queue if + * the length of the queue is less than max. + * + * @param osal_msg_q_t *q_ptr - OSAL queue + * @param void *msg_ptr - OSAL message + * @param uint8 max - maximum length of queue + * + * @return TRUE if message was enqueued, FALSE otherwise + */ +uint8 osal_msg_enqueue_max( osal_msg_q_t *q_ptr, void *msg_ptr, uint8 max ) +{ + void *list; + uint8 ret = FALSE; + halIntState_t intState; + + // Hold off interrupts + HAL_ENTER_CRITICAL_SECTION(intState); + + // If first message in queue + if ( *q_ptr == NULL ) + { + *q_ptr = msg_ptr; + ret = TRUE; + } + else + { + // Find end of queue or max + list = *q_ptr; + max--; + while ( (OSAL_MSG_NEXT( list ) != NULL) && (max > 0) ) + { + list = OSAL_MSG_NEXT( list ); + max--; + } + + // Add message to end of queue if max not reached + if ( max != 0 ) + { + OSAL_MSG_NEXT( list ) = msg_ptr; + ret = TRUE; + } + } + + // Re-enable interrupts + HAL_EXIT_CRITICAL_SECTION(intState); + + return ret; +} + +/********************************************************************* + * @fn osal_set_event + * + * @brief + * + * This function is called to set the event flags for a task. The + * event passed in is OR'd into the task's event variable. + * + * @param uint8 task_id - receiving tasks ID + * @param uint8 event_flag - what event to set + * + * @return SUCCESS, MSG_BUFFER_NOT_AVAIL, FAILURE, INVALID_TASK + */ +#ifdef OSAL_PORT2TIRTOS +uint8 osal_set_event_raw( uint8 task_id, uint16 event_flag ) +#else /* OSAL_PORT2TIRTOS */ +uint8 osal_set_event( uint8 task_id, uint16 event_flag ) +#endif /* OSAL_PORT2TIRTOS */ +{ +#ifdef USE_ICALL + if (task_id & OSAL_PROXY_ID_FLAG) + { + /* Destination is a proxy task */ + osal_msg_hdr_t *hdr; + ICall_EntityID src, dst; + uint8 taskid; + + struct _osal_event_msg_t + { + uint16 signature; + uint16 event_flag; + } *msg_ptr = (struct _osal_event_msg_t *) + osal_msg_allocate(sizeof(*msg_ptr)); + + if (!msg_ptr) + { + return MSG_BUFFER_NOT_AVAIL; + } + msg_ptr->signature = 0xffffu; + msg_ptr->event_flag = event_flag; + hdr = (osal_msg_hdr_t *)msg_ptr - 1; + + taskid = osal_self(); + if (taskid == TASK_NO_TASK) + { + /* Call must have been made from either an ISR or a user-thread */ + src = osal_notask_entity; + } + else + { + src = (ICall_EntityID) osal_dispatch_entities[taskid + tasksCnt]; + } + + if (src == OSAL_INVALID_DISPATCH_ID) + { + /* The source entity is not registered */ + osal_msg_deallocate((uint8 *) msg_ptr); + ICall_abort(); + return FAILURE; + } + dst = osal_proxy2alien(task_id); + hdr->dest_id = TASK_NO_TASK; + if (ICall_send(src, dst, + ICALL_MSG_FORMAT_KEEP, msg_ptr) == + ICALL_ERRNO_SUCCESS) + { + return SUCCESS; + } + osal_msg_deallocate((uint8 *) msg_ptr); + return FAILURE; + } +#endif /* USE_ICALL */ + + 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 +#ifdef USE_ICALL + ICall_signal(osal_semaphore); +#endif /* USE_ICALL */ + return ( SUCCESS ); + } + else + { + return ( INVALID_TASK ); + } +} + +/********************************************************************* + * @fn osal_clear_event + * + * @brief + * + * This function is called to clear the event flags for a task. The + * event passed in is masked out of the task's event variable. + * + * @param uint8 task_id - receiving tasks ID + * @param uint8 event_flag - what event to clear + * + * @return SUCCESS, INVALID_TASK + */ +uint8 osal_clear_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); // Clear the event bit(s) + HAL_EXIT_CRITICAL_SECTION(intState); // Release interrupts + return ( SUCCESS ); + } + else + { + return ( INVALID_TASK ); + } +} + +/********************************************************************* + * @fn osal_isr_register + * + * @brief + * + * This function is called to register a service routine with an + * interrupt. When the interrupt occurs, this service routine is called. + * + * @param uint8 interrupt_id - Interrupt number + * @param void (*isr_ptr)( uint8* ) - function pointer to ISR + * + * @return SUCCESS, INVALID_INTERRUPT_ID, + */ +uint8 osal_isr_register( uint8 interrupt_id, void (*isr_ptr)( uint8* ) ) +{ + // Remove these statements when functionality is complete + (void)interrupt_id; + (void)isr_ptr; + return ( SUCCESS ); +} + +/********************************************************************* + * @fn osal_int_enable + * + * @brief + * + * This function is called to enable an interrupt. Once enabled, + * occurrence of the interrupt causes the service routine associated + * with that interrupt to be called. + * + * If INTS_ALL is the interrupt_id, interrupts (in general) are enabled. + * If a single interrupt is passed in, then interrupts still have + * to be enabled with another call to INTS_ALL. + * + * @param uint8 interrupt_id - Interrupt number + * + * @return SUCCESS or INVALID_INTERRUPT_ID + */ +uint8 osal_int_enable( uint8 interrupt_id ) +{ + + if ( interrupt_id == INTS_ALL ) + { + HAL_ENABLE_INTERRUPTS(); + return ( SUCCESS ); + } + else + { + return ( INVALID_INTERRUPT_ID ); + } +} + +/********************************************************************* + * @fn osal_int_disable + * + * @brief + * + * This function is called to disable an interrupt. When a disabled + * interrupt occurs, the service routine associated with that + * interrupt is not called. + * + * If INTS_ALL is the interrupt_id, interrupts (in general) are disabled. + * If a single interrupt is passed in, then just that interrupt is disabled. + * + * @param uint8 interrupt_id - Interrupt number + * + * @return SUCCESS or INVALID_INTERRUPT_ID + */ +uint8 osal_int_disable( uint8 interrupt_id ) +{ + + if ( interrupt_id == INTS_ALL ) + { + HAL_DISABLE_INTERRUPTS(); + return ( SUCCESS ); + } + else + { + return ( INVALID_INTERRUPT_ID ); + } +} + +/********************************************************************* + * @fn osal_init_system + * + * @brief + * + * This function initializes the "task" system by creating the + * tasks defined in the task table (OSAL_Tasks.h). + * + * @param void + * + * @return SUCCESS + */ +uint8 osal_init_system( void ) +{ +#if !defined USE_ICALL && !defined OSAL_PORT2TIRTOS + // Initialize the Memory Allocation System + osal_mem_init(); +#endif /* !defined USE_ICALL && !defined OSAL_PORT2TIRTOS */ + + // Initialize the message queue + osal_qHead = NULL; + + // Initialize the timers + osalTimerInit(); + + // Initialize the Power Management System + osal_pwrmgr_init(); + +#ifdef USE_ICALL + /* Prepare memory space for service enrollment */ + osal_prepare_svc_enroll(); +#endif /* USE_ICALL */ + + // Initialize the system tasks. + osalInitTasks(); + +#if !defined USE_ICALL && !defined OSAL_PORT2TIRTOS + // Setup efficient search for the first free block of heap. + osal_mem_kick(); +#endif /* !defined USE_ICALL && !defined OSAL_PORT2TIRTOS */ + +#ifdef USE_ICALL + // Initialize variables used to track timing and provide OSAL timer service + osal_last_timestamp = (uint_least32_t) ICall_getTicks(); + osal_tickperiod = (uint_least32_t) ICall_getTickPeriod(); + osal_max_msecs = (uint_least32_t) ICall_getMaxMSecs(); + /* Reduce ceiling considering potential latency */ + osal_max_msecs -= 2; +#endif /* USE_ICALL */ + + return ( SUCCESS ); +} + +/********************************************************************* + * @fn osal_start_system + * + * @brief + * + * This function is the main loop function of the task system (if + * ZBIT and UBIT are not defined). This Function doesn't return. + * + * @param void + * + * @return none + */ +void osal_start_system( void ) +{ +#ifdef USE_ICALL + /* Kick off timer service in order to allocate resources upfront. + * The first timeout is required to schedule next OSAL timer event + * as well. */ + ICall_Errno errno = ICall_setTimer(1, osal_msec_timer_cback, + (void *) osal_msec_timer_seq, + &osal_timerid_msec_timer); + if (errno != ICALL_ERRNO_SUCCESS) + { + ICall_abort(); + } +#endif /* USE_ICALL */ + +#if !defined ( ZBIT ) && !defined ( UBIT ) + for(;;) // Forever Loop +#endif + { + osal_run_system(); + +#ifdef USE_ICALL + ICall_wait(ICALL_TIMEOUT_FOREVER); +#endif /* USE_ICALL */ + } +} + +#ifdef USE_ICALL +/********************************************************************* + * @fn osal_alien2proxy + * + * @brief + * + * Assign or retrieve a proxy OSAL task id for an external ICall entity. + * + * @param origid ICall entity id + * + * @return proxy OSAL task id + */ +static uint8 osal_alien2proxy(ICall_EntityID origid) +{ + size_t i; + + for (i = 0; i < OSAL_MAX_NUM_PROXY_TASKS; i++) + { + if (osal_proxy_tasks[i] == OSAL_INVALID_DISPATCH_ID) + { + /* proxy not found. Create a new one */ + osal_proxy_tasks[i] = (uint8) origid; + return (OSAL_PROXY_ID_FLAG | i); + } + else if ((ICall_EntityID) osal_proxy_tasks[i] == origid) + { + return (OSAL_PROXY_ID_FLAG | i); + } + } + /* abort */ + ICall_abort(); + return TASK_NO_TASK; +} + +/********************************************************************* + * @fn osal_proxy2alien + * + * @brief + * + * Retrieve the ICall entity id for a proxy OSAL task id + * + * @param proxyid Proxy OSAL task id + * + * @return ICall entity id + */ +static ICall_EntityID osal_proxy2alien(uint8 proxyid) +{ + proxyid ^= OSAL_PROXY_ID_FLAG; + if (proxyid >= OSAL_MAX_NUM_PROXY_TASKS) + { + /* abort */ + ICall_abort(); + } + return (ICall_EntityID) osal_proxy_tasks[proxyid]; +} + +/********************************************************************* + * @fn osal_dispatch2id + * + * @brief + * + * Retrieve OSAL task id mapped to a designated ICall entity id + * + * @param entity ICall entity id + * + * @return OSAL task id + */ +static uint8 osal_dispatch2id(ICall_EntityID entity) +{ + size_t i; + + for (i = 0; i < tasksCnt; i++) + { + if ((ICall_EntityID) osal_dispatch_entities[i] == entity) + { + return i; + } + } + return TASK_NO_TASK; +} + +/********************************************************************* + * @fn osal_msec_timer_cback + * + * @brief + * + * This function is a callback function for ICall_setTimer() service + * used to implement OSAL timer + * + * @param arg In this case, the timer sequence number is passed. + * + * @return None + */ +static void osal_msec_timer_cback(void *arg) +{ + unsigned seq = (unsigned) arg; + halIntState_t intState; + + HAL_ENTER_CRITICAL_SECTION(intState); + if (seq == osal_msec_timer_seq) + { + ICall_signal(osal_semaphore); + } + HAL_EXIT_CRITICAL_SECTION(intState); +} + +/********************************************************************* + * @fn osal_service_entry + * + * @brief + * + * This function is service function for messaging service + * + * @param args arguments. + * + * @return ICall error code + */ +ICall_Errno osal_service_entry(ICall_FuncArgsHdr *args) +{ + if (args->func == ICALL_MSG_FUNC_GET_LOCAL_MSG_ENTITY_ID) + { + /* Get proxy ID */ + ((ICall_GetLocalMsgEntityIdArgs *)args)->localId = + osal_alien2proxy(((ICall_GetLocalMsgEntityIdArgs *)args)->entity); + if (((ICall_GetLocalMsgEntityIdArgs *)args)->localId == TASK_NO_TASK) + { + return ICALL_ERRNO_NO_RESOURCE; + } + } + else + { + return ICALL_ERRNO_INVALID_FUNCTION; + } + return ICALL_ERRNO_SUCCESS; +} +#endif /* USE_ICALL */ + +/********************************************************************* + * @fn osal_run_system + * + * @brief + * + * This function will make one pass through the OSAL taskEvents table + * and call the task_event_processor() function for the first task that + * is found with at least one event pending. If there are no pending + * events (all tasks), this function puts the processor into Sleep. + * + * @param void + * + * @return none + */ +void osal_run_system( void ) +{ + uint8 idx = 0; + +#ifdef USE_ICALL + uint32 next_timeout_prior = osal_next_timeout(); +#else /* USE_ICALL */ +#ifndef HAL_BOARD_CC2538 + osalTimeUpdate(); +#endif + + Hal_ProcessPoll(); +#endif /* USE_ICALL */ + +#ifdef USE_ICALL + { + /* Update osal timers to the latest before running any OSAL processes + * regardless of wakeup callback from ICall because OSAL timers are added + * relative to the current time. */ + unsigned long newtimestamp = ICall_getTicks(); + uint32 milliseconds; + + if (osal_tickperiod == 1000) + { + milliseconds = newtimestamp - osal_last_timestamp; + osal_last_timestamp = newtimestamp; + } + else + { + unsigned long long delta = (unsigned long long) + ((newtimestamp - osal_last_timestamp) & 0xfffffffful); + delta *= osal_tickperiod; + delta /= 1000; + milliseconds = (uint32) delta; + osal_last_timestamp += (uint32) (delta * 1000 / osal_tickperiod); + } + osalAdjustTimer(milliseconds); + /* Set a value that will never match osal_next_timeout() + * return value so that the next time can be scheduled. + */ + next_timeout_prior = 0xfffffffful; + } + if (osal_eventloop_hook) + { + osal_eventloop_hook(); + } + + for (;;) + { + void *msg; + ICall_EntityID src, dst; + osal_msg_hdr_t *hdr; + uint8 dest_id; + + if (ICall_fetchMsg(&src, &dst, &msg) != ICALL_ERRNO_SUCCESS) + { + break; + } + hdr = (osal_msg_hdr_t *) msg - 1; + dest_id = osal_dispatch2id(dst); + if (dest_id == TASK_NO_TASK) + { + /* Something wrong */ + ICall_abort(); + } + else + { + /* Message towards one of the tasks */ + /* Create a proxy task ID if necessary and + * queue the message to the OSAL internal queue. + */ + uint8 proxyid = osal_alien2proxy(hdr->srcentity); + + if (hdr->format == ICALL_MSG_FORMAT_1ST_CHAR_TASK_ID) + { + uint8 *bytes = msg; + *bytes = proxyid; + } + else if (hdr->format == ICALL_MSG_FORMAT_3RD_CHAR_TASK_ID) + { + uint8 *bytes = msg; + bytes[2] = proxyid; + } + /* now queue the message to the OSAL queue */ + osal_msg_send(dest_id, msg); + } + } +#endif /* USE_ICALL */ + + 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 ) && !defined(USE_ICALL) + else // Complete pass through all task events with no activity? + { + 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 + +#if defined USE_ICALL + /* Note that scheduling wakeup at this point instead of + * scheduling it upon ever OSAL start timer request, + * would only work if OSAL start timer call is made + * from OSAL tasks, but not from either ISR or + * non-OSAL application thread. + * In case, OSAL start timer is called from non-OSAL + * task, the scheduling should be part of OSAL_Timers + * module. + * Such a change to OSAL_Timers module was not made + * in order not to diverge the OSAL implementations + * too drastically between pure OSAL solution vs. + * OSAL upon service dispatcher (RTOS). + * TODO: reconsider the above statement. + */ + { + halIntState_t intState; + + uint32 next_timeout_post = osal_next_timeout(); + if (next_timeout_post != next_timeout_prior) + { + /* Next wakeup time has to be scheduled */ + if (next_timeout_post == 0) + { + /* No timer. Set time to the max */ + next_timeout_post = OSAL_TIMERS_MAX_TIMEOUT; + } + if (next_timeout_post > osal_max_msecs) + { + next_timeout_post = osal_max_msecs; + } + /* Restart timer */ + HAL_ENTER_CRITICAL_SECTION(intState); + ICall_stopTimer(osal_timerid_msec_timer); + ICall_setTimerMSecs(next_timeout_post, osal_msec_timer_cback, + (void *) (++osal_msec_timer_seq), + &osal_timerid_msec_timer); + HAL_EXIT_CRITICAL_SECTION(intState); + } + } +#endif /* USE_ICALL */ +} + +/********************************************************************* + * @fn osal_buffer_uint32 + * + * @brief + * + * Buffer an uint32 value - LSB first. + * + * @param buf - buffer + * @param val - uint32 value + * + * @return pointer to end of destination buffer + */ +uint8* osal_buffer_uint32( uint8 *buf, uint32 val ) +{ + *buf++ = BREAK_UINT32( val, 0 ); + *buf++ = BREAK_UINT32( val, 1 ); + *buf++ = BREAK_UINT32( val, 2 ); + *buf++ = BREAK_UINT32( val, 3 ); + + return buf; +} + +/********************************************************************* + * @fn osal_buffer_uint24 + * + * @brief + * + * Buffer an uint24 value - LSB first. Note that type uint24 is + * typedef to uint32 in comdef.h + * + * @param buf - buffer + * @param val - uint24 value + * + * @return pointer to end of destination buffer + */ +uint8* osal_buffer_uint24( uint8 *buf, uint24 val ) +{ + *buf++ = BREAK_UINT32( val, 0 ); + *buf++ = BREAK_UINT32( val, 1 ); + *buf++ = BREAK_UINT32( val, 2 ); + + return buf; +} + +/********************************************************************* + * @fn osal_isbufset + * + * @brief + * + * Is all of the array elements set to a value? + * + * @param buf - buffer to check + * @param val - value to check each array element for + * @param len - length to check + * + * @return TRUE if all "val" + * FALSE otherwise + */ +uint8 osal_isbufset( uint8 *buf, uint8 val, uint8 len ) +{ + uint8 x; + + if ( buf == NULL ) + { + return ( FALSE ); + } + + for ( x = 0; x < len; x++ ) + { + // Check for non-initialized value + if ( buf[x] != val ) + { + return ( FALSE ); + } + } + return ( TRUE ); +} + +/********************************************************************* + * @fn osal_self + * + * @brief + * + * This function returns the task ID of the current (active) task. + * + * @param void + * + * @return active task ID or TASK_NO_TASK if no task is active + */ +uint8 osal_self( void ) +{ + return ( activeTaskID ); +} + +/********************************************************************* + */ diff --git a/include/OSAL.h b/include/OSAL.h new file mode 100644 index 0000000..3c727c2 --- /dev/null +++ b/include/OSAL.h @@ -0,0 +1,361 @@ +/****************************************************************************** + Filename: OSAL.h + Revised: $Date: 2014-06-30 16:38:56 -0700 (Mon, 30 Jun 2014) $ + Revision: $Revision: 39297 $ + + Description: This API allows the software components in the Z-Stack to be + written independently of the specifics of the operating system, + kernel, or tasking environment (including control loops or + connect-to-interrupt systems). + + + Copyright 2004-2014 Texas Instruments Incorporated. All rights reserved. + + IMPORTANT: Your use of this Software is limited to those specific rights + granted under the terms of a software license agreement between the user + who downloaded the software, his/her employer (which must be your employer) + and Texas Instruments Incorporated (the "License"). You may not use this + Software unless you agree to abide by the terms of the License. The License + limits your use, and you acknowledge, that the Software may not be modified, + copied or distributed unless embedded on a Texas Instruments microcontroller + or used solely and exclusively in conjunction with a Texas Instruments radio + frequency transceiver, which is integrated into your product. Other than for + the foregoing purpose, you may not use, reproduce, copy, prepare derivative + works of, modify, distribute, perform, display or sell this Software and/or + its documentation for any purpose. + + YOU FURTHER ACKNOWLEDGE AND AGREE THAT THE SOFTWARE AND DOCUMENTATION ARE + PROVIDED “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, + INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY, TITLE, + NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL + TEXAS INSTRUMENTS OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER CONTRACT, + NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR OTHER + LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES + INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE + OR CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT + OF SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES + (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS. + + Should you have any questions regarding your right to use this Software, + contact Texas Instruments Incorporated at www.TI.com. +******************************************************************************/ + +#ifndef OSAL_H +#define OSAL_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +/********************************************************************* + * INCLUDES + */ + +#include + +#include "comdef.h" +#include "OSAL_Memory.h" +#include "OSAL_Timers.h" + +#ifdef USE_ICALL +#include +#endif /* USE_ICALL */ + +/********************************************************************* + * MACROS + */ +#if ( UINT_MAX == 65535 ) /* 8-bit and 16-bit devices */ + #define osal_offsetof(type, member) ((uint16) &(((type *) 0)->member)) +#else /* 32-bit devices */ + #define osal_offsetof(type, member) ((uint32) &(((type *) 0)->member)) +#endif + +#define OSAL_MSG_NEXT(msg_ptr) ((osal_msg_hdr_t *) (msg_ptr) - 1)->next + +#define OSAL_MSG_Q_INIT(q_ptr) *(q_ptr) = NULL + +#define OSAL_MSG_Q_EMPTY(q_ptr) (*(q_ptr) == NULL) + +#define OSAL_MSG_Q_HEAD(q_ptr) (*(q_ptr)) + +#define OSAL_MSG_LEN(msg_ptr) ((osal_msg_hdr_t *) (msg_ptr) - 1)->len + +#define OSAL_MSG_ID(msg_ptr) ((osal_msg_hdr_t *) (msg_ptr) - 1)->dest_id + +/********************************************************************* + * CONSTANTS + */ + +/*** Interrupts ***/ +#define INTS_ALL 0xFF + +/********************************************************************* + * TYPEDEFS + */ +#ifdef USE_ICALL +typedef ICall_MsgHdr osal_msg_hdr_t; +#else /* USE_ICALL */ +typedef struct +{ + void *next; +#ifdef OSAL_PORT2TIRTOS + /* Limited OSAL port to TI-RTOS requires compatibility with ROM + * code compiled with USE_ICALL compile flag. */ + uint32 reserved; +#endif /* OSAL_PORT2TIRTOS */ + uint16 len; + uint8 dest_id; +} osal_msg_hdr_t; +#endif /* USE_ICALL */ + +typedef struct +{ + uint8 event; + uint8 status; +} osal_event_hdr_t; + +typedef void * osal_msg_q_t; + +#ifdef USE_ICALL +/* High resolution timer callback function type */ +typedef void (*osal_highres_timer_cback_t)(void *arg); +#endif /* USE_ICALL */ + +/********************************************************************* + * GLOBAL VARIABLES + */ +#ifdef USE_ICALL +extern ICall_Semaphore osal_semaphore; +extern ICall_EntityID osal_entity; +extern uint_least32_t osal_tickperiod; +extern void (*osal_eventloop_hook)(void); +#endif /* USE_ICALL */ + + +/********************************************************************* + * FUNCTIONS + */ + +/*** Message Management ***/ + + /* + * Task Message Allocation + */ + extern uint8 * osal_msg_allocate(uint16 len ); + + /* + * Task Message Deallocation + */ + extern uint8 osal_msg_deallocate( uint8 *msg_ptr ); + + /* + * Send a Task Message + */ + extern uint8 osal_msg_send( uint8 destination_task, uint8 *msg_ptr ); + + /* + * Push a Task Message to head of queue + */ + extern uint8 osal_msg_push_front( uint8 destination_task, uint8 *msg_ptr ); + + /* + * Receive a Task Message + */ + extern uint8 *osal_msg_receive( uint8 task_id ); + + /* + * Find in place a matching Task Message / Event. + */ + extern osal_event_hdr_t *osal_msg_find(uint8 task_id, uint8 event); + + /* + * Count the number of queued OSAL messages matching Task ID / Event. + */ + extern uint8 osal_msg_count(uint8 task_id, uint8 event); + + /* + * Enqueue a Task Message + */ + extern void osal_msg_enqueue( osal_msg_q_t *q_ptr, void *msg_ptr ); + + /* + * Enqueue a Task Message Up to Max + */ + extern uint8 osal_msg_enqueue_max( osal_msg_q_t *q_ptr, void *msg_ptr, uint8 max ); + + /* + * Dequeue a Task Message + */ + extern void *osal_msg_dequeue( osal_msg_q_t *q_ptr ); + + /* + * Push a Task Message to head of queue + */ + extern void osal_msg_push( osal_msg_q_t *q_ptr, void *msg_ptr ); + + /* + * Extract and remove a Task Message from queue + */ + extern void osal_msg_extract( osal_msg_q_t *q_ptr, void *msg_ptr, void *prev_ptr ); + +#ifdef USE_ICALL + extern ICall_Errno osal_service_entry(ICall_FuncArgsHdr *args); +#endif /* USE_ICALL */ + + +/*** Task Synchronization ***/ + + /* + * Set a Task Event + */ + extern uint8 osal_set_event( uint8 task_id, uint16 event_flag ); + + + /* + * Clear a Task Event + */ + extern uint8 osal_clear_event( uint8 task_id, uint16 event_flag ); + + +/*** Interrupt Management ***/ + + /* + * Register Interrupt Service Routine (ISR) + */ + extern uint8 osal_isr_register( uint8 interrupt_id, void (*isr_ptr)( uint8* ) ); + + /* + * Enable Interrupt + */ + extern uint8 osal_int_enable( uint8 interrupt_id ); + + /* + * Disable Interrupt + */ + extern uint8 osal_int_disable( uint8 interrupt_id ); + + +/*** Task Management ***/ + +#ifdef USE_ICALL + /* + * Enroll dispatcher registered entity ID + */ + extern void osal_enroll_dispatchid(uint8 taskid, + ICall_EntityID dispatchid); + + /* + * Enroll an OSAL task to use another OSAL task's enrolled entity ID + * when sending a message. + */ + extern void osal_enroll_senderid(uint8 taskid, ICall_EntityID dispatchid); + + /* + * Enroll entity ID to be used as sender entity ID for non OSAL task + */ + extern void osal_enroll_notasksender(ICall_EntityID dispatchid); +#endif /* USE_ICALL */ + + /* + * Initialize the Task System + */ + extern uint8 osal_init_system( void ); + + /* + * System Processing Loop + */ +#if defined (ZBIT) + extern __declspec(dllexport) void osal_start_system( void ); +#else + extern void osal_start_system( void ); +#endif + + /* + * One Pass Throu the OSAL Processing Loop + */ + extern void osal_run_system( void ); + + /* + * Get the active task ID + */ + extern uint8 osal_self( void ); + + +/*** Helper Functions ***/ + + /* + * String Length + */ + extern int osal_strlen( char *pString ); + + /* + * Memory copy + */ + extern void *osal_memcpy( void*, const void GENERIC *, unsigned int ); + + /* + * Memory Duplicate - allocates and copies + */ + extern void *osal_memdup( const void GENERIC *src, unsigned int len ); + + /* + * Reverse Memory copy + */ + extern void *osal_revmemcpy( void*, const void GENERIC *, unsigned int ); + + /* + * Memory compare + */ + extern uint8 osal_memcmp( const void GENERIC *src1, const void GENERIC *src2, unsigned int len ); + + /* + * Memory set + */ + extern void *osal_memset( void *dest, uint8 value, int len ); + + /* + * Build a uint16 out of 2 bytes (0 then 1). + */ + extern uint16 osal_build_uint16( uint8 *swapped ); + + /* + * Build a uint32 out of sequential bytes. + */ + extern uint32 osal_build_uint32( uint8 *swapped, uint8 len ); + + /* + * Convert long to ascii string + */ + #if !defined ( ZBIT ) && !defined ( ZBIT2 ) && !defined (UBIT) + extern uint8 *_ltoa( uint32 l, uint8 * buf, uint8 radix ); + #endif + + /* + * Random number generator + */ + extern uint16 osal_rand( void ); + + /* + * Buffer an uint32 value - LSB first. + */ + extern uint8* osal_buffer_uint32( uint8 *buf, uint32 val ); + + /* + * Buffer an uint24 value - LSB first + */ + extern uint8* osal_buffer_uint24( uint8 *buf, uint24 val ); + + /* + * Is all of the array elements set to a value? + */ + extern uint8 osal_isbufset( uint8 *buf, uint8 val, uint8 len ); + +/********************************************************************* +*********************************************************************/ + +#ifdef __cplusplus +} +#endif + +#endif /* OSAL_H */ diff --git a/include/ZComDef.h b/include/ZComDef.h new file mode 100644 index 0000000..aebdf0f --- /dev/null +++ b/include/ZComDef.h @@ -0,0 +1,489 @@ +/************************************************************************************************** + Filename: ZComDef.h + Revised: $Date: 2014-11-24 23:50:22 -0800 (Mon, 24 Nov 2014) $ + Revision: $Revision: 41235 $ + + Description: Type definitions and macros. + + + Copyright 2004-2014 Texas Instruments Incorporated. All rights reserved. + + IMPORTANT: Your use of this Software is limited to those specific rights + granted under the terms of a software license agreement between the user + who downloaded the software, his/her employer (which must be your employer) + and Texas Instruments Incorporated (the "License"). You may not use this + Software unless you agree to abide by the terms of the License. The License + limits your use, and you acknowledge, that the Software may not be modified, + copied or distributed unless embedded on a Texas Instruments microcontroller + or used solely and exclusively in conjunction with a Texas Instruments radio + frequency transceiver, which is integrated into your product. Other than for + the foregoing purpose, you may not use, reproduce, copy, prepare derivative + works of, modify, distribute, perform, display or sell this Software and/or + its documentation for any purpose. + + YOU FURTHER ACKNOWLEDGE AND AGREE THAT THE SOFTWARE AND DOCUMENTATION ARE + PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, + INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY, TITLE, + NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL + TEXAS INSTRUMENTS OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER CONTRACT, + NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR OTHER + LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES + INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE + OR CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT + OF SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES + (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS. + + Should you have any questions regarding your right to use this Software, + contact Texas Instruments Incorporated at www.TI.com. +**************************************************************************************************/ + +#ifndef ZCOMDEF_H +#define ZCOMDEF_H + +#ifdef __cplusplus +extern "C" +{ +#endif + + +/********************************************************************* + * INCLUDES + */ +#include "comdef.h" +#include "saddr.h" + + +/********************************************************************* + * CONSTANTS + */ +#define osal_cpyExtAddr(a, b) sAddrExtCpy((a), (const uint8 *)(b)) +#define osal_ExtAddrEqual(a, b) sAddrExtCmp((const uint8 *)(a), (const uint8 *)(b)) +#define osal_copyAddress(a, b) sAddrCpy( (sAddr_t *)(a), (const sAddr_t *)(b) ) + +/********************************************************************* + * CONSTANTS + */ + +// Build Device Types - Used during compilation +// These are the types of devices to build +// Bit masked into ZSTACK_DEVICE_BUILD +#define DEVICE_BUILD_COORDINATOR 0x01 +#define DEVICE_BUILD_ROUTER 0x02 +#define DEVICE_BUILD_ENDDEVICE 0x04 + +/*** Return Values ***/ +#define ZSUCCESS SUCCESS + +/*** Component IDs ***/ +#define COMPID_OSAL 0 +#define COMPID_MTEL 1 +#define COMPID_MTSPCI 2 +#define COMPID_NWK 3 +#define COMPID_NWKIF 4 +#define COMPID_MACCB 5 +#define COMPID_MAC 6 +#define COMPID_APP 7 +#define COMPID_TEST 8 + +#define COMPID_RTG 9 +#define COMPID_DATA 11 + +/* Temp CompIDs for testing */ +#define COMPID_TEST_NWK_STARTUP 20 +#define COMPID_TEST_SCAN_CONFIRM 21 +#define COMPID_TEST_ASSOC_CONFIRM 22 +#define COMPID_TEST_REMOTE_DATA_CONFIRM 23 + +// OSAL NV Item IDs +#define ZCD_NV_EX_LEGACY 0x0000 +#define ZCD_NV_EX_ADDRMGR 0x0001 +#define ZCD_NV_EX_BINDING_TABLE 0x0002 +#define ZCD_NV_EX_DEVICE_LIST 0x0003 + +// OSAL NV item IDs +#define ZCD_NV_EXTADDR 0x0001 +#define ZCD_NV_BOOTCOUNTER 0x0002 +#define ZCD_NV_STARTUP_OPTION 0x0003 +#define ZCD_NV_START_DELAY 0x0004 + +// NWK Layer NV item IDs +#define ZCD_NV_NIB 0x0021 +#define ZCD_NV_DEVICE_LIST 0x0022 +#define ZCD_NV_ADDRMGR 0x0023 +#define ZCD_NV_POLL_RATE_OLD16 0x0024 // Deprecated when poll rate changed from 16 to 32 bits +#define ZCD_NV_POLL_RATE 0x0035 +#define ZCD_NV_QUEUED_POLL_RATE 0x0025 +#define ZCD_NV_RESPONSE_POLL_RATE 0x0026 +#define ZCD_NV_REJOIN_POLL_RATE 0x0027 +#define ZCD_NV_DATA_RETRIES 0x0028 +#define ZCD_NV_POLL_FAILURE_RETRIES 0x0029 +#define ZCD_NV_STACK_PROFILE 0x002A +#define ZCD_NV_INDIRECT_MSG_TIMEOUT 0x002B +#define ZCD_NV_ROUTE_EXPIRY_TIME 0x002C +#define ZCD_NV_EXTENDED_PAN_ID 0x002D +#define ZCD_NV_BCAST_RETRIES 0x002E +#define ZCD_NV_PASSIVE_ACK_TIMEOUT 0x002F +#define ZCD_NV_BCAST_DELIVERY_TIME 0x0030 +#define ZCD_NV_NWK_MODE 0x0031 +#define ZCD_NV_CONCENTRATOR_ENABLE 0x0032 +#define ZCD_NV_CONCENTRATOR_DISCOVERY 0x0033 +#define ZCD_NV_CONCENTRATOR_RADIUS 0x0034 + // 0x0035 used above for new 32 bit Poll Rate +#define ZCD_NV_CONCENTRATOR_RC 0x0036 +#define ZCD_NV_NWK_MGR_MODE 0x0037 +#define ZCD_NV_SRC_RTG_EXPIRY_TIME 0x0038 +#define ZCD_NV_ROUTE_DISCOVERY_TIME 0x0039 +#define ZCD_NV_NWK_ACTIVE_KEY_INFO 0x003A +#define ZCD_NV_NWK_ALTERN_KEY_INFO 0x003B +#define ZCD_NV_ROUTER_OFF_ASSOC_CLEANUP 0x003C +#define ZCD_NV_NWK_LEAVE_REQ_ALLOWED 0x003D +#define ZCD_NV_NWK_CHILD_AGE_ENABLE 0x003E +#define ZCD_NV_DEVICE_LIST_KA_TIMEOUT 0x003F + +// APS Layer NV item IDs +#define ZCD_NV_BINDING_TABLE 0x0041 +#define ZCD_NV_GROUP_TABLE 0x0042 +#define ZCD_NV_APS_FRAME_RETRIES 0x0043 +#define ZCD_NV_APS_ACK_WAIT_DURATION 0x0044 +#define ZCD_NV_APS_ACK_WAIT_MULTIPLIER 0x0045 +#define ZCD_NV_BINDING_TIME 0x0046 +#define ZCD_NV_APS_USE_EXT_PANID 0x0047 +#define ZCD_NV_APS_USE_INSECURE_JOIN 0x0048 +#define ZCD_NV_COMMISSIONED_NWK_ADDR 0x0049 + +#define ZCD_NV_APS_NONMEMBER_RADIUS 0x004B // Multicast non_member radius +#define ZCD_NV_APS_LINK_KEY_TABLE 0x004C +#define ZCD_NV_APS_DUPREJ_TIMEOUT_INC 0x004D +#define ZCD_NV_APS_DUPREJ_TIMEOUT_COUNT 0x004E +#define ZCD_NV_APS_DUPREJ_TABLE_SIZE 0x004F + +// System statistics and metrics NV ID +#define ZCD_NV_DIAGNOSTIC_STATS 0x0050 + +// Additional NWK Layer NV item IDs +#define ZCD_NV_NWK_PARENT_INFO 0x0051 +#define ZCD_NV_NWK_ENDDEV_TIMEOUT_DEF 0x0052 +#define ZCD_NV_END_DEV_TIMEOUT_VALUE 0x0053 +#define ZCD_NV_END_DEV_CONFIGURATION 0x0054 + +#define ZCD_NV_BDBNODEISONANETWORK 0x0055 //bdbNodeIsOnANetwork attribute +#define ZCD_NV_BDBREPORTINGCONFIG 0x0056 + +// Security NV Item IDs +#define ZCD_NV_SECURITY_LEVEL 0x0061 +#define ZCD_NV_PRECFGKEY 0x0062 +#define ZCD_NV_PRECFGKEYS_ENABLE 0x0063 +#define ZCD_NV_SECURITY_MODE 0x0064 +#define ZCD_NV_SECURE_PERMIT_JOIN 0x0065 +#define ZCD_NV_APS_LINK_KEY_TYPE 0x0066 +#define ZCD_NV_APS_ALLOW_R19_SECURITY 0x0067 +#define ZCD_NV_DISTRIBUTED_KEY 0x0068 //Default distributed nwk key Id. Nv ID not in use + +#define ZCD_NV_IMPLICIT_CERTIFICATE 0x0069 +#define ZCD_NV_DEVICE_PRIVATE_KEY 0x006A +#define ZCD_NV_CA_PUBLIC_KEY 0x006B +#define ZCD_NV_KE_MAX_DEVICES 0x006C + +#define ZCD_NV_USE_DEFAULT_TCLK 0x006D +//deprecated: TRUSTCENTER_ADDR (16-bit) 0x006E +#define ZCD_NV_RNG_COUNTER 0x006F +#define ZCD_NV_RANDOM_SEED 0x0070 +#define ZCD_NV_TRUSTCENTER_ADDR 0x0071 + +#define ZCD_NV_CERT_283 0x0072 +#define ZCD_NV_PRIVATE_KEY_283 0x0073 +#define ZCD_NV_PUBLIC_KEY_283 0x0074 + +#define ZCD_NV_NWK_SEC_MATERIAL_TABLE_START 0x0075 +#define ZCD_NV_NWK_SEC_MATERIAL_TABLE_END 0x0080 + + +// ZDO NV Item IDs +#define ZCD_NV_USERDESC 0x0081 +#define ZCD_NV_NWKKEY 0x0082 +#define ZCD_NV_PANID 0x0083 +#define ZCD_NV_CHANLIST 0x0084 +#define ZCD_NV_LEAVE_CTRL 0x0085 +#define ZCD_NV_SCAN_DURATION 0x0086 +#define ZCD_NV_LOGICAL_TYPE 0x0087 +#define ZCD_NV_NWKMGR_MIN_TX 0x0088 +#define ZCD_NV_NWKMGR_ADDR 0x0089 + +#define ZCD_NV_ZDO_DIRECT_CB 0x008F + +// ZCL NV item IDs +#define ZCD_NV_SCENE_TABLE 0x0091 +#define ZCD_NV_MIN_FREE_NWK_ADDR 0x0092 +#define ZCD_NV_MAX_FREE_NWK_ADDR 0x0093 +#define ZCD_NV_MIN_FREE_GRP_ID 0x0094 +#define ZCD_NV_MAX_FREE_GRP_ID 0x0095 +#define ZCD_NV_MIN_GRP_IDS 0x0096 +#define ZCD_NV_MAX_GRP_IDS 0x0097 +#define ZCD_NV_OTA_BLOCK_REQ_DELAY 0x0098 + +// Non-standard NV item IDs +#define ZCD_NV_SAPI_ENDPOINT 0x00A1 + +// NV Items Reserved for Commissioning Cluster Startup Attribute Set (SAS): +// 0x00B1 - 0x00BF: Parameters related to APS and NWK layers +// 0x00C1 - 0x00CF: Parameters related to Security +// 0x00D1 - 0x00DF: Current key parameters +#define ZCD_NV_SAS_SHORT_ADDR 0x00B1 +#define ZCD_NV_SAS_EXT_PANID 0x00B2 +#define ZCD_NV_SAS_PANID 0x00B3 +#define ZCD_NV_SAS_CHANNEL_MASK 0x00B4 +#define ZCD_NV_SAS_PROTOCOL_VER 0x00B5 +#define ZCD_NV_SAS_STACK_PROFILE 0x00B6 +#define ZCD_NV_SAS_STARTUP_CTRL 0x00B7 + +#define ZCD_NV_SAS_TC_ADDR 0x00C1 +#define ZCD_NV_SAS_TC_MASTER_KEY 0x00C2 +#define ZCD_NV_SAS_NWK_KEY 0x00C3 +#define ZCD_NV_SAS_USE_INSEC_JOIN 0x00C4 +#define ZCD_NV_SAS_PRECFG_LINK_KEY 0x00C5 +#define ZCD_NV_SAS_NWK_KEY_SEQ_NUM 0x00C6 +#define ZCD_NV_SAS_NWK_KEY_TYPE 0x00C7 +#define ZCD_NV_SAS_NWK_MGR_ADDR 0x00C8 + +#define ZCD_NV_SAS_CURR_TC_MASTER_KEY 0x00D1 +#define ZCD_NV_SAS_CURR_NWK_KEY 0x00D2 +#define ZCD_NV_SAS_CURR_PRECFG_LINK_KEY 0x00D3 + +// NV Items Reserved for Trust Center Link Key Table entries +// 0x0101 - 0x01FF +#define ZCD_NV_TCLK_SEED 0x0101 //Seed +#define ZCD_NV_TCLK_JOIN_DEV 0x0102 //Nv Id where Joining device store their APS key. Key is in plain text. +#define ZCD_NV_TCLK_DEFAULT 0x0103 //Not accually a Nv Item but Id used by SecMgr + +#define ZCD_NV_TCLK_IC_TABLE_START 0x0104 //IC keys, refered with shift byte +#define ZCD_NV_TCLK_IC_TABLE_END 0x0110 + +#define ZCD_NV_TCLK_TABLE_START 0x0111 //Entries to store users of the keys +#define ZCD_NV_TCLK_TABLE_END 0x01FF + +// NV Items Reserved for APS Link Key Table entries +// 0x0201 - 0x02FF +#define ZCD_NV_APS_LINK_KEY_DATA_START 0x0201 // APS key data +#define ZCD_NV_APS_LINK_KEY_DATA_END 0x02FF + +// NV items used to duplicate system elements +#define ZCD_NV_DUPLICATE_BINDING_TABLE 0x0300 +#define ZCD_NV_DUPLICATE_DEVICE_LIST 0x0301 +#define ZCD_NV_DUPLICATE_DEVICE_LIST_KA_TIMEOUT 0x0302 + +// NV Items Reserved for Proxy Table entries +// 0x0310 - 0x033F +#define ZCD_NV_PROXY_TABLE_START 0x0310 +#define ZCD_NV_PROXY_TABLE_END 0x033F + +// NV Items Reserved for applications (user applications) +// 0x0401 – 0x0FFF + + +// ZCD_NV_STARTUP_OPTION values +// These are bit weighted - you can OR these together. +// Setting one of these bits will set their associated NV items +// to code initialized values. +#define ZCD_STARTOPT_DEFAULT_CONFIG_STATE 0x01 +#define ZCD_STARTOPT_DEFAULT_NETWORK_STATE 0x02 +#define ZCD_STARTOPT_AUTO_START 0x04 +#define ZCD_STARTOPT_CLEAR_CONFIG ZCD_STARTOPT_DEFAULT_CONFIG_STATE +#define ZCD_STARTOPT_CLEAR_STATE ZCD_STARTOPT_DEFAULT_NETWORK_STATE +//FrameCounter should be persistence across factory new resets, this should not +//used as part of FN reset procedure. Set to reset the FrameCounter of all +//Nwk Security Material +#define ZCD_STARTOPT_CLEAR_NWK_FRAME_COUNTER 0x80 + +#define ZCL_KE_IMPLICIT_CERTIFICATE_LEN 48 +#define ZCL_KE_CA_PUBLIC_KEY_LEN 22 +#define ZCL_KE_DEVICE_PRIVATE_KEY_LEN 21 + +/********************************************************************* + * TYPEDEFS + */ + +/*** Data Types ***/ +typedef uint8 byte; +typedef uint16 UINT16; +typedef int16 INT16; + +enum +{ + AddrNotPresent = 0, + AddrGroup = 1, + Addr16Bit = 2, + Addr64Bit = 3, + AddrBroadcast = 15 +}; + +#define Z_EXTADDR_LEN 8 + +typedef byte ZLongAddr_t[Z_EXTADDR_LEN]; + +typedef struct +{ + union + { + uint16 shortAddr; + ZLongAddr_t extAddr; + } addr; + byte addrMode; +} zAddrType_t; + +// Redefined Generic Status Return Values for code backwards compatibility +#define ZSuccess SUCCESS +#define ZFailure FAILURE +#define ZInvalidParameter INVALIDPARAMETER + +// ZStack status values must start at 0x10, after the generic status values (defined in comdef.h) +#define ZMemError 0x10 +#define ZBufferFull 0x11 +#define ZUnsupportedMode 0x12 +#define ZMacMemError 0x13 + +#define ZSapiInProgress 0x20 +#define ZSapiTimeout 0x21 +#define ZSapiInit 0x22 + +#define ZNotAuthorized 0x7E + +#define ZMalformedCmd 0x80 +#define ZUnsupClusterCmd 0x81 + +// OTA Status values +#define ZOtaAbort 0x95 +#define ZOtaImageInvalid 0x96 +#define ZOtaWaitForData 0x97 +#define ZOtaNoImageAvailable 0x98 +#define ZOtaRequireMoreImage 0x99 + +// APS status values +#define ZApsFail 0xb1 +#define ZApsTableFull 0xb2 +#define ZApsIllegalRequest 0xb3 +#define ZApsInvalidBinding 0xb4 +#define ZApsUnsupportedAttrib 0xb5 +#define ZApsNotSupported 0xb6 +#define ZApsNoAck 0xb7 +#define ZApsDuplicateEntry 0xb8 +#define ZApsNoBoundDevice 0xb9 +#define ZApsNotAllowed 0xba +#define ZApsNotAuthenticated 0xbb + + // Security status values +#define ZSecNoKey 0xa1 +#define ZSecOldFrmCount 0xa2 +#define ZSecMaxFrmCount 0xa3 +#define ZSecCcmFail 0xa4 +#define ZSecFailure 0xad + + + // NWK status values +#define ZNwkInvalidParam 0xc1 +#define ZNwkInvalidRequest 0xc2 +#define ZNwkNotPermitted 0xc3 +#define ZNwkStartupFailure 0xc4 +#define ZNwkAlreadyPresent 0xc5 +#define ZNwkSyncFailure 0xc6 +#define ZNwkTableFull 0xc7 +#define ZNwkUnknownDevice 0xc8 +#define ZNwkUnsupportedAttribute 0xc9 +#define ZNwkNoNetworks 0xca +#define ZNwkLeaveUnconfirmed 0xcb +#define ZNwkNoAck 0xcc // not in spec +#define ZNwkNoRoute 0xcd + + // MAC status values +#define ZMacSuccess 0x00 +#define ZMacBeaconLoss 0xe0 +#define ZMacChannelAccessFailure 0xe1 +#define ZMacDenied 0xe2 +#define ZMacDisableTrxFailure 0xe3 +#define ZMacFailedSecurityCheck 0xe4 +#define ZMacFrameTooLong 0xe5 +#define ZMacInvalidGTS 0xe6 +#define ZMacInvalidHandle 0xe7 +#define ZMacInvalidParameter 0xe8 +#define ZMacNoACK 0xe9 +#define ZMacNoBeacon 0xea +#define ZMacNoData 0xeb +#define ZMacNoShortAddr 0xec +#define ZMacOutOfCap 0xed +#define ZMacPANIDConflict 0xee +#define ZMacRealignment 0xef +#define ZMacTransactionExpired 0xf0 +#define ZMacTransactionOverFlow 0xf1 +#define ZMacTxActive 0xf2 +#define ZMacUnAvailableKey 0xf3 +#define ZMacUnsupportedAttribute 0xf4 +#define ZMacUnsupported 0xf5 +#define ZMacSrcMatchInvalidIndex 0xff + +typedef Status_t ZStatus_t; + +typedef struct +{ + uint8 txCounter; // Counter of transmission success/failures + uint8 txCost; // Average of sending rssi values if link staus is enabled + // i.e. NWK_LINK_STATUS_PERIOD is defined as non zero + uint8 rxLqi; // average of received rssi values + // needs to be converted to link cost (1-7) before used + uint8 inKeySeqNum; // security key sequence number + uint32 inFrmCntr; // security frame counter.. + uint16 txFailure; // higher values indicate more failures +} linkInfo_t; + +/********************************************************************* + * Global System Messages + */ + +#define SPI_INCOMING_ZTOOL_PORT 0x21 // Raw data from ZTool Port (not implemented) +#define SPI_INCOMING_ZAPP_DATA 0x22 // Raw data from the ZAPP port (see serialApp.c) +#define MT_SYS_APP_MSG 0x23 // Raw data from an MT Sys message +#define MT_SYS_APP_RSP_MSG 0x24 // Raw data output for an MT Sys message +#define MT_SYS_OTA_MSG 0x25 // Raw data output for an MT OTA Rsp +#define MT_SYS_APP_PB_ZCL_CMD 0x26 // MT APP PB ZCL command + +#define AF_DATA_CONFIRM_CMD 0xFD // Data confirmation +#define AF_REFLECT_ERROR_CMD 0xFE // Reflected message error message +#define AF_INCOMING_MSG_CMD 0x1A // Incoming MSG type message +#define AF_INCOMING_KVP_CMD 0x1B // Incoming KVP type message +#define AF_INCOMING_GRP_KVP_CMD 0x1C // Incoming Group KVP type message + +//#define KEY_CHANGE 0xC0 // Key Events + +#define ZDO_NEW_DSTADDR 0xD0 // ZDO has received a new DstAddr for this app +#define ZDO_STATE_CHANGE 0xD1 // ZDO has changed the device's network state +#define ZDO_MATCH_DESC_RSP_SENT 0xD2 // ZDO match descriptor response was sent +#define ZDO_CB_MSG 0xD3 // ZDO incoming message callback +#define ZDO_NETWORK_REPORT 0xD4 // ZDO received a Network Report message +#define ZDO_NETWORK_UPDATE 0xD5 // ZDO received a Network Update message +#define ZDO_ADDR_CHANGE_IND 0xD6 // ZDO was informed of device address change + +#define NM_CHANNEL_INTERFERE 0x31 // NwkMgr received a Channel Interference message +#define NM_ED_SCAN_CONFIRM 0x32 // NwkMgr received an ED Scan Confirm message +#define SAPS_CHANNEL_CHANGE 0x33 // Stub APS has changed the device's channel +#define ZCL_INCOMING_MSG 0x34 // Incoming ZCL foundation message +#define ZCL_KEY_ESTABLISH_IND 0x35 // ZCL Key Establishment Completion Indication +#define ZCL_OTA_CALLBACK_IND 0x36 // ZCL OTA Completion Indication + + +// OSAL System Message IDs/Events Reserved for applications (user applications) +// 0xE0 – 0xFC + +/********************************************************************* + * GLOBAL VARIABLES + */ + +/********************************************************************* + * FUNCTIONS + */ + +/********************************************************************* +*********************************************************************/ + +#ifdef __cplusplus +} +#endif + +#endif /* ZCOMDEF_H */ diff --git a/include/i2c.h b/include/i2c.h new file mode 100644 index 0000000..c8d3bf2 --- /dev/null +++ b/include/i2c.h @@ -0,0 +1,181 @@ +/****************************************************************************** +* Filename: i2c.h +* Revised: $Date: 2013-01-21 06:25:21 -0800 (Mon, 21 Jan 2013) $ +* Revision: $Revision: 9178 $ +* +* Description: Prototypes for the I2C Driver. +* +* +* Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/ +* +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* +* Neither the name of Texas Instruments Incorporated nor the names of +* its contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +******************************************************************************/ + +#ifndef __I2C_H__ +#define __I2C_H__ + +//***************************************************************************** +// +// If building with a C++ compiler, make all of the definitions in this header +// have a C binding. +// +//***************************************************************************** +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "hw_types.h" + +//***************************************************************************** +// +// Defines for the API. +// +//***************************************************************************** + +//***************************************************************************** +// +// Interrupt defines. +// +//***************************************************************************** +#define I2C_INT_MASTER 0x00000001 +#define I2C_INT_SLAVE 0x00000002 + +//***************************************************************************** +// +// I2C Master commands. +// +//***************************************************************************** +#define I2C_MASTER_CMD_SINGLE_SEND \ + 0x00000007 +#define I2C_MASTER_CMD_SINGLE_RECEIVE \ + 0x00000007 +#define I2C_MASTER_CMD_BURST_SEND_START \ + 0x00000003 +#define I2C_MASTER_CMD_BURST_SEND_CONT \ + 0x00000001 +#define I2C_MASTER_CMD_BURST_SEND_FINISH \ + 0x00000005 +#define I2C_MASTER_CMD_BURST_SEND_ERROR_STOP \ + 0x00000004 +#define I2C_MASTER_CMD_BURST_RECEIVE_START \ + 0x0000000b +#define I2C_MASTER_CMD_BURST_RECEIVE_CONT \ + 0x00000009 +#define I2C_MASTER_CMD_BURST_RECEIVE_FINISH \ + 0x00000005 +#define I2C_MASTER_CMD_BURST_RECEIVE_ERROR_STOP \ + 0x00000004 + +//***************************************************************************** +// +// I2C Master error status. +// +//***************************************************************************** +#define I2C_MASTER_ERR_NONE 0 +#define I2C_MASTER_ERR_ADDR_ACK 0x00000004 +#define I2C_MASTER_ERR_DATA_ACK 0x00000008 +#define I2C_MASTER_ERR_ARB_LOST 0x00000010 + +//***************************************************************************** +// +// I2C Slave action requests +// +//***************************************************************************** +#define I2C_SLAVE_ACT_NONE 0 +#define I2C_SLAVE_ACT_RREQ 0x00000001 // Master has sent data +#define I2C_SLAVE_ACT_TREQ 0x00000002 // Master has requested data +#define I2C_SLAVE_ACT_RREQ_FBR 0x00000005 // Master has sent first byte + +//***************************************************************************** +// +// Miscellaneous I2C driver definitions. +// +//***************************************************************************** +#define I2C_MASTER_MAX_RETRIES 1000 // Number of retries + + +//***************************************************************************** +// +// I2C Slave interrupts. +// +//***************************************************************************** +#define I2C_SLAVE_INT_STOP 0x00000004 // Stop Condition Interrupt. +#define I2C_SLAVE_INT_START 0x00000002 // Start Condition Interrupt. +#define I2C_SLAVE_INT_DATA 0x00000001 // Data Interrupt. + + +//***************************************************************************** +// +// Prototypes for the APIs. +// +//***************************************************************************** +extern void I2CIntRegister(void (*pfnHandler)(void)); +extern void I2CIntUnregister(void); +extern bool I2CMasterBusBusy(void); +extern bool I2CMasterBusy(void); +extern void I2CMasterControl(uint32_t ui32Cmd); +extern uint32_t I2CMasterDataGet(void); +extern void I2CMasterDataPut(uint8_t ui8Data); +extern void I2CMasterDisable(void); +extern void I2CMasterEnable(void); +extern uint32_t I2CMasterErr(void); +extern void I2CMasterInitExpClk(uint32_t ui32I2CClk, bool bFast); +extern void I2CMasterIntClear(void); +extern void I2CMasterIntDisable(void); +extern void I2CMasterIntEnable(void); +extern bool I2CMasterIntStatus(bool bMasked); +extern void I2CMasterSlaveAddrSet(uint8_t ui8SlaveAddr, + bool bReceive); +extern uint32_t I2CSlaveDataGet(void); +extern void I2CSlaveDataPut(uint8_t ui8Data); +extern void I2CSlaveDisable(void); +extern void I2CSlaveEnable(void); +extern void I2CSlaveInit(uint8_t ui8SlaveAddr); +extern void I2CSlaveIntClear(void); +extern void I2CSlaveIntDisable(void); +extern void I2CSlaveIntEnable(void); +extern void I2CSlaveIntClearEx(uint32_t ui32IntFlags); +extern void I2CSlaveIntDisableEx(uint32_t ui32IntFlags); +extern void I2CSlaveIntEnableEx(uint32_t ui32IntFlags); +extern bool I2CSlaveIntStatus(bool bMasked); +extern uint32_t I2CSlaveIntStatusEx(bool bMasked); +extern uint32_t I2CSlaveStatus(void); + +//***************************************************************************** +// +// Mark the end of the C bindings section for C++ compilers. +// +//***************************************************************************** +#ifdef __cplusplus +} +#endif + +#endif // __I2C_H__