arch/arm/src/lpc54xx: Add an RTC driver and a RTC character driver lower half. configs/lpcxpresso-lpc54628: Add logic to register the RTC character driver if it is enabled. Enable the RTC and RTC character driver in the NSH configuration.

This commit is contained in:
Gregory Nutt 2017-12-25 13:56:06 -06:00
parent 7e7bdd181f
commit 0b91074850
12 changed files with 1389 additions and 12 deletions

View File

@ -406,6 +406,11 @@ config LPC54_LCD
default n
depends on ARCH_LPC54_HAVE_LCD
config LPC54_RTC
bool "RTC"
default n
select RTC
config LPC54_SDMMC
bool "SD/MMC"
default n

View File

@ -105,6 +105,13 @@ ifeq ($(CONFIG_LPC54_GPIOIRQ),y)
CHIP_CSRCS += lpc54_gpioirq.c
endif
ifeq ($(CONFIG_RTC),y)
CHIP_CSRCS += lpc54_rtc.c
ifeq ($(CONFIG_RTC_DRIVER),y)
CHIP_CSRCS += lpc54_rtc_lowerhalf.c
endif
endif
ifeq ($(CONFIG_LPC54_WWDT),y)
CHIP_CSRCS += lpc54_wwdt.c
endif

View File

@ -0,0 +1,96 @@
/********************************************************************************************
* arch/arm/src/lpc54xx/lpc54_rtc.h
*
* Copyright (C) 2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
********************************************************************************************/
#ifndef __ARCH_ARM_SRC_LPC54XX_CHIP_LPC54_RTC_H
#define __ARCH_ARM_SRC_LPC54XX_CHIP_LPC54_RTC_H
/********************************************************************************************
* Included Files
********************************************************************************************/
#include <nuttx/config.h>
#include "chip/lpc54_memorymap.h"
/********************************************************************************************
* Pre-processor Definitions
********************************************************************************************/
#define LPC54_RTC_NGPREGS 8 /* Nubmer of general purpose registers */
/* Register offsets *************************************************************************/
#define LPC54_RTC_CTRL_OFFSET 0x0000 /* RTC control */
#define LPC54_RTC_MATCH_OFFSET 0x0004 /* RTC match */
#define LPC54_RTC_COUNT_OFFSET 0x0008 /* RTC counter */
#define LPC54_RTC_WAKE_OFFSET 0x000c /* High-resolution/wake-up timer control */
/* General purpose registers */
#define LPC54_RTC_GPREG_OFFSET(n) (0x0040 + ((n) << 2))
/* Register addresses ***********************************************************************/
#define LPC54_RTC_CTRL (LPC54_RTC_BASE + LPC54_RTC_CTRL_OFFSET)
#define LPC54_RTC_MATCH (LPC54_RTC_BASE + LPC54_RTC_MATCH_OFFSET)
#define LPC54_RTC_COUNT (LPC54_RTC_BASE + LPC54_RTC_COUNT_OFFSET)
#define LPC54_RTC_WAKE (LPC54_RTC_BASE + LPC54_RTC_WAKE_OFFSET)
/* General purpose registers */
#define LPC54_RTC_GPREG(n) (LPC54_RTC_BASE + LPC54_RTC_GPREG_OFFSET(n))
/* Register bit definitions *****************************************************************/
/* RTC control */
#define RTC_CTRL_SWRESET (1 << 0) /* Bit 0: Software reset control */
#define RTC_CTRL_ALARM1HZ (1 << 2) /* Bit 2: RTC 1 Hz timer alarm flag status */
#define RTC_CTRL_WAKE1KHZ (1 << 3) /* Bit 3: RTC 1 kHz timer wake-up flag status */
#define RTC_CTRL_ALARMDPDEN (1 << 4) /* Bit 4: RTC 1 Hz timer alarm enable for deep power-down */
#define RTC_CTRL_WAKEDPDEN (1 << 5) /* Bit 5: RTC 1 kHz timer wake-up enable for deep power-down */
#define RTC_CTRL_RTC1KHZEN (1 << 6) /* Bit 6: RTC 1 kHz clock enable */
#define RTC_CTRL_RTCEN (1 << 7) /* Bit 7: RTC enable */
#define RTC_CTRL_OSCPD (1 << 8) /* Bit 8: RTC oscillator power-down control */
/* RTC match (32-bit timer match value) */
/* RTC counter (32-bit counter value) */
/* High-resolution/wake-up timer control */
#define RTC_WAKE_MASK 0xffff /* Bits 0-15: 16 hi-resoution/wake-up timer */
/* General purpose registers (32-bit value) */
#endif /* __ARCH_ARM_SRC_LPC54XX_CHIP_LPC54_RTC_H */

View File

@ -279,7 +279,7 @@
#define LPC54_SYSCON_FROCTRL (LPC54_SYSCON_BASE + LPC54_SYSCON_FROCTRL_OFFSET)
#define LPC54_SYSCON_SYSOSCCTRL (LPC54_SYSCON_BASE + LPC54_SYSCON_SYSOSCCTRL_OFFSET)
#define LPC54_SYSCON_WDTOSCCTRL (LPC54_SYSCON_BASE + LPC54_SYSCON_WDTOSCCTRL_OFFSET)
#define LPC54_SYSCON_RTCOSCCTRL_ (LPC54_SYSCON_BASE + LPC54_SYSCON_RTCOSCCTRL_OFFSET)
#define LPC54_SYSCON_RTCOSCCTRL (LPC54_SYSCON_BASE + LPC54_SYSCON_RTCOSCCTRL_OFFSET)
#define LPC54_SYSCON_USBPLLCTRL (LPC54_SYSCON_BASE + LPC54_SYSCON_USBPLLCTRL_OFFSET)
#define LPC54_SYSCON_USBPLLSTAT (LPC54_SYSCON_BASE + LPC54_SYSCON_USBPLLSTAT_OFFSET)
#define LPC54_SYSCON_SYSPLLCTRL (LPC54_SYSCON_BASE + LPC54_SYSCON_SYSPLLCTRL_OFFSET)
@ -741,8 +741,8 @@
#define SYSCON_WDTOSCCTRL_FREQSEL_SHIFT (5) /* Bits 5-9: Frequency select */
#define SYSCON_WDTOSCCTRL_FREQSEL_MASK (0x1f << SYSCON_WDTOSCCTRL_FREQSEL_SHIFT)
# define SYSCON_WDTOSCCTRL_FREQSEL_04pMHZ (1 << SYSCON_WDTOSCCTRL_FREQSEL_SHIFT) /* 0.4 MHz */
# define SYSCON_WDTOSCCTRL_FREQSEL_0p75MHZ (2 << SYSCON_WDTOSCCTRL_FREQSEL_SHIFT) /* 0.6 MHz */
# define SYSCON_WDTOSCCTRL_FREQSEL_0p9MHZ (3 << SYSCON_WDTOSCCTRL_FREQSEL_SHIFT) /* 0.75 MHz */
# define SYSCON_WDTOSCCTRL_FREQSEL_0p6MHZ (2 << SYSCON_WDTOSCCTRL_FREQSEL_SHIFT) /* 0.6 MHz */
# define SYSCON_WDTOSCCTRL_FREQSEL_0p75MHZ (3 << SYSCON_WDTOSCCTRL_FREQSEL_SHIFT) /* 0.75 MHz */
# define SYSCON_WDTOSCCTRL_FREQSEL_0p9MHZ (4 << SYSCON_WDTOSCCTRL_FREQSEL_SHIFT) /* 0.9 MHz */
# define SYSCON_WDTOSCCTRL_FREQSEL_1p0MHZ (5 << SYSCON_WDTOSCCTRL_FREQSEL_SHIFT) /* 1.0 MHz */
# define SYSCON_WDTOSCCTRL_FREQSEL_1p2MHZ (6 << SYSCON_WDTOSCCTRL_FREQSEL_SHIFT) /* 1.2 MHz */
@ -773,7 +773,9 @@
# define SYSCON_WDTOSCCTRL_FREQSEL_3p05MHZ (31 << SYSCON_WDTOSCCTRL_FREQSEL_SHIFT) /* 3.05 MHz */
/* RTC oscillator 32 kHz output control */
#define SYSCON_RTCOSCCTRL_
#define SYSCON_RTCOSCCTRL_EN (1 << 0) /* Bit 0: RTC 32 kHz clock enable */
/* USB PLL control */
#define SYSCON_USBPLLCTRL_
/* USB PLL status */

View File

@ -0,0 +1,377 @@
/****************************************************************************
* arch/arm/src/lpc54/lpc54_rtc.c
*
* Copyright (C) 2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#include <time.h>
#include <errno.h>
#include <nuttx/arch.h>
#include <nuttx/irq.h>
#include <nuttx/timers/rtc.h>
#include <arch/board/board.h>
#include "up_arch.h"
#include "chip/lpc54_rtc.h"
#include "lpc54_enableclk.h"
#include "lpc54_rtc.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* Configuration ************************************************************/
#ifdef CONFIG_RTC_HIRES
# error "CONFIG_RTC_HIRES is not supported"
#endif
/****************************************************************************
* Private Data
****************************************************************************/
#ifdef CONFIG_RTC_ALARM
/* Callback to use when the alarm expires */
static alarmcb_t g_alarmcb;
#endif
/****************************************************************************
* Public Data
****************************************************************************/
/* Variable determines if the RTC has been initialized and enabled. */
volatile bool g_rtc_enabled = false;
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: lpc54_rtc_interrupt
*
* Description:
* RTC interrupt service routine
*
* Input Parameters:
* irq - The IRQ number that generated the interrupt
* context - Architecture specific register save information.
*
* Returned Value:
* Zero (OK) on success; A negated errno value on failure.
*
****************************************************************************/
#ifdef CONFIG_RTC_ALARM
static int lpc54_rtc_interrupt(int irq, void *context, FAR void *arg)
{
uint32_t status = getreg16(LPC54_RTC_CTRL);
if ((status & RTC_CTRL_ALARM1HZ) != 0 && g_alarmcb != NULL)
{
/* Clear pending status */
putreg32(status | RTC_CTRL_ALARM1HZ | RTC_CTRL_WAKE1KHZ, LPC54_RTC_CTRL);
/* Perform the alarm callback */
g_alarmcb();
g_alarmcb = NULL;
}
return OK;
}
#endif
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: up_rtc_initialize
*
* Description:
* Initialize the hardware RTC per the selected configuration. This function is
* called once during the OS initialization sequence
*
* Input Parameters:
* None
*
* Returned Value:
* Zero (OK) on success; a negated errno on failure
*
****************************************************************************/
int up_rtc_initialize(void)
{
uint32_t regval;
/* Enable the clock to the RTC register interface and peripheral clock. */
lpc54_rtc_enableclk();
/* If the 32 kHz output of the RTC is used by another part of the system, enable it
* via the EN bit in the RTCOSCCTRL register
*/
putreg32(SYSCON_RTCOSCCTRL_EN, LPC54_SYSCON_RTCOSCCTRL);
/* The RTC is already running or, perhaps waiting to be enabled if it was never
* configured. We will set enable the RTC only if the time if initialized by
* higher level logic.
*/
g_rtc_enabled = true;
return OK;
}
/****************************************************************************
* Name: up_rtc_time
*
* Description:
* Get the current time in seconds. This is similar to the standard time()
* function. This interface is only required if the low-resolution RTC/counter
* hardware implementation selected. It is only used by the RTOS during
* initialization to set up the system time when CONFIG_RTC is set.
*
* Input Parameters:
* None
*
* Returned Value:
* The current time in seconds
*
****************************************************************************/
time_t up_rtc_time(void)
{
/* Read and return the 32-bit 1Hz RTC counter value */
return getreg32(LPC54_RTC_COUNT);
}
/****************************************************************************
* Name: up_rtc_settime
*
* Description:
* Set the RTC to the provided time. All RTC implementations must be
* able to set their time based on a standard timespec.
*
* Input Parameters:
* tp - the time to use
*
* Returned Value:
* Zero (OK) on success; a negated errno on failure
*
****************************************************************************/
int up_rtc_settime(FAR const struct timespec *tp)
{
irqstate_t flags;
uint32_t regval;
/* Read the Break out the time values */
flags = enter_critical_section();
/* Make sure the the RTC is out of reset, but not enabled. */
regval = getreg32(LPC54_RTC_CTRL);
regval &= ~(RTC_CTRL_SWRESET | RTC_CTRL_RTCEN | RTC_CTRL_RTC1KHZEN |
RTC_CTRL_OSCPD);
putreg32(regval, LPC54_RTC_CTRL);
/* Then write the time in seconds to the counter register. NOTE that we
* can only write to this register when the RTC_EN bit in the RTC CTRL
* Register is 0.
*/
putreg32(tp->tv_sec, LPC54_RTC_COUNT);
/* (Re-)enabled the RTC. The counter increments one second after the
* RTC_EN bit is set.
*/
regval |= RTC_CTRL_RTCEN;
putreg32(regval, LPC54_RTC_CTRL);
/* Make sure that magic value is in the general purpose register */
putreg32(RTC_MAGIC, RTC_MAGIC_REG);
leave_critical_section(flags);
return OK;
}
/****************************************************************************
* Name: lpc54_rtc_setalarm
*
* Description:
* Set up an alarm.
*
* Input Parameters:
* tp - The time to set the alarm
* callback - The function to call when the alarm expires.
*
* Returned Value:
* Zero (OK) on success; a negated errno on failure
*
****************************************************************************/
#ifdef CONFIG_RTC_ALARM
int lpc54_rtc_setalarm(FAR const struct timespec *tp, alarmcb_t callback)
{
irqstate_t flags;
uint32_t regval;
int ret = -EBUSY;
/* Is there already something waiting on the ALARM? */
flags = enter_critical_section();
if (g_alarmcb == NULL)
{
/* No.. Save the callback function pointer */
g_alarmcb = callback;
/* Make sure the the RTC is out of reset. */
regval = getreg32(LPC54_RTC_CTRL);
regval &= ~(RTC_CTRL_SWRESET | RTC_CTRL_ALARMDPDEN | RTC_CTRL_RTC1KHZEN |
RTC_CTRL_WAKEDPDEN | RTC_CTRL_OSCPD);
putreg32(regval, LPC54_RTC_CTRL);
/* Make sure that the ALARM interrupt is attached and enabled. */
irq_attach(LPC54_IRQ_RTC, lpc54_rtc_interrupt, NULL);
up_enable_irq(LPC54_IRQ_RTC);
/* Set the alarm match register */
putreg32(tp->tv_sec, LPC54_RTC_MATCH);
/* Enable RTC alarm */
regval |= RTC_CTRL_ALARMDPDEN;
putreg32(regval, LPC54_RTC_CTRL);
ret = OK;
}
leave_critical_section(flags);
return ret;
}
#endif
/****************************************************************************
* Name: lpc54_rtc_rdalarm
*
* Description:
* Query an alarm configured in hardware.
*
* Input Parameters:
* time - Current alarm setting.
*
* Returned Value:
* Zero (OK) on success; a negated errno on failure
*
****************************************************************************/
#ifdef CONFIG_RTC_ALARM
int lpc54_rtc_rdalarm(FAR struct tm *time)
{
uint32_t match;
match = getreg32(LPC54_RTC_MATCH);
(void)gmtime_r((time_t *)&match, time);
return OK;
}
#endif
/****************************************************************************
* Name: lpc54_rtc_cancelalarm
*
* Description:
* Cancel a pending alarm alarm
*
* Input Parameters:
* none
*
* Returned Value:
* Zero (OK) on success; a negated errno on failure
*
****************************************************************************/
#ifdef CONFIG_RTC_ALARM
int lpc54_rtc_cancelalarm(void)
{
irqstate_t flags;
uint32_t regval;
int ret = -ENODATA;
flags = enter_critical_section();
if (g_alarmcb != NULL)
{
/* Cancel the global callback function */
g_alarmcb = NULL;
/* Disable the Alarm interrupt */
up_disable_irq(LPC54_IRQ_RTC);
/* Unset the alarm */
regval = getreg32(LPC54_RTC_CTRL);
regval &= ~(RTC_CTRL_SWRESET | RTC_CTRL_ALARMDPDEN | RTC_CTRL_RTC1KHZEN |
RTC_CTRL_WAKEDPDEN | RTC_CTRL_OSCPD);
putreg32(regval, LPC54_RTC_CTRL);
ret = OK;
}
leave_critical_section(flags);
return ret;
}
#endif

View File

@ -0,0 +1,172 @@
/****************************************************************************
* arch/arm/src/lpc54xx/lpc54_rtc.h
*
* Copyright (C) 2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#ifndef __ARCH_ARM_SRC_LPC54XX_LPC54_RTC_H
#define __ARCH_ARM_SRC_LPC54XX_LPC54_RTC_H
#include <nuttx/config.h>
#include "chip.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define RTC_MAGIC (0xfacefeed)
#define RTC_MAGIC_REG LPC54_RTC_GPREG(0)
/****************************************************************************
* Public Types
****************************************************************************/
#ifndef __ASSEMBLY__
#ifdef CONFIG_RTC_ALARM
/* The form of an alarm callback */
typedef CODE void (*alarmcb_t)(void);
#endif
/****************************************************************************
* Public Data
****************************************************************************/
#undef EXTERN
#if defined(__cplusplus)
#define EXTERN extern "C"
extern "C"
{
#else
#define EXTERN extern
#endif
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: lpc54_rtc_setalarm
*
* Description:
* Set up an alarm.
*
* Input Parameters:
* tp - the time to set the alarm
* callback - the function to call when the alarm expires.
*
* Returned Value:
* Zero (OK) on success; a negated errno on failure
*
****************************************************************************/
#ifdef CONFIG_RTC_ALARM
struct timespec;
int lpc54_rtc_setalarm(FAR const struct timespec *tp, alarmcb_t callback);
#endif
/****************************************************************************
* Name: lpc54_rtc_rdalarm
*
* Description:
* Query an alarm configured in hardware.
*
* Input Parameters:
* time - Current alarm setting.
*
* Returned Value:
* Zero (OK) on success; a negated errno on failure
*
****************************************************************************/
#ifdef CONFIG_RTC_ALARM
struct tm;
int lpc54_rtc_rdalarm(FAR struct tm *time);
#endif
/****************************************************************************
* Name: lpc54_rtc_cancelalarm
*
* Description:
* Cancel a pending alarm alarm
*
* Input Parameters:
* none
*
* Returned Value:
* Zero (OK) on success; a negated errno on failure
*
****************************************************************************/
#ifdef CONFIG_RTC_ALARM
int lpc54_rtc_cancelalarm(void);
#endif
/****************************************************************************
* Name: lpc54_rtc_lowerhalf
*
* Description:
* Instantiate the RTC lower half driver for the LPC54. General usage:
*
* #include <nuttx/timers/rtc.h>
* #include "lpc54_rtc.h"
*
* struct rtc_lowerhalf_s *lower;
* lower = lpc54_rtc_lowerhalf();
* rtc_initialize(0, lower);
*
* Input Parameters:
* None
*
* Returned Value:
* On success, a non-NULL RTC lower interface is returned. NULL is
* returned on any failure.
*
****************************************************************************/
#ifdef CONFIG_RTC_DRIVER
struct rtc_lowerhalf_s;
FAR struct rtc_lowerhalf_s *lpc54_rtc_lowerhalf(void);
#endif
#undef EXTERN
#if defined(__cplusplus)
}
#endif
#endif /* __ASSEMBLY__ */
#endif /* __ARCH_ARM_SRC_LPC54XX_LPC54_RTC_H */

View File

@ -0,0 +1,660 @@
/****************************************************************************
* arch/arm/src/lpc54xx/lpc54_rtc_lowerhalf.c
*
* Copyright (C) 2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <sys/types.h>
#include <stdbool.h>
#include <string.h>
#include <errno.h>
#include <nuttx/arch.h>
#include <nuttx/timers/rtc.h>
#include "up_arch.h"
#include "chip/lpc54_rtc.h"
#include "lpc54_rtc.h"
#ifdef CONFIG_RTC_DRIVER
/****************************************************************************
* Private Types
****************************************************************************/
#ifdef CONFIG_RTC_ALARM
struct lpc54_cbinfo_s
{
volatile rtc_alarm_callback_t cb; /* Callback when the alarm expires */
volatile FAR void *priv; /* Private argument to accompany callback */
};
#endif
/* This is the private type for the RTC state. It must be cast compatible
* with struct rtc_lowerhalf_s.
*/
struct lpc54_lowerhalf_s
{
/* This is the contained reference to the read-only, lower-half
* operations vtable (which may lie in FLASH or ROM)
*/
FAR const struct rtc_ops_s *ops;
/* Data following is private to this driver and not visible outside of
* this file.
*/
sem_t devsem; /* Threads can only exclusively access the RTC */
#ifdef CONFIG_RTC_ALARM
/* Alarm callback information */
struct lpc54_cbinfo_s cbinfo;
#endif
#ifdef CONFIG_RTC_PERIODIC
/* Periodic wakeup information */
struct lower_setperiodic_s periodic;
#endif
};
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
/* Prototypes for static methods in struct rtc_ops_s */
static int lpc54_rdtime(FAR struct rtc_lowerhalf_s *lower,
FAR struct rtc_time *rtctime);
static int lpc54_settime(FAR struct rtc_lowerhalf_s *lower,
FAR const struct rtc_time *rtctime);
static bool lpc54_havesettime(FAR struct rtc_lowerhalf_s *lower);
#ifdef CONFIG_RTC_ALARM
static int lpc54_setalarm(FAR struct rtc_lowerhalf_s *lower,
FAR const struct lower_setalarm_s *alarminfo);
static int lpc54_setrelative(FAR struct rtc_lowerhalf_s *lower,
FAR const struct lower_setrelative_s *alarminfo);
static int lpc54_cancelalarm(FAR struct rtc_lowerhalf_s *lower,
int alarmid);
static int lpc54_rdalarm(FAR struct rtc_lowerhalf_s *lower,
FAR struct lower_rdalarm_s *alarminfo);
#endif
#ifdef CONFIG_RTC_PERIODIC
static int lpc54_setperiodic(FAR struct rtc_lowerhalf_s *lower,
FAR const struct lower_setperiodic_s *alarminfo);
static int lpc54_cancelperiodic(FAR struct rtc_lowerhalf_s *lower, int id);
#endif
/****************************************************************************
* Private Data
****************************************************************************/
/* LPC54 RTC driver operations */
static const struct rtc_ops_s g_rtc_ops =
{
.rdtime = lpc54_rdtime,
.settime = lpc54_settime,
.havesettime = lpc54_havesettime,
#ifdef CONFIG_RTC_ALARM
.setalarm = lpc54_setalarm,
.setrelative = lpc54_setrelative,
.cancelalarm = lpc54_cancelalarm,
.rdalarm = lpc54_rdalarm,
#endif
#ifdef CONFIG_RTC_PERIODIC
.setperiodic = lpc54_setperiodic,
.cancelperiodic = lpc54_cancelperiodic,
#endif
#ifdef CONFIG_RTC_IOCTL
.ioctl = NULL,
#endif
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
.destroy = NULL,
#endif
};
/* LPC54 RTC device state */
static struct lpc54_lowerhalf_s g_rtc_lowerhalf =
{
.ops = &g_rtc_ops,
};
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: lpc54_alarm_callback
*
* Description:
* This is the function that is called from the RTC driver when the alarm
* goes off. It just invokes the upper half drivers callback.
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
****************************************************************************/
#ifdef CONFIG_RTC_ALARM
static void lpc54_alarm_callback(void)
{
FAR struct lpc54_cbinfo_s *cbinfo = &g_rtc_lowerhalf.cbinfo;
/* Sample and clear the callback information to minimize the window in
* time in which race conditions can occur.
*/
rtc_alarm_callback_t cb = (rtc_alarm_callback_t)cbinfo->cb;
FAR void *arg = (FAR void *)cbinfo->priv;
cbinfo->cb = NULL;
cbinfo->priv = NULL;
/* Perform the callback */
if (cb != NULL)
{
cb(arg, 0);
}
}
#endif /* CONFIG_RTC_ALARM */
/****************************************************************************
* Name: lpc54_rdtime
*
* Description:
* Implements the rdtime() method of the RTC driver interface
*
* Input Parameters:
* lower - A reference to RTC lower half driver state structure
* rcttime - The location in which to return the current RTC time.
*
* Returned Value:
* Zero (OK) is returned on success; a negated errno value is returned
* on any failure.
*
****************************************************************************/
static int lpc54_rdtime(FAR struct rtc_lowerhalf_s *lower,
FAR struct rtc_time *rtctime)
{
time_t timer;
/* The resolution of time is only 1 second */
timer = up_rtc_time();
/* Convert the one second epoch time to a struct tm */
if (!gmtime_r(&timer, (FAR struct tm *)rtctime))
{
int errcode = get_errno();
DEBUGASSERT(errcode > 0);
return -errcode;
}
return OK;
}
/****************************************************************************
* Name: lpc54_settime
*
* Description:
* Implements the settime() method of the RTC driver interface
*
* Input Parameters:
* lower - A reference to RTC lower half driver state structure
* rcttime - The new time to set
*
* Returned Value:
* Zero (OK) is returned on success; a negated errno value is returned
* on any failure.
*
****************************************************************************/
static int lpc54_settime(FAR struct rtc_lowerhalf_s *lower,
FAR const struct rtc_time *rtctime)
{
struct timespec ts;
/* Convert the struct rtc_time to a time_t. Here we assume that struct
* rtc_time is cast compatible with struct tm.
*/
ts.tv_sec = mktime((FAR struct tm *)rtctime);
ts.tv_nsec = 0;
/* Now set the time (to one second accuracy) */
return up_rtc_settime(&ts);
}
/****************************************************************************
* Name: lpc54_havesettime
*
* Description:
* Implements the havesettime() method of the RTC driver interface
*
* Input Parameters:
* lower - A reference to RTC lower half driver state structure
*
* Returned Value:
* Returns true if RTC date-time have been previously set.
*
****************************************************************************/
static bool lpc54_havesettime(FAR struct rtc_lowerhalf_s *lower)
{
return getreg32(RTC_MAGIC_REG) == RTC_MAGIC;
}
/****************************************************************************
* Name: lpc54_setalarm
*
* Description:
* Set a new alarm. This function implements the setalarm() method of the
* RTC driver interface
*
* Input Parameters:
* lower - A reference to RTC lower half driver state structure
* alarminfo - Provided information needed to set the alarm
*
* Returned Value:
* Zero (OK) is returned on success; a negated errno value is returned
* on any failure.
*
****************************************************************************/
#ifdef CONFIG_RTC_ALARM
static int lpc54_setalarm(FAR struct rtc_lowerhalf_s *lower,
FAR const struct lower_setalarm_s *alarminfo)
{
FAR struct lpc54_lowerhalf_s *priv;
FAR struct lpc54_cbinfo_s *cbinfo;
int ret;
DEBUGASSERT(lower != NULL && alarminfo != NULL && alarminfo->id == 0);
priv = (FAR struct lpc54_lowerhalf_s *)lower;
ret = nxsem_wait(&priv->devsem);
if (ret < 0)
{
return ret;
}
ret = -EINVAL;
if (alarminfo->id == 0)
{
struct timespec ts;
/* Convert the RTC time to a timespec (1 second accuracy) */
ts.tv_sec = mktime((FAR struct tm *)&alarminfo->time);
ts.tv_nsec = 0;
/* Remember the callback information */
cbinfo = &priv->cbinfo;
cbinfo->cb = alarminfo->cb;
cbinfo->priv = alarminfo->priv;
/* And set the alarm */
ret = lpc54_rtc_setalarm(&ts, lpc54_alarm_callback);
if (ret < 0)
{
cbinfo->cb = NULL;
cbinfo->priv = NULL;
}
}
nxsem_post(&priv->devsem);
return ret;
}
#endif
/****************************************************************************
* Name: lpc54_setrelative
*
* Description:
* Set a new alarm relative to the current time. This function implements
* the setrelative() method of the RTC driver interface
*
* Input Parameters:
* lower - A reference to RTC lower half driver state structure
* alarminfo - Provided information needed to set the alarm
*
* Returned Value:
* Zero (OK) is returned on success; a negated errno value is returned
* on any failure.
*
****************************************************************************/
#ifdef CONFIG_RTC_ALARM
static int lpc54_setrelative(FAR struct rtc_lowerhalf_s *lower,
FAR const struct lower_setrelative_s *alarminfo)
{
FAR struct lpc54_lowerhalf_s *priv;
FAR struct lpc54_cbinfo_s *cbinfo;
FAR struct timespec ts;
int ret = -EINVAL;
DEBUGASSERT(lower != NULL && alarminfo != NULL && alarminfo->id == 0);
priv = (FAR struct lpc54_lowerhalf_s *)lower;
if (alarminfo->id == 0 && alarminfo->reltime > 0)
{
/* Disable pre-emption while we do this so that we don't have to worry
* about being suspended and working on an old time.
*/
sched_lock();
/* Get the current time in seconds */
ts.tv_sec = up_rtc_time();
ts.tv_nsec = 0;
/* Add the seconds offset. Add one to the number of seconds because
* we are unsure of the phase of the timer.
*/
ts.tv_sec += (alarminfo->reltime + 1);
/* Remember the callback information */
cbinfo = &priv->cbinfo;
cbinfo->cb = alarminfo->cb;
cbinfo->priv = alarminfo->priv;
/* And set the alarm */
ret = lpc54_rtc_setalarm(&ts, lpc54_alarm_callback);
if (ret < 0)
{
cbinfo->cb = NULL;
cbinfo->priv = NULL;
}
sched_unlock();
}
return ret;
}
#endif
/****************************************************************************
* Name: lpc54_cancelalarm
*
* Description:
* Cancel the current alarm. This function implements the cancelalarm()
* method of the RTC driver interface
*
* Input Parameters:
* lower - A reference to RTC lower half driver state structure
* alarminfo - Provided information needed to set the alarm
*
* Returned Value:
* Zero (OK) is returned on success; a negated errno value is returned
* on any failure.
*
****************************************************************************/
#ifdef CONFIG_RTC_ALARM
static int lpc54_cancelalarm(FAR struct rtc_lowerhalf_s *lower, int alarmid)
{
FAR struct lpc54_lowerhalf_s *priv;
FAR struct lpc54_cbinfo_s *cbinfo;
DEBUGASSERT(lower != NULL);
DEBUGASSERT(alarmid == 0);
priv = (FAR struct lpc54_lowerhalf_s *)lower;
/* Nullify callback information to reduce window for race conditions */
cbinfo = &priv->cbinfo;
cbinfo->cb = NULL;
cbinfo->priv = NULL;
/* Then cancel the alarm */
return lpc54_rtc_cancelalarm();
}
#endif
/****************************************************************************
* Name: lpc54_rdalarm
*
* Description:
* Query the RTC alarm.
*
* Input Parameters:
* lower - A reference to RTC lower half driver state structure
* alarminfo - Provided information needed to query the alarm
*
* Returned Value:
* Zero (OK) is returned on success; a negated errno value is returned
* on any failure.
*
****************************************************************************/
#ifdef CONFIG_RTC_ALARM
static int lpc54_rdalarm(FAR struct rtc_lowerhalf_s *lower,
FAR struct lower_rdalarm_s *alarminfo)
{
int ret = -EINVAL;
DEBUGASSERT(lower != NULL && alarminfo != NULL && alarminfo->id == 0 &&
alarminfo->time != NULL);
if (alarminfo->id == 0)
{
ret = lpc54_rtc_rdalarm((FAR struct tm *)alarminfo->time);
}
return ret;
}
#endif
/****************************************************************************
* Name: lpc54_periodic_callback
*
* Description:
* This is the function that is called from the RTC driver when the periodic
* wakeup goes off. It just invokes the upper half drivers callback.
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
****************************************************************************/
#ifdef CONFIG_RTC_PERIODIC
static int lpc54_periodic_callback(void)
{
FAR struct lpc54_lowerhalf_s *lower;
struct lower_setperiodic_s *cbinfo;
rtc_wakeup_callback_t cb;
FAR void *priv;
lower = (FAR struct lpc54_lowerhalf_s *)&g_rtc_lowerhalf;
cbinfo = &lower->periodic;
cb = (rtc_wakeup_callback_t)cbinfo->cb;
priv = (FAR void *)cbinfo->priv;
/* Perform the callback */
if (cb != NULL)
{
cb(priv, 0);
}
return OK;
}
#endif /* CONFIG_RTC_PERIODIC */
/****************************************************************************
* Name: lpc54_setperiodic
*
* Description:
* Set a new periodic wakeup relative to the current time, with a given
* period. This function implements the setperiodic() method of the RTC
* driver interface
*
* Input Parameters:
* lower - A reference to RTC lower half driver state structure
* alarminfo - Provided information needed to set the wakeup activity
*
* Returned Value:
* Zero (OK) is returned on success; a negated errno value is returned
* on any failure.
*
****************************************************************************/
#ifdef CONFIG_RTC_PERIODIC
static int lpc54_setperiodic(FAR struct rtc_lowerhalf_s *lower,
FAR const struct lower_setperiodic_s *alarminfo)
{
FAR struct lpc54_lowerhalf_s *priv;
int ret;
ASSERT(lower != NULL && alarminfo != NULL);
priv = (FAR struct lpc54_lowerhalf_s *)lower;
ret = nxsem_wait(&priv->devsem);
if (ret < 0)
{
return ret;
}
memcpy(&priv->periodic, alarminfo, sizeof(struct lower_setperiodic_s));
ret = lpc54_rtc_setperiodic(&alarminfo->period, lpc54_periodic_callback);
nxsem_post(&priv->devsem);
return ret;
}
#endif
/****************************************************************************
* Name: lpc54_cancelperiodic
*
* Description:
* Cancel the current periodic wakeup activity. This function implements
* the cancelperiodic() method of the RTC driver interface
*
* Input Parameters:
* lower - A reference to RTC lower half driver state structure
*
* Returned Value:
* Zero (OK) is returned on success; a negated errno value is returned
* on any failure.
*
****************************************************************************/
#ifdef CONFIG_RTC_PERIODIC
static int lpc54_cancelperiodic(FAR struct rtc_lowerhalf_s *lower, int id)
{
FAR struct lpc54_lowerhalf_s *priv;
int ret;
DEBUGASSERT(lower != NULL);
priv = (FAR struct lpc54_lowerhalf_s *)lower;
DEBUGASSERT(id == 0);
ret = nxsem_wait(&priv->devsem);
if (ret < 0)
{
return ret;
}
ret = lpc54_rtc_cancelperiodic();
nxsem_post(&priv->devsem);
return ret;
}
#endif
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: lpc54_rtc_lowerhalf
*
* Description:
* Instantiate the RTC lower half driver for the LPC54. General usage:
*
* #include <nuttx/timers/rtc.h>
* #include "lpc54_rtc.h>
*
* struct rtc_lowerhalf_s *lower;
* lower = lpc54_rtc_lowerhalf();
* rtc_initialize(0, lower);
*
* Input Parameters:
* None
*
* Returned Value:
* On success, a non-NULL RTC lower interface is returned. NULL is
* returned on any failure.
*
****************************************************************************/
FAR struct rtc_lowerhalf_s *lpc54_rtc_lowerhalf(void)
{
nxsem_init(&g_rtc_lowerhalf.devsem, 0, 1);
return (FAR struct rtc_lowerhalf_s *)&g_rtc_lowerhalf;
}
#endif /* CONFIG_RTC_DRIVER */

View File

@ -96,7 +96,7 @@
#else /* !CONFIG_STM32_STM32F10XX */
#if !defined(CONFIG_RTC_MAGIC)
# define CONFIG_RTC_MAGIC (0xfacefeee)
# define CONFIG_RTC_MAGIC (0xfacefeed)
#endif
#if !defined(CONFIG_RTC_MAGIC_REG)
@ -137,7 +137,7 @@ extern "C"
* Public Functions
****************************************************************************/
/************************************************************************************
/****************************************************************************
* Name: stm32_rtc_irqinitialize
*
* Description:
@ -150,7 +150,7 @@ extern "C"
* Returned Value:
* Zero (OK) on success; a negated errno on failure
*
************************************************************************************/
****************************************************************************/
int stm32_rtc_irqinitialize(void);
@ -208,7 +208,7 @@ int stm32_rtc_setdatetime(FAR const struct tm *tp);
* Instantiate the RTC lower half driver for the STM32. General usage:
*
* #include <nuttx/timers/rtc.h>
* #include "stm32_rtc.h>
* #include "stm32_rtc.h"
*
* struct rtc_lowerhalf_s *lower;
* lower = stm32_rtc_lowerhalf();

View File

@ -73,6 +73,8 @@ STATUS
2017-12-24: Added basic DMA support; brought in the WWDT driver from the
LPC43 which has the same peripheral. Neither tested; almost certainly
non-functional without some additional investment.
2017-12-25: Added an RTC driver. It appears to be functional but has not
been well tested.
There is still no support for the Accelerometer, SPIFI, Ethernet, or USB.
There is a complete, but not-yet-functional SD card drirver. There is a
@ -344,6 +346,21 @@ Configurations
CONFIG_NSH_MMCSDSLOTNO=0
6. The RTC is enabled in this configuration.
NuttShell (NSH) NuttX-7.23
nsh> date
Jan 01 00:00:06 1970
nsh> date -s "DEC 25 08:00:00 2017"
nsh> date
Dec 25 08:00:01 2017
After reset:
NuttShell (NSH) NuttX-7.23
nsh> date
Dec 25 08:00:05 2017
nxwm:
This is a special configuration setup for the NxWM window manager

View File

@ -25,6 +25,7 @@ CONFIG_LPC54_EMC_DYNAMIC_CS0=y
CONFIG_LPC54_EMC=y
CONFIG_LPC54_GPIOIRQ=y
CONFIG_LPC54_I2C2_MASTER=y
CONFIG_LPC54_RTC=y
CONFIG_LPC54_USART0=y
CONFIG_MAX_TASKS=16
CONFIG_MAX_WDOGPARMS=2
@ -43,6 +44,9 @@ CONFIG_RAM_SIZE=163840
CONFIG_RAM_START=0x10000000
CONFIG_RAW_BINARY=y
CONFIG_RR_INTERVAL=200
CONFIG_RTC_ALARM=y
CONFIG_RTC_DRIVER=y
CONFIG_RTC_IOCTL=y
CONFIG_SCHED_WAITPID=y
CONFIG_SDCLONE_DISABLE=y
CONFIG_START_DAY=2

View File

@ -57,6 +57,11 @@
# include "lpc54_sdmmc.h"
#endif
#ifdef CONFIG_RTC_DRIVER
# include <nuttx/timers/rtc.h>
# include "lpc54_rtc.h"
#endif
#include "lpcxpresso-lpc54628.h"
/****************************************************************************
@ -81,6 +86,9 @@ int lpc54_bringup(void)
{
#ifdef HAVE_MMCSD
struct sdio_dev_s *sdmmc;
#endif
#ifdef HAVE_RTC_DRIVER
struct rtc_lowerhalf_s *rtc;
#endif
int ret;
@ -94,8 +102,30 @@ int lpc54_bringup(void)
}
#endif
FAR struct sdio_dev_s *lpc54_sdmmc_initialize(int slotno);
#ifdef HAVE_RTC_DRIVER
/* Instantiate the STM32 lower-half RTC driver */
rtc = lpc54_rtc_lowerhalf();
if (rtc == NULL)
{
syslog(LOG_ERR,
"ERROR: Failed to instantiate the RTC lower-half driver\n");
}
else
{
/* Bind the lower half driver and register the combined RTC driver
* as /dev/rtc0
*/
ret = rtc_initialize(0, rtc);
if (ret < 0)
{
syslog(LOG_ERR,
"ERROR: Failed to bind/register the RTC driver: %d\n",
ret);
}
}
#endif
#ifdef HAVE_I2CTOOL
/* Register I2C drivers on behalf of the I2C tool */

View File

@ -49,9 +49,10 @@
* Pre-processor Definitions
****************************************************************************/
#define HAVE_I2CTOOL 1
#define HAVE_FT5x06 1
#define HAVE_MMCSD 1
#define HAVE_I2CTOOL 1
#define HAVE_FT5x06 1
#define HAVE_MMCSD 1
#define HAVE_RTC_DRIVER 1
/* Do we need to register I2C drivers on behalf of the I2C tool? */
@ -118,6 +119,12 @@
# undef HAVE_MMCSD
#endif
/* Check if we can support the RTC driver */
#if !defined(CONFIG_RTC) || !defined(CONFIG_RTC_DRIVER)
# undef HAVE_RTC_DRIVER
#endif
/* Indices into a sparse I2C array. Used with lpc54_i2c_handle() */
#ifdef CONFIG_LPC54_I2C0_MASTER