[KPSDK] Revert Enet driver to older version - compatible with lwip port

- this will be reverted back along with an updated lwip K64F implementation
pull/494/head
0xc0170 2014-09-16 15:15:32 +01:00
parent a83f8e809d
commit cfd2a98b57
20 changed files with 2710 additions and 8328 deletions

View File

@ -29,180 +29,80 @@
*/
#include "fsl_phy_driver.h"
#include "fsl_enet_hal.h"
#ifndef MBED_NO_ENET
/*******************************************************************************
* Variables
******************************************************************************/
uint16_t oldPhyStatus, newPhyStatus;
extern const uint32_t g_enetBaseAddr[];
/*! @brief Define Phy API structure for MAC application*/
const enet_phy_api_t g_enetPhyApi =
{
phy_auto_discover,
phy_init,
phy_get_link_speed,
phy_get_link_status,
phy_get_link_duplex,
};
/*******************************************************************************
* Code
******************************************************************************/
/*FUNCTION****************************************************************
*
* Function Name: PHY_DRV_Write
* Return Value: The execution status.
* Description: PHY Write function.
* This interface write data over the SMI to the specified PHY register.
* This function is called by all PHY interfaces.
*END*********************************************************************/
uint32_t PHY_DRV_Write(uint32_t instance, uint32_t phyAddr, uint32_t phyReg, uint32_t data)
{
uint32_t counter = kEnetMaxTimeout, baseAddr;
baseAddr = g_enetBaseAddr[instance];
/* Check if the mii is enabled*/
if (!ENET_HAL_GetSMI(baseAddr))
{
return kStatus_ENET_SMIUninitialized;
}
/* Clear the SMI interrupt event*/
ENET_HAL_ClearIntStatusFlag(baseAddr, kEnetMiiInterrupt);
/* Set write command*/
ENET_HAL_SetSMIWrite(baseAddr, phyAddr, phyReg, kEnetWriteValidFrame, data);
/* Wait for MII complete*/
do{
counter --;
}while(ENET_HAL_GetIntStatusFlag(baseAddr, kEnetMiiInterrupt) && (counter > 0));
/* Check for timeout*/
if (!counter)
{
return kStatus_ENET_SMIVisitTimeout;
}
/* Clear MII intrrupt event*/
ENET_HAL_ClearIntStatusFlag(baseAddr, kEnetMiiInterrupt);
return kStatus_ENET_Success;
}
/*FUNCTION****************************************************************
*
* Function Name: PHY_DRV_Read
* Return Value: The execution status.
* Description: Read function.
* This interface read data over the SMI from the specified PHY register,
* This function is called by all PHY interfaces.
*END*********************************************************************/
uint32_t PHY_DRV_Read(uint32_t instance, uint32_t phyAddr, uint32_t phyReg, uint32_t *dataPtr)
{
uint32_t counter = kEnetMaxTimeout, baseAddr;
/* Check the input parameters*/
if (!dataPtr)
{
return kStatus_ENET_InvalidInput;
}
baseAddr = g_enetBaseAddr[instance];
/* Check if the mii is enabled*/
if (!ENET_HAL_GetSMI(baseAddr))
{
return kStatus_ENET_SMIUninitialized;
}
/* Clear the MII interrupt event*/
ENET_HAL_ClearIntStatusFlag(baseAddr, kEnetMiiInterrupt);
/* Read command operation*/
ENET_HAL_SetSMIRead(baseAddr, phyAddr, phyReg, kEnetReadValidFrame);
/* Wait for MII complete*/
do{
counter --;
}while(!ENET_HAL_GetIntStatusFlag(baseAddr, kEnetMiiInterrupt) && (counter > 0));
/* Check for timeout*/
if (!counter)
{
return kStatus_ENET_SMIVisitTimeout;
}
/* Get data from mii register*/
*dataPtr = ENET_HAL_GetSMIData(baseAddr);
/* Clear MII interrupt event*/
ENET_HAL_ClearIntStatusFlag(baseAddr, kEnetMiiInterrupt);
return kStatus_ENET_Success;
}
/*FUNCTION****************************************************************
*
* Function Name: PHY_DRV_Init
* Function Name: phy_init
* Return Value: The execution status.
* Description: Initialize Phy.
* This interface provides initialize functions for PHY, This is called by enet
* initialize function. PHY is usually deault auto-negotiation. so there is no
* This interface provides initialize functions for Phy, This is called by enet
* initialize function. Phy is usually deault auto-negotiation. so there is no
* need to do the intialize about this. we just need to check the loop mode.
*END*********************************************************************/
uint32_t PHY_DRV_Init(uint32_t instance, uint32_t phyAddr, bool isLoopEnabled)
uint32_t phy_init(enet_dev_if_t * enetIfPtr)
{
uint32_t data,dataStatus;
uint32_t counter = kEnetMaxTimeout;
uint32_t data;
uint32_t counter;
uint32_t result;
/* Check input parameters*/
if (!enetIfPtr)
{
return kStatus_PHY_InvaildInput;
}
/* Reset Phy*/
result = PHY_DRV_Write(instance, phyAddr, kEnetPhyCR, kEnetPhyReset);
if(result != kStatus_ENET_Success)
if ((result = (enetIfPtr->macApiPtr->enet_mii_read(enetIfPtr->deviceNumber,
enetIfPtr->phyCfgPtr->phyAddr,kEnetPhySR,&data))) == kStatus_PHY_Success)
{
return result;
}
else
{
do{
counter --;
/* Wait for complete*/
result = PHY_DRV_Read(instance, phyAddr, kEnetPhyCR, &data);
if(result != kStatus_ENET_Success)
{
return result;
}
}while((data & kEnetPhyReset) && (counter > 0));
/* Check for timeout */
if (!counter)
if ((data & kEnetPhyAutoNegAble) != 0)
{
return kStatus_ENET_SMIVisitTimeout;
}
}
result = PHY_DRV_Read(instance, phyAddr, kEnetPhySR, &dataStatus);
if(result != kStatus_ENET_Success)
{
return result;
}
if (((dataStatus & kEnetPhyAutoNegAble) != 0) && ((dataStatus & kEnetPhyAutoNegComplete) == 0))
{
/* Set Autonegotiation*/
if(PHY_DRV_Write(instance, phyAddr, kEnetPhyCR, data | kEnetPhyAutoNeg)== kStatus_ENET_Success)
for (counter = 0; counter < kEnetMaxTimeout; counter++)
{
if (PHY_DRV_Read(instance, phyAddr, kEnetPhySR, &dataStatus)== kStatus_ENET_Success)
/* Set Autonegotiation*/
enetIfPtr->macApiPtr->enet_mii_write(enetIfPtr->deviceNumber,
enetIfPtr->phyCfgPtr->phyAddr, kEnetPhyCR, kEnetPhyAutoNeg);
for (counter = 0; counter < kPhyTimeout; counter++)
{
if ((dataStatus & kEnetPhyAutoNegComplete) != 0)
if (enetIfPtr->macApiPtr->enet_mii_read(enetIfPtr->deviceNumber,
enetIfPtr->phyCfgPtr->phyAddr,kEnetPhySR,&data)== kStatus_PHY_Success)
{
break;
}
}
if ((data & kEnetPhyAutoNegComplete) != 0)
{
break;
}
}
}
if (counter == kPhyTimeout)
{
return kStatus_PHY_TimeOut;
}
}
}
if (isLoopEnabled)
if (enetIfPtr->phyCfgPtr->isLoopEnabled)
{
/* First read the current status in control register*/
if (PHY_DRV_Read(instance, phyAddr, kEnetPhyCR, &data) == kStatus_ENET_Success)
if (enetIfPtr->macApiPtr->enet_mii_read(enetIfPtr->deviceNumber,
enetIfPtr->phyCfgPtr->phyAddr,kEnetPhyCR,&data))
{
result = PHY_DRV_Write(instance, phyAddr,kEnetPhyCR,(data|kEnetPhyLoop));
return result;
result = enetIfPtr->macApiPtr->enet_mii_write(enetIfPtr->deviceNumber,
enetIfPtr->phyCfgPtr->phyAddr,kEnetPhyCR,(data|kEnetPhyLoop));
}
}
@ -211,64 +111,67 @@ uint32_t PHY_DRV_Init(uint32_t instance, uint32_t phyAddr, bool isLoopEnabled)
/*FUNCTION****************************************************************
*
* Function Name: PHY_DRV_Autodiscover
* Function Name: phy_auto_discover
* Return Value: The execution status.
* Description: Phy address auto discover.
* This function provides a interface to get phy address using phy address auto
* discovering, this interface is used when the phy address is unknown.
*END*********************************************************************/
uint32_t PHY_DRV_Autodiscover(uint32_t instance, uint32_t *phyAddr)
uint32_t phy_auto_discover(enet_dev_if_t * enetIfPtr)
{
uint32_t addrIdx,data;
uint32_t result = kStatus_ENET_PHYAutoDiscoverFail;
/* Check input param*/
if(!phyAddr)
uint32_t result = kStatus_PHY_Fail;
/* Check input parameters*/
if (!enetIfPtr)
{
return kStatus_ENET_InvalidInput;
return kStatus_PHY_InvaildInput;
}
for (addrIdx = 0; addrIdx < kEnetPhyRegAll; addrIdx++)
for (addrIdx = 0; addrIdx < 32; addrIdx++)
{
result = PHY_DRV_Read(instance, addrIdx, kEnetPhyId1, &data);
if ((result == kStatus_ENET_Success) && (data != 0) && (data != 0xffff) )
enetIfPtr->phyCfgPtr->phyAddr = addrIdx;
result = enetIfPtr->macApiPtr->enet_mii_read(enetIfPtr->deviceNumber,
enetIfPtr->phyCfgPtr->phyAddr,kEnetPhyId1,&data);
if ((result == kStatus_PHY_Success) && (data != 0) && (data != 0xffff) )
{
*phyAddr = addrIdx;
return kStatus_ENET_Success;
return kStatus_PHY_Success;
}
}
return result;
}
/*FUNCTION****************************************************************
*
* Function Name: PHY_DRV_GetLinkSpeed
* Function Name: phy_get_link_speed
* Return Value: The execution status.
* Description: Get phy link speed.
* This function provides a interface to get link speed.
*END*********************************************************************/
uint32_t PHY_DRV_GetLinkSpeed(uint32_t instance, uint32_t phyAddr, enet_phy_speed_t *speed)
uint32_t phy_get_link_speed(enet_dev_if_t * enetIfPtr, enet_phy_speed_t *status)
{
uint32_t result = kStatus_ENET_Success;
uint32_t result = kStatus_PHY_Success;
uint32_t data;
/* Check input parameters*/
if (!speed)
if ((!enetIfPtr) || (!status))
{
return kStatus_ENET_InvalidInput;
return kStatus_PHY_InvaildInput;
}
result = PHY_DRV_Read(instance, phyAddr, kEnetPhyCt1,&data);
if (result == kStatus_ENET_Success)
result = enetIfPtr->macApiPtr->enet_mii_read(enetIfPtr->deviceNumber,
enetIfPtr->phyCfgPtr->phyAddr, kEnetPhyCt2,&data);
if (result == kStatus_PHY_Success)
{
data &= kEnetPhySpeedDulpexMask;
if ((kEnetPhy100HalfDuplex == data) || (kEnetPhy100FullDuplex == data))
{
*speed = kEnetSpeed100M;
*status = kEnetSpeed100M;
}
else
{
*speed = kEnetSpeed10M;
*status = kEnetSpeed10M;
}
}
@ -277,29 +180,31 @@ uint32_t PHY_DRV_GetLinkSpeed(uint32_t instance, uint32_t phyAddr, enet_phy_spee
/*FUNCTION****************************************************************
*
* Function Name: PHY_DRV_GetLinkStatus
* Function Name: phy_get_link_status
* Return Value: The execution status.
* Description: Get phy link status.
* This function provides a interface to get link status to see if the link
* status is on or off.
*END*********************************************************************/
uint32_t PHY_DRV_GetLinkStatus(uint32_t instance, uint32_t phyAddr, bool *status)
uint32_t phy_get_link_status(enet_dev_if_t * enetIfPtr, bool *status)
{
uint32_t result = kStatus_ENET_Success;
uint32_t result = kStatus_PHY_Success;
uint32_t data;
/* Check input parameters*/
if (!status)
if ((!enetIfPtr) || (!status))
{
return kStatus_ENET_InvalidInput;
return kStatus_PHY_InvaildInput;
}
result = PHY_DRV_Read(instance, phyAddr, kEnetPhyCR, &data);
if ((result == kStatus_ENET_Success) && (!(data & kEnetPhyReset)))
result = enetIfPtr->macApiPtr->enet_mii_read(enetIfPtr->deviceNumber,
enetIfPtr->phyCfgPtr->phyAddr,kEnetPhyCR,&data);
if ((result == kStatus_PHY_Success) && (!(data & kEnetPhyReset)))
{
data = 0;
result = PHY_DRV_Read(instance, phyAddr, kEnetPhySR, &data);
if (result == kStatus_ENET_Success)
result = enetIfPtr->macApiPtr->enet_mii_read(enetIfPtr->deviceNumber,
enetIfPtr->phyCfgPtr->phyAddr,kEnetPhySR, &data);
if (result == kStatus_PHY_Success)
{
if (!(kEnetPhyLinkStatus & data))
{
@ -317,25 +222,26 @@ uint32_t PHY_DRV_GetLinkSpeed(uint32_t instance, uint32_t phyAddr, enet_phy_spee
/*FUNCTION****************************************************************
*
* Function Name: PHY_DRV_GetLinkDuplex
* Function Name: phy_get_link_duplex
* Return Value: The execution status.
* Description: Get phy link duplex.
* This function provides a interface to get link duplex to see if the link
* duplex is full or half.
*END*********************************************************************/
uint32_t PHY_DRV_GetLinkDuplex(uint32_t instance, uint32_t phyAddr, enet_phy_duplex_t *status)
uint32_t phy_get_link_duplex(enet_dev_if_t * enetIfPtr, enet_phy_duplex_t *status)
{
uint32_t result = kStatus_ENET_Success;
uint32_t result = kStatus_PHY_Success;
uint32_t data;
/* Check input parameters*/
if (!status)
if ((!enetIfPtr) || (!status))
{
return kStatus_ENET_InvalidInput;
return kStatus_PHY_InvaildInput;
}
result = PHY_DRV_Read(instance, phyAddr,kEnetPhyCt1,&data);
if (result == kStatus_ENET_Success)
result = enetIfPtr->macApiPtr->enet_mii_read(enetIfPtr->deviceNumber,
enetIfPtr->phyCfgPtr->phyAddr,kEnetPhyCt2,&data);
if (result == kStatus_PHY_Success)
{
data &= kEnetPhySpeedDulpexMask;
if ((kEnetPhy10FullDuplex == data) || (kEnetPhy100FullDuplex == data))
@ -351,57 +257,6 @@ uint32_t PHY_DRV_GetLinkDuplex(uint32_t instance, uint32_t phyAddr, enet_phy_dup
return result;
}
/*FUNCTION****************************************************************
*
* Function Name: PHY_DRV_UpdateSpeed
* Return Value: The execution status.
* Description: Poll Phy speed change.
* This function provides a interface to moniter the change of the link speed.
*END*********************************************************************/
bool PHY_DRV_UpdateSpeed(uint32_t instance, uint32_t phyAddr, enet_phy_speed_t *status)
{
bool link;
if(PHY_DRV_GetLinkSpeed(instance, phyAddr, status)== kStatus_ENET_Success)
{
if(status)
{
newPhyStatus |= kPhyLinkSpeed;
}
else
{
newPhyStatus &= ~kPhyLinkSpeed;
}
}
if(PHY_DRV_GetLinkStatus(instance, phyAddr, &link)== kStatus_ENET_Success)
{
if(link)
{
newPhyStatus |= kPhyLinkon;
}
else
{
newPhyStatus &= ~kPhyLinkon;
}
}
if(newPhyStatus != oldPhyStatus)
{
oldPhyStatus = newPhyStatus;
if(newPhyStatus & kPhyLinkon)
{
return true;
}
else
{
return false;
}
}
return false;
}
#endif /* MBED_NO_ENET */
/*******************************************************************************
* EOF

View File

@ -32,6 +32,7 @@
#include <stdint.h>
#include <stdbool.h>
#include "fsl_enet_driver.h"
/*!
* @addtogroup phy_driver
* @{
@ -42,72 +43,81 @@
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @brief Defines the PHY return status. */
typedef enum _phy_status
{
kStatus_PHY_Success = 0, /*!< Success*/
kStatus_PHY_InvaildInput = 1, /*!< Invalid PHY input parameter*/
kStatus_PHY_TimeOut = 2, /*!< PHY timeout*/
kStatus_PHY_Fail = 3 /*!< PHY fail*/
} phy_status_t;
/*! @brief Defines the ENET timeout.*/
typedef enum _phy_timeout
{
kPhyTimeout = 0x10000, /*!< ENET resets timeout.*/
} phy_timeout_t;
/*! @brief Defines the PHY register.*/
typedef enum _enet_phy_register
{
kEnetPhyCR = 0U, /*!< PHY control register */
kEnetPhySR = 1U, /*!< PHY status register*/
kEnetPhyId1 = 2U, /*!< PHY identification register 1*/
kEnetPhyId2 = 3U, /*!< PHY identification register 2*/
kEnetPhyCt1 = 0x1eU, /*!< PHY control1 register*/
kEnetPhyCt2 = 0x1fU, /*!< PHY control2 register*/
kEnetPhyRegAll = 0x20U /*!< Total PHY register numbers*/
kEnetPhyCR = 0, /*!< PHY control register */
kEnetPhySR = 1, /*!< PHY status register*/
kEnetPhyId1 = 2, /*!< PHY identification register 1*/
kEnetPhyId2 = 3, /*!< PHY identification register 2*/
kEnetPhyCt2 = 0x1e /*!< PHY control2 register*/
} enet_phy_register_t;
/*! @brief Defines the control flag in control register.*/
typedef enum _enet_phy_controlreg
/*! @brief Defines the control flag.*/
typedef enum _enet_phy_control
{
kEnetPhyAutoNeg = 0x1000U,/*!< ENET PHY auto negotiation control*/
kEnetPhySpeed = 0x2000U, /*! ENET PHY speed control*/
kEnetPhyLoop = 0x4000U, /*!< ENET PHY loop control*/
kEnetPhyReset = 0x8000U, /*!< ENET PHY reset control*/
kEnetPhy10HalfDuplex = 0x01U, /*!< ENET PHY 10M half duplex*/
kEnetPhy100HalfDuplex = 0x02U,/*!< ENET PHY 100M half duplex*/
kEnetPhy10FullDuplex = 0x05U,/*!< ENET PHY 10M full duplex*/
kEnetPhy100FullDuplex = 0x06U/*!< ENET PHY 100M full duplex*/
} enet_phy_controlreg_t;
/*! @brief Defines the control flag in status register.*/
typedef enum _enet_phy_statusreg
{
kEnetPhyLinkStatus = 0x04U, /*!< ENET PHY link status bit*/
kEnetPhyAutoNegAble = 0x08U, /*!< ENET PHY auto negotiation ability*/
kEnetPhySpeedDulpexMask = 0x07U, /*!< ENET PHY speed mask on status register 2*/
kEnetPhyAutoNegComplete = 0x20U /*!< ENET PHY auto negotiation complete*/
} enet_phy_statusreg_t;
/*! @brief Define PHY's link status*/
typedef enum _enet_phy_link_status
{
kPhyLinkSpeed = 0x1U, /*!< PHY Link speed */
kPhyLinkon = 0x2U /*!< PHY link status*/
}enet_phy_link_status_t;
kEnetPhyAutoNeg = 0x1000,/*!< ENET PHY auto negotiation control*/
kEnetPhySpeed = 0x2000, /*! ENET PHY speed control*/
kEnetPhyLoop = 0x4000, /*!< ENET PHY loop control*/
kEnetPhyReset = 0x8000, /*!< ENET PHY reset control*/
kEnetPhy10HalfDuplex = 0x01, /*!< ENET PHY 10 M half duplex*/
kEnetPhy100HalfDuplex = 0x02,/*!< ENET PHY 100 M half duplex*/
kEnetPhy10FullDuplex = 0x05,/*!< ENET PHY 10 M full duplex*/
kEnetPhy100FullDuplex = 0x06/*!< ENET PHY 100 M full duplex*/
} enet_phy_control_t;
/*! @brief Defines the PHY link speed. */
typedef enum _enet_phy_speed
{
kEnetSpeed10M = 0U, /*!< ENET PHY 10 M speed*/
kEnetSpeed100M = 1U /*!< ENET PHY 100 M speed*/
kEnetSpeed10M = 0, /*!< ENET PHY 10 M speed*/
kEnetSpeed100M = 1 /*!< ENET PHY 100 M speed*/
} enet_phy_speed_t;
/*! @brief Defines the PHY link duplex.*/
typedef enum _enet_phy_duplex
{
kEnetHalfDuplex = 0U, /*!< ENET PHY half duplex*/
kEnetFullDuplex = 1U /*!< ENET PHY full duplex*/
kEnetHalfDuplex = 0, /*!< ENET PHY half duplex*/
kEnetFullDuplex = 1 /*!< ENET PHY full duplex*/
} enet_phy_duplex_t;
/*! @brief Defines the basic configuration for PHY.*/
typedef struct ENETPhyConfig
/*! @brief Defines the PHY status.*/
typedef enum _enet_phy_status
{
bool isAutodiscoverEnabled; /*!< PHY address auto discover*/
uint8_t phyAddr; /*!< PHY address*/
bool isLoopEnabled; /*!< Switcher to enable the HY loop mode*/
} enet_phy_config_t;
kEnetPhyLinkStatus = 0x4, /*!< ENET PHY link status bit*/
kEnetPhyAutoNegAble = 0x08, /*!< ENET PHY auto negotiation ability*/
kEnetPhyAutoNegComplete = 0x20, /*!< ENET PHY auto negotiation complete*/
kEnetPhySpeedDulpexMask = 0x07 /*!< ENET PHY speed mask on status register 2*/
} enet_phy_status_t;
/*! @brief Defines the basic PHY application.*/
typedef struct ENETPhyApi
{
uint32_t (* phy_auto_discover)(enet_dev_if_t * enetIfPtr);/*!< PHY auto discover*/
uint32_t (* phy_init)(enet_dev_if_t * enetIfPtr);/*!< PHY initialize*/
uint32_t (* phy_get_link_speed)(enet_dev_if_t * enetIfPtr, enet_phy_speed_t *speed);/*!< Get PHY speed*/
uint32_t (* phy_get_link_status)(enet_dev_if_t * enetIfPtr, bool *status);/*! Get PHY link status*/
uint32_t (* phy_get_link_duplex)(enet_dev_if_t * enetIfPtr, enet_phy_duplex_t *duplex);/*!< Get PHY link duplex*/
} enet_phy_api_t;
/*******************************************************************************
* Global variables
******************************************************************************/
extern const enet_phy_api_t g_enetPhyApi;
/*******************************************************************************
* API
@ -121,102 +131,49 @@ extern "C" {
* @name PHY Driver
* @{
*/
/*!
* @brief PHY Write function.
*
* This interface write data over the SMI to the specified PHY register.
* This function is called by all PHY interfaces.
*
* @param instance The ENET instance number.
* @param phyAddr The PHY address.
* @param phyReg The PHY register.
* @param data The data written to the phy register.
* @return The execution status.
*/
uint32_t PHY_DRV_Write(uint32_t instance, uint32_t phyAddr, uint32_t phyReg, uint32_t data);
/*!
* @brief PHY Read function.
*
* This interface read data over the SMI from the specified PHY register.
* This function is called by all PHY interfaces.
*
* @param instance The ENET instance number.
* @param phyAddr The PHY address.
* @param phyReg The PHY register.
* @param dataPtr The address to store the data read from the phy register.
* @return The execution status.
*/
uint32_t PHY_DRV_Read(uint32_t instance, uint32_t phyAddr, uint32_t phyReg, uint32_t *dataPtr);
/*!
* @brief Initializes PHY.
*
* @param instance The ENET instance number.
* @param phyAddr The PHY address.
* @param isLoopEnabled The flag to enable or disable phy internal loopback.
* @param enetIfPtr The ENET context structure.
* @return The execution status.
*/
uint32_t PHY_DRV_Init(uint32_t instance, uint32_t phyAddr, bool isLoopEnabled);
uint32_t phy_init(enet_dev_if_t * enetIfPtr);
/*!
* @brief PHY address auto discover.
*
*
* This function provides a interface to get phy address using phy address auto
* discovering, this interface is used when the phy address is unknown.
*
* @param instance The ENET instance structure.
* @param phyAddr The address of discovered PHY address.
* @param enetIfPtr The ENET context structure.
* @return The execution status.
*/
uint32_t PHY_DRV_Autodiscover(uint32_t instance, uint32_t *phyAddr);
uint32_t phy_auto_discover(enet_dev_if_t * enetIfPtr);
/*!
* @brief Gets the PHY link speed.
*
* @param instance The ENET instance number.
* @param phyAddr The PHY address.
* @param speed The address of PHY link speed.
* @param enetIfPtr The ENET context structure.
* @param status The link speed of PHY.
* @return The execution status.
*/
uint32_t PHY_DRV_GetLinkSpeed(uint32_t instance, uint32_t phyAddr, enet_phy_speed_t *speed);
uint32_t phy_get_link_speed(enet_dev_if_t * enetIfPtr, enet_phy_speed_t *status);
/*!
* @brief Gets the PHY link status.
*
* @param instance The ENET instance number.
* @param phyAddr The PHY address.
* @param enetIfPtr The ENET context structure.
* @param status The link on or down status of the PHY.
* - True the link is on.
* - False the link is down.
* @return The execution status.
*/
uint32_t PHY_DRV_GetLinkStatus(uint32_t instance, uint32_t phyAddr, bool *status);
uint32_t phy_get_link_status(enet_dev_if_t * enetIfPtr, bool *status);
/*!
* @brief Gets the PHY link duplex.
*
* @param instance The ENET instance number.
* @param phyAddr The PHY address.
* @param status The link duplex of PHY.
* @param enetIfPtr The ENET context structure.
* @param status The link duplex status of PHY.
* @return The execution status.
*/
uint32_t PHY_DRV_GetLinkDuplex(uint32_t instance, uint32_t phyAddr, enet_phy_duplex_t *status);
/*!
* @brief Upate PHY link speed.
*
* This function provides a interface to moniter the change of the link speed.
*
* @param instance The ENET instance number.
* @param phyAddr The PHY address.
* @param status The link speed of PHY.
* @return The PHY link speed change flag.
* - True PHY link speed changed effectively.
* - False PHY link speed not changed effectively.
*/
bool PHY_DRV_UpdateSpeed(uint32_t instance, uint32_t phyAddr, enet_phy_speed_t *status);
uint32_t phy_get_link_duplex(enet_dev_if_t * enetIfPtr, enet_phy_duplex_t *status);
/* @} */

View File

@ -1,48 +0,0 @@
/*
* 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.
*/
#include "fsl_enet_common.h"
#ifndef MBED_NO_ENET
/*! @brief Table of base addresses for Enet instances. */
const uint32_t g_enetBaseAddr[] = ENET_BASE_ADDRS;
/*! @brief Table to save enet IRQ enum numbers defined in CMSIS header file. */
const IRQn_Type g_enetTxIrqId[] = ENET_Transmit_IRQS;
const IRQn_Type g_enetRxIrqId[] = ENET_Receive_IRQS;
const IRQn_Type g_enetTsIrqId[] = ENET_1588_Timer_IRQS;
const IRQn_Type g_enetErrIrqId[] = ENET_Error_IRQS;
#endif /* MBED_NO_ENET */
/*******************************************************************************
* EOF
******************************************************************************/

View File

@ -1,56 +0,0 @@
/*
* 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.
*/
#ifndef __ENET_COMMON_H__
#define __ENET_COMMON_H__
#include <stdint.h>
#include "fsl_enet_features.h"
#include "fsl_device_registers.h"
#include "fsl_enet_hal.h"
#ifndef MBED_NO_ENET
/*! @brief Array for eDMA module register base address. */
extern const uint32_t g_enetBaseAddr[];
/*! @brief Two-dimentional array for enet interrupt vector number. */
extern const IRQn_Type g_enetTxIrqId[];
extern const IRQn_Type g_enetRxIrqId[];
extern const IRQn_Type g_enetTsIrqId[];
extern const IRQn_Type g_enetErrIrqId[];
#endif /* MBED_NO_ENET */
#endif /* __ENET_COMMON_H__ */
/*******************************************************************************
* EOF
******************************************************************************/

View File

@ -35,6 +35,49 @@
******************************************************************************/
/* Internal irq number*/
typedef enum _enet_irq_number
{
kEnetTsTimerNumber = 0, /*!< ENET ts_timer irq number*/
kEnetReceiveNumber = 1, /*!< ENET receive irq number*/
kEnetTransmitNumber = 2, /*!< ENET transmit irq number*/
kEnetMiiErrorNumber = 3 /*!< ENET mii error irq number*/
}enet_irq_number_t;
#if FSL_FEATURE_ENET_SUPPORT_PTP
extern enet_ptp_master_time_data_t g_ptpMasterTime;
#if FSL_FEATURE_ENET_PTP_TIMER_CHANNEL_INTERRUPT
#define ENET_TIMER_CHANNEL_NUM 2
#endif
#endif
#if defined (K64F12_SERIES) || defined (K70F12_SERIES)
IRQn_Type enet_irq_ids[HW_ENET_INSTANCE_COUNT][FSL_FEATURE_ENET_INTERRUPT_COUNT] =
{
{ ENET_1588_Timer_IRQn, ENET_Receive_IRQn, ENET_Transmit_IRQn, ENET_Error_IRQn}
};
uint8_t enetIntMap[kEnetIntNum] =
{
kEnetTsTimerNumber,
kEnetTsTimerNumber,
kEnetMiiErrorNumber,
kEnetMiiErrorNumber,
kEnetMiiErrorNumber,
kEnetMiiErrorNumber,
kEnetMiiErrorNumber,
kEnetMiiErrorNumber,
kEnetMiiErrorNumber,
kEnetReceiveNumber,
kEnetReceiveNumber,
kEnetTransmitNumber,
kEnetTransmitNumber,
kEnetMiiErrorNumber,
kEnetMiiErrorNumber,
kEnetMiiErrorNumber
};
#endif
/*******************************************************************************
* Code
******************************************************************************/

View File

@ -0,0 +1,4 @@
ENET_DRIVER_DIR := $(SDK_ROOT)/platform/drivers/enet
SOURCES += $(ENET_DRIVER_DIR)/src/fsl_enet_driver.c \
$(ENET_DRIVER_DIR)/src/fsl_enet_irq.c
INCLUDES += $(ENET_DRIVER_DIR)

View File

@ -1,85 +1,56 @@
/*
** ###################################################################
** Version: rev. 1.0, 2014-05-14
** Build: b140527
**
** Abstract:
** Chip specific module features.
**
** Copyright: 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.
**
** http: www.freescale.com
** mail: support@freescale.com
**
** Revisions:
** - rev. 1.0 (2014-05-14)
** Customer release.
**
** ###################################################################
*/
* 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_ENET_FEATURES_H__)
#define __FSL_ENET_FEATURES_H__
#if defined(CPU_MK63FN1M0VLQ12) || defined(CPU_MK63FN1M0VMD12) || defined(CPU_MK64FX512VDC12) || defined(CPU_MK64FN1M0VDC12) || \
defined(CPU_MK64FX512VLL12) || defined(CPU_MK64FN1M0VLL12) || defined(CPU_MK64FX512VLQ12) || defined(CPU_MK64FN1M0VLQ12) || \
defined(CPU_MK64FX512VMD12) || defined(CPU_MK64FN1M0VMD12) || defined(CPU_MK65FN2M0CAC18) || defined(CPU_MK65FX1M0CAC18) || \
defined(CPU_MK65FN2M0VMI18) || defined(CPU_MK65FX1M0VMI18) || defined(CPU_MK66FN2M0VLQ18) || defined(CPU_MK66FX1M0VLQ18) || \
defined(CPU_MK66FN2M0VMD18) || defined(CPU_MK66FX1M0VMD18)
/* @brief Has buffer descriptor byte swapping (register bit field ECR[DBSWP]). */
#define FSL_FEATURE_ENET_DMA_BIG_ENDIAN_ONLY (0)
/* @brief Has precision time protocol (IEEE 1588) support (register bit field ECR[EN1588], registers ATCR, ATVR, ATOFF, ATPER, ATCOR, ATINC, ATSTMP). */
#define FSL_FEATURE_ENET_SUPPORT_PTP (1)
/* @brief Number of associated interrupt vectors. */
#define FSL_FEATURE_ENET_INTERRUPT_COUNT (4)
/* @brief Errata 2597: No support for IEEE 1588 timestamp timer overflow interrupt. */
#define FSL_FEATURE_ENET_PTP_TIMER_CHANNEL_INTERRUPT_ERRATA_2579 (0)
/* @brief Has threshold for the number of frames in the receive FIFO (register bit field RSEM[STAT_SECTION_EMPTY]). */
#define FSL_FEATURE_ENET_HAS_RECEIVE_STATUS_THRESHOLD (1)
#elif defined(CPU_MK70FN1M0VMF12) || defined(CPU_MK70FX512VMF12) || defined(CPU_MK70FN1M0VMF15) || defined(CPU_MK70FX512VMF15) || \
defined(CPU_MK70FN1M0VMJ12) || defined(CPU_MK70FX512VMJ12) || defined(CPU_MK70FN1M0VMJ15) || defined(CPU_MK70FX512VMJ15)
/* @brief Has buffer descriptor byte swapping (register bit field ECR[DBSWP]). */
#define FSL_FEATURE_ENET_DMA_BIG_ENDIAN_ONLY (0)
/* @brief Has precision time protocol (IEEE 1588) support (register bit field ECR[EN1588], registers ATCR, ATVR, ATOFF, ATPER, ATCOR, ATINC, ATSTMP). */
#define FSL_FEATURE_ENET_SUPPORT_PTP (1)
/* @brief Number of associated interrupt vectors. */
#define FSL_FEATURE_ENET_INTERRUPT_COUNT (4)
/* @brief Errata 2597: No support for IEEE 1588 timestamp timer overflow interrupt. */
#define FSL_FEATURE_ENET_PTP_TIMER_CHANNEL_INTERRUPT_ERRATA_2579 (0)
/* @brief Has threshold for the number of frames in the receive FIFO (register bit field RSEM[STAT_SECTION_EMPTY]). */
#define FSL_FEATURE_ENET_HAS_RECEIVE_STATUS_THRESHOLD (0)
#if defined(CPU_MK63FN1M0VMD12) || defined(CPU_MK63FN1M0VMD12WS)
#define FSL_FEATURE_ENET_DMA_BIG_ENDIAN_ONLY (1)
#define FSL_FEATURE_ENET_SUPPORT_PTP (0)
#define FSL_FEATURE_ENET_INTERRUPT_COUNT (4)
#define FSL_FEATURE_ENET_PTP_TIMER_CHANNEL_INTERRUPT (0)
#elif defined(CPU_MK64FN1M0VMD12) || defined(CPU_MK64FX512VMD12)
#define FSL_FEATURE_ENET_DMA_BIG_ENDIAN_ONLY (0)
#define FSL_FEATURE_ENET_SUPPORT_PTP (0)
#define FSL_FEATURE_ENET_INTERRUPT_COUNT (4)
#define FSL_FEATURE_ENET_PTP_TIMER_CHANNEL_INTERRUPT (0)
#elif defined(CPU_MK70FN1M0VMJ12)
#define FSL_FEATURE_ENET_DMA_BIG_ENDIAN_ONLY (1)
#define FSL_FEATURE_ENET_SUPPORT_PTP (0)
#define FSL_FEATURE_ENET_INTERRUPT_COUNT (4)
#else
#define MBED_NO_ENET
#error "No valid CPU defined"
#endif
#endif /* __FSL_ENET_FEATURES_H__ */
#endif /* __FSL_ENET_FEATURES_H__*/
/*******************************************************************************
* EOF
******************************************************************************/

View File

@ -1,855 +0,0 @@
/*
* 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_H__)
#define __FSL_OS_ABSTRACTION_H__
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
#if defined __CC_ARM
#define inline __inline
#endif
/*!
* @addtogroup os_abstraction
* @{
*/
/*! @brief Defines the return status of OSA's functions */
typedef enum _osa_status_t
{
kStatus_OSA_Success = 0U, /*!< Success */
kStatus_OSA_Error = 1U, /*!< Failed */
kStatus_OSA_Timeout = 2U, /*!< Timeout occurs while waiting */
kStatus_OSA_Idle = 3U /*!< Used for bare metal only, the wait object is not ready
and timeout still not occur */
} osa_status_t;
/*! @brief The event flags are cleared automatically or manually.*/
typedef enum _osa_event_clear_mode_t
{
kEventAutoClear = 0U, /*!< The flags of the event will be cleared automatically. */
kEventManualClear = 1U /*!< The flags of the event will be cleared manually. */
} osa_event_clear_mode_t;
/*! @brief Locks the task scheduler or disables interrupt in critical section. */
typedef enum _osa_critical_section_mode_t
{
kCriticalLockSched = 0U, /*!< Lock scheduler in critical section. */
kCriticalDisableInt = 1U /*!< Disable interrupt in critical selection. */
} osa_critical_section_mode_t;
/* Include required header file based on RTOS selection */
#if defined (FSL_RTOS_MQX)
#define USE_RTOS 1
#include "fsl_os_abstraction_mqx.h"
#elif defined (FSL_RTOS_FREE_RTOS)
#define USE_RTOS 1
#include "fsl_os_abstraction_free_rtos.h"
#elif defined (FSL_RTOS_UCOSII)
#define USE_RTOS 1
#include "fsl_os_abstraction_ucosii.h"
#elif defined (FSL_RTOS_UCOSIII)
#define USE_RTOS 1
#include "fsl_os_abstraction_ucosiii.h"
#else
#define USE_RTOS 0
#include "fsl_os_abstraction_bm.h"
#endif
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
/*!
* @name Counting Semaphore
* @{
*/
/*!
* @brief Creates a semaphore with a given value.
*
* This function creates a semaphore and sets the value to the parameter
* initValue.
*
* @param pSem Pointer to the semaphore.
* @param initValue Initial value the semaphore will be set to.
*
* @retval kStatus_OSA_Success The semaphore is created successfully.
* @retval kStatus_OSA_Error The semaphore can not be created.
*
* Example:
@code
semaphore_t mySem;
OSA_SemaCreate(&mySem, 0);
@endcode
*
*/
osa_status_t OSA_SemaCreate(semaphore_t *pSem, uint8_t initValue);
/*!
* @brief Pending a semaphore with timeout.
*
* This function checks the semaphore's counting value. If it is positive,
* decreases it and returns kStatus_OSA_Success. Otherwise, a timeout is used
* to wait.
*
* @param pSem Pointer to the semaphore.
* @param timeout The maximum number of milliseconds to wait if semaphore is not
* positive. Pass OSA_WAIT_FOREVER to wait indefinitely, pass 0
* will return kStatus_OSA_Timeout immediately.
*
* @retval kStatus_OSA_Success The semaphore is received.
* @retval kStatus_OSA_Timeout The semaphore is not received within the specified 'timeout'.
* @retval kStatus_OSA_Error An incorrect parameter was passed.
* @retval kStatus_OSA_Idle The semaphore is not available and 'timeout' is not exhausted,
* This is only for bare metal.
*
* @note With bare metal, a semaphore can not be waited by more than one task
* at the same time.
*
* Example:
* @code
osa_status_t status;
status = OSA_SemaWait(&mySem, 100);
switch(status)
{
//...
}
@endcode
*
*/
osa_status_t OSA_SemaWait(semaphore_t *pSem, uint32_t timeout);
/*!
* @brief Signals for someone waiting on the semaphore to wake up.
*
* Wakes up one task that is waiting on the semaphore. If no task is waiting, increases
* the semaphore's counting value.
*
* @param pSem Pointer to the semaphore to signal.
*
* @retval kStatus_OSA_Success The semaphore is successfully signaled.
* @retval kStatus_OSA_Error The object can not be signaled or invalid parameter.
*
* Example:
* @code
osa_status_t status;
status = OSA_SemaPost(&mySem);
switch(status)
{
//...
}
@endcode
*
*/
osa_status_t OSA_SemaPost(semaphore_t *pSem);
/*!
* @brief Destroys a previously created semaphore.
*
* @param pSem Pointer to the semaphore to destroy.
*
* @retval kStatus_OSA_Success The semaphore is successfully destroyed.
* @retval kStatus_OSA_Error The semaphore can not be destroyed.
*
* Example:
* @code
osa_status_t status;
status = OSA_SemaDestroy(&mySem);
switch(status)
{
//...
}
@endcode
*
*/
osa_status_t OSA_SemaDestroy(semaphore_t *pSem);
/* @} */
/*!
* @name Mutex
* @{
*/
/*!
* @brief Create an unlocked mutex.
*
* This function creates a non-recursive mutex and sets it to unlocked status.
*
* @param pMutex Pointer to the Mutex.
*
* @retval kStatus_OSA_Success The mutex is created successfully.
* @retval kStatus_OSA_Error The mutex can not be created.
*
* Example:
@code
mutex_t myMutex;
osa_status_t status;
status = OSA_MutexCreate(&myMutex);
switch (status)
{
//...
}
@endcode
*
*/
osa_status_t OSA_MutexCreate(mutex_t *pMutex);
/*!
* @brief Waits for a mutex and locks it.
*
* This function checks the mutex's status. If it is unlocked, locks it and returns the
* kStatus_OSA_Success. Otherwise, waits for a timeout in milliseconds to lock.
*
* @param pMutex Pointer to the Mutex.
* @param timeout The maximum number of milliseconds to wait for the mutex.
* If the mutex is locked, Pass the value OSA_WAIT_FOREVER will
* wait indefinitely, pass 0 will return kStatus_OSA_Timeout
* immediately.
*
* @retval kStatus_OSA_Success The mutex is locked successfully.
* @retval kStatus_OSA_Timeout Timeout occurred.
* @retval kStatus_OSA_Error Incorrect parameter was passed.
* @retval kStatus_OSA_Idle The mutex is not available and 'timeout' is not exhausted,
* This is only for bare metal.
*
* @note This is non-recursive mutex, a task can not try to lock the mutex it has locked.
*
* Example:
@code
osa_status_t status;
status = OSA_MutexLock(&myMutex, 100);
switch (status)
{
//...
}
@endcode
*
*/
osa_status_t OSA_MutexLock(mutex_t *pMutex, uint32_t timeout);
/*!
* @brief Unlocks a previously locked mutex.
*
* @param pMutex Pointer to the Mutex.
*
* @retval kStatus_OSA_Success The mutex is successfully unlocked.
* @retval kStatus_OSA_Error The mutex can not be unlocked or invalid parameter.
*
* Example:
@code
osa_status_t status;
status = OSA_MutexUnlock(&myMutex);
switch (status)
{
//...
}
@endcode
*/
osa_status_t OSA_MutexUnlock(mutex_t *pMutex);
/*!
* @brief Destroys a previously created mutex.
*
* @param pMutex Pointer to the Mutex.
*
* @retval kStatus_OSA_Success The mutex is successfully destroyed.
* @retval kStatus_OSA_Error The mutex can not be destroyed.
*
* Example:
@code
osa_status_t status;
status = OSA_MutexDestroy(&myMutex);
switch (status)
{
//...
}
@endcode
*
*/
osa_status_t OSA_MutexDestroy(mutex_t *pMutex);
/* @} */
/*!
* @name Event signalling
* @{
*/
/*!
* @brief Initializes an event object with all flags cleared.
*
* This function creates an event object and set its clear mode. If clear mode
* is kEventAutoClear, when a task gets the event flags, these flags will be
* cleared automatically. If clear mode is kEventManualClear, these flags must
* be cleared manually.
*
* @param pEvent Pointer to the event object to initialize.
* @param clearMode The event is auto-clear or manual-clear.
*
* @retval kStatus_OSA_Success The event object is successfully created.
* @retval kStatus_OSA_Error The event object is not created.
*
* Example:
@code
event_t myEvent;
OSA_EventCreate(&myEvent, kEventAutoClear);
@endcode
*
*/
osa_status_t OSA_EventCreate(event_t *pEvent, osa_event_clear_mode_t clearMode);
/*!
* @brief Waits for specified event flags to be set.
*
* This function waits for a combination of flags to be set in an event object.
* Applications can wait for any/all bits to be set. Also this function could
* obtain the flags who wakeup the waiting task.
*
* @param pEvent Pointer to the event.
* @param flagsToWait Flags that to wait.
* @param waitAll Wait all flags or any flag to be set.
* @param timeout The maximum number of milliseconds to wait for the event.
* If the wait condition is not met, pass OSA_WAIT_FOREVER will
* wait indefinitely, pass 0 will return kStatus_OSA_Timeout
* immediately.
* @param setFlags Flags that wakeup the waiting task are obtained by this parameter.
*
* @retval kStatus_OSA_Success The wait condition met and function returns successfully.
* @retval kStatus_OSA_Timeout Has not met wait condition within timeout.
* @retval kStatus_OSA_Error An incorrect parameter was passed.
* @retval kStatus_OSA_Idle The wait condition is not met and 'timeout' is not exhausted,
* This is only for bare metal.
*
* @note 1. With bare metal, a event object can not be waited by more than one tasks
* at the same time.
* 2. Please pay attention to the flags bit width, FreeRTOS uses the most
* significant 8 bis as control bits, so do not wait these bits while using
* FreeRTOS.
*
* Example:
@code
osa_status_t status;
event_flags_t setFlags;
status = OSA_EventWait(&myEvent, 0x01, true, 100, &setFlags);
switch (status)
{
//...
}
@endcode
*
*/
osa_status_t OSA_EventWait(event_t *pEvent,
event_flags_t flagsToWait,
bool waitAll,
uint32_t timeout,
event_flags_t *setFlags);
/*!
* @brief Sets one or more event flags.
*
* Sets specified flags of an event object.
*
* @param pEvent Pointer to the event.
* @param flagsToSet Flags to be set.
*
* @retval kStatus_OSA_Success The flags were successfully set.
* @retval kStatus_OSA_Error An incorrect parameter was passed.
*
* Example:
@code
osa_status_t status;
status = OSA_EventSet(&myEvent, 0x01);
switch (status)
{
//...
}
@endcode
*
*/
osa_status_t OSA_EventSet(event_t *pEvent, event_flags_t flagsToSet);
/*!
* @brief Clears one or more flags.
*
* Clears specified flags of an event object.
*
* @param pEvent Pointer to the event.
* @param flagsToClear Flags to be clear.
*
* @retval kStatus_OSA_Success The flags were successfully cleared.
* @retval kStatus_OSA_Error An incorrect parameter was passed.
*
* Example:
@code
osa_status_t status;
status = OSA_EventClear(&myEvent, 0x01);
switch (status)
{
//...
}
@endcode
*
*/
osa_status_t OSA_EventClear(event_t *pEvent, event_flags_t flagsToClear);
/*!
* @brief Destroys a previously created event object.
*
* @param pEvent Pointer to the event.
*
* @retval kStatus_OSA_Success The event is successfully destroyed.
* @retval kStatus_OSA_Error Event destruction failed.
*
* Example:
@code
osa_status_t status;
status = OSA_EventDestroy(&myEvent);
switch (status)
{
//...
}
@endcode
*
*/
osa_status_t OSA_EventDestroy(event_t *pEvent);
/* @} */
/*!
* @name Task management
* @{
*/
/*!
* @brief Creates a task.
*
* This function is used to create task based on the resources defined
* by the macro OSA_TASK_DEFINE.
*
* @param task The task function entry.
* @param name The name of this task.
* @param stackSize The stack size in byte.
* @param stackMem Pointer to the stack.
* @param priority Initial priority of the task.
* @param param Pointer to be passed to the task when it is created.
* @param usesFloat This task will use float register or not.
* @param handler Pointer to the task handler.
*
* @retval kStatus_OSA_Success The task is successfully created.
* @retval kStatus_OSA_Error The task can not be created..
*
* Example:
@code
osa_status_t status;
OSA_TASK_DEFINE(task_func, stackSize);
status = OSA_TaskCreate(task_func,
"task_name",
stackSize,
task_func_stack,
prio,
param,
false,
&task_func_task_handler);
switch (status)
{
//...
}
@endcode
*
* @note Use the return value to check whether the task is
* created successfully. DO NOT check handler. For uC/OS-III,
* handler is not NULL even if the task creation has failed.
*/
osa_status_t OSA_TaskCreate(task_t task,
uint8_t *name,
uint16_t stackSize,
task_stack_t *stackMem,
uint16_t priority,
task_param_t param,
bool usesFloat,
task_handler_t *handler);
/*!
* @brief Destroys a previously created task.
*
* @param handler The handler of the task to destroy. Returned by the OSA_TaskCreate function.
*
* @retval kStatus_OSA_Success The task was successfully destroyed.
* @retval kStatus_OSA_Error Task destruction failed or invalid parameter.
*
* Example:
@code
osa_status_t status;
status = OSA_TaskDestroy(myTaskHandler);
switch (status)
{
//...
}
@endcode
*
*/
osa_status_t OSA_TaskDestroy(task_handler_t handler);
/*!
* @brief Puts the active task to the end of scheduler's queue.
*
* When a task calls this function, it gives up the CPU and puts itself to the
* end of a task ready list.
*
* @retval kStatus_OSA_Success The function is called successfully.
* @retval kStatus_OSA_Error Error occurs with this function.
*
* Example:
@code
osa_status_t status;
status = OSA_TaskYield();
switch (status)
{
//...
}
@endcode
*
*/
osa_status_t OSA_TaskYield(void);
/*!
* @brief Gets the handler of active task.
*
* @return Handler to current active task.
*
* Example:
@code
task_handler_t handler = OSA_TaskYield();
@endcode
*
*/
task_handler_t OSA_TaskGetHandler(void);
/*!
* @brief Gets the priority of a task.
*
* @param handler The handler of the task whose priority is received.
*
* @return Task's priority.
*
* Example:
@code
uint16_t taskPrio = OSA_TaskGetPriority(taskHandler);
@endcode
*
*/
uint16_t OSA_TaskGetPriority(task_handler_t handler);
/*!
* @brief Sets the priority of a task.
*
* @param handler The handler of the task whose priority is received.
* @param priority The priority to set.
*
* @retval kStatus_OSA_Success Task's priority is set successfully.
* @retval kStatus_OSA_Error Task's priority can not be set.
*
* Example:
@code
osa_status_t status;
status = OSA_TaskSetPriority(taskHandler, newPrio);
switch (status)
{
//...
}
@endcode
*
*/
osa_status_t OSA_TaskSetPriority(task_handler_t handler, uint16_t priority);
/* @} */
/*!
* @name Message queues
* @{
*/
/*!
* @brief Initializes a message queue.
*
* This function initializes the message queue that was declared previously.
* This is an example demonstrating use:
@code
msg_queue_handler_t handler;
MSG_QUEUE_DECLARE(my_message, msg_num, msg_size);
handler = OSA_MsgQCreate(my_message, msg_num, msg_size);
@endcode
*
* @param queue The queue declared through the MSG_QUEUE_DECLARE macro.
* @param message_number The number of elements in the queue.
* @param message_size Size of every elements in words.
*
* @return Handler to access the queue for put and get operations. If message queue
* created failed, return 0.
*/
msg_queue_handler_t OSA_MsgQCreate(msg_queue_t *queue,
uint16_t message_number,
uint16_t message_size);
/*!
* @brief Puts a message at the end of the queue.
*
* This function puts a message to the end of the message queue. If the queue
* is full, this function returns the kStatus_OSA_Error;
*
* @param handler Queue handler returned by the OSA_MsgQCreate function.
* @param pMessage Pointer to the message to be put into the queue.
*
* @retval kStatus_OSA_Success Message successfully put into the queue.
* @retval kStatus_OSA_Error The queue was full or an invalid parameter was passed.
*
* Example:
@code
osa_status_t status;
struct MESSAGE messageToPut = ...;
status = OSA_MsgQPut(queueHandler, &messageToPut);
switch (status)
{
//...
}
@endcode
*
*/
osa_status_t OSA_MsgQPut(msg_queue_handler_t handler, void* pMessage);
/*!
* @brief Reads and remove a message at the head of the queue.
*
* This function gets a message from the head of the message queue. If the
* queue is empty, timeout is used to wait.
*
* @param handler Queue handler returned by the OSA_MsgQCreate function.
* @param pMessage Pointer to a memory to save the message.
* @param timeout The number of milliseconds to wait for a message. If the
* queue is empty, pass OSA_WAIT_FOREVER will wait indefinitely,
* pass 0 will return kStatus_OSA_Timeout immediately.
*
* @retval kStatus_OSA_Success Message successfully obtained from the queue.
* @retval kStatus_OSA_Timeout The queue remains empty after timeout.
* @retval kStatus_OSA_Error Invalid parameter.
* @retval kStatus_OSA_Idle The queue is empty and 'timeout' is not exhausted,
* This is only for bare metal.
*
* @note With bere metal, there should be only one process waiting on the queue.
*
* Example:
@code
osa_status_t status;
struct MESSAGE messageToGet;
status = OSA_MsgQGet(queueHandler, &messageToGet, 100);
switch (status)
{
//...
}
@endcode
*
*/
osa_status_t OSA_MsgQGet(msg_queue_handler_t handler,
void *pMessage,
uint32_t timeout);
/*!
* @brief Destroys a previously created queue.
*
* @param handler Queue handler returned by the OSA_MsgQCreate function.
*
* @retval kStatus_OSA_Success The queue was successfully destroyed.
* @retval kStatus_OSA_Error Message queue destruction failed.
*
* Example:
@code
osa_status_t status;
status = OSA_MsgQDestroy(queueHandler);
switch (status)
{
//...
}
@endcode
*
*/
osa_status_t OSA_MsgQDestroy(msg_queue_handler_t handler);
/* @} */
/*!
* @name Memory Management
* @{
*/
/*!
* @brief Reserves the requested amount of memory in bytes.
*
* @param size Amount of bytes to reserve.
*
* @return Pointer to the reserved memory. NULL if memory could not be allocated.
*/
void * OSA_MemAlloc(size_t size);
/*!
* @brief Reserves the requested amount of memory in bytes and initializes it to 0.
*
* @param size Amount of bytes to reserve.
*
* @return Pointer to the reserved memory. NULL if memory could not be allocated.
*/
void * OSA_MemAllocZero(size_t size);
/*!
* @brief Releases the memory previously reserved.
*
* @param ptr Pointer to the start of the memory block previously reserved.
*
* @retval kStatus_OSA_Success Memory correctly freed.
* @retval kStatus_OSA_Error Error occurs during free the memory.
*/
osa_status_t OSA_MemFree(void *ptr);
/* @} */
/*!
* @name Time management
* @{
*/
/*!
* @brief Delays execution for a number of milliseconds.
*
* @param delay The time in milliseconds to wait.
*/
void OSA_TimeDelay(uint32_t delay);
/*!
* @brief Gets the current time since system boot in milliseconds.
*
* @return Current time in milliseconds.
*/
uint32_t OSA_TimeGetMsec(void);
/* @} */
/*!
* @name Interrupt management
* @{
*/
/*!
* @brief Installs the interrupt handler.
*
* @param IRQNumber IRQ number of the interrupt.
* @param handler The interrupt handler to install.
*
* @retval kStatus_OSA_Success Handler is installed successfully.
* @retval kStatus_OSA_Error Handler could not be installed.
*/
osa_status_t OSA_InstallIntHandler (int32_t IRQNumber,
void (*handler)(void));
/* @} */
/*!
* @name Critical section
* @{
*/
/*!
* @brief Enters the critical section to ensure some code is not preempted.
*
* @param mode Lock task scheduler of disable interrupt in critical section.
* Pass kCriticalLockSched to lock task scheduler,
* pass kCriticalDisableInt to disable interrupt.
*/
void OSA_EnterCritical(osa_critical_section_mode_t mode);
/*!
* @brief Exits the critical section.
*
* @param mode Lock task scheduler of disable interrupt in critical section.
* Pass kCriticalLockSched to lock task scheduler,
* pass kCriticalDisableInt to disable interrupt.
*/
void OSA_ExitCritical(osa_critical_section_mode_t mode);
/* @} */
/*!
* @name OSA initialize
* @{
*/
/*!
* @brief Initializes the RTOS services.
*
* This function sets up the basic RTOS services. It should be called
* first in the main function.
*
* @retval kStatus_OSA_Success RTOS services are initialized successfully.
* @retval kStatus_OSA_Error Error occurs during initialization.
*/
osa_status_t OSA_Init(void);
/*!
* @brief Starts the RTOS.
*
* This function starts the RTOS scheduler and may never return.
*
* @retval kStatus_OSA_Success RTOS starts to run successfully.
* @retval kStatus_OSA_Error Error occurs when start RTOS.
*/
osa_status_t OSA_Start(void);
/* @} */
#if defined(__cplusplus)
}
#endif
/*! @}*/
#endif /* __FSL_OS_ABSTRACTION_H__ */
/*******************************************************************************
* EOF
******************************************************************************/

View File

@ -1,185 +0,0 @@
/*
* 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_BM_H__)
#define __FSL_OS_ABSTRACTION_BM_H__
/*!
* @addtogroup os_abstraction_bm
* @{
*/
/*******************************************************************************
* Declarations
******************************************************************************/
/*! @brief Type for an semaphore */
typedef struct Semaphore
{
volatile bool isWaiting; /*!< Is any task waiting for a timeout on this object */
volatile uint8_t semCount; /*!< The count value of the object */
uint32_t time_start; /*!< The time to start timeout */
uint32_t timeout; /*!< Timeout to wait in milliseconds */
} semaphore_t;
/*! @brief Type for a mutex */
typedef struct Mutex
{
volatile bool isWaiting; /*!< Is any task waiting for a timeout on this mutex */
volatile bool isLocked; /*!< Is the object locked or not */
uint32_t time_start; /*!< The time to start timeout */
uint32_t timeout; /*!< Timeout to wait in milliseconds */
} mutex_t;
/*! @brief Type for an event flags group, bit 32 is reserved */
typedef uint32_t event_flags_t;
/*! @brief Type for an event object */
typedef struct Event
{
volatile bool isWaiting; /*!< Is any task waiting for a timeout on this event */
uint32_t time_start; /*!< The time to start timeout */
uint32_t timeout; /*!< Timeout to wait in milliseconds */
volatile event_flags_t flags; /*!< The flags status */
osa_event_clear_mode_t clearMode; /*!< Auto clear or manual clear */
} event_t;
/*! @brief Type for task parameter */
typedef void* task_param_t;
/*! @brief Type for a task pointer */
typedef void (* task_t)(task_param_t param);
/*! @brief Task control block for bare metal. */
typedef struct TaskControlBlock
{
task_t p_func; /*!< Task's entry */
task_param_t param; /*!< Task's parameter */
struct TaskControlBlock *next; /*!< Pointer to next task control block */
struct TaskControlBlock *prev; /*!< Pointer to previous task control block */
} task_control_block_t;
/*! @brief Type for a task handler, returned by the OSA_TaskCreate function */
typedef task_control_block_t* task_handler_t;
/*! @brief Type for a task stack */
typedef uint32_t task_stack_t;
/*! @brief Type for a message queue */
typedef struct MsgQueue
{
uint32_t *queueMem; /*!< Points to the queue memory */
uint16_t number; /*!< The number of messages in the queue */
uint16_t size; /*!< The size in words of each message */
uint16_t head; /*!< Index of the next message to be read */
uint16_t tail; /*!< Index of the next place to write to */
semaphore_t queueSem; /*!< Semaphore wakeup tasks waiting for msg */
volatile bool isEmpty; /*!< Whether queue is empty */
}msg_queue_t;
/*! @brief Type for a message queue handler */
typedef msg_queue_t* msg_queue_handler_t;
/*! @brief Constant to pass as timeout value in order to wait indefinitely. */
#define OSA_WAIT_FOREVER 0xFFFFFFFFU
/*! @brief How many tasks can the bare metal support. */
#define TASK_MAX_NUM 5
/*!
* @name Thread management
* @{
*/
/*!
* @brief Defines a task.
*
* This macro defines resources for a task statically. Then, the OSA_TaskCreate
* creates the task based-on these resources.
*
* @param task The task function.
* @param stackSize The stack size this task needs in bytes.
*/
#define OSA_TASK_DEFINE(task, stackSize) \
task_stack_t* task##_stack = NULL; \
task_handler_t task##_task_handler
#if defined(__cplusplus)
extern "C" {
#endif /* __cplusplus*/
/*!
* @brief Calls all task functions one time except for the current task.
*
* This function calls all other task functions one time. If current
* task is waiting for an event triggered by other tasks, this function
* could be used to trigger the event.
*
* @note There should be only one task calls this function, if more than
* one task call this function, stack overflow may occurs. Be careful
* to use this function.
*
*/
void OSA_PollAllOtherTasks(void);
#if defined(__cplusplus)
}
#endif /* __cplusplus*/
/* @} */
/*!
* @name Message queues
* @{
*/
/*!
* @brief This macro statically reserves the memory required for the queue.
*
* @param name Identifier for the memory region.
* @param number Number of elements in the queue.
* @param size Size of every element in words.
*/
#define MSG_QUEUE_DECLARE(name, number, size) uint32_t queueMem_##name[number * size]; \
msg_queue_t entity_##name = { \
.queueMem = queueMem_##name \
}; \
msg_queue_t *name = &(entity_##name)
/* @} */
/*! @}*/
#endif /* __FSL_OS_ABSTRACTION_BM_H__ */
/*******************************************************************************
* EOF
******************************************************************************/

View File

@ -1,983 +0,0 @@
/*
* 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.
*/
#include <assert.h>
#include "fsl_os_abstraction.h"
#include "fsl_interrupt_manager.h"
#include "fsl_clock_manager.h"
#include "fsl_lptmr_hal.h"
#include "fsl_lptmr_features.h"
/* Include lptmr features to check wether lptimer module is available. */
/* Only one lptmr and always use it. */
#define BM_LPTMR_INSTANCE 0
#define BM_LPTMR_BASE LPTMR0_BASE
/*FUNCTION**********************************************************************
*
* Function Name : time_diff
* Description : This function gets the difference between two time stamp,
* time overflow is considered.
*
*END**************************************************************************/
static uint32_t time_diff(uint32_t time_start, uint32_t time_end)
{
if (time_end >= time_start)
{
return time_end - time_start;
}
else
{
/* lptmr count is 16 bits. */
return 0xFFFFU - time_start + time_end + 1;
}
}
/*FUNCTION**********************************************************************
*
* Function Name : OSA_SemaCreate
* Description : This function is used to create a semaphore. Return
* kStatus_OSA_Success if create successfully, otherwise return kStatus_OSA_Error.
*
*END**************************************************************************/
osa_status_t OSA_SemaCreate(semaphore_t *pSem, uint8_t initValue)
{
assert(pSem);
pSem->semCount = initValue;
pSem->isWaiting = false;
pSem->time_start = 0u;
pSem->timeout = 0u;
return kStatus_OSA_Success;
}
/*FUNCTION**********************************************************************
*
* Function Name : OSA_SemaWait
* Description : This function checks the semaphore's counting value, if it is
* positive, decreases it and returns kStatus_OSA_Success, otherwise, timeout
* will be used for wait. The parameter timeout indicates how long should wait
* in milliseconds. Pass OSA_WAIT_FOREVER to wait indefinitely, pass 0 will
* return kStatus_OSA_Timeout immediately if semaphore is not positive.
* This function returns kStatus_OSA_Success if the semaphore is received, returns
* kStatus_OSA_Timeout if the semaphore is not received within the specified
* 'timeout', returns kStatus_OSA_Error if any errors occur during waiting,
* returns kStatus_OSA_Idle if the semaphore is not available and 'timeout' is
* not exhausted, because wait functions should not block with bare metal.
*
*END**************************************************************************/
osa_status_t OSA_SemaWait(semaphore_t *pSem, uint32_t timeout)
{
uint32_t currentTime;
assert(pSem);
/* Check the sem count first. Deal with timeout only if not already set */
if (pSem->semCount)
{
INT_SYS_DisableIRQGlobal();
pSem->semCount --;
pSem->isWaiting = false;
INT_SYS_EnableIRQGlobal();
return kStatus_OSA_Success;
}
else
{
if (0 == timeout)
{
/* If timeout is 0 and semaphore is not available, return kStatus_OSA_Timeout. */
return kStatus_OSA_Timeout;
}
else if (pSem->isWaiting)
{
/* Check for timeout */
currentTime = OSA_TimeGetMsec();
if (pSem->timeout < time_diff(pSem->time_start, currentTime))
{
INT_SYS_DisableIRQGlobal();
pSem->isWaiting = false;
INT_SYS_EnableIRQGlobal();
return kStatus_OSA_Timeout;
}
}
else if (timeout != OSA_WAIT_FOREVER) /* If don't wait forever, start the timer */
{
/* Start the timeout counter */
INT_SYS_DisableIRQGlobal();
pSem->isWaiting = true;
INT_SYS_EnableIRQGlobal();
pSem->time_start = OSA_TimeGetMsec();
pSem->timeout = timeout;
}
}
return kStatus_OSA_Idle;
}
/*FUNCTION**********************************************************************
*
* Function Name : OSA_SemaPost
* Description : This function is used to wake up one task that wating on the
* semaphore. If no task is waiting, increase the semaphore. The function returns
* kStatus_OSA_Success if the semaphre is post successfully, otherwise returns
* kStatus_OSA_Error.
*
*END**************************************************************************/
osa_status_t OSA_SemaPost(semaphore_t *pSem)
{
assert(pSem);
/* The max value is 0xFF */
if (0xFF == pSem->semCount)
{
return kStatus_OSA_Error;
}
INT_SYS_DisableIRQGlobal();
++pSem->semCount;
INT_SYS_EnableIRQGlobal();
return kStatus_OSA_Success;
}
/*FUNCTION**********************************************************************
*
* Function Name : OSA_SemaDestroy
* Description : This function is used to destroy a semaphore.
* Return kStatus_OSA_Success if the semaphore is destroyed successfully, otherwise
* return kStatus_OSA_Error.
*
*END**************************************************************************/
osa_status_t OSA_SemaDestroy(semaphore_t *pSem)
{
assert(pSem);
return kStatus_OSA_Success;
}
/*FUNCTION**********************************************************************
*
* Function Name : OSA_MutexCreate
* Description : This function is used to create a mutex.
* Return kStatus_OSA_Success if create successfully, otherwise return kStatus_OSA_Error.
*
*END**************************************************************************/
osa_status_t OSA_MutexCreate(mutex_t *pMutex)
{
assert(pMutex);
pMutex->isLocked = false;
pMutex->isWaiting = false;
pMutex->time_start = 0u;
pMutex->timeout = 0u;
return kStatus_OSA_Success;
}
/*FUNCTION**********************************************************************
*
* Function Name : OSA_MutexLock
* Description : This function checks the mutex's status, if it is unlocked,
* lock it and returns kStatus_OSA_Success, otherwise, timeout will be used for
* wait. The parameter timeout indicates how long should wait in milliseconds.
* Pass OSA_WAIT_FOREVER to wait indefinitely, pass 0 will return the value
* kStatus_OSA_Timeout immediately if mutex is locked.
* This function returns kStatus_OSA_Success if the mutex is obtained, returns
* kStatus_OSA_Timeout if the mutex is not obtained within the specified
* 'timeout', returns kStatus_OSA_Error if any errors occur during waiting,
* returns kStatus_OSA_Idle if the mutex is not available and 'timeout' is
* not exhausted, because wait functions should not block with bare metal.
*
*END**************************************************************************/
osa_status_t OSA_MutexLock(mutex_t *pMutex, uint32_t timeout)
{
uint32_t currentTime;
assert(pMutex);
/* Always check first. Deal with timeout only if not available. */
if (pMutex->isLocked == false)
{
/* Get the lock and return success */
INT_SYS_DisableIRQGlobal();
pMutex->isLocked = true;
pMutex->isWaiting = false;
INT_SYS_EnableIRQGlobal();
return kStatus_OSA_Success;
}
else
{
if (0 == timeout)
{
/* If timeout is 0 and mutex is not available, return kStatus_OSA_Timeout. */
return kStatus_OSA_Timeout;
}
else if (pMutex->isWaiting)
{
/* Check for timeout */
currentTime = OSA_TimeGetMsec();
if (pMutex->timeout < time_diff(pMutex->time_start, currentTime))
{
INT_SYS_DisableIRQGlobal();
pMutex->isWaiting = false;
INT_SYS_EnableIRQGlobal();
return kStatus_OSA_Timeout;
}
}
else if (timeout != OSA_WAIT_FOREVER) /* If dont't wait forever, start timer. */
{
/* Start the timeout counter */
INT_SYS_DisableIRQGlobal();
pMutex->isWaiting = true;
INT_SYS_EnableIRQGlobal();
pMutex->time_start = OSA_TimeGetMsec();
pMutex->timeout = timeout;
}
}
return kStatus_OSA_Idle;
}
/*FUNCTION**********************************************************************
*
* Function Name : OSA_MutexUnlock
* Description : This function is used to unlock a mutex.
*
*END**************************************************************************/
osa_status_t OSA_MutexUnlock(mutex_t *pMutex)
{
assert(pMutex);
INT_SYS_DisableIRQGlobal();
pMutex->isLocked = false;
INT_SYS_EnableIRQGlobal();
return kStatus_OSA_Success;
}
/*FUNCTION**********************************************************************
*
* Function Name : OSA_MutexDestroy
* Description : This function is used to destroy a mutex.
* Return kStatus_OSA_Success if the lock object is destroyed successfully, otherwise
* return kStatus_OSA_Error.
*
*END**************************************************************************/
osa_status_t OSA_MutexDestroy(mutex_t *pMutex)
{
assert(pMutex);
return kStatus_OSA_Success;
}
/*FUNCTION**********************************************************************
*
* Function Name : OSA_EventCreate
* Description : This function is used to create a event object. Return
* kStatus_OSA_Success if create successfully, otherwise return kStatus_OSA_Error.
*
*END**************************************************************************/
osa_status_t OSA_EventCreate(event_t *pEvent, osa_event_clear_mode_t clearMode)
{
assert(pEvent);
pEvent->isWaiting = false;
pEvent->flags = 0;
pEvent->clearMode = clearMode;
pEvent->time_start = 0u;
pEvent->timeout = 0u;
return kStatus_OSA_Success;
}
/*FUNCTION**********************************************************************
*
* Function Name : OSA_EventWait
* Description : This function checks the event's status, if it meets the wait
* condition, return kStatus_OSA_Success, otherwise, timeout will be used for
* wait. The parameter timeout indicates how long should wait in milliseconds.
* Pass OSA_WAIT_FOREVER to wait indefinitely, pass 0 will return the value
* kStatus_OSA_Timeout immediately if wait condition is not met. The event flags
* will be cleared if the event is auto clear mode. Flags that wakeup waiting
* task could be obtained from the parameter setFlags.
* This function returns kStatus_OSA_Success if wait condition is met, returns
* kStatus_OSA_Timeout if wait condition is not met within the specified
* 'timeout', returns kStatus_OSA_Error if any errors occur during waiting,
* returns kStatus_OSA_Idle if wait condition is not met and 'timeout' is
* not exhausted, because wait functions should not block with bare metal.
*
*END**************************************************************************/
osa_status_t OSA_EventWait(event_t *pEvent,
event_flags_t flagsToWait,
bool waitAll,
uint32_t timeout,
event_flags_t *setFlags)
{
uint32_t currentTime;
assert(pEvent);
assert(setFlags);
osa_status_t retVal = kStatus_OSA_Idle;
*setFlags = pEvent->flags & flagsToWait;
/* Check the event flag first, if does not meet wait condition, deal with timeout. */
if ((((!waitAll) && (*setFlags))) || (*setFlags == flagsToWait))
{
INT_SYS_DisableIRQGlobal();
pEvent->isWaiting = false;
if(kEventAutoClear == pEvent->clearMode)
{
pEvent->flags &= ~flagsToWait;
}
INT_SYS_EnableIRQGlobal();
return kStatus_OSA_Success;
}
else
{
if (0 == timeout)
{
/* If timeout is 0 and wait condition is not met, return kStatus_OSA_Timeout. */
return kStatus_OSA_Timeout;
}
else if (pEvent->isWaiting)
{
/* Check for timeout */
currentTime = OSA_TimeGetMsec();
if (pEvent->timeout < time_diff(pEvent->time_start, currentTime))
{
INT_SYS_DisableIRQGlobal();
pEvent->isWaiting = false;
INT_SYS_EnableIRQGlobal();
retVal = kStatus_OSA_Timeout;
}
}
else if(timeout != OSA_WAIT_FOREVER) /* If no timeout, don't start the timer */
{
/* Start the timeout counter */
INT_SYS_DisableIRQGlobal();
pEvent->isWaiting = true;
INT_SYS_EnableIRQGlobal();
pEvent->time_start = OSA_TimeGetMsec();
pEvent->timeout = timeout;
}
}
return retVal;
}
/*FUNCTION**********************************************************************
*
* Function Name : OSA_EventSet
* Description : Set one or more event flags of an event object.
* Return kStatus_OSA_Success if set successfully, kStatus_OSA_Error if failed.
*
*END**************************************************************************/
osa_status_t OSA_EventSet(event_t *pEvent, event_flags_t flagsToSet)
{
assert(pEvent);
/* Set flags ensuring atomic operation */
INT_SYS_DisableIRQGlobal();
pEvent->flags |= flagsToSet;
INT_SYS_EnableIRQGlobal();
return kStatus_OSA_Success;
}
/*FUNCTION**********************************************************************
*
* Function Name : OSA_EventClear
* Description : Clear one or more event flags of an event object.
* Return kStatus_OSA_Success if clear successfully, kStatus_OSA_Error if failed.
*
*END**************************************************************************/
osa_status_t OSA_EventClear(event_t *pEvent, event_flags_t flagsToClear)
{
assert(pEvent);
/* Clear flags ensuring atomic operation */
INT_SYS_DisableIRQGlobal();
pEvent->flags &= ~flagsToClear;
INT_SYS_EnableIRQGlobal();
return kStatus_OSA_Success;
}
/*FUNCTION**********************************************************************
*
* Function Name : OSA_EventDestroy
* Description : This function is used to destroy a event object. Return
* kStatus_OSA_Success if the event object is destroyed successfully, otherwise
* return kStatus_OSA_Error.
*
*END**************************************************************************/
osa_status_t OSA_EventDestroy(event_t *pEvent)
{
assert(pEvent);
return kStatus_OSA_Success;
}
/* The task APIs are only available if TASK_MAX_NUM>0. */
#if (TASK_MAX_NUM > 0)
/* Global variales for task. */
static task_handler_t g_curTask; /* Current task. */
/*
* All task control blocks in g_taskControlBlockPool will be linked as a
* list, and the list is managed by the pointer g_freeTaskControlBlock.
*/
static task_control_block_t g_taskControlBlockPool[TASK_MAX_NUM];
/*
* Pointer to the free task control blocks. To create a task, we should get
* task control block from this pointer. When task is destroyed, the control
* block will be returned and managed by this pointer.
*/
static task_control_block_t *g_freeTaskControlBlock;
/* Head node of task list, all tasks will be linked to this head node. */
static task_control_block_t g_taskListHead;
/*FUNCTION**********************************************************************
*
* Function Name : task_init
* Description : This function is used to initialize bare metal's task system,
* it will prepare task control block pool and initialize corresponding
* structures. This function should be called before creating any tasks.
*
*END**************************************************************************/
void task_init(void)
{
int32_t i = TASK_MAX_NUM-1;
g_taskControlBlockPool[i].next = NULL;
while (i--)
{
/* Link all task control blocks to a list. */
g_taskControlBlockPool[i].next = &g_taskControlBlockPool[i+1];
}
g_freeTaskControlBlock = g_taskControlBlockPool;
/* Initialize task list. */
g_taskListHead.next = &g_taskListHead;
g_taskListHead.prev = &g_taskListHead;
}
/*FUNCTION**********************************************************************
*
* Function Name : OSA_TaskCreate
* Description : This function will register the task function and parameter
* to task list, so that the task functions can be called in turn. Return
* kStatus_OSA_Success if register successfully, otherwise return kStatus_OSA_Error;
*
*END**************************************************************************/
osa_status_t OSA_TaskCreate(task_t task,
uint8_t *name,
uint16_t stackSize,
task_stack_t *stackMem,
uint16_t priority,
task_param_t param,
bool usesFloat,
task_handler_t *handler)
{
task_control_block_t *p_newTaskControlBlock;
task_control_block_t *p_taskListTail;
if (!g_freeTaskControlBlock)
{
/* No more task control blocks can be got. */
return kStatus_OSA_Error;
}
else
{
/* Get new task control block from pool. */
p_newTaskControlBlock = g_freeTaskControlBlock;
g_freeTaskControlBlock = g_freeTaskControlBlock->next;
/* Set task entry and parameter.*/
p_newTaskControlBlock->p_func = task;
p_newTaskControlBlock->param = param;
/* Add p_newTaskControlBlock to the tail of task list. */
p_taskListTail = g_taskListHead.prev;
p_taskListTail->next = p_newTaskControlBlock;
p_newTaskControlBlock->next = &g_taskListHead;
g_taskListHead.prev = p_newTaskControlBlock;
p_newTaskControlBlock->prev = p_taskListTail;
/* Task handler is pointer of task control block. */
*handler = p_newTaskControlBlock;
return kStatus_OSA_Success;
}
}
/*FUNCTION**********************************************************************
*
* Function Name : OSA_TaskDestroy
* Description : This function will remove task control block from task list,
* so that the task functions will not called by anymore.
* Return kStatus_OSA_Success if successfully, otherwise return kStatus_OSA_Error;
*
*END**************************************************************************/
osa_status_t OSA_TaskDestroy(task_handler_t handler)
{
assert(handler);
/* Remove task control block from task list. */
handler->prev->next = handler->next;
handler->next->prev = handler->prev;
/*
* If current task is destroyed, then g_curTask will point to the previous
* task, so that the subsequent tasks could be called. Check the function
* OSA_Start for more details.
*/
if (handler == g_curTask)
{
g_curTask = handler->prev;
}
/* Put task control block back to pool. */
handler->prev = NULL;
handler->next = g_freeTaskControlBlock;
g_freeTaskControlBlock = handler;
return kStatus_OSA_Success;
}
/*FUNCTION**********************************************************************
*
* Function Name : OSA_TaskYield
* Description : This function is not implement with bare metal.
*
*END**************************************************************************/
osa_status_t OSA_TaskYield(void)
{
return kStatus_OSA_Success;
}
/*FUNCTION**********************************************************************
*
* Function Name : OSA_TaskGetHandler
* Description : This function is used to get current active task's handler.
*
*END**************************************************************************/
task_handler_t OSA_TaskGetHandler(void)
{
return g_curTask;
}
/*FUNCTION**********************************************************************
*
* Function Name : OSA_TaskGetPriority
* Description : This function is not implement with bare metal.
*
*END**************************************************************************/
uint16_t OSA_TaskGetPriority(task_handler_t handler)
{
return 0;
}
/*FUNCTION**********************************************************************
*
* Function Name : OSA_TaskSetPriority
* Description : This function is not implement with bare metal.
*
*END**************************************************************************/
osa_status_t OSA_TaskSetPriority(task_handler_t handler, uint16_t priority)
{
return kStatus_OSA_Success;
}
#endif
/*FUNCTION**********************************************************************
*
* Function Name : OSA_MsgQCreate
* Description : This function is used to create a message queue.
* Return the handle to the message queue if create successfully, otherwise
* return 0.
*
*END**************************************************************************/
msg_queue_handler_t OSA_MsgQCreate(msg_queue_t *queue,
uint16_t message_number,
uint16_t message_size)
{
assert(queue);
queue->number = message_number;
queue->size = message_size;
queue->head = 0;
queue->tail = 0;
queue->isEmpty = true;
if(kStatus_OSA_Success == OSA_SemaCreate(&queue->queueSem, 0))
{
return queue;
}
else
{
return NULL;
}
}
/*FUNCTION**********************************************************************
*
* Function Name : OSA_MsgQPut
* Description : This function is used to put a message to a message queue.
* Return kStatus_OSA_Success if the message is put successfully, otherwise
* return kStatus_OSA_Error.
*
*END**************************************************************************/
osa_status_t OSA_MsgQPut(msg_queue_handler_t handler, void* pMessage)
{
assert(handler);
uint32_t *from_ptr, *to_ptr;
uint16_t msgSize;
/* Check that there is room in the queue */
INT_SYS_DisableIRQGlobal();
if((handler->tail != handler->head) || (handler->isEmpty))
{
from_ptr = (uint32_t*)pMessage;
to_ptr = &handler->queueMem[handler->tail * handler->size];
/* Copy entire message into the queue, based on the size configured at creation */
msgSize = handler->size;
while(msgSize--)
{
*to_ptr++ = *from_ptr++;
}
/* Adjust tail pointer and wrap in case the end of the buffer is reached */
++handler->tail;
if(handler->tail == handler->number)
{
handler->tail = 0;
}
/* If queue was empty, clear the empty flag and signal that it is not empty anymore */
if(handler->isEmpty)
{
handler->isEmpty = false;
OSA_SemaPost(&handler->queueSem);
}
INT_SYS_EnableIRQGlobal();
return kStatus_OSA_Success;
}
else
{
INT_SYS_EnableIRQGlobal();
return kStatus_OSA_Error;
}
}
/*FUNCTION**********************************************************************
*
* Function Name : OSA_MsgQGet
* Description : This function checks the queue's status, if it is not empty,
* get message from it and return kStatus_OSA_Success, otherwise, timeout will
* be used for wait. The parameter timeout indicates how long should wait in
* milliseconds. Pass OSA_WAIT_FOREVER to wait indefinitely, pass 0 will return
* kStatus_OSA_Timeout immediately if queue is empty.
* This function returns kStatus_OSA_Success if message is got successfully,
* returns kStatus_OSA_Timeout if message queue is empty within the specified
* 'timeout', returns kStatus_OSA_Error if any errors occur during waiting,
* returns kStatus_OSA_Idle if message queue is empty and 'timeout' is
* not exhausted, because wait functions should not block with bare metal.
*
*END**************************************************************************/
osa_status_t OSA_MsgQGet(msg_queue_handler_t handler,
void *pMessage,
uint32_t timeout)
{
assert(handler);
osa_status_t retVal = kStatus_OSA_Error;
uint32_t *from_ptr, *to_ptr;
uint16_t msgSize;
INT_SYS_DisableIRQGlobal();
/* Check if the queue is not empty */
if(!handler->isEmpty)
{
from_ptr = &handler->queueMem[handler->head * handler->size];
to_ptr = (uint32_t*)(pMessage);
/* Copy entire message into the queue, based on the size configured at creation */
msgSize = handler->size;
while(msgSize--)
{
*to_ptr++ = *from_ptr++;
}
/* Adjust head pointer and wrap in case the end of the buffer is reached */
++handler->head;
if(handler->head == handler->number)
{
handler->head = 0;
}
/* If queue was empty, clear the empty flag and signal that it is not empty anymore */
if(handler->head == handler->tail)
{
handler->isEmpty = true;
/* Set semapohre to 0 because the queue is empty. */
(void)OSA_SemaWait(&handler->queueSem, 0);
}
INT_SYS_EnableIRQGlobal();
retVal = kStatus_OSA_Success;
}
else
{
INT_SYS_EnableIRQGlobal();
/* Wait for the semaphore if the queue was empty */
retVal = OSA_SemaWait(&handler->queueSem, timeout);
}
return retVal;
}
/*FUNCTION**********************************************************************
*
* Function Name : OSA_MsgQDestroy
* Description : This function is used to destroy the message queue.
* Return kStatus_OSA_Success if the message queue is destroyed successfully,
* otherwise return kStatus_OSA_Error.
*
*END**************************************************************************/
osa_status_t OSA_MsgQDestroy(msg_queue_handler_t handler)
{
assert(handler);
return OSA_SemaDestroy(&handler->queueSem);
}
/*FUNCTION**********************************************************************
*
* Function Name : OSA_MemAlloc
* Description : This function is used to allocate amount of memory in bytes.
* Return the pointer to the memory if success, otherwise return NULL;
*
*END**************************************************************************/
void * OSA_MemAlloc(size_t size)
{
return malloc(size);
}
/*FUNCTION**********************************************************************
*
* Function Name : OSA_MemAllocZero
* Description : This function is used to allocate amount of memory in bytes
* and initializes it to 0.
* Return the pointer to the memory if success, otherwise return NULL;
*
*END**************************************************************************/
void * OSA_MemAllocZero(size_t size)
{
return calloc(1, size);
}
/*FUNCTION**********************************************************************
*
* Function Name : OSA_MemFree
* Description : This function is used to free the memory previously allocated.
*
*END**************************************************************************/
osa_status_t OSA_MemFree(void *ptr)
{
free(ptr);
return kStatus_OSA_Success;
}
/*FUNCTION**********************************************************************
*
* Function Name : OSA_TimeDelay
* Description : This function is used to delay for a number of milliseconds.
*
*END**************************************************************************/
void OSA_TimeDelay(uint32_t delay)
{
uint32_t currTime, timeStart;
timeStart = OSA_TimeGetMsec();
do {
currTime = OSA_TimeGetMsec(); /* Get current time stamp */
} while (delay >= time_diff(timeStart, currTime));
}
/*FUNCTION**********************************************************************
*
* Function Name : OSA_TimeGetMsec
* Description : This function gets current time in milliseconds.
*
*END**************************************************************************/
uint32_t OSA_TimeGetMsec(void)
{
return LPTMR_HAL_GetCounterValue(BM_LPTMR_BASE);
}
/*FUNCTION**********************************************************************
*
* Function Name : interrupt_handler_register
* Description : This function is used to install interrupt handler.
* For bare metal, this function is empty.
*
*END**************************************************************************/
osa_status_t OSA_InstallIntHandler (int32_t IRQNumber,
void (*handler)(void))
{
INT_SYS_InstallHandler((IRQn_Type)IRQNumber, handler);
return kStatus_OSA_Success;
}
/*FUNCTION**********************************************************************
*
* Function Name : OSA_EnterCritical
* Description : This function is used to ensure some code will not be preempted.
*
*END**************************************************************************/
void OSA_EnterCritical(osa_critical_section_mode_t mode)
{
if (kCriticalDisableInt == mode)
{
INT_SYS_DisableIRQGlobal();
}
else
{
return;
}
}
/*FUNCTION**********************************************************************
*
* Function Name : OSA_ExitCritical
* Description : This function is used to exit critical section.
*
*END**************************************************************************/
void OSA_ExitCritical(osa_critical_section_mode_t mode)
{
if (kCriticalDisableInt == mode)
{
INT_SYS_EnableIRQGlobal();
}
else
{
return;
}
}
/*FUNCTION**********************************************************************
*
* Function Name : OSA_Init
* Description : This function is used to setup the basic services, it should
* be called first in function main. Return kStatus_OSA_Success if services
* are initialized successfully, otherwise return kStatus_OSA_Error.
*
*END**************************************************************************/
osa_status_t OSA_Init(void)
{
#if (TASK_MAX_NUM > 0)
task_init();
#endif
/*
* Setup LP Timer for timeout and delay.
* Use 1kHz LPO as clock source, disable prescaler, freerun mode.
*/
CLOCK_SYS_EnableLptimerClock(BM_LPTMR_INSTANCE);
LPTMR_HAL_SetTimerModeMode(BM_LPTMR_BASE, kLptmrTimerModeTimeCounter);
LPTMR_HAL_SetFreeRunningCmd(BM_LPTMR_BASE, true);
LPTMR_HAL_SetPrescalerCmd(BM_LPTMR_BASE, false);
LPTMR_HAL_SetPrescalerClockSourceMode(BM_LPTMR_BASE, kLptmrPrescalerClockSourceLpo);
LPTMR_HAL_SetIntCmd(BM_LPTMR_BASE,false);
LPTMR_HAL_Enable(BM_LPTMR_BASE);
return kStatus_OSA_Success;
}
/*FUNCTION**********************************************************************
*
* Function Name : OSA_Start
* Description : This function is used to start RTOS scheduler.
*
*END**************************************************************************/
osa_status_t OSA_Start(void)
{
#if (TASK_MAX_NUM > 0)
g_curTask = &g_taskListHead;
for(;;)
{
if (g_curTask->p_func)
{
g_curTask->p_func(g_curTask->param);
}
g_curTask = g_curTask->next;
}
#else
for(;;)
{
}
#endif
}
#if (TASK_MAX_NUM > 0)
/*FUNCTION**********************************************************************
*
* Function Name : OSA_PollAllOtherTasks
* Description : This function calls all task functions except current task
* one time. It is only for bare metal.
*
*END**************************************************************************/
void OSA_PollAllOtherTasks(void)
{
task_handler_t curTaskSave = g_curTask;
g_curTask = g_taskListHead.next;
while ((g_curTask->p_func) && (g_curTask!=curTaskSave))
{
g_curTask->p_func(g_curTask->param);
g_curTask = g_curTask->next;
}
g_curTask = curTaskSave;
}
#endif
/*******************************************************************************
* EOF
******************************************************************************/

View File

@ -0,0 +1,572 @@
/*
* 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_H__)
#define __FSL_OS_ABSTRACTION_H__
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
#if defined __CC_ARM
#define inline __inline
#endif
/*!
* @addtogroup os_abstraction
* @{
*/
/*! @brief Status values to be returned by functions. */
typedef enum
{
kSuccess = 0, /*!< Functions work correctly. */
kError, /*!< Functions work failed. */
kTimeout, /*!< Timeout occurs while waiting for an object. */
kIdle /*!< Can not get the object in non-blocking mode.*/
}fsl_rtos_status;
/*! @brief The event flags are set or not.*/
typedef enum
{
kFlagNotSet = 0, /*!< The flags checked are set. */
kFlagSet /*!< The flags checked are not set. */
}event_status;
/*! @brief The event flags are cleared automatically or manually.*/
typedef enum
{
kEventAutoClr = 0, /*!< The flags of the event will be cleared automatically. */
kEventManualClr /*!< The flags of the event will be cleared manually. */
}event_clear_type;
// Temporary "fix", until the proper macros are integrated in the on-line build system
#define FSL_RTOS_MBED
/* Include required header file based on RTOS selection */
#if defined (FSL_RTOS_MQX)
/*! @brief Macro to set message queue copy messages to internal memory or not. */
#define __FSL_RTOS_MSGQ_COPY_MSG__ 1
#include "fsl_os_abstraction_mqx.h"
#elif defined (FSL_RTOS_FREE_RTOS)
#define __FSL_RTOS_MSGQ_COPY_MSG__ 1
#include "fsl_os_abstraction_free_rtos.h"
#elif defined (FSL_RTOS_UCOSII)
#define __FSL_RTOS_MSGQ_COPY_MSG__ 1
#include "fsl_os_abstraction_ucosii.h"
#elif defined (FSL_RTOS_UCOSIII)
#define __FSL_RTOS_MSGQ_COPY_MSG__ 1
#include "fsl_os_abstraction_ucosiii.h"
#elif defined (FSL_RTOS_CMSIS)
#define __FSL_RTOS_MSGQ_COPY_MSG__ 0
#include "fsl_os_abstraction_cmsis.h"
#elif defined (FSL_RTOS_MBED)
#define __FSL_RTOS_MSGQ_COPY_MSG__ 1
#include "fsl_os_abstraction_mbed.h"
#else
#define __FSL_RTOS_MSGQ_COPY_MSG__ 1
#include "fsl_os_abstraction_bm.h"
#endif
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
/*!
* @name Synchronization
* @{
*/
/*!
* @brief Initialize a synchronization object to a given state.
*
* @param obj The sync object to initialize.
* @param initValue The initial value the object will be set to.
*
* @retval kSuccess The object was successfully created.
* @retval kError Invalid parameter or no more objects can be created.
*/
fsl_rtos_status sync_create(sync_object_t *obj, uint8_t initValue);
/*!
* @brief Wait for the synchronization object.
*
* This function checks the sync object's counting value, if it is
* positive, decreases it and returns kSuccess, otherwise, timeout will be
* used for wait.
*
* @param obj Pointer to the synchronization object.
* @param timeout The maximum number of milliseconds to wait for the object to be signalled.
* Pass the #kSyncWaitForever constant to wait indefinitely for someone to signal the object.
* A value of 0 should not be passed to this function. Instead, use sync_poll for
* a non blocking check.
*
* @retval kSuccess The object was signalled.
* @retval kTimeout A timeout occurred.
* @retval kError An incorrect parameter was passed.
* @retval kIdle The object has not been signalled.
*
* @note There could be only one process waiting for the object at the same time.
*/
fsl_rtos_status sync_wait(sync_object_t *obj, uint32_t timeout);
/*!
* @brief Checks a synchronization object's status.
*
* This function is used to poll a sync object's status.
* If the sync object's counting value is positive, decrease it and return
* kSuccess. If the object's counting value is 0, the function will
* return kIdle immediately
*
* @param obj The synchronization object.
*
* @retval kSuccess The object was signalled.
* @retval kIdle The object was not signalled.
* @retval kError An incorrect parameter was passed.
*/
fsl_rtos_status sync_poll(sync_object_t *obj);
/*!
* @brief Signal for someone waiting on the synchronization object to wake up.
*
* This function should not be called from an ISR.
*
* @param obj The synchronization object to signal.
*
* @retval kSuccess The object was successfully signaled.
* @retval kError The object can not be signaled or invalid parameter.
*/
fsl_rtos_status sync_signal(sync_object_t *obj);
/*!
* @brief Signal for someone waiting on the synchronization object to wake up.
*
* This function should only be called from an ISR.
*
* @param obj The synchronization object to signal.
*
* @retval kSuccess The object was successfully signaled.
* @retval kError The object can not be signaled or invalid parameter.
*/
fsl_rtos_status sync_signal_from_isr(sync_object_t *obj);
/*!
* @brief Destroy a previously created synchronization object.
*
* @param obj The synchronization object to destroy.
*
* @retval kSuccess The object was successfully destroyed.
* @retval kError Object destruction failed.
*/
fsl_rtos_status sync_destroy(sync_object_t *obj);
/* @} */
/*!
* @name Resource locking
* @{
*/
/*!
* @brief Initialize a locking object.
*
* @param obj The lock object to initialize.
*
* @retval kSuccess The lock is created successfully.
* @retval kError Tke lock creation failed.
*/
fsl_rtos_status lock_create(lock_object_t *obj);
/*!
* @brief Wait for the object to be unlocked and lock it.
*
* This function will wait for some time or wait forever if could not get the lock.
*
* @param obj The locking object.
* @param timeout The maximum number of milliseconds to wait for the mutex.
* Pass the #kSyncWaitForever constant to wait indefinitely for someone to unlock the object.
* A value of 0 should not be passed to this function. Instead, use lock_poll for a non
* blocking check.
*
* @retval kSuccess The lock was obtained.
* @retval kTimeout A timeout occurred.
* @retval kError An incorrect parameter was passed.
*/
fsl_rtos_status lock_wait(lock_object_t *obj, uint32_t timeout);
/*!
* @brief Checks if a locking object can be locked and locks it if possible.
*
* This function returns instantly if could not get the lock.
*
* @param obj The locking object.
*
* @retval kSuccess The lock was obtained.
* @retval kIdle The lock could not be obtained.
* @retval kError An incorrect parameter was passed.
*
* @note There could be only one process waiting for the object at the same time.
* For RTOSes, wait for a lock recursively by one task is not supported.
*
*/
fsl_rtos_status lock_poll(lock_object_t *obj);
/*!
* @brief Unlock a previously locked object.
*
* @param obj The locking object to unlock.
*
* @retval kSuccess The object was successfully unlocked.
* @retval kError The object can not be unlocked or invalid parameter.
*/
fsl_rtos_status lock_release(lock_object_t *obj);
/*!
* @brief Destroy a previously created locking object.
*
* @param obj The locking object to destroy.
*
* @retval kSuccess The object was successfully destroyed.
* @retval kError Object destruction failed.
*/
fsl_rtos_status lock_destroy(lock_object_t *obj);
/* @} */
/*!
* @name Event signaling
* @{
*/
/*!
* @brief Initializes the event object.
*
* When the object is created, the flags is 0.
*
* @param obj Pointer to the event object to initialize.
* @param clearType The event is auto-clear or manual-clear.
*
* @retval kSuccess The object was successfully created.
* @retval kError Incorrect parameter or no more objects can be created.
*/
fsl_rtos_status event_create(event_object_t *obj, event_clear_type clearType);
/*!
* @brief Wait for any event flags to be set.
*
* This function will wait for some time or wait forever if no flags are set. Any flags set
* will wake up the function.
*
* @param obj The event object.
* @param timeout The maximum number of milliseconds to wait for the event.
* Pass the #kSyncWaitForever constant to wait indefinitely. A value of 0 should not be passed
* to this function.
* @param setFlags Pointer to receive the flags that were set.
*
* @retval kSuccess An event was set.
* @retval kTimeout A timeout occurred.
* @retval kError An incorrect parameter was passed.
*/
fsl_rtos_status event_wait(event_object_t *obj, uint32_t timeout, event_group_t *setFlags);
/*!
* @brief Set one or more event flags of an event object.
*
* This function should not be called from an ISR.
*
* @param obj The event object.
* @param flags Event flags to be set.
*
* @retval kSuccess The flags were successfully set.
* @retval kError An incorrect parameter was passed.
*
* @note There could be only one process waiting for the event.
*
*/
fsl_rtos_status event_set(event_object_t *obj, event_group_t flags);
/*!
* @brief Set one or more event flags of an event object.
*
* This function should only be called from an ISR.
*
* @param obj The event object.
* @param flags Event flags to be set.
*
* @retval kSuccess The flags were successfully set.
* @retval kError An incorrect parameter was passed.
*/
fsl_rtos_status event_set_from_isr(event_object_t *obj, event_group_t flags);
/*!
* @brief Clear one or more events of an event object.
*
* This function should not be called from an ISR.
*
* @param obj The event object.
* @param flags Event flags to be clear.
*
* @retval kSuccess The flags were successfully cleared.
* @retval kError An incorrect parameter was passed.
*/
fsl_rtos_status event_clear(event_object_t *obj, event_group_t flags);
/*!
* @brief Check the flags are set or not.
*
* @param obj The event object.
* @param flag The flag to check.
*
* @retval kFlagsSet The flags checked are set.
* @retval kFlagsNotSet The flags checked are not set or got an error.
*/
event_status event_check_flags(event_object_t *obj, event_group_t flag);
/*!
* @brief Destroy a previously created event object.
*
* @param obj The event object to destroy.
*
* @retval kSuccess The object was successfully destroyed.
* @retval kError Event destruction failed.
*/
fsl_rtos_status event_destroy(event_object_t *obj);
/* @} */
/*!
* @name Thread management
* @{
*/
/*!
* @brief Create a task.
*
* This function is wrapped by the macro task_create. Generally, this function is for
* internal use only, applications must use FSL_RTOS_TASK_DEFINE to define resources for
* task statically then use task_create to create task. If applications have prepare
* the resouces for task dynamically, they can use this function to create the task.
*
* @param task The task function.
* @param name The name of this task.
* @param stackSize The stack size in byte.
* @param stackMem Pointer to the stack. For bare metal, MQX and FreeRTOS, this could be NULL.
* @param priority Initial priority of the task.
* @param param Pointer to be passed to the task when it is created.
* @param usesFloat This task will use float register or not.
* @param handler Pointer to the task handler.
*
* @retval kSuccess The task was successfully created.
* @retval kError The task could not be created.
*
* @note Different tasks can not use the same task function.
*/
fsl_rtos_status __task_create(task_t task, uint8_t *name, uint16_t stackSize,
task_stack_t *stackMem, uint16_t priority,
void *param, bool usesFloat, task_handler_t *handler);
/*!
* @brief Destroy a previously created task.
* @note Depending on the RTOS, task resources may or may not be automatically freed,
* and this function may not return if the current task is destroyed.
*
* @param handler The handler of the task to destroy. Returned by the task_create function.
*
* @retval kSuccess The task was successfully destroyed.
* @retval kError Task destruction failed or invalid parameter.
*/
fsl_rtos_status task_destroy(task_handler_t handler);
/* @} */
/*!
* @name Message queues
* @{
*/
/*!
* @brief Initialize the message queue.
*
* This function will initialize the message queue that declared previously.
* Here is an example demonstrating how to use:
@code
msg_queue_handler_t handler;
MSG_QUEUE_DECLARE(my_message, msg_num, msg_size);
handler = msg_queue_create(&my_message, msg_num, msg_size);
@endcode
*
* @param queue The queue declared through the MSG_QUEUE_DECLARE macro.
* @param number The number of elements in the queue.
* @param size Size of every elements in words.
*
* @retval Handler to access the queue for put and get operations. If message queue
* created failed, return 0.
*/
msg_queue_handler_t msg_queue_create(msg_queue_t *queue, uint16_t number, uint16_t size);
/*!
* @brief Introduce an element at the tail of the queue.
*
* @param handler Queue handler returned by the msg_queue_create function.
* @param item Pointer to the element to be introduced in the queue.
*
* @retval kSuccess Element successfully introduced in the queue.
* @retval kError The queue was full or an invalid parameter was passed.
*/
fsl_rtos_status msg_queue_put(msg_queue_handler_t handler, msg_queue_item_t item);
/*!
* @brief Read and remove an element at the head of the queue.
*
* @param handler Queue handler returned by the msg_queue_create function.
* @param item Pointer to store a pointer to the element of the queue.
* @param timeout In case the queue is empty, the number of milliseconds to
* wait for an element to be introduced into the queue. Use 0 to return
* immediately or #kSyncWaitForever to wait indefinitely.
*
* @retval kSuccess Element successfully obtained from the queue.
* @retval kTimeout If a timeout was specified, the queue remained empty after timeout.
* @retval kError The queue was empty or the handler was invalid.
* @retval kIdle The queue was empty and the timeout has not expired.
*
* @note There should be only one process waiting on the queue.
*/
fsl_rtos_status msg_queue_get(msg_queue_handler_t handler,
msg_queue_item_t *item,
uint32_t timeout);
/*!
* @brief Discards all elements in the queue and leaves the queue empty.
*
* @param handler Queue handler returned by the msg_queue_create function.
*
* @retval kSuccess Queue successfully emptied.
* @retval kError Emptying queue failed.
*/
fsl_rtos_status msg_queue_flush(msg_queue_handler_t handler);
/*!
* @brief Destroy a previously created queue.
*
* @param handler Queue handler returned by the msg_queue_create function.
*
* @retval kSuccess The queue was successfully destroyed.
* @retval kError Message queue destruction failed.
*/
fsl_rtos_status msg_queue_destroy(msg_queue_handler_t handler);
/* @} */
#ifndef FSL_RTOS_MBED
/*!
* @name Memory Management
* @{
*/
/*!
* @brief Reserves the requested amount of memory in bytes.
*
* @param size Amount of bytes to reserve.
*
* @retval Pointer to the reserved memory. NULL if memory could not be allocated.
*/
void * mem_allocate(size_t size);
/*!
* @brief Reserves the requested amount of memory in bytes and initializes it to 0.
*
* @param size Amount of bytes to reserve.
*
* @retval Pointer to the reserved memory. NULL if memory could not be allocated.
*/
void * mem_allocate_zero(size_t size);
/*!
* @brief Releases the memory previously reserved.
*
* @param ptr Pointer to the start of the memory block previously reserved.
*
* @retval kSuccess Memory correctly released.
*/
fsl_rtos_status mem_free(void *ptr);
#endif
/* @} */
/*!
* @name Time management
* @{
*/
/*!
* @brief Delays execution for a number of milliseconds.
*
* @param delay The time in milliseconds to wait.
*/
void time_delay(uint32_t delay);
/* @} */
/*!
* @name Interrupt management
* @{
*/
/*!
* @brief Install interrupt handler.
*
* @param irqNumber IRQ number of the interrupt.
* @param handler The interrupt handler to install.
*
* @retval kSuccess Handler is installed successfully.
* @retval kSuccess Handler could not be installed.
*/
fsl_rtos_status interrupt_handler_register(int32_t irqNumber, void (*handler)(void));
/* @} */
#if defined(__cplusplus)
}
#endif
/*! @}*/
#endif /* __FSL_OS_ABSTRACTION_H__ */
/*******************************************************************************
* EOF
******************************************************************************/

View File

@ -35,10 +35,4 @@ typedef int msg_queue_handler_t;
typedef void msg_queue_t;
typedef int msg_queue_item_t;
typedef int semaphore_t;
typedef int mutex_t;
typedef int event_t;
typedef int event_flags_t;
typedef int task_param_t;
#endif // #ifdef FSL_OS_ABSTRACTION_MBED_H_

View File

@ -20,14 +20,14 @@
#include "fsl_os_abstraction.h"
#include "wait_api.h"
// fsl_rtos_status lock_destroy(lock_object_t *obj) {
// return kSuccess;
// }
fsl_rtos_status lock_destroy(lock_object_t *obj) {
return kSuccess;
}
// fsl_rtos_status event_set(event_object_t *obj, event_group_t flags) {
// return kSuccess;
// }
fsl_rtos_status event_set(event_object_t *obj, event_group_t flags) {
return kSuccess;
}
void time_delay(uint32_t delay) {
wait_ms(delay);

View File

@ -0,0 +1,311 @@
/*
* 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.
*/
/*************************************************************************************************
* Includes Section
************************************************************************************************/
#include "sw_timer.h"
#include "fsl_interrupt_manager.h"
#include "fsl_clock_manager.h"
#include "fsl_pit_driver.h"
/*************************************************************************************************
* Defines & Macros Section
************************************************************************************************/
#ifndef SW_TIMER_NUMBER_CHANNELS
/*! Number of channels to be used as timers. The maximum value of channels supported is 32.*/
#define SW_TIMER_NUMBER_CHANNELS (32)
/*! Defines the count unit in ms of the software timer.*/
#define SW_TIMER_COUNT_UNIT_MS (1)
#endif
/*! Return if the timer channel is reserved.*/
#define IS_TIMER_CHANNEL_RESERVED(chann) (gs_areChannelsEnabled & (channel_enabler_t)(1 << chann))
/*************************************************************************************************
* Typedef Section
************************************************************************************************/
#if (SW_TIMER_NUMBER_CHANNELS <= 8)
/*! Defines the size of variable that stores "enable" flags of each channel.*/
typedef uint8_t channel_enabler_t;
#else
#if (SW_TIMER_NUMBER_CHANNELS <= 16)
/*! Defines the size of variable that stores "enable" flags of each channel.*/
typedef uint16_t channel_enabler_t;
#else
#if (SW_TIMER_NUMBER_CHANNELS <= 32)
/*! Defines the size of variable that stores "enable" flags of each channel.*/
typedef uint32_t channel_enabler_t;
#else
#error "Cannot handle more than 32 auxiliary software timer channels."
#endif
#endif
#endif
/*************************************************************************************************
* Global Constants Section
************************************************************************************************/
/*************************************************************************************************
* Static Constants Section
************************************************************************************************/
/** Constant to select the PIT timer channel to use for timebase. Channels 0 and 1 have special
* hardware trigger capabilities, so they should be avoided.
*/
static const uint8_t kSWTimerPITChannel = FSL_FEATURE_PIT_TIMER_COUNT - 1;
/*************************************************************************************************
* Global Variables Section
************************************************************************************************/
/*************************************************************************************************
* Static Variables Section
************************************************************************************************/
/*! Free running counter that everyone can read.*/
static volatile time_free_counter_t gs_freeCounter;
/*! Independent counters of software timer module. A counter is defined for every channel.*/
static volatile time_counter_t gs_channelCounters[SW_TIMER_NUMBER_CHANNELS];
/*! Variable used to indicate which channels are enabled. Bit 0 corresponds to channel 0, bit 1 to*/
/*! channel 1, etc.*/
static volatile channel_enabler_t gs_areChannelsEnabled;
/*************************************************************************************************
* Functions Section
************************************************************************************************/
/* See sw_timer.h for documentation of this function.*/
uint32_t sw_timer_init_service(void)
{
pit_user_config_t pitConfig;
/* All channels are disabled*/
gs_areChannelsEnabled = 0;
/* Init free running counter*/
gs_freeCounter = 0;
/* Define PIT channel init structure. */
pitConfig.isInterruptEnabled = true;
pitConfig.isTimerChained = false;
pitConfig.periodUs = 1000;/* Set 1ms period */
/* Init PIT module and enable all timers run in debug mode.*/
pit_init_module(true);
/* Init PIT channel. */
pit_init_channel(kSWTimerPITChannel, &pitConfig);
/* Register PIT callback function.*/
pit_register_isr_callback_function(kSWTimerPITChannel, sw_timer_update_counters);
/* Start timer counting. */
pit_timer_start(kSWTimerPITChannel);
return kSwTimerStatusSuccess;
}
/* See sw_timer.h for documentation of this function.*/
void sw_timer_shutdown_service(void)
{
pit_shutdown();
}
/* See sw_timer.h for documentation of this function.*/
uint8_t sw_timer_reserve_channel(void)
{
static uint8_t lastFreeChannel = 0;
uint8_t searchIndex;
uint8_t newReservedChannel;
/* Initialize search index with the last free channel to search faster for a free channel*/
searchIndex = lastFreeChannel;
/* Not channel available by default*/
newReservedChannel = kSwTimerChannelNotAvailable;
/* Searching for a free channel*/
do {
/* The channel is free*/
if(!IS_TIMER_CHANNEL_RESERVED(searchIndex))
{
/* Set channel as reserved*/
newReservedChannel = searchIndex;
gs_areChannelsEnabled |= (1u << newReservedChannel);
/* Update last free channel with the next channel*/
lastFreeChannel = newReservedChannel + 1;
/* Flag of the last channel has been checked and need to start over with channel 0*/
if (lastFreeChannel == SW_TIMER_NUMBER_CHANNELS)
{
lastFreeChannel = 0;
}
}
/* The channel is already reserved*/
else
{
searchIndex = (searchIndex + 1) % SW_TIMER_NUMBER_CHANNELS;
}
}while((searchIndex != lastFreeChannel) &&
(kSwTimerChannelNotAvailable == newReservedChannel));
return newReservedChannel;
}
/* See sw_timer.h for documentation of this function.*/
sw_timer_channel_status_t sw_timer_get_channel_status(uint8_t timerChannel)
{
sw_timer_channel_status_t channelStatus;
/* Is it a valid channel?*/
if(SW_TIMER_NUMBER_CHANNELS > timerChannel)
{
/* The channel is reserved*/
if(IS_TIMER_CHANNEL_RESERVED(timerChannel))
{
/* The timeout has expired*/
if(0 >= gs_channelCounters[timerChannel])
{
channelStatus = kSwTimerChannelExpired;
}
/* The counter is still counting*/
else
{
channelStatus = kSwTimerChannelStillCounting;
}
}
/* The channel is not reserved*/
else
{
channelStatus = kSwTimerChannelIsDisable;
}
}
/* The channel is not valid*/
else
{
channelStatus = kSwTimerChannelNotAvailable;
}
return channelStatus;
}
/* See sw_timer.h for documentation of this function.*/
uint32_t sw_timer_start_channel(uint8_t timerChannel, time_counter_t timeout)
{
uint32_t startStatus;
/* Is it a valid channel?*/
if(SW_TIMER_NUMBER_CHANNELS > timerChannel)
{
/* Set the given timeout in the corresponding channel counter. The timeout should be a */
/* multiple of SW_TIMER_COUNT_UNIT_MS, otherwise it will be taken the integer part of the */
/* division.*/
gs_channelCounters[timerChannel] = timeout / SW_TIMER_COUNT_UNIT_MS;
startStatus = kSwTimerStatusSuccess;
}
else
{
startStatus = kSwTimerStatusInvalidChannel;
}
return startStatus;
}
/* See sw_timer.h for documentation of this function.*/
uint32_t sw_timer_release_channel(uint8_t timerChannel)
{
uint32_t releaseStatus;
/* Is it a valid channel?*/
if(SW_TIMER_NUMBER_CHANNELS > timerChannel)
{
/* Set channel as disable*/
gs_areChannelsEnabled &= (~(1u << timerChannel));
releaseStatus = kSwTimerStatusSuccess;
}
else
{
releaseStatus = kSwTimerStatusInvalidChannel;
}
return releaseStatus;
}
/* See sw_timer.h for documentation of this function.*/
time_free_counter_t sw_timer_get_free_counter(void)
{
return gs_freeCounter;
}
/* See sw_timer.h for documentation of this function.*/
void sw_timer_update_counters(void)
{
uint8_t index;
index = SW_TIMER_NUMBER_CHANNELS;
do {
--index;
/* Decrement all counters. To determine if the timeout has expired call */
--gs_channelCounters[index];
} while(0 != index);
/* Increment free running counter*/
++gs_freeCounter;
}
/*******************************************************************************
* EOF
******************************************************************************/

View File

@ -0,0 +1,191 @@
/*
* 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(__SW_TIMER_H__)
#define __SW_TIMER_H__
#include <stdint.h>
#include <stdbool.h>
/*! @addtogroup sw_timer Software Timer
* @brief This module is used to interface with Abstract Timer HAL to generate periodical timeouts
* required through different modules of the AOA protocol. This block will be based on 1ms
* ticks for all the timeout calculations. The HAL Interface block used to communicate with
* this must have the same 1ms timeout configured. This module can generate different
* software timer channels based on the same 1ms.
*/
/*! @{*/
/*! Definition of the possible status of a software channel timer. */
typedef enum SwTimerChannelStatus
{
kSwTimerChannelExpired = 0x00, /*!< Indicates the timer channel has counted the given ms*/
kSwTimerChannelStillCounting = 0x01, /*!< Indicates the timeout of the channel has not expired
and the timer is still counting.*/
kSwTimerChannelIsDisable = 0x02, /*!< Indicates the timer channel is not reserved. */
kSwTimerChannelNotAvailable = 0xFF /*!< Indicates there are not available channels to reserve
or the requested channel is not available.*/
}sw_timer_channel_status_t;
/*! List of status and errors. */
enum _sw_timer_errors
{
kSwTimerStatusSuccess, /*!< The execution was successful.*/
kSwTimerStatusFail, /*!< The execution failed.*/
kSwTimerStatusInvalidChannel /*!< The given channel is not valid. Valid channels are 0 to
(SW_TIMER_NUMBER_CHANNELS - 1). */
};
/*!
* Data type of the counter of each timer channel. If it is an int8_t the counter will count
* up to 127ms, int16_t up to 32767ms and int32_t up to 2147483647ms.
*/
typedef int32_t time_counter_t;
/*! Max timeout value according to size of the time counter */
enum sw_timer_timeouts
{
kSwTimerMaxTimeout = 2147483647
};
/*!
* Data type of the free running counter. This data type should be unsigned and will count up to
* 255ms if it is uint8_t, 65535ms for uint16_t and 4294967295ms for uint32_t.
*/
typedef uint32_t time_free_counter_t;
#if defined(__cplusplus)
extern "C" {
#endif /* __cplusplus*/
/*!
* @brief Initializes the software timer module. Prepares variables and HAL layer to provide timer
* services. Starts the free running counter which will be available to get its value any
* time while the service is running; it is useful whenever a module wants to keep track of
* time, but do not wants to reserve a channel.
*
* @return status_t Returns software timer status after initialization.
* @retval kSwTimerStatusSuccess The initialization was successful and the software timer is ready
* to provide services.
* @retval kSwTimerStatusFail The initialization failed.
*/
uint32_t sw_timer_init_service(void);
/*!
* @brief Deinitializes the software timer module. Shutdown HAL layer, so no timer service can be
* provided after the execution of this function.
*
* @return void
*/
void sw_timer_shutdown_service(void);
/*!
* @brief Reserves a free timer channel to be used by any module and returns its identifier.
*
* @return uint8_t Returns the number of the channel that was reserved.
* @retval Any value between 0 and SW_TIMER_NUMBER_CHANNELS is a valid channel. It indicates the
* channel was reserved and can be used.
* @retval kSwTimerChannelNotAvailable If there is not any available channel, because all
* channels are already reserved.
*/
uint8_t sw_timer_reserve_channel(void);
/*!
* @brief Returns the actual status of the given timer channel. The timer has to be previously
* started to return a valid status.
*
* @param timerChannel [in] Indicates the timer channel which status is going to be returned.
*
* @return sw_timer_channel_status_t Current status of the given timer channel.
* @retval kSwTimerChannelExpired Indicates the timer channel has counted the given ms.
* @retval kSwTimerChannelStillCounting Indicates the timeout of the channel has not expired and
the timer is still counting.
* @retval kSwTimerChannelIsDisable Indicates the timer channel is not reserved.
* @retval kSwTimerChannelNotAvailable Indicates the timer channel is invalid.
*/
sw_timer_channel_status_t sw_timer_get_channel_status(uint8_t timerChannel);
/*!
* @brief Starts the count down of the given timer channel. The timer channel has to be previously
* reserved.
*
* @param timerChannel [in] Indicates the timer channel that is going to be started.
* @param timeout [in] Time in ms that the timer channel will count. The timeout should be
a multiple of count unit of the timer, otherwise it will be taken
the integer part of the division and the exact count will not be
achieved
*
* @return status_t Reports failures in the execution of the function.
* @retval kSwTimerStatusSuccess A channel was started successfully.
* @retval kSwTimerStatusInvalidChannel The timer channel is invalid, it does not exist.
*/
uint32_t sw_timer_start_channel(uint8_t timerChannel, time_counter_t timeout);
/*!
* @brief Releases the given timer channel, so it can be used by someone else.
*
* @param timerChannel [in] Identifier of the timer channel.
*
* @return status_t Reports failures in the execution of the function.
* @retval kSwTimerStatusSuccess A channel was released successfully.
* @retval kSwTimerStatusInvalidChannel The timer channel is invalid, it does not exist.
*/
uint32_t sw_timer_release_channel(uint8_t timerChannel);
/*!
* @brief Gets the current value of the free running counter. Any module can keep track of the time
* by reading this counter and calculates time difference. No reservation of timer channel
* is needed. Consider for calculations that when the counter overflows it will start from
* 0 again.
*
* @return time_free_counter_t Returns current count of the free running counter.
*/
time_free_counter_t sw_timer_get_free_counter(void);
/*!
* @brief This function is called every 1ms by the interruption and update count down values of all
* timer channels.
*
* @return void
*/
void sw_timer_update_counters(void);
#if defined(__cplusplus)
}
#endif /* __cplusplus*/
/*! @}*/
/*Group sw_timer*/
#endif /* __SW_TIMER_H__ */
/*******************************************************************************
* EOF
******************************************************************************/