Marco Merlin
Published © Apache-2.0

rIoTwear mbed

Develop on NXP Rapid IoT Prototyping kit with ARM mbed and free tools.

IntermediateProtip4 hours697
rIoTwear mbed

Things used in this project

Hardware components

Rapid IoT Prototyping Kit
NXP Rapid IoT Prototyping Kit
×1
MikroE hexiwear docking station
×1

Software apps and online services

Mbed Studio
Arm Mbed Studio
Microsoft visual studio code

Story

Read more

Code

pcf2123 RTC source

C/C++
pcf2123 RTC library
/*
 * Copyright (c) 2018 NXP
 *
 * 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 the copyright holder 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.
 */

/*!
 * @file
 * This is the source file for the real time clock sensor PCF2123 driver.
 */

#include "pcf2123.h"
#include <string.h>
#include <assert.h>

/* REGISTERS */
#define PCF2123_REG_CTRL1       (0x00)    /* Control Register 1 */
#define PCF2123_REG_CTRL2       (0x01)    /* Control Register 2 */
#define PCF2123_REG_SC          (0x02)    /* datetime */
#define PCF2123_REG_MN          (0x03)
#define PCF2123_REG_HR          (0x04)
#define PCF2123_REG_DM          (0x05)
#define PCF2123_REG_DW          (0x06)
#define PCF2123_REG_MO          (0x07)
#define PCF2123_REG_YR          (0x08)
#define PCF2123_REG_ALRM_MN     (0x09)    /* Alarm Registers */
#define PCF2123_REG_ALRM_HR     (0x0a)
#define PCF2123_REG_ALRM_DM     (0x0b)
#define PCF2123_REG_ALRM_DW     (0x0c)
#define PCF2123_REG_OFFSET      (0x0d)    /* Clock Rate Offset Register */
#define PCF2123_REG_TMR_CLKOUT  (0x0e)    /* Timer Registers */
#define PCF2123_REG_CTDWN_TMR   (0x0f)

/* PCF2123_REG_CTRL1 BITS */
#define CTRL1_CLEAR             (0)                         /* Clear */
#define CTRL1_CORR_INT          (1<<1)                      /* Correction irq enable */
#define CTRL1_12_HOUR           (1<<2)                      /* 12 hour time */
#define CTRL1_SW_RESET          (1<<6) | (1<<4) | (1<<3)    /* Software reset */
#define CTRL1_STOP              (1<<5)                      /* Stop the clock */
#define CTRL1_EXT_TEST          (1<<7)                      /* External clock test mode */

/* PCF2123_REG_CTRL2 BITS */
#define CTRL2_TIE       (1)         /* Countdown timer irq enable */
#define CTRL2_AIE       (1<<1)      /* Alarm irq enable */
#define CTRL2_TF        (1<<2)      /* Countdown timer flag */
#define CTRL2_AF        (1<<3)      /* Alarm flag */
#define CTRL2_TI_TP     (1<<4)      /* Irq pin generates pulse */
#define CTRL2_MSF       (1<<5)      /* Minute or second irq flag */
#define CTRL2_SI        (1<<6)      /* Second irq enable */
#define CTRL2_MI        (1<<7)      /* Minute irq enable */

/* PCF2123_REG_SC BITS */
#define OSC_HAS_STOPPED      (1<<7)    /* Clock has been stopped */

/* PCF2123_REG_ALRM_XX BITS */
#define ALARM_ENABLE         (1<<7)    /* MN, HR, DM, or DW alarm enable */

/* PCF2123_REG_TMR_CLKOUT BITS */
#define CD_TMR_TE            (1<<3)    /* Countdown timer enable */

/* PCF2123_REG_OFFSET BITS */
#define OFFSET_SIGN_BIT       6         /* 2's complement sign bit */
#define OFFSET_COARSE         (1<<7)    /* Coarse mode offset */
#define OFFSET_STEP           (2170)    /* Offset step in parts per billion */

/* PCF2123 MASKS */
#define COF_MASK              0x70      // bits 6 to 4
#define CTD_MASK              0x03      // bits 1 to 0

/* PCF2123 SHIFTS */
#define COF_SHIFT             4
#define ALARM_EN_SHIFT        7

/*****************************************************************************
 * Variables
 ****************************************************************************/
static pcf2123_IoFunc_t sIoFunc;
static settingsPCF_t settings;
static bool initDriverDone = false;
static bool initHwDone = false;

/*****************************************************************************
 * Private functions
 ****************************************************************************/
static uint8_t PCF_SoftReset();

// software reset
uint8_t PCF_SoftReset()
{
    uint8_t wBuf[2] = {PCF2123_WRITE | PCF2123_REG_CTRL1, CTRL1_SW_RESET};

    // Reset all registers to POR value
    // 32.768 kHz on pin CLKOUT active, 24 hour mode is selected, Offset register is set to 0
    // No alarms set, Timer disabled, No interrupts enabled
    if (sIoFunc.SPI_Write(wBuf, 2) != 0) return PCF2123_I2C_ERROR;
    else return PCF2123_SUCCESS;
}

/*****************************************************************************
 * Public functions
 ****************************************************************************/

// wrap the low level function (I2C write, I2C read, WaitMsec) required by PCF2123 driver
// this function does not initialize the HW
void PCF2123_Init_Driver(pcf2123_IoFunc_t* pIoFunc){
	assert((pIoFunc != NULL) &&
		   (pIoFunc->SPI_Read != NULL) &&
		   (pIoFunc->SPI_Write != NULL) &&
		   (pIoFunc->WaitMsec != NULL));
    sIoFunc = *pIoFunc;
    initDriverDone = true;
}

void PCF2123_Deinit_Driver(){
	if (initHwDone)
	{
		/* Deinit HW */
		// nothing to do as already very low consumption
	}
	/* Deinit driver */
	initDriverDone = false;
	initHwDone = false;
}

// Initialize the sensor
pcf2123_status_t PCF2123_Init_Hw(const settingsPCF_t* pcfSettings, bool initTime)
{
	pcf2123_status_t status = PCF2123_SUCCESS;

	if (!initDriverDone) return PCF2123_INIT_ERROR;
	assert(pcfSettings != NULL);

	/* trick to allow calling internal public functions */
	initHwDone = true;

	// initialize internal structures which will be used from now on
    memcpy( (void*)&settings, (void*)pcfSettings, sizeof(settings) );

    if (settings.Softreset == true)
    {
        // Reset all registers to POR values
        status = PCF_SoftReset();
        if (status != PCF2123_SUCCESS) goto return_status;
    }

    // Set Date and Time
    if(initTime)
    {
		status = PCF2123_SetDateTime(&settings);
		if (status != PCF2123_SUCCESS) goto return_status;
    }

    // Set Clock output pin frequency
    status = PCF2123_SetClockOutputFreq(settings.clockOutputFreq);
    if (status != PCF2123_SUCCESS) goto return_status;

    // Set/reset Minute & second interrupt
    status = PCF2123_SetMinSecInterrupt(settings.MinInterrupt, settings.SecInterrupt, settings.PulseInterrupt);
    if (status != PCF2123_SUCCESS) goto return_status;

    return_status:
    if (status != PCF2123_SUCCESS) initHwDone = false;
    return status;
}

// Read all the chip registers
pcf2123_status_t PCF2123_Dump(uint8_t *pcfReg)
{
    uint8_t wBuf[17];

	if (!initHwDone) return PCF2123_INIT_ERROR;
	assert(pcfReg != NULL);

    wBuf[0] = PCF2123_READ | PCF2123_REG_CTRL1;    // read + sub address;    // Start reading at register address 0
    // read all registers
    if (sIoFunc.SPI_Read(wBuf, pcfReg, 16) != 0) return PCF2123_I2C_ERROR; // Read all 16 registers

    return PCF2123_SUCCESS;
}

// Read Date and Time
pcf2123_status_t PCF2123_GetDateTime(settingsPCF_t* pcfDateTime)
{
    uint8_t wBuf[8] = {0};
    uint8_t rBuf[8] = {0};

	if (!initHwDone) return PCF2123_INIT_ERROR;
	assert(pcfDateTime != NULL);

    wBuf[0] = PCF2123_READ | (PCF2123_REG_SC);    // read + sub address;    // Start reading at register address 0
    // read all registers
    if (sIoFunc.SPI_Read(wBuf, rBuf, 7) != 0) return PCF2123_I2C_ERROR; // Read all 16 registers
    pcfDateTime->seconds = rBuf[1];
    pcfDateTime->minutes = rBuf[2];
    pcfDateTime->hours = rBuf[3];
    pcfDateTime->days =rBuf[4];
    pcfDateTime->weekdays = rBuf[5];
    pcfDateTime->months = rBuf[6];
    pcfDateTime->years =rBuf[7];

    return PCF2123_SUCCESS;
}

// Set Date and Time
pcf2123_status_t PCF2123_SetDateTime(settingsPCF_t* pcfDateTime)
{
    uint8_t wBuf[8] = {0};
    uint8_t rBuf[8] = {0};

	if (!initHwDone) return PCF2123_INIT_ERROR;
	assert(pcfDateTime != NULL);

    // set STOP bit <=> stop RTC clock before updating date and time
    wBuf[0] = PCF2123_READ | PCF2123_REG_CTRL1;
    if (sIoFunc.SPI_Read(wBuf, rBuf, 1) != 0) return PCF2123_I2C_ERROR;    // read REG_CTRL1

    wBuf[0] = PCF2123_WRITE | PCF2123_REG_CTRL1;
    wBuf[1] = rBuf[1] | CTRL1_STOP;                                        // Set STOP bit
    wBuf[1] = (pcfDateTime->mode12_24 == CTRL1_12_HOUR) ? wBuf[1]|CTRL1_12_HOUR : wBuf[1]&~CTRL1_12_HOUR ;    // Set 12_24H bit
    if (sIoFunc.SPI_Write(wBuf, 2) != 0) return PCF2123_I2C_ERROR;        // Write it back

    // set the date and time
    wBuf[0] = PCF2123_WRITE | PCF2123_REG_SC;
    wBuf[1] = pcfDateTime->seconds;
    wBuf[2] = pcfDateTime->minutes;
    wBuf[3] = pcfDateTime->hours;
    wBuf[4] = pcfDateTime->days;
    wBuf[5] = pcfDateTime->weekdays;
    wBuf[6] = pcfDateTime->months;
    wBuf[7] = pcfDateTime->years;
    if (sIoFunc.SPI_Write(wBuf, 8) != 0) return PCF2123_I2C_ERROR;        // Write it back

    // reset STOP bit <=> restart RTC clock
    wBuf[0] = PCF2123_READ | PCF2123_REG_CTRL1;
    if (sIoFunc.SPI_Read(wBuf, rBuf, 1) != 0) return PCF2123_I2C_ERROR;    // read REG_CTRL1

    wBuf[0] = PCF2123_WRITE | PCF2123_REG_CTRL1;
    wBuf[1] = rBuf[1]  &~CTRL1_STOP ;            // reset STOP bit
    if (sIoFunc.SPI_Write(wBuf, 2) != 0) return PCF2123_I2C_ERROR;        // Write it back

    return PCF2123_SUCCESS;
}

// Set Clock output pin frequency from 1Hz up to 32768Hz, or disabled = High Z
pcf2123_status_t PCF2123_SetClockOutputFreq(clockOutputPCF_t pcfClockOutputFreq)
{
    uint8_t wBuf[2] = {0};
    uint8_t rBuf[2] = {0};

	if (!initHwDone) return PCF2123_INIT_ERROR;

    // read register Timer_clkout and set COF[2:0] field = clock output frequency
    wBuf[0] = PCF2123_READ | PCF2123_REG_TMR_CLKOUT;
    if (sIoFunc.SPI_Read(wBuf, rBuf, 1) != 0) return PCF2123_I2C_ERROR;

    wBuf[0] = PCF2123_WRITE | PCF2123_REG_TMR_CLKOUT;
    wBuf[1] = (rBuf[1] & ~COF_MASK) | (pcfClockOutputFreq << COF_SHIFT);    // Set COF[2:0]
    if (sIoFunc.SPI_Write(wBuf, 2) != 0) return PCF2123_I2C_ERROR;

    return PCF2123_SUCCESS;
}

// Set Countdown interrupt
// interrupt generated when countdown flag set
pcf2123_status_t PCF2123_SetCountdownInterrupt(bool Countdown_Int)
{
    uint8_t wBuf[2] = {0};
    uint8_t rBuf[2] = {0};

	if (!initHwDone) return PCF2123_INIT_ERROR;

    // read register CTRL_2 and reset TF bit
    wBuf[0] = PCF2123_READ | PCF2123_REG_CTRL2;
    if (sIoFunc.SPI_Read(wBuf, rBuf, 1) != 0) return PCF2123_I2C_ERROR;

    wBuf[0] = PCF2123_WRITE | PCF2123_REG_CTRL2;
    wBuf[1] = (Countdown_Int == true) ? wBuf[1] | CTRL2_TIE : wBuf[1] & ~CTRL2_TIE;        // Set/Reset countdown interrupt
    if (sIoFunc.SPI_Write(wBuf, 2) != 0) return PCF2123_I2C_ERROR;

    return PCF2123_SUCCESS;
}

// Set Countdown timer source clock.
pcf2123_status_t PCF2123_SetCountdownMode(bool CountDownEn, cdmodePCF_t CountDownMode)
{
    uint8_t wBuf[2] = {0};
    uint8_t rBuf[2] = {0};

	if (!initHwDone) return PCF2123_INIT_ERROR;

    // read register Timer_clkout. Set CTD[1:0] and TE
    wBuf[0] = PCF2123_READ | PCF2123_REG_TMR_CLKOUT;
    if (sIoFunc.SPI_Read(wBuf, rBuf, 1) != 0) return PCF2123_I2C_ERROR;

    wBuf[0] = PCF2123_WRITE | PCF2123_REG_TMR_CLKOUT;
    wBuf[1] = (CountDownEn == true) ? rBuf[1] | CD_TMR_TE : rBuf[1] &~CD_TMR_TE;    // Set/reset TE bit
    wBuf[1] = (wBuf[1] & ~CTD_MASK) | (CountDownMode);    // Set CTD[1:0]
    if (sIoFunc.SPI_Write(wBuf, 2) != 0) return PCF2123_I2C_ERROR;

    return PCF2123_SUCCESS;
}

// Set Countdown timer value
pcf2123_status_t PCF2123_SetCountdownTimer(uint8_t CDT_Value)
{
    uint8_t wBuf[2] = {PCF2123_WRITE | PCF2123_REG_CTDWN_TMR, CDT_Value};

	if (!initHwDone) return PCF2123_INIT_ERROR;

    if (sIoFunc.SPI_Write(wBuf, 2) != 0) return PCF2123_I2C_ERROR;

    return PCF2123_SUCCESS;
}

// Set Offset register
pcf2123_status_t PCF2123_SetOffset(bool mode, uint8_t Offset)
{
    uint8_t wBuf[2] = {PCF2123_WRITE | PCF2123_REG_OFFSET, (mode << 7) | (Offset & 0x7f)};

	if (!initHwDone) return PCF2123_INIT_ERROR;

    if (sIoFunc.SPI_Write(wBuf, 2) != 0) return PCF2123_I2C_ERROR;

    return PCF2123_SUCCESS;
}

// Set Minute and second interrupt
pcf2123_status_t PCF2123_SetMinSecInterrupt(bool Minute_Int, bool Second_Int, bool Pulse_Int)
{
    uint8_t wBuf[2] = {0};
    uint8_t rBuf[2] = {0};

	if (!initHwDone) return PCF2123_INIT_ERROR;

    // read register CTRL_2 and set MI/SI bits
    wBuf[0] = PCF2123_READ | PCF2123_REG_CTRL2;
    if (sIoFunc.SPI_Read(wBuf, rBuf, 1) != 0) return PCF2123_I2C_ERROR;

    wBuf[0] = PCF2123_WRITE | PCF2123_REG_CTRL2;
    wBuf[1] = (Minute_Int == true) ? wBuf[1] | CTRL2_MI : wBuf[1] & ~CTRL2_MI;        // Set/Reset minute interrupt
    wBuf[1] = (Second_Int == true) ? wBuf[1] | CTRL2_SI : wBuf[1] & ~CTRL2_SI;        // Set/Reset minute interrupt
    wBuf[1] = (Pulse_Int == true) ? wBuf[1] | CTRL2_TI_TP : wBuf[1] & ~CTRL2_TI_TP;    // Set/Reset interrupt pulse mode
    if (sIoFunc.SPI_Write(wBuf, 2) != 0) return PCF2123_I2C_ERROR;

    return PCF2123_SUCCESS;
}

// Set Alarm interrupt
pcf2123_status_t PCF2123_SetAlarmInterrupt(bool Alarm_Int)
{
    uint8_t wBuf[2] = {0};
    uint8_t rBuf[2] = {0};

	if (!initHwDone) return PCF2123_INIT_ERROR;

    // read register CTRL_2 and reset TF bit
    wBuf[0] = PCF2123_READ | PCF2123_REG_CTRL2;
    if (sIoFunc.SPI_Read(wBuf, rBuf, 1) != 0) return PCF2123_I2C_ERROR;

    wBuf[0] = PCF2123_WRITE | PCF2123_REG_CTRL2;
    wBuf[1] = (Alarm_Int == true) ? wBuf[1] | CTRL2_AIE : wBuf[1] & ~CTRL2_AIE;        // Set/Reset alarm interrupt
    if (sIoFunc.SPI_Write(wBuf, 2) != 0) return PCF2123_I2C_ERROR;

    return PCF2123_SUCCESS;
}

// Clear minute or second interrupt flag MSF
pcf2123_status_t PCF2123_ClearMinSecInterruptFlag()
{
    uint8_t wBuf[2] = {0};
    uint8_t rBuf[2] = {0};

	if (!initHwDone) return PCF2123_INIT_ERROR;

    // read register CTRL_2 and reset MSF bit
    wBuf[0] = PCF2123_READ | PCF2123_REG_CTRL2;
    if (sIoFunc.SPI_Read(wBuf, rBuf, 1) != 0) return PCF2123_I2C_ERROR;

    wBuf[0] = PCF2123_WRITE | PCF2123_REG_CTRL2;
    wBuf[1] &= ~CTRL2_MSF;                                                // Reset MSF bit
    if (sIoFunc.SPI_Write(wBuf, 2) != 0) return PCF2123_I2C_ERROR;

    return PCF2123_SUCCESS;
}

// Clear Timer countdown flag TF
pcf2123_status_t PCF2123_ClearCountdownInterruptFlag()
{
    uint8_t wBuf[2] = {0};
    uint8_t rBuf[2] = {0};

	if (!initHwDone) return PCF2123_INIT_ERROR;

    // read register CTRL_2 and reset TF bit
    wBuf[0] = PCF2123_READ | PCF2123_REG_CTRL2;
    if (sIoFunc.SPI_Read(wBuf, rBuf, 1) != 0) return PCF2123_I2C_ERROR;

    wBuf[0] = PCF2123_WRITE | PCF2123_REG_CTRL2;
    wBuf[1] &= ~CTRL2_TF;                                                // Reset TF bit
    if (sIoFunc.SPI_Write(wBuf, 2) != 0) return PCF2123_I2C_ERROR;

    return PCF2123_SUCCESS;
}

// Clear Alarm flag AF
pcf2123_status_t PCF2123_ClearAlarmInterruptFlag()
{
    uint8_t wBuf[2] = {0};
    uint8_t rBuf[2] = {0};

	if (!initHwDone) return PCF2123_INIT_ERROR;

    // read register CTRL_2 and reset TF bit
    wBuf[0] = PCF2123_READ | PCF2123_REG_CTRL2;
    if (sIoFunc.SPI_Read(wBuf, rBuf, 1) != 0) return PCF2123_I2C_ERROR;

    wBuf[0] = PCF2123_WRITE | PCF2123_REG_CTRL2;
    wBuf[1] &= ~CTRL2_AF;                                                // Reset AF bit
    if (sIoFunc.SPI_Write(wBuf, 2) != 0) return PCF2123_I2C_ERROR;

    return PCF2123_SUCCESS;
}

// Set Minute alarm
pcf2123_status_t PCF2123_SetMinuteAlarm(bool AlarmEn, uint8_t Minute)
{
    uint8_t wBuf[2] = {0};

	if (!initHwDone) return PCF2123_INIT_ERROR;

    wBuf[0] = PCF2123_WRITE | PCF2123_REG_ALRM_MN;
    wBuf[1] = (~AlarmEn << ALARM_EN_SHIFT) | (Minute & 0x7F);    // Alarm AE_M: minute alarm enabled when 0
    if (sIoFunc.SPI_Write(wBuf, 2) != 0) return PCF2123_I2C_ERROR;

    return PCF2123_SUCCESS;
}

// Set Hour alarm
pcf2123_status_t PCF2123_SetHourAlarm(bool AlarmEn, bool AMPM, uint8_t Hour)
{
    uint8_t wBuf[2] = {0};
    uint8_t rBuf[2] = {0};

	if (!initHwDone) return PCF2123_INIT_ERROR;

    // read register CTRL_1 to check if 12H or 24H mode is selected
    wBuf[0] = PCF2123_READ | PCF2123_REG_CTRL1;
    if (sIoFunc.SPI_Read(wBuf, rBuf, 1) != 0) return PCF2123_I2C_ERROR;

    wBuf[0] = PCF2123_WRITE | PCF2123_REG_ALRM_HR;
    wBuf[1] = (rBuf[1] & CTRL1_12_HOUR) ? (~AlarmEn << ALARM_EN_SHIFT) | (Hour & 0x7F) : (~AlarmEn << ALARM_EN_SHIFT) | (AMPM << 5) | (Hour & 0x3F);

    if (sIoFunc.SPI_Write(wBuf, 2) != 0) return PCF2123_I2C_ERROR;

    return PCF2123_SUCCESS;
}

// Set Day alarm
pcf2123_status_t PCF2123_SetDayAlarm(bool AlarmEn, uint8_t Day)
{
    uint8_t wBuf[2] = {0};

	if (!initHwDone) return PCF2123_INIT_ERROR;

    wBuf[0] = PCF2123_WRITE | PCF2123_REG_ALRM_DM;
    wBuf[1] = (~AlarmEn << ALARM_EN_SHIFT) | (Day & 0x3F);
    if (sIoFunc.SPI_Write(wBuf, 2) != 0) return PCF2123_I2C_ERROR;

    return PCF2123_SUCCESS;
}

// Set Weekday alarm
pcf2123_status_t PCF2123_SetWeekdayAlarm(bool AlarmEn, uint8_t Weekday)
{
    uint8_t wBuf[2] = {0};

	if (!initHwDone) return PCF2123_INIT_ERROR;

    wBuf[0] = PCF2123_WRITE | PCF2123_REG_ALRM_DW;
    wBuf[1] = (~AlarmEn << ALARM_EN_SHIFT) | (Weekday & 0x03);
    if (sIoFunc.SPI_Write(wBuf, 2) != 0) return PCF2123_I2C_ERROR;

    return PCF2123_SUCCESS;
}

SPI Bus Share Source

C/C++
SPI Bus Share between KW41 and K64
/*
 * Copyright 2017 NXP
 *
 * 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 the copyright holder 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 <string.h>
#include "fsl_gpio.h"
#include "board.h"
#include "fsl_dspi.h"
#include "fsl_port.h"
#include "spi_flash_driver.h"
#include "pin_mux.h"
#include "pin_mux_rpk.h"
#if defined(FSL_RTOS_FREE_RTOS)
#include "fsl_os_abstraction.h"
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
#endif
#include "spi_bus_share.h"
#if defined(CPU_MK64FN1M0VMD12)
#include "port_interrupts.h"
#endif
#if !defined(FSL_RTOS_FREE_RTOS)
#include "microseconds.h"
#endif
//#if defined(RAPID_IOT) && defined(CPU_MKW41Z512VHT4)
//#include "portmacro.h"
//#endif

//! @addtogroup spi_bus_share
//! @{

////////////////////////////////////////////////////////////////////////////////
// Prototypes
////////////////////////////////////////////////////////////////////////////////


////////////////////////////////////////////////////////////////////////////////
// Variables
////////////////////////////////////////////////////////////////////////////////

// Uncomment to use SPI bus flow control between the K64 and K41 processors
#define RPK_USE_FLOW_CONTROL 1
volatile bool bSPIBusgInitialized = false;
volatile bool mSPIBusLocked = false;
volatile bool mSPIBusRequest = false;

volatile static int icount = 0;
volatile static int IRQCount = 0;
volatile static int IRQCountSave = 0;


////////////////////////////////////////////////////////////////////////////////
// Code
////////////////////////////////////////////////////////////////////////////////

//! @brief Initialize SPI Bus so it can be used
status_t SPI_Bus_Share_Init(void)
{
    if (!bSPIBusgInitialized)
    {
        SPI_Bus_Share_Release_Access();
        bSPIBusgInitialized = true;
    }
    return(SPI_BUS_SHARE_NO_ERROR);
}


#if defined(CPU_MK64FN1M0VMD12)
void BOARD_K41Z_RTS_IRQ_HANDLER(uint32_t pin_nb)
{
    IRQCount+=1;

    if(!bSPIBusgInitialized)
        return;

    if(!mSPIBusLocked && !mSPIBusRequest)
           GPIO_WritePinOutput(BOARD_INITPINS_KW41_UART_CTS_GPIO, BOARD_INITPINS_KW41_UART_CTS_PIN, 1);

    GPIO_ClearPinsInterruptFlags(BOARD_INITPINS_KW41_UART_RTS_GPIO, 1U << BOARD_INITPINS_KW41_UART_RTS_PIN);
}
#endif


//! @brief Uninitialize SPI Bus so it can be used by another app / device
status_t SPI_Bus_Share_DeInit(void)
{
    SPI_Bus_Share_Release_Access();
    return(SPI_BUS_SHARE_NO_ERROR);
}


status_t SPI_Bus_Share_Get_Access(void)
{
    if(mSPIBusLocked)
        return(SPI_BUS_SHARE_NO_ERROR);

    // Make sure this driver is initialized
    if (!bSPIBusgInitialized)
        SPI_Bus_Share_Init();

    SPI_Bus_Share_Wait_For_Access();
    OS_App_WaitUsec(20);
    BOARD_ConfigurePins_RPK_SPI_Bus();
    OS_App_WaitUsec(20);
    icount+=1;
    return(SPI_BUS_SHARE_NO_ERROR);
}


status_t SPI_Bus_Share_Release_Access(void)
{
    if(!mSPIBusLocked)
        return(SPI_BUS_SHARE_NO_ERROR);

    OS_App_WaitUsec(20);
    BOARD_UnConfigurePins_RPK_SPI_Bus();
    OS_App_WaitUsec(20);
    icount+=1;

#if defined(RAPID_IOT) && defined(CPU_MKW41Z512VHT4)
    // Release SPI access to K64F by setting RTS pin low
    GPIO_WritePinOutput(BOARD_INITPINS_K64F_UART_RTS_PC5_GPIO, BOARD_INITPINS_K64F_UART_RTS_PC5_GPIO_PIN, 0);
#endif

    mSPIBusLocked = false;
    return(SPI_BUS_SHARE_NO_ERROR);
}

status_t SPI_Bus_Share_Wait_For_Access(void)
{

#ifndef RPK_USE_FLOW_CONTROL
    return(SPI_BUS_SHARE_NO_ERROR);
#endif

    // PC4 (CTS) connected to PE27
    // PC5 (RTS) connected to PE26
#if defined(RAPID_IOT) && defined(CPU_MKW41Z512VHT4)

    uint32_t i=0;
    icount=0;

    // Wait until the K64F approves the request
    while(1)
    {
        // Request SPI access from the K64F
        GPIO_WritePinOutput(BOARD_INITPINS_K64F_UART_RTS_PC5_GPIO, BOARD_INITPINS_K64F_UART_RTS_PC5_GPIO_PIN, 0);
        OS_App_WaitUsec(1);
        GPIO_WritePinOutput(BOARD_INITPINS_K64F_UART_RTS_PC5_GPIO, BOARD_INITPINS_K64F_UART_RTS_PC5_GPIO_PIN, 1);
        OS_App_WaitUsec(1);
        for(i=0;i<100;i++)
        {
            if(GPIO_ReadPinInput(BOARD_INITPINS_K64F_UART_CTS_PC4_GPIO, BOARD_INITPINS_K64F_UART_CTS_PC4_GPIO_PIN)!=0)
            {
                OS_App_WaitUsec(1);
                if(GPIO_ReadPinInput(BOARD_INITPINS_K64F_UART_CTS_PC4_GPIO, BOARD_INITPINS_K64F_UART_CTS_PC4_GPIO_PIN)!=0)
                    break;
            }
            icount+=1;
        }
        if(i<100)
        {
            icount+=1;
            mSPIBusLocked=true;
            break;
        }
    }

#elif defined(RAPID_IOT) && defined(CPU_MK64FN1M0VMD12)
    if(GPIO_ReadPinInput(BOARD_INITPINS_KW41_RST_GPIO, BOARD_INITPINS_KW41_RST_GPIO_PIN)!=0)
    {
        while(1)
        {
            mSPIBusRequest = true;
            IRQCountSave = IRQCount;
            if(GPIO_ReadPinInput(BOARD_INITPINS_KW41_UART_RTS_GPIO, BOARD_INITPINS_KW41_UART_RTS_PIN)==0)
            {
                GPIO_WritePinOutput(BOARD_INITPINS_KW41_UART_CTS_GPIO, BOARD_INITPINS_KW41_UART_CTS_PIN, 0);
                if(IRQCountSave == IRQCount)
                {
                    mSPIBusLocked = true;
                    break;
                }
            }
            else
            {
                GPIO_WritePinOutput(BOARD_INITPINS_KW41_UART_CTS_GPIO, BOARD_INITPINS_KW41_UART_CTS_PIN, 1);
                while(GPIO_ReadPinInput(BOARD_INITPINS_KW41_UART_RTS_GPIO, BOARD_INITPINS_KW41_UART_RTS_PIN)!=0)
                {
                    OS_App_WaitMsec(1);
                }
                GPIO_WritePinOutput(BOARD_INITPINS_KW41_UART_CTS_GPIO, BOARD_INITPINS_KW41_UART_CTS_PIN, 0);
                while(GPIO_ReadPinInput(BOARD_INITPINS_KW41_UART_RTS_GPIO, BOARD_INITPINS_KW41_UART_RTS_PIN)!=0)
                {
                    OS_App_WaitMsec(1);
                }
                mSPIBusLocked = true;
                break;
            }
        }
    }
    else
    {
        mSPIBusLocked = true;
    }
#endif
    mSPIBusRequest = false;
    return(SPI_BUS_SHARE_NO_ERROR);
}

void OS_App_WaitMsec(uint32_t msec)
{
#if !defined(BOOTLOADER)
#if defined(RAPID_IOT) && defined(CPU_MKW41Z512VHT4)

#if defined(FSL_RTOS_FREE_RTOS)
    BaseType_t tskSchState = xTaskGetSchedulerState();

    /* Check if the task scheduler has started */
    if (taskSCHEDULER_NOT_STARTED != tskSchState)
    {
        OSA_TimeDelay(msec);
    }
    else
    {
        volatile uint32_t count = msec * 1000;
        while (count--);
    }
#else
    microseconds_delay(msec*1000);
#endif
#else
    App_WaitMsec(msec);
#endif
#else
    microseconds_delay(msec*1000);
#endif
}


void OS_App_WaitUsec(uint32_t usec)
{
#if !defined(BOOTLOADER)
#if defined(RAPID_IOT) && defined(CPU_MKW41Z512VHT4)

#if defined(FSL_RTOS_FREE_RTOS)
    BaseType_t tskSchState = xTaskGetSchedulerState();

    /* Check if the task scheduler has started */
    if (taskSCHEDULER_NOT_STARTED != tskSchState)
    {
        OSA_TimeDelay_Usec(usec);
    }
    else
    {
        volatile uint32_t count = usec;
        while (count--);
    }
#else
    microseconds_delay(usec);
#endif
#else
    App_WaitUsec(usec);
#endif
#else
    microseconds_delay(usec);
#endif
}

//! @}

////////////////////////////////////////////////////////////////////////////////
// EOF
////////////////////////////////////////////////////////////////////////////////

PCF2123 RTC header

C Header File
PCF2123 RTC header
/*
 * Copyright (c) 2018 NXP
 *
 * 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 the copyright holder 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.
 */

/*!
 * @file
 * This is the header file for the real time clock sensor PCF2123 driver.
 */

#ifndef PCF2123_H_
#define PCF2123_H_

/*!
 * @addtogroup pcf2123 PCF2123 real time clock sensor API
 * @{
 */

#include <stdbool.h>
#include <EmbeddedTypes.h>

typedef struct _pcf2123_IoFunc_t
{
  uint8_t   (*SPI_Read)(uint8_t *writeBuf, uint8_t *readBuf, uint32_t readSize);
  uint8_t   (*SPI_Write)(uint8_t *writeBuf, uint32_t writeSize);
  void      (*WaitMsec)(uint32_t millisec);
} pcf2123_IoFunc_t, *ppcf2123_IoFunc_t;

/*****************************************************************************
 * Types/enumerations/variables
 ****************************************************************************/

#define PCF2123_NB_REG           (16)    // Nb of registers

/* READ/WRITE ADDRESS BITS */
#define PCF2123_WRITE            (1<<4)
#define PCF2123_READ             ((1<<7) | (1<<4))
#define PCF2123_ADDRESS_MASK     (0x0f)

typedef enum
{
  PCF2123_SUCCESS,
  PCF2123_I2C_ERROR,
  PCF2123_INIT_ERROR,
  PCF2123_TIMEOUT
} pcf2123_status_t;

//***************************************
// Structure that contains PCF settings.
//***************************************

typedef enum {
  PCF2123_MODE_24HOURS    = 0,
  PCF2123_MODE_12HOURS    = (1<<2),
} modePCF_t;

typedef enum {
    Sunday        = 0,
    Monday        = 1,
    Tuesday       = 2,
    Wednesday     = 3,
    Thursday      = 4,
    Friday        = 5,
    Saturday      = 6,
} weekdaysPCF_t;

typedef enum {
    January       = 0x1,
    February      = 0x2,
    March         = 0x3,
    April         = 0x4,
    May           = 0x5,
    June          = 0x6,
    July          = 0x7,
    August        = 0x8,
    September     = 0x9,
    October       = 0x10,
    November      = 0x11,
    December      = 0x12,
} monthsPCF_t;

typedef enum {
    clkoutFreq_32768   = 0,        // Clock output frequency = 32768Hz
    clkoutfreq_16384   = 1,
    clkoutFreq_8192    = 2,
    clkoutFreq_4096    = 3,
    clkoutFreq_2408    = 4,
    clkoutFreq_1024    = 5,
    clkoutFreq_1       = 6,        // Clock output frequency = 1Hz
    clkout_High_Z      = 7,        // Clock output is High Z
} clockOutputPCF_t;

typedef enum
{
    CD_TMR_4096KHZ        = 0,    /* 4096 KHz countdown timer */
    CD_TMR_64HZ           = 1,    /* 64 Hz countdown timer */
    CD_TMR_1HZ            = 2,    /* 1 Hz countdown timer */
    CD_TMR_60th_HZ        = 3,    /* 60th Hz countdown timer */
} cdmodePCF_t;

typedef struct {
    modePCF_t           mode12_24;          // 12H or 24H mode
    bool                Softreset;          // Force software reset => Date, time and interrupts need to be set after
    uint8_t             seconds;            // seconds in BCD
    uint8_t             minutes;            // minutes in BCD
    uint8_t             hours;              // hours in BCD.
                                            /* 24H mode: bit 5,4 used for first digit
                                               12H mode: bit 5=AM/PM, bit 4 used for first digit */
    uint8_t             days;               // day in BCD
    weekdaysPCF_t       weekdays;           //
    monthsPCF_t         months;             // actual month coded in BCD
    uint8_t             years;              // 2 digits
    clockOutputPCF_t    clockOutputFreq;    // Clock output pin frequency from 1H to 32768Hz or Disabled = high Z
    bool                MinInterrupt;       // Minute interrupt
    bool                SecInterrupt;       // Second interrupt
    bool                PulseInterrupt;     // Interrupt generate a pulse when true. Follows timer flag when false
} settingsPCF_t;


/*****************************************************************************
 * Function Prototypes
 ****************************************************************************/

/*!
 * @brief   Initialize PCF2123 driver.
 * @param   pIoFunc  Pointer to a structure of external functions or values
 */
void PCF2123_Init_Driver(pcf2123_IoFunc_t* pIoFunc);

/*!
 * @brief   De-initialize PCF2123 driver.
 */
void PCF2123_Denit_Driver();

/*!
 * @brief   Initialize PCF2123 hardware.
 * @param   pcfSettings  Pointer to a configuration structure
 * @return  The return status value (0 for success)
 */
pcf2123_status_t PCF2123_Init_Hw(const settingsPCF_t* pcfSettings, bool initTime);

/*!
 * @brief Read all chip registers.
 * @param   pcfReg  Pointer to register dump.
 * @return  The return status value (0 for success)
 */
pcf2123_status_t PCF2123_Dump(uint8_t *pcfReg);

/*!
 * @brief Set Offset register
 * The offset is made once every two hours in the normal mode, or once every hour in the
 * course mode. Each LSB will introduce an offset of 2.17 ppm for normal mode and
 * 4.34 ppm for course mode. The values of 2.17 ppm and 4.34 ppm are based on a nominal
 * 32.768 kHz clock. The offset value is coded in two’s complement giving a range of +63 LSB to -64 LSB.
 * Normal mode = 0, Course mode = 1
 * @param   mode (normal = 0, course = 1)
 * @param   Offset (+63..-64, two's complement)
 * @return  The return status value (0 for success)
 */
pcf2123_status_t PCF2123_SetOffset(bool mode, uint8_t Offset);

/*!
 * @brief Read Date and Time
 * @param   pcfDateTime  Pointer to the updated structure
 * @return  The return status value (0 for success)
 */
pcf2123_status_t PCF2123_GetDateTime(settingsPCF_t* pcfDateTime);

/*!
 * @brief Set Date and Time
 * @param   pcfDateTime  Pointer to the reference structure
 * @return  The return status value (0 for success)
 */
pcf2123_status_t PCF2123_SetDateTime(settingsPCF_t* pcfDateTime);

/*!
 * @brief Set Clock output pin frequency from 1Hz up to 32768Hz, or disabled = High Z
 * @param   pcfClockOutputFreq  Pointer to the clock output frequency value
 * @return  The return status value (0 for success)
 */
pcf2123_status_t PCF2123_SetClockOutputFreq(clockOutputPCF_t pcfClockOutputFreq);

/*!
 * @brief Set Minute and second interrupt
 * The minute and second interrupts (bits MI and SI) are pre-defined timers for generating
 * periodic interrupts. The timers can be enabled independently from one another. However,
 * a minute interrupt enabled on top of a second interrupt will not be distinguishable since it
 * will occur at the same time
 * @param   Minute_Int Enable the minute interrupt
 * @param   Second_Int Enable the second interrupt
 * @param   Pulse_Int  Enable the pulse interrupt
 * @return  The return status value (0 for success)
 */
pcf2123_status_t PCF2123_SetMinSecInterrupt(bool Minute_Int, bool Second_Int, bool Pulse_Int);

/*!
 * @brief Set Alarm interrupt
 * Interrupt generated when alarm flag set.
 * @param   Alarm_Int Enable the alarm interrupt
 * @return  The return status value (0 for success)
 */
pcf2123_status_t PCF2123_SetAlarmInterrupt(bool Alarm_Int);

/*!
 * @brief Set Countdown interrupt
 * Interrupt generated when countdown flag set.
 * @param   Countdown_Int Enable the countdown interrupt
 * @return  The return status value (0 for success)
 */
pcf2123_status_t PCF2123_SetCountdownInterrupt(bool Countdown_Int);

/*!
 * @brief Set Countdown timer source clock
 * @param   CountDownEn Enable the countdown timer source clock
 * @param   CountDownMode Countdown mode (CD_TMR_4096KHZ, CD_TMR_64HZ, CD_TMR_1HZ, CD_TMR_60th_HZ)
 * @return  The return status value (0 for success)
 */
pcf2123_status_t PCF2123_SetCountdownMode(bool CountDownEn, cdmodePCF_t CountDownMode);

/*!
 * @brief Set Countdown timer value
 * @param   CDT_Value Countdown timer value
 * @return  The return status value (0 for success)
 */
pcf2123_status_t PCF2123_SetCountdownTimer(uint8_t CDT_Value);

/*!
 * @brief Set Minute alarm
 * Minute alarm information coded in *** BCD format ***
 * When the register Minute_alarm is loaded with a valid minute and it's corresponding alarm bit is logic 0
 * that information will be compared with the current minute.
 * @param   AlarmEn Enable alarm
 * @param   Minute  Number of minutes
 * @return  The return status value (0 for success)
 */
pcf2123_status_t PCF2123_SetMinuteAlarm(bool AlarmEn, uint8_t Minute);

/*!
 * @brief Set Hour alarm
 * Hour alarm information coded in *** BCD format ***.
 * When the register Hour is loaded with a valid hour and it's corresponding alarm bit is logic 0
 * that information will be compared with the current hour.
 * AMPM = 0 indicates AM (only valid in 12 hours mode)
 * @param   AlarmEn Enable alarm
 * @param   AMPM  AMPM mode (0 is AM, 1 is PM)
 * @param   Hour  Number of hours
 * @return  The return status value (0 for success)
 */
pcf2123_status_t PCF2123_SetHourAlarm(bool AlarmEn, bool AMPM, uint8_t Hour);

/*!
 * @brief Set Day alarm
 * Day alarm information coded in *** BCD format ***.
 * When the register Day_alarm is loaded with a valid day and it's corresponding alarm bit is logic 0
 * that information will be compared with the current Day.
 * @param   AlarmEn Enable alarm
 * @param   Day     Number of days
 * @return  The return status value (0 for success)
 */
pcf2123_status_t PCF2123_SetDayAlarm(bool AlarmEn, uint8_t Day);

/*!
 * @brief Set Weekday alarm
 * Weekday alarm information coded in *** BCD format ***.
 * When the register weekday_alarm is loaded with a valid day and it's corresponding alarm bit is logic 0
 * that information will be compared with the current weekday.
 * @param   AlarmEn Enable alarm
 * @param   Weekday Day of the week (0-6: 0 is Sunday, etc.)
 * @return  The return status value (0 for success)
 */
pcf2123_status_t PCF2123_SetWeekdayAlarm(bool AlarmEn, uint8_t Weekday);

/*!
 * @brief Clear minute or second interrupt flag MSF
 * @return  The return status value (0 for success)
 */
pcf2123_status_t PCF2123_ClearMinSecInterruptFlag();

/*!
 * @brief Clear Timer countdown flag TF
 * Flag set as the end of a timer countdown.
 * @return  The return status value (0 for success)
 */
pcf2123_status_t PCF2123_ClearCountdownInterruptFlag();

/*!
 * @brief Clear Alarm flag AF
 * Flag set by alarm event.
 * @return  The return status value (0 for success)
 */
pcf2123_status_t PCF2123_ClearAlarmInterruptFlag();

/*! @}*/

#endif /* PCF2123_H_ */

SPI Bus Share Header

C Header File
SPI Bus Share Header
/*
 * Copyright 2017 NXP
 *
 * 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 the copyright holder 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 _SPI_BUS_SHARE_INIT_H_
#define _SPI_BUS_SHARE_INIT_H_

#include "fsl_common.h"

//! @addtogroup SPI_Share
//! @{

////////////////////////////////////////////////////////////////////////////////
// Definitions
////////////////////////////////////////////////////////////////////////////////

#define SPI_BUS_SHARE_NO_ERROR 0
#define SPI_BUS_SHARE_ERROR 1


////////////////////////////////////////////////////////////////////////////////
// Prototypes
////////////////////////////////////////////////////////////////////////////////


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

status_t SPI_Bus_Share_Init(void);
status_t SPI_Bus_Share_DeInit(void);
status_t SPI_Bus_Share_Get_Access(void);
status_t SPI_Bus_Share_Release_Access(void);
status_t SPI_Bus_Share_Wait_For_Access(void);
void OS_App_WaitMsec(uint32_t msec);
void OS_App_WaitUsec(uint32_t usec);
void BOARD_K41Z_RTS_IRQ_HANDLER(uint32_t pin_nb);

#if defined(__cplusplus)
}
#endif // __cplusplus

//! @}

#endif // _SPI_BUS_SHARE_INIT_H_
////////////////////////////////////////////////////////////////////////////////
// EOF
////////////////////////////////////////////////////////////////////////////////

Credits

Marco Merlin

Marco Merlin

4 projects • 7 followers
Electronics Engineer, passionate for tech and music, able to "get things done", curious and aspiring to "solve real-life problems".

Comments