/*
 * Copyright (c) 2013 - 2014, Freescale Semiconductor, Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * o Redistributions of source code must retain the above copyright notice, this list
 *   of conditions and the following disclaimer.
 *
 * o 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.
 *
 * o Neither the name of Freescale Semiconductor, Inc. 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 HOLDER 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.
 */
#if !defined(__FSL_OS_ABSTRACTION_MQX_H__)
#define __FSL_OS_ABSTRACTION_MQX_H__


#if defined ( __IAR_SYSTEMS_ICC__ )
/** 
 * Workaroung to disable MISRA C message suppress warnings for IAR compiler.
 * Will be removed when MQX gets MISRA C compliant. 
 * http://supp.iar.com/Support/?note=24725 
 */
#define MISRAC_DISABLE _Pragma ("diag_suppress=                       \
    Pm001,Pm002,Pm003,Pm004,Pm005,Pm006,Pm007,Pm008,Pm009,Pm010,Pm011,\
    Pm012,Pm013,Pm014,Pm015,Pm016,Pm017,Pm018,Pm019,Pm020,Pm021,Pm022,\
    Pm023,Pm024,Pm025,Pm026,Pm027,Pm028,Pm029,Pm030,Pm031,Pm032,Pm033,\
    Pm034,Pm035,Pm036,Pm037,Pm038,Pm039,Pm040,Pm041,Pm042,Pm043,Pm044,\
    Pm045,Pm046,Pm047,Pm048,Pm049,Pm050,Pm051,Pm052,Pm053,Pm054,Pm055,\
    Pm056,Pm057,Pm058,Pm059,Pm060,Pm061,Pm062,Pm063,Pm064,Pm065,Pm066,\
    Pm067,Pm068,Pm069,Pm070,Pm071,Pm072,Pm073,Pm074,Pm075,Pm076,Pm077,\
    Pm078,Pm079,Pm080,Pm081,Pm082,Pm083,Pm084,Pm085,Pm086,Pm087,Pm088,\
    Pm089,Pm090,Pm091,Pm092,Pm093,Pm094,Pm095,Pm096,Pm097,Pm098,Pm099,\
    Pm100,Pm101,Pm102,Pm103,Pm104,Pm105,Pm106,Pm107,Pm108,Pm109,Pm110,\
    Pm111,Pm112,Pm113,Pm114,Pm115,Pm116,Pm117,Pm118,Pm119,Pm120,Pm121,\
    Pm122,Pm123,Pm124,Pm125,Pm126,Pm127,Pm128,Pm129,Pm130,Pm131,Pm132,\
    Pm133,Pm134,Pm135,Pm136,Pm137,Pm138,Pm139,Pm140,Pm141,Pm142,Pm143,\
    Pm144,Pm145,Pm146,Pm147,Pm148,Pm149,Pm150,Pm151,Pm152,Pm153,Pm154,\
    Pm155")

#define MISRAC_ENABLE _Pragma ("diag_default=                         \
    Pm001,Pm002,Pm003,Pm004,Pm005,Pm006,Pm007,Pm008,Pm009,Pm010,Pm011,\
    Pm012,Pm013,Pm014,Pm015,Pm016,Pm017,Pm018,Pm019,Pm020,Pm021,Pm022,\
    Pm023,Pm024,Pm025,Pm026,Pm027,Pm028,Pm029,Pm030,Pm031,Pm032,Pm033,\
    Pm034,Pm035,Pm036,Pm037,Pm038,Pm039,Pm040,Pm041,Pm042,Pm043,Pm044,\
    Pm045,Pm046,Pm047,Pm048,Pm049,Pm050,Pm051,Pm052,Pm053,Pm054,Pm055,\
    Pm056,Pm057,Pm058,Pm059,Pm060,Pm061,Pm062,Pm063,Pm064,Pm065,Pm066,\
    Pm067,Pm068,Pm069,Pm070,Pm071,Pm072,Pm073,Pm074,Pm075,Pm076,Pm077,\
    Pm078,Pm079,Pm080,Pm081,Pm082,Pm083,Pm084,Pm085,Pm086,Pm087,Pm088,\
    Pm089,Pm090,Pm091,Pm092,Pm093,Pm094,Pm095,Pm096,Pm097,Pm098,Pm099,\
    Pm100,Pm101,Pm102,Pm103,Pm104,Pm105,Pm106,Pm107,Pm108,Pm109,Pm110,\
    Pm111,Pm112,Pm113,Pm114,Pm115,Pm116,Pm117,Pm118,Pm119,Pm120,Pm121,\
    Pm122,Pm123,Pm124,Pm125,Pm126,Pm127,Pm128,Pm129,Pm130,Pm131,Pm132,\
    Pm133,Pm134,Pm135,Pm136,Pm137,Pm138,Pm139,Pm140,Pm141,Pm142,Pm143,\
    Pm144,Pm145,Pm146,Pm147,Pm148,Pm149,Pm150,Pm151,Pm152,Pm153,Pm154,\
    Pm155")
#else
/* Empty MISRA C macros for other toolchains. */
#define MISRAC_DISABLE
#define MISRAC_ENABLE
#endif
      
      
#include <stdint.h>
/* Include MQX RTOS API */
MISRAC_DISABLE
#include "mqx_sdk_config.h"
#include "mqx.h"
#include "lwevent.h"
#include "lwsem.h"
#include "mutex.h"
#include "lwmsgq.h"
MISRAC_ENABLE


#ifndef __FSL_RTOS_MSGQ_COPY_MSG__
#define __FSL_RTOS_MSGQ_COPY_MSG__ 1
#endif

/*!
* @addtogroup os_abstraction_mqx
* @{
*/


/*******************************************************************************
 * Declarations
 ******************************************************************************/

/*! @brief Type for an interrupt synchronization object. */
typedef LWSEM_STRUCT sync_object_t;

/*! @brief Type for a resource locking object. */
typedef MUTEX_STRUCT lock_object_t;

/*! @brief Type for an event group object. */
typedef LWEVENT_STRUCT event_object_t;

/*! @brief Type for an event flags group. Bit 32 is reserved. */
typedef _mqx_uint event_group_t;

/*! @brief Type for a task pointer. */
typedef TASK_FPTR task_t;

/*! @brief Type for a task handler, returned by the task_create function. */
typedef _task_id task_handler_t;

/*! @brief Type for a task stack. */
typedef uint32_t task_stack_t;

/* Internal struct for message queue holding one message more needed for flushing the queue. */
typedef struct mqx_osa_queue {
    _mqx_max_type *one_msg;
    _mqx_max_type *msgq;
} MQX_OSA_QUEUE;

/*! @brief Type for a message queue declaration and creation. */
typedef MQX_OSA_QUEUE msg_queue_t;

/*! @brief Type for a message queue declaration and creation. */
typedef void *msg_queue_handler_t;

/*! @brief Type for a message queue item. */
#if __FSL_RTOS_MSGQ_COPY_MSG__
//typedef _mqx_max_type_ptr msg_queue_item_t; // The _mqx_max_type_ptr should be default type. We use void * for USB.
typedef void *msg_queue_item_t;
#else
typedef void *msg_queue_item_t;
#endif

enum sync_timeouts
{
    /*! @brief Constant to pass for the sync_wait() timeout in order to wait indefinitely. */
    kSyncWaitForever = UINT32_MAX
};

/*! @brief Macro passed to the task_destroy function to destroy the current task. */
#define FSL_RTOS_CURRENT_TASK   ((task_handler_t)MQX_NULL_TASK_ID)

/*! @brief Definition of how MQX handles the message queues */
#ifndef __FSL_RTOS_MSGQ_COPY_MSG__
#define __FSL_RTOS_MSGQ_COPY_MSG__ 1
#endif

/*******************************************************************************
 * API
 ******************************************************************************/

#if defined(__cplusplus)
extern "C" {
#endif

/*!
* @name Interrupt handler synchronization
* @{
*/

/*!
 * @brief Create the synchronization object. To be used instead of a standard
 *      declaration.
 *
 * @param obj The sync object to create.
 */
#define sync_object_declare(obj)    sync_object_t obj
/*@}*/


/*!
* @name Thread management
* @{
*/


/*!
 * @brief Creates a task descriptor that is used to create the task with task_create.
 *
 * @param task The task function.
 * @param stackSize Number of elements in the stack for this task.
 * @param name String to assign to the task.
 * @param usesFloat Boolean that indicates whether the task uses the floating point unit.
 */
#define FSL_RTOS_TASK_DEFINE(task, stackSize, name, usesFloat) const uint16_t fslTaskStackSize_##task = stackSize; \
                                                               const uint8_t fslTaskName_##task[] = name; \
                                                               const bool fslTaskFloatUse_##task = usesFloat

/*!
 * @brief Creates and sets the task to active.
 *
 * @param task The task function.
 * @param priority Initial priority of the task.
 * @param param Pointer to be passed to the task when it is created.
 * @param handler Returns the identifier to be used afterwards to destroy the task.
 *
 * @retval kSuccess The task was successfully created.
 * @retval kError Creation of task failed.
 */
#define task_create(task, priority, param, handler)   __task_create(task, \
                                                                   (uint8_t *)fslTaskName_##task, \
                                                                   fslTaskStackSize_##task, \
                                                                   NULL, \
                                                                   priority, \
                                                                   param, \
                                                                   fslTaskFloatUse_##task, \
                                                                   handler)

/*@}*/

/*!
* @name Message queues
* @{
*/

/* Internal macro that computes number of _mqx_max_type elements needed to cover size bytes. */
#define SIZE_IN_MMT_UNITS(size) ((size + sizeof(_mqx_max_type) - 1) / sizeof(_mqx_max_type))

/*!
 * @brief This macro statically reserves the memory required for the queue.
 * @note The queue will store pointers to the elements, and no the elements themselves. The
 *       element must continue to exist in memory for the receiving end to properly get the
 *       contents.
 *
 * @param name Identifier for the memory region.
 * @param number Number of elements in the queue.
 * @param size Size of element in 4B units.
 */

#if __FSL_RTOS_MSGQ_COPY_MSG__

#define MSG_QUEUE_DECLARE(name, number, size) \
    _mqx_max_type mqxq_##name[SIZE_IN_MMT_UNITS(sizeof(LWMSGQ_STRUCT)) + SIZE_IN_MMT_UNITS(size * 4) * number]; \
    _mqx_max_type mqxm_##name[SIZE_IN_MMT_UNITS(size * 4)]; \
    MQX_OSA_QUEUE name = { \
        .one_msg = mqxm_##name, \
        .msgq = mqxq_##name, \
    }

#else /*__FSL_RTOS_MSGQ_COPY_MSG__ */

#define MSG_QUEUE_DECLARE(name, number) \
    _mqx_max_type mqxq_##name[SIZE_IN_MMT_UNITS(sizeof(LWMSGQ_STRUCT)) + SIZE_IN_MMT_UNITS(sizeof(msg_queue_item_t)) * number]; \
    _mqx_max_type mqxm_##name[SIZE_IN_MMT_UNITS(sizeof(msg_queue_item_t))]; \
    MQX_OSA_QUEUE name = { \
        .one_msg = mqxm_##name, \
        .msgq = mqxq_##name, \
    }

#endif /* __FSL_RTOS_MSGQ_COPY_MSG__*/

/*@}*/


/*!
* @name Critical Sections
* @{
*/

/*! @brief Ensures the following code will not be preempted. Required attention to other system events may be delayed. */
void rtos_enter_critical(void);

/*! @brief Allows preemption */
void rtos_exit_critical(void);

/*@}*/


#if defined(__cplusplus)
}
#endif

/*! @}*/

#endif /* __FSL_OS_ABSTRACTION_MQX_H__ */
/*******************************************************************************
 * EOF
 ******************************************************************************/

