Hi,
I was using lab1 of the medical tower board mcf51, and I'm trying to port the following real time counter driver to the KL25z.
/******************************************************************************
*
* Freescale Semiconductor Inc.
* (c) Copyright 2004-2010 Freescale Semiconductor, Inc.
* ALL RIGHTS RESERVED.
*
******************************************************************************
*
* THIS SOFTWARE IS PROVIDED BY FREESCALE "AS IS" AND ANY EXPRESSED 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 FREESCALE OR ITS 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.
*
**************************************************************************//*!
*
* @file TPM.c
*
* @author
*
* @version
*
* @date June-17-2009
*
* @brief This file configures Real Time Counter (RTC) for Timer
* Implementation
*****************************************************************************/
/******************************************************************************
* Includes
*****************************************************************************/
#include <string.h>
#include "derivative.h" /* include peripheral declarations */
#include "types.h" /* Contains User Defined Data Types */
#include "RealTimerCounter.h"
#if MAX_TIMER_OBJECTS
/*****************************************************************************
* Local Functions Prototypes
*****************************************************************************/
static uint_8 TimerInit(void);
static void EnableTimerInterrupt(void);
static void DisableTimerInterrupt(void);
/****************************************************************************
* Global Variables
****************************************************************************/
/* Array of Timer Objects */
TIMER_OBJECT g_TimerObjectArray[MAX_TIMER_OBJECTS];
/*****************************************************************************
* Global Functions Prototypes
*****************************************************************************/
uint_8 TimerQInitialize(uint_8 controller_ID);
uint_8 AddTimerQ(PTIMER_OBJECT pTimerObject);
uint_8 RemoveTimerQ(uint_8 index);
/*****************************************************************************
* Global Functions
*****************************************************************************/
#if (defined(_MC9S08MM128_H) || defined(_MC9S08JE128_H))
#pragma CODE_SEG DEFAULT
#endif
/******************************************************************************
*
* @name TimerQInitialize
*
* @brief Initializes RTC, Timer Object Queue and System Clock Counter
*
* @param controller_ID : Controller ID
*
* @return None
*****************************************************************************
* This function initializes System Clock Counter, Timer Queue and Initializes
* System Timer
*****************************************************************************/
uint_8 TimerQInitialize(uint_8 controller_ID)
{
UNUSED (controller_ID)
(void)memset(g_TimerObjectArray, (int)NULL, sizeof(g_TimerObjectArray));
return TimerInit();
}
/******************************************************************************
*
* @name AddTimerQ
*
* @brief Adds Timer Object to Timer Queue
*
* @param pTimerObject : Pointer to Timer Object
*
* @return None
*****************************************************************************
* Adds Timer Object to Timer Queue
*****************************************************************************/
uint_8 AddTimerQ(PTIMER_OBJECT pTimerObject)
{
uint_8 index;
if(pTimerObject == NULL)
return (uint_8)ERR_INVALID_PARAM;
if(pTimerObject->msCount == (unsigned int)INVALID_TIME_COUNT)
return (uint_8)ERR_INVALID_PARAM;
for(index = 0; index < MAX_TIMER_OBJECTS; index++)
{
/* Disable Timer Interrupts */
DisableTimerInterrupt();
if(g_TimerObjectArray[index].pfnTimerCallback == NULL)
{
(void)memcpy(&g_TimerObjectArray[index], pTimerObject, sizeof(TIMER_OBJECT));
/* Enable Timer Interrupts */
EnableTimerInterrupt();
break;
}
/* Enable Timer Interrupts */
EnableTimerInterrupt();
}
if(index == MAX_TIMER_OBJECTS)
return (uint_8)ERR_TIMER_QUEUE_FULL;
return index;
}
/******************************************************************************
*
* @name RemoveTimerQ
*
* @brief Removes Timer Object from Timer Queue
*
* @param index : Index of Timer Object
*
* @return None
*****************************************************************************
* Removes Timer Object from Timer Queue
*****************************************************************************/
uint_8 RemoveTimerQ(uint_8 index)
{
if(index >= MAX_TIMER_OBJECTS)
return (uint_8)ERR_INVALID_PARAM;
/* Disable Timer Interrupts */
DisableTimerInterrupt();
(void)memset(&g_TimerObjectArray[index], (int)NULL, sizeof(TIMER_OBJECT));
/* Enable Timer Interrupts */
EnableTimerInterrupt();
return (uint_8)ERR_SUCCESS;
}
/******************************************************************************
* @name TimerInit
*
* @brief This is RTC initialization function
*
* @return None
*
******************************************************************************
* Intiializes the RTC module registers
*****************************************************************************/
static uint_8 TimerInit(void)
{
PTAD_PTAD5 = 1;
PTAD_PTAD6 = 1;
PTBD_PTBD0 = 1;
PTADD_PTADD5 = 1;
PTADD_PTADD6 = 1;
PTBDD_PTBDD0 = 1;
TPM2SC = 0;
TPM2MOD = 1500;
TPM2SC_PS = 0x04;
EnableTimerInterrupt();
TPM2SC_CLKSx = 0x1; /* Select Internal Clock Source */
return ERR_SUCCESS;
}
/******************************************************************************
* @name EnableTimerInterrupt
*
* @brief This routine enables Timer Interrupt
*
* @return None
*
******************************************************************************
* Enables RTC Timer Interrupt
*****************************************************************************/
static void EnableTimerInterrupt(void)
{
/* Enable Timer Interrupt */
TPM2SC_TOIE = 0x1;
return;
}
/******************************************************************************
* @name DisableTimerInterrupt
*
* @brief This routine disables Timer Interrupt
*
* @return None
*
******************************************************************************
* Disables RTC Timer Interrupt
*****************************************************************************/
static void DisableTimerInterrupt(void)
{
/* Disable Timer Interrupt */
TPM2SC_TOIE = 0x0;
return;
}
/******************************************************************************
* @name Timer_ISR
*
* @brief This routine services RTC Interrupt
*
* @param None
*
* @return None
*
******************************************************************************
* Services RTC Interrupt. If a Timer Object expires, then removes the object
* from Timer Queue and Calls the callback function (if registered)
*****************************************************************************/
static void TimerHandler(void);
#if (defined(_MC9S08MM128_H) || defined(_MC9S08JE128_H))
#pragma CODE_SEG NON_BANKED
#endif
interrupt Timer_ISR(void)
{
TimerHandler();
}
#if (defined(_MC9S08MM128_H) || defined(_MC9S08JE128_H))
#pragma CODE_SEG DEFAULT
#endif
#if (defined(_MC9S08MM128_H) || defined(_MC9S08JE128_H))
#pragma CODE_SEG NON_BANKED
#endif
interrupt Timer1_ISR(void)
{
TimerHandler();
}
#if (defined(_MC9S08MM128_H) || defined(_MC9S08JE128_H))
#pragma CODE_SEG DEFAULT
#endif
static void TimerHandler(void)
{
uint_8 index;
if(TPM2SC & TPM1SC_TOF_MASK)
{
/* Clear RTC Interrupt */
TPM2SC_TOF = 0x0;
/* Call Pending Timer CallBacks */
for (index = 0; index < MAX_TIMER_OBJECTS; index++)
{
PTIMER_OBJECT ptemp = &g_TimerObjectArray[index];
if(ptemp->pfnTimerCallback == NULL)
{
continue;
}
ptemp->msCount--;
if (ptemp->msCount == 0)
{
PFNTIMER_CALLBACK pfnTimerCallback = ptemp->pfnTimerCallback;
#ifdef TIMER_CALLBACK_ARG
void *parg = ptemp->arg;
#endif
(void)RemoveTimerQ(index);
#ifdef TIMER_CALLBACK_ARG
pfnTimerCallback(parg);
#else
pfnTimerCallback();
#endif
}
}
}
}
#endif
Anyone know if there is a compatible version for the KL25z for the above code? Thank you.
Hi Paco shnaidler,
I am not familiar with mcf51, but if you just want the KL25 RTC driver, we have the KSDK1.3.0 code for your reference.
Please download the KSDK1.3.0 code from this link:http://kex.freescale.com/en/welcome
Select the FRDM-KL25 board, then generate the KSDK1.3.0 code and download it.
You can find the RTC code in folder: C:\Freescale\KSDK_1.3.0\examples\frdmkl25z\driver_examples\rtc
Wish it helps you!
If you still have question, please contact me!
Have a great day,
Jingjing
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
Hi Jingjing,
I was able to implement a timer with interrupt, and that solved my problem. Thank you.
I'm experiencing a new problem with the kl25z. It is related to I2c. I'm using processor expert code, and I don't have a consistent results.
I converted the following write function from an old i2c driver to processor expert's write method. I did the following:
converted this:
vfnIICV1Write(DSC_SLAVE_ADDRESS, (UINT8 *)&CmdEcgDiagnosticModeStartMeasurement, 1);
//To this
WriteAccRegs(I2C_DeviceData, &DataState, DSC_SLAVE_ADDRESS, 1, (UINT8 *)&CmdEcgDiagnosticModeStartMeasurement);
Hi Paco,
About the PE I2C code, we still have the according project.
Please download the sample code from this link:
After you install it, you can find it from folder:KL25 Sample Code\kl25_sc_rev10\klxx-sc-pex\projects\MQX_Lite_i2c_demo\cw
It is the codewarrior project.
Besides, you also can use the KSDK1.3.0 driver, the I2C project folder:C:\Freescale\KSDK_1.3.0\examples\frdmkl26z\driver_examples\i2c
Wish it helps you!
If you still have question, please contact me!
Have a great day,
Jingjing
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
Thank you for the example codes, I have a question thats confusing me:
Are those ReadAccRegs and WriteAccRegs functions only specific to the MMA845xQ or are they universal? I mean can I use the same functions to read and write from the MED-EKG board for example?
bool ReadAccRegs(LDD_TDeviceData *I2CPtr,
TDataState *DataState, uint8_t Address, uint8_t RegCount, uint8_t *Buffer)
{
LDD_I2C_TBusState BusState;
DataState->Sent = FALSE;
I2C_MasterSendBlock(I2CPtr, &Address, sizeof(Address), LDD_I2C_NO_SEND_STOP);
while (!DataState->Sent) {}
if (!DataState->Sent) {
return FALSE;
}
DataState->Received = FALSE;
I2C_MasterReceiveBlock(I2CPtr, Buffer, RegCount, LDD_I2C_SEND_STOP);
while (!DataState->Received) {}
do {I2C_CheckBus(I2CPtr, &BusState);}
while (BusState != LDD_I2C_IDLE);
if (!DataState->Received) {
return FALSE;
}
return TRUE;
}
bool WriteAccRegs(LDD_TDeviceData *I2CPtr,
TDataState *DataState, uint8_t Address, uint8_t RegCount, uint8_t *Data)
{
LDD_I2C_TBusState BusState;
const uint8_t MAX_REG_COUNT = 16;
uint8_t SendBuffer[MAX_REG_COUNT];
SendBuffer[0] = Address;
memcpy(&SendBuffer[1], Data, RegCount);
DataState->Sent = FALSE;
I2C_MasterSendBlock(I2CPtr, &SendBuffer, RegCount + 1, LDD_I2C_SEND_STOP);
while (!DataState->Sent) {}
do {I2C_CheckBus(I2CPtr, &BusState);}
while(BusState != LDD_I2C_IDLE);
if (!DataState->Sent) {
return FALSE;
}
return TRUE;
}
Hi paco,
The function ReadAccRegs and WriteAccRegs is for MMA845xQ, but don't worry, I2C_MasterSendBlock and I2C_MasterReceiveBlock are all the universal function. actually, you can modify the function ReadAccRegs and WriteAccRegs to fit your slave device, if your device is the same operation procedure, of course, you can these functions.
About the MED-EKG compatible, you need to check the MED-EKG document. There has an application about KINETIS MED-EKG, but not for I2C:
Have a great day,
Jingjing
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------