From 7aa8039179fd8c718f21ed3eefc61d08200e120c Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Mon, 17 Jun 2019 12:25:43 -0600 Subject: [PATCH] Squashed commit of the following: commit f5080f53516a853408dd80f09f85e1d1c139133f Author: Gregory Nutt Date: Mon Jun 17 12:24:22 2019 -0600 arch/z80/src/ez80/ez80_spi.c: SPI driver still does not work. But the driver now has timeouts so that at least it does not hang the system on startup. commit 5241e9ae643981c43c8c7fa8478a01d0c2e17eb0 Author: Gregory Nutt Date: Mon Jun 17 10:45:11 2019 -0600 arch/z80/src/ez80: Fixes to SPI baud rate calculation. commit ce2e9e3703485563a0a5b6a57e4080ad45d91fd7 Author: Gregory Nutt Date: Mon Jun 17 09:29:13 2019 -0600 arch/z80/src/ez80: Cosmetic and unnecessary clean-up or serial driver. commit 77287c8508a7e3262068d3e8cf1c5f8e27f3a144 Author: Gregory Nutt Date: Mon Jun 17 09:08:56 2019 -0600 arch/z80/src/common and arch/z80/src/ez80: Clean up some assertion-related logic. commit 4d2d3594c22f7240119255825fce2d2437301404 Author: Gregory Nutt Date: Mon Jun 17 07:48:21 2019 -0600 configs/makerlisp/nsh/defconfig: Enable STACKDUMP on assertion. commit 76b7a2faa3f213dd26634dd9440d12f746cac097 Author: Gregory Nutt Date: Mon Jun 17 07:47:55 2019 -0600 configs/makerlisp/include/board.h: Don't put the board in reset on a simple assertion, onlhy a full panic. commit 0a0dc12edcd39c07696769cb7249d8c39a148ccc Author: Gregory Nutt Date: Mon Jun 17 07:46:54 2019 -0600 arch/z80/src/ez80/ez80_rtc_lowerhalf.c: Remove all references to alarm ID. commit 1a4dba1075fcf6466e87520a8ba66bbf91d696d7 Author: Gregory Nutt Date: Mon Jun 17 07:33:29 2019 -0600 configs/makerlisp/src/ez80_bringup.c: Fix an error that was causing MMC/SD to fail to initialize. Unfortunately now the system hangs. commit 145a395c7a8e73336fe62caf803d108c59e306a5 Author: Gregory Nutt Date: Mon Jun 17 07:32:50 2019 -0600 arch/z80/src/ez80: Add an RTC lower half driver. Initial commit is just the STM32 RTC lower half with name changes. --- arch/z80/src/common/up_assert.c | 2 +- arch/z80/src/common/up_stackdump.c | 42 +- arch/z80/src/common/z80_internal.h | 2 +- arch/z80/src/ez80/Make.defs | 18 +- arch/z80/src/ez80/ez80_getsp.asm | 62 +++ arch/z80/src/ez80/ez80_registerdump.c | 12 +- arch/z80/src/ez80/ez80_rtc_lowerhalf.c | 604 +++++++++++++++++++++++++ arch/z80/src/ez80/ez80_serial.c | 76 ++-- arch/z80/src/ez80/ez80_spi.c | 148 ++++-- configs/makerlisp/README.txt | 14 +- configs/makerlisp/include/board.h | 2 +- configs/makerlisp/nsh/defconfig | 1 + configs/makerlisp/src/ez80_bringup.c | 4 +- configs/makerlisp/src/ez80_spi.c | 2 +- 14 files changed, 872 insertions(+), 117 deletions(-) create mode 100644 arch/z80/src/ez80/ez80_getsp.asm create mode 100644 arch/z80/src/ez80/ez80_rtc_lowerhalf.c diff --git a/arch/z80/src/common/up_assert.c b/arch/z80/src/common/up_assert.c index 6fbfc266a9..152d688224 100644 --- a/arch/z80/src/common/up_assert.c +++ b/arch/z80/src/common/up_assert.c @@ -190,7 +190,7 @@ void up_assert(void) (void)syslog_flush(); #ifdef CONFIG_BOARD_CRASHDUMP - board_crashdump(up_getsp(), running_task(), filename, lineno); + board_crashdump(Z80_getsp(), running_task(), filename, lineno); #endif _up_assert(EXIT_FAILURE); diff --git a/arch/z80/src/common/up_stackdump.c b/arch/z80/src/common/up_stackdump.c index 7731057b3e..a6239bd610 100644 --- a/arch/z80/src/common/up_stackdump.c +++ b/arch/z80/src/common/up_stackdump.c @@ -1,7 +1,7 @@ /**************************************************************************** * arch/z80/src/common/up_stackdump.c * - * Copyright (C) 2007-2009, 2016 Gregory Nutt. All rights reserved. + * Copyright (C) 2007-2009, 2016, 2019 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -49,29 +49,24 @@ #ifdef CONFIG_ARCH_STACKDUMP /**************************************************************************** - * Private Functions + * Public Functions ****************************************************************************/ -/**************************************************************************** - * Name: up_getsp - ****************************************************************************/ -#warning TO BE PROVIDED - /**************************************************************************** * Name: up_stackdump ****************************************************************************/ -static void up_stackdump(void) +void up_stackdump(void) { - struct tcb_s *rtcb = this_task(); - uint16_t sp = up_getsp(); - uint16_t stack_base = (uint16_t)rtcb->adj_stack_ptr; - uint16_t stack_size = (uint16_t)rtcb->adj_stack_size; - uint16_t stack; + FAR struct tcb_s *rtcb = this_task(); + uintptr_t sp = z80_getsp(); + uintptr_t stack_base = (uintptr_t)rtcb->adj_stack_ptr; + uintptr_t stack_size = (uintptr_t)rtcb->adj_stack_size; + uintptr_t stack; - _alert("stack_base: %04x\n", stack_base); - _alert("stack_size: %04x\n", stack_size); - _alert("sp: %04x\n", sp); + _alert("stack_base: %06x\n", stack_base); + _alert("stack_size: %06x\n", stack_size); + _alert("sp: %06x\n", sp); if (sp >= stack_base || sp < stack_base - stack_size) { @@ -83,12 +78,17 @@ static void up_stackdump(void) stack = sp; } - for (stack = stack & ~0x0f; stack < stack_base; stack += 8*sizeof(uint16_t)) + for (stack = stack & ~0x0f; stack < stack_base; stack += 16) { - uint16_t *ptr = (uint16_t*)stack; - _alert("%04x: %04x %04x %04x %04x %04x %04x %04x %04x\n", - stack, ptr[0], ptr[1], ptr[2], ptr[3], - ptr[4], ptr[5], ptr[6], ptr[7]); + FAR uint8_t *ptr = (FAR uint8_t*)stack; + + _alert("%06x: %02x %02x %02x %02x %02x %02x %02x %02x ", + "%02x %02x %02x %02x %02x %02x %02x %02x\n", + stack, + ptr[0], ptr[1], ptr[2], ptr[3], + ptr[4], ptr[5], ptr[6], ptr[7], + ptr[8], ptr[9], ptr[10], ptr[11], + ptr[12], ptr[13], ptr[14], ptr[15]); } } diff --git a/arch/z80/src/common/z80_internal.h b/arch/z80/src/common/z80_internal.h index 21913fb0ef..1c68d9c297 100644 --- a/arch/z80/src/common/z80_internal.h +++ b/arch/z80/src/common/z80_internal.h @@ -194,7 +194,7 @@ int up_multicastfilter(FAR struct net_driver_s *dev, FAR uint8_t *mac, bool enab /* Return the current value of the stack pointer (used in stack dump logic) */ -uint16_t up_getsp(void); +uintptr_t z80_getsp(void); /* Dump stack and registers */ diff --git a/arch/z80/src/ez80/Make.defs b/arch/z80/src/ez80/Make.defs index f5e48016ba..ac8c588501 100644 --- a/arch/z80/src/ez80/Make.defs +++ b/arch/z80/src/ez80/Make.defs @@ -44,16 +44,29 @@ CMN_CSRCS += up_reprioritizertr.c up_idle.c up_assert.c z80_doirq.c CMN_CSRCS += up_mdelay.c up_stackframe.c up_udelay.c up_usestack.c CMN_CSRCS += up_puts.c +ifeq ($(CONFIG_ARCH_STACKDUMP),y) +CMN_CSRCS += up_stackdump.c +endif + CHIP_ASRCS = ez80_startup.asm ez80_io.asm ez80_irqsave.asm CHIP_ASRCS += ez80_saveusercontext.asm ez80_restorecontext.asm + ifeq ($(CONFIG_ARCH_CHIP_EZ80F91),y) CHIP_ASRCS += ez80f91_init.asm endif +ifeq ($(CONFIG_ARCH_STACKDUMP),y) +CHIP_ASRCS += ez80_getsp.asm +endif + CHIP_SSRCS = CHIP_CSRCS = ez80_clock.c ez80_initialstate.c ez80_irq.c ez80_copystate.c CHIP_CSRCS += ez80_schedulesigaction.c ez80_sigdeliver.c ez80_lowuart.c -CHIP_CSRCS += ez80_timerisr.c ez80_serial.c ez80_registerdump.c +CHIP_CSRCS += ez80_timerisr.c ez80_serial.c + +ifeq ($(CONFIG_ARCH_STACKDUMP),y) +CHIP_CSRCS += ez80_registerdump.c +endif ifeq ($(CONFIG_EZ80_I2C),y) CHIP_CSRCS += ez80_i2c.c @@ -65,6 +78,9 @@ endif ifeq ($(CONFIG_EZ80_RTC),y) CHIP_CSRCS += ez80_rtc.c +ifeq ($(CONFIG_RTC_DRIVER),y) +CHIP_CSRCS += ez80_rtc_lowerhalf.c +endif endif ifeq ($(CONFIG_ARCH_CHIP_EZ80F91),y) diff --git a/arch/z80/src/ez80/ez80_getsp.asm b/arch/z80/src/ez80/ez80_getsp.asm new file mode 100644 index 0000000000..b95a444062 --- /dev/null +++ b/arch/z80/src/ez80/ez80_getsp.asm @@ -0,0 +1,62 @@ +;************************************************************************** +; arch/z80/src/ez80/ez80_getsp.asm +; +; Copyright (C) 2019 Gregory Nutt. All rights reserved. +; Author: Gregory Nutt +; +; 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. +; +;************************************************************************** + +;************************************************************************** +; Global Symbols Exported +;************************************************************************** + + xdef _z80_getsp + +;************************************************************************** +; Code +;************************************************************************** + + segment CODE + .assume ADL=1 + +;************************************************************************** +;* Name: _z80_getsp +;* +;* Description: +;* Return the current value of the stack pointer +;* +;************************************************************************** + +_z80_getsp: + ld hl, #0 ; Initialize HL to zero + add hl, sp ; Add the stack pointer to HL + ret ; Return stack pointer in HL + + end diff --git a/arch/z80/src/ez80/ez80_registerdump.c b/arch/z80/src/ez80/ez80_registerdump.c index 96bb0da1a8..636900449d 100644 --- a/arch/z80/src/ez80/ez80_registerdump.c +++ b/arch/z80/src/ez80/ez80_registerdump.c @@ -1,7 +1,7 @@ /**************************************************************************** * arch/z80/src/ez80/ez80_registerdump.c * - * Copyright (C) 2008-2009, 2016 Gregory Nutt. All rights reserved. + * Copyright (C) 2008-2009, 2016, 2019 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -49,10 +49,6 @@ #ifdef CONFIG_ARCH_STACKDUMP -/**************************************************************************** - * Pre-processor Definitions - ****************************************************************************/ - /**************************************************************************** * Private Data ****************************************************************************/ @@ -60,14 +56,14 @@ static chipreg_t s_last_regs[XCPTCONTEXT_REGS]; /**************************************************************************** - * Private Functions + * Public Functions ****************************************************************************/ /**************************************************************************** * Name: z80_registerdump ****************************************************************************/ -static void ez80_registerdump(void) +void ez80_registerdump(void) { volatile chipreg_t *regs = g_current_regs; @@ -93,7 +89,7 @@ static void ez80_registerdump(void) regs[XCPT_BC], regs[XCPT_DE], regs[XCPT_HL]); _alert("IX: %06x IY: %06x\n", regs[XCPT_IX], regs[XCPT_IY]); - _alert("SP: %06x PC: %06x\n" + _alert("SP: %06x PC: %06x\n", regs[XCPT_SP], regs[XCPT_PC]); #endif } diff --git a/arch/z80/src/ez80/ez80_rtc_lowerhalf.c b/arch/z80/src/ez80/ez80_rtc_lowerhalf.c new file mode 100644 index 0000000000..9504865f57 --- /dev/null +++ b/arch/z80/src/ez80/ez80_rtc_lowerhalf.c @@ -0,0 +1,604 @@ +/**************************************************************************** + * arch/z80/src/ez80/ez80_rtc_lowerhalf.c + * + * Copyright (C) 2019 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include +#include + +#include +#include + +#include "up_arch.h" + +#include "chip.h" +#include "ez80_rtc.h" + +#ifdef CONFIG_RTC_DRIVER + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +#ifdef CONFIG_RTC_ALARM +struct ez80_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 ez80_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 ez80_cbinfo_s cbinfo; +#endif +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ +/* Prototypes for static methods in struct rtc_ops_s */ + +static int ez80_rdtime(FAR struct rtc_lowerhalf_s *lower, + FAR struct rtc_time *rtctime); +static int ez80_settime(FAR struct rtc_lowerhalf_s *lower, + FAR const struct rtc_time *rtctime); +static bool ez80_havesettime(FAR struct rtc_lowerhalf_s *lower); + +#ifdef CONFIG_RTC_ALARM +static int ez80_setalarm(FAR struct rtc_lowerhalf_s *lower, + FAR const struct lower_setalarm_s *alarminfo); +static int ez80_setrelative(FAR struct rtc_lowerhalf_s *lower, + FAR const struct lower_setrelative_s *alarminfo); +static int ez80_cancelalarm(FAR struct rtc_lowerhalf_s *lower); +static int ez80_rdalarm(FAR struct rtc_lowerhalf_s *lower, + FAR struct lower_rdalarm_s *alarminfo); +#endif + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* eZ80 RTC driver operations */ + +static const struct rtc_ops_s g_rtc_ops = +{ + .rdtime = ez80_rdtime, + .settime = ez80_settime, + .havesettime = ez80_havesettime, +#ifdef CONFIG_RTC_ALARM + .setalarm = ez80_setalarm, + .setrelative = ez80_setrelative, + .cancelalarm = ez80_cancelalarm, + .rdalarm = ez80_rdalarm, +#endif +#ifdef CONFIG_RTC_PERIODIC + .setperiodic = NULL, + .cancelperiodic = NULL, +#endif +#ifdef CONFIG_RTC_IOCTL + .ioctl = NULL, +#endif +#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS + .destroy = NULL, +#endif +}; + +/* eZ80 RTC device state */ + +static struct ez80_lowerhalf_s g_rtc_lowerhalf = +{ + .ops = &g_rtc_ops, +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: ez80_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 ez80_alarm_callback(FAR void *arg) +{ + FAR struct ez80_lowerhalf_s *lower; + FAR struct ez80_cbinfo_s *cbinfo; + rtc_alarm_callback_t cb; + FAR void *priv; + + lower = (struct ez80_lowerhalf_s *)arg; + cbinfo = &lower->cbinfo; + + /* Sample and clear the callback information to minimize the window in + * time in which race conditions can occur. + */ + + cb = (rtc_alarm_callback_t)cbinfo->cb; + priv = (FAR void *)cbinfo->priv; + DEBUGASSERT(priv != NULL); + + cbinfo->cb = NULL; + cbinfo->priv = NULL; + + /* Perform the callback */ + + if (cb != NULL) + { + cb(priv); + } +} +#endif + +/**************************************************************************** + * Name: ez80_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 ez80_rdtime(FAR struct rtc_lowerhalf_s *lower, + FAR struct rtc_time *rtctime) +{ +#if defined(CONFIG_RTC_DATETIME) + /* This operation depends on the fact that struct rtc_time is cast + * compatible with struct tm. + */ + + return up_rtc_getdatetime((FAR struct tm *)rtctime); + +#elif defined(CONFIG_RTC_HIRES) + FAR struct timespec ts; + int ret; + + /* Get the higher resolution time */ + + ret = up_rtc_gettime(&ts); + if (ret < 0) + { + goto errout_with_errno; + } + + /* Convert the one second epoch time to a struct tm. This operation + * depends on the fact that struct rtc_time and struct tm are cast + * compatible. + */ + + if (!gmtime_r(&ts.tv_sec, (FAR struct tm *)rtctime)) + { + goto errout_with_errno; + } + + return OK; + +errout_with_errno: + ret = get_errno(); + DEBUGASSERT(ret > 0); + return -ret; + +#else + 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; +#endif +} + +/**************************************************************************** + * Name: ez80_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 ez80_settime(FAR struct rtc_lowerhalf_s *lower, + FAR const struct rtc_time *rtctime) +{ +#ifdef CONFIG_RTC_DATETIME + /* This operation depends on the fact that struct rtc_time is cast + * compatible with struct tm. + */ + + return ez80_rtc_setdatetime((FAR const struct tm *)rtctime); + +#else + 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); +#endif +} + +/**************************************************************************** + * Name: ez80_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 ez80_havesettime(FAR struct rtc_lowerhalf_s *lower) +{ + return getreg32(RTC_MAGIC_REG) == RTC_MAGIC_TIME_SET; +} + +/**************************************************************************** + * Name: ez80_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 ez80_setalarm(FAR struct rtc_lowerhalf_s *lower, + FAR const struct lower_setalarm_s *alarminfo) +{ + FAR struct ez80_lowerhalf_s *priv; + FAR struct ez80_cbinfo_s *cbinfo; + struct alm_setalarm_s lowerinfo; + int ret; + + /* ID0-> Alarm A; ID1 -> Alarm B */ + + DEBUGASSERT(lower != NULL && alarminfo != NULL); + DEBUGASSERT(alarminfo->id == RTC_ALARMA || alarminfo->id == RTC_ALARMB); + priv = (FAR struct ez80_lowerhalf_s *)lower; + + ret = nxsem_wait(&priv->devsem); + if (ret < 0) + { + return ret; + } + + /* Remember the callback information */ + + cbinfo = &priv->cbinfo; + cbinfo->cb = alarminfo->cb; + cbinfo->priv = alarminfo->priv; + cbinfo->id = alarminfo->id; + + /* Set the alarm */ + + lowerinfo.as_id = alarminfo->id; + lowerinfo.as_cb = ez80_alarm_callback; + lowerinfo.as_arg = priv; + memcpy(&lowerinfo.as_time, &alarminfo->time, sizeof(struct tm)); + + /* And set the alarm */ + + ret = ez80_rtc_setalarm(&lowerinfo); + if (ret < 0) + { + cbinfo->cb = NULL; + cbinfo->priv = NULL; + } + + nxsem_post(&priv->devsem); + + return ret; +} +#endif + +/**************************************************************************** + * Name: ez80_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 ez80_setrelative(FAR struct rtc_lowerhalf_s *lower, + FAR const struct lower_setrelative_s *alarminfo) +{ + struct lower_setalarm_s setalarm; + struct tm time; + time_t seconds; + int ret = -EINVAL; + + DEBUGASSERT(lower != NULL && alarminfo != NULL); + DEBUGASSERT(alarminfo->id == RTC_ALARMA || alarminfo->id == RTC_ALARMB); + + if ((alarminfo->id == RTC_ALARMA || alarminfo->id == RTC_ALARMB) && + 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 broken out format */ + + ret = up_rtc_getdatetime(&time); + if (ret >= 0) + { + /* Convert to seconds since the epoch */ + + seconds = mktime(&time); + + /* Add the seconds offset. Add one to the number of seconds + * because we are unsure of the phase of the timer. + */ + + seconds += (alarminfo->reltime + 1); + + /* And convert the time back to broken out format */ + + (void)gmtime_r(&seconds, (FAR struct tm *)&setalarm.time); + + /* The set the alarm using this absolute time */ + + setalarm.id = alarminfo->id; + setalarm.cb = alarminfo->cb; + setalarm.priv = alarminfo->priv; + + ret = ez80_setalarm(lower, &setalarm); + } + + sched_unlock(); + } + + return ret; +} +#endif + +/**************************************************************************** + * Name: ez80_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 ez80_cancelalarm(FAR struct rtc_lowerhalf_s *lower) +{ + FAR struct ez80_lowerhalf_s *priv; + FAR struct ez80_cbinfo_s *cbinfo; + int ret; + + DEBUGASSERT(lower != NULL); + priv = (FAR struct ez80_lowerhalf_s *)lower; + + ret = nxsem_wait(&priv->devsem); + if (ret < 0) + { + return ret; + } + + /* Nullify callback information to reduce window for race conditions */ + + cbinfo = &priv->cbinfo; + cbinfo->cb = NULL; + cbinfo->priv = NULL; + + /* Then cancel the alarm */ + + ret = ez80_rtc_cancelalarm(); + nxsem_post(&priv->devsem); + + return ret; +} +#endif + +/**************************************************************************** + * Name: ez80_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 ez80_rdalarm(FAR struct rtc_lowerhalf_s *lower, + FAR struct lower_rdalarm_s *alarminfo) +{ + struct alm_rdalarm_s lowerinfo; + int ret = -EINVAL; + + DEBUGASSERT(lower != NULL && alarminfo != NULL && alarminfo->time != NULL); + DEBUGASSERT(alarminfo->id == RTC_ALARMA || alarminfo->id == RTC_ALARMB); + + /* 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(); + + lowerinfo.ar_id = alarminfo->id; + lowerinfo.ar_time = alarminfo->time; + + ret = ez80_rtc_rdalarm(&lowerinfo); + sched_unlock(); + + return ret; +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: ez80_rtc_lowerhalf + * + * Description: + * Instantiate the RTC lower half driver for the eZ80. General usage: + * + * #include + * #include "ez80_rtc.h> + * + * struct rtc_lowerhalf_s *lower; + * lower = ez80_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 *ez80_rtc_lowerhalf(void) +{ + nxsem_init(&g_rtc_lowerhalf.devsem, 0, 1); + + return (FAR struct rtc_lowerhalf_s *)&g_rtc_lowerhalf; +} + +#endif /* CONFIG_RTC_DRIVER */ diff --git a/arch/z80/src/ez80/ez80_serial.c b/arch/z80/src/ez80/ez80_serial.c index 552ad391e4..c3800d3a9a 100644 --- a/arch/z80/src/ez80/ez80_serial.c +++ b/arch/z80/src/ez80/ez80_serial.c @@ -253,7 +253,7 @@ static uart_dev_t g_uart1port = * Name: ez80_serialin ****************************************************************************/ -static inline uint8_t ez80_serialin(struct ez80_dev_s *priv, uint8_t offset) +static uint8_t ez80_serialin(FAR struct ez80_dev_s *priv, uint8_t offset) { return inp(priv->uartbase + offset); } @@ -262,8 +262,8 @@ static inline uint8_t ez80_serialin(struct ez80_dev_s *priv, uint8_t offset) * Name: ez80_serialout ****************************************************************************/ -static inline void ez80_serialout(struct ez80_dev_s *priv, uint8_t offset, - uint8_t value) +static void ez80_serialout(FAR struct ez80_dev_s *priv, uint8_t offset, + uint8_t value) { outp(priv->uartbase + offset, value); } @@ -272,7 +272,7 @@ static inline void ez80_serialout(struct ez80_dev_s *priv, uint8_t offset, * Name: ez80_disableuartint ****************************************************************************/ -static inline void ez80_disableuartint(struct ez80_dev_s *priv) +static void ez80_disableuartint(FAR struct ez80_dev_s *priv) { uint8_t ier = ez80_serialin(priv, EZ80_UART_IER); ier &= ~EZ80_UARTEIR_INTMASK; @@ -283,7 +283,7 @@ static inline void ez80_disableuartint(struct ez80_dev_s *priv) * Name: ez80_restoreuartint ****************************************************************************/ -static inline void ez80_restoreuartint(struct ez80_dev_s *priv, uint8_t bits) +static void ez80_restoreuartint(FAR struct ez80_dev_s *priv, uint8_t bits) { uint8_t ier = ez80_serialin(priv, EZ80_UART_IER); ier |= bits & (EZ80_UARTEIR_TIE|EZ80_UARTEIR_RIE); @@ -294,7 +294,7 @@ static inline void ez80_restoreuartint(struct ez80_dev_s *priv, uint8_t bits) * Name: ez80_waittxready ****************************************************************************/ -static inline void ez80_waittxready(struct ez80_dev_s *priv) +static void ez80_waittxready(FAR struct ez80_dev_s *priv) { int tmp; @@ -311,7 +311,7 @@ static inline void ez80_waittxready(struct ez80_dev_s *priv) * Name: ez80_setbaud ****************************************************************************/ -static inline void ez80_setbaud(struct ez80_dev_s *priv, uint24_t baud) +static void ez80_setbaud(FAR struct ez80_dev_s *priv, uint24_t baud) { uint32_t brg_divisor; uint8_t lctl; @@ -350,10 +350,10 @@ static inline void ez80_setbaud(struct ez80_dev_s *priv, uint24_t baud) * ****************************************************************************/ -static int ez80_setup(struct uart_dev_s *dev) +static int ez80_setup(FAR struct uart_dev_s *dev) { #ifndef CONFIG_SUPPRESS_UART_CONFIG - struct ez80_dev_s *priv = dev->priv; + FAR struct ez80_dev_s *priv = dev->priv; uint8_t reg; uint8_t cval; @@ -414,9 +414,9 @@ static int ez80_setup(struct uart_dev_s *dev) * ****************************************************************************/ -static void ez80_shutdown(struct uart_dev_s *dev) +static void ez80_shutdown(FAR struct uart_dev_s *dev) { - struct ez80_dev_s *priv = (struct ez80_dev_s*)dev->priv; + FAR struct ez80_dev_s *priv = (FAR struct ez80_dev_s*)dev->priv; ez80_disableuartint(priv); } @@ -435,9 +435,9 @@ static void ez80_shutdown(struct uart_dev_s *dev) * ****************************************************************************/ -static int ez80_attach(struct uart_dev_s *dev) +static int ez80_attach(FAR struct uart_dev_s *dev) { - struct ez80_dev_s *priv = (struct ez80_dev_s*)dev->priv; + FAR struct ez80_dev_s *priv = (FAR struct ez80_dev_s*)dev->priv; /* Attach the IRQ */ @@ -454,9 +454,9 @@ static int ez80_attach(struct uart_dev_s *dev) * ****************************************************************************/ -static void ez80_detach(struct uart_dev_s *dev) +static void ez80_detach(FAR struct uart_dev_s *dev) { - struct ez80_dev_s *priv = (struct ez80_dev_s*)dev->priv; + FAR struct ez80_dev_s *priv = (FAR struct ez80_dev_s*)dev->priv; ez80_disableuartint(priv); irq_detach(priv->irq); } @@ -474,9 +474,9 @@ static void ez80_detach(struct uart_dev_s *dev) * ****************************************************************************/ -static int ez80_interrupt(int irq, void *context, void *arg) +static int ez80_interrupt(int irq, FAR void *context, FAR void *arg) { - struct uart_dev_s *dev = (struct uart_dev_s *)arg; + FAR struct uart_dev_s *dev = (FAR struct uart_dev_s *)arg; struct ez80_dev_s *priv; volatile uint32_t cause; @@ -512,7 +512,7 @@ static int ez80_interrupt(int irq, void *context, void *arg) * ****************************************************************************/ -static int ez80_ioctl(struct file *filep, int cmd, unsigned long arg) +static int ez80_ioctl(FAR struct file *filep, int cmd, unsigned long arg) { return -ENOTTY; } @@ -527,9 +527,9 @@ static int ez80_ioctl(struct file *filep, int cmd, unsigned long arg) * ****************************************************************************/ -static int ez80_receive(struct uart_dev_s *dev, unsigned int *status) +static int ez80_receive(FAR struct uart_dev_s *dev, FAR unsigned int *status) { - struct ez80_dev_s *priv = (struct ez80_dev_s*)dev->priv; + FAR struct ez80_dev_s *priv = (FAR struct ez80_dev_s*)dev->priv; uint8_t rbr = ez80_serialin(priv, EZ80_UART_RBR); uint8_t lsr = ez80_serialin(priv, EZ80_UART_LSR); @@ -545,9 +545,9 @@ static int ez80_receive(struct uart_dev_s *dev, unsigned int *status) * ****************************************************************************/ -static void ez80_rxint(struct uart_dev_s *dev, bool enable) +static void ez80_rxint(FAR struct uart_dev_s *dev, bool enable) { - struct ez80_dev_s *priv = (struct ez80_dev_s*)dev->priv; + FAR struct ez80_dev_s *priv = (FAR struct ez80_dev_s*)dev->priv; uint8_t ier = ez80_serialin(priv, EZ80_UART_IER); if (enable) @@ -572,9 +572,9 @@ static void ez80_rxint(struct uart_dev_s *dev, bool enable) * ****************************************************************************/ -static bool ez80_rxavailable(struct uart_dev_s *dev) +static bool ez80_rxavailable(FAR struct uart_dev_s *dev) { - struct ez80_dev_s *priv = (struct ez80_dev_s*)dev->priv; + FAR struct ez80_dev_s *priv = (FAR struct ez80_dev_s*)dev->priv; return (ez80_serialin(priv, EZ80_UART_LSR) & EZ80_UARTLSR_DR) != 0; } @@ -586,9 +586,9 @@ static bool ez80_rxavailable(struct uart_dev_s *dev) * ****************************************************************************/ -static void ez80_send(struct uart_dev_s *dev, int ch) +static void ez80_send(FAR struct uart_dev_s *dev, int ch) { - struct ez80_dev_s *priv = (struct ez80_dev_s*)dev->priv; + FAR struct ez80_dev_s *priv = (FAR struct ez80_dev_s*)dev->priv; ez80_serialout(priv, EZ80_UART_THR, (uint8_t)ch); } @@ -600,9 +600,9 @@ static void ez80_send(struct uart_dev_s *dev, int ch) * ****************************************************************************/ -static void ez80_txint(struct uart_dev_s *dev, bool enable) +static void ez80_txint(FAR struct uart_dev_s *dev, bool enable) { - struct ez80_dev_s *priv = (struct ez80_dev_s*)dev->priv; + FAR struct ez80_dev_s *priv = (FAR struct ez80_dev_s*)dev->priv; uint8_t ier = ez80_serialin(priv, EZ80_UART_IER); if (enable) @@ -623,13 +623,13 @@ static void ez80_txint(struct uart_dev_s *dev, bool enable) * Name: ez80_txready * * Description: - * Return true if the tranmsit fifo is not full + * Return true if the transmit fifo is not full * ****************************************************************************/ -static bool ez80_txready(struct uart_dev_s *dev) +static bool ez80_txready(FAR struct uart_dev_s *dev) { - struct ez80_dev_s *priv = (struct ez80_dev_s*)dev->priv; + FAR struct ez80_dev_s *priv = (FAR struct ez80_dev_s*)dev->priv; return (ez80_serialin(priv, EZ80_UART_LSR) & EZ80_UARTLSR_THRE) != 0; } @@ -641,9 +641,9 @@ static bool ez80_txready(struct uart_dev_s *dev) * ****************************************************************************/ -static bool ez80_txempty(struct uart_dev_s *dev) +static bool ez80_txempty(FAR struct uart_dev_s *dev) { - struct ez80_dev_s *priv = (struct ez80_dev_s*)dev->priv; + FAR struct ez80_dev_s *priv = (FAR struct ez80_dev_s*)dev->priv; return (ez80_serialin(priv, EZ80_UART_LSR) & EZ80_UARTLSR_TEMT) != 0; } @@ -734,7 +734,7 @@ void z80_serial_initialize(void) int up_putc(int ch) { #ifdef CONSOLE_DEV - struct ez80_dev_s *priv = (struct ez80_dev_s*)CONSOLE_DEV.priv; + FAR struct ez80_dev_s *priv = (FAR struct ez80_dev_s*)CONSOLE_DEV.priv; uint8_t ier = ez80_serialin(priv, EZ80_UART_IER); ez80_disableuartint(priv); @@ -779,14 +779,6 @@ int up_putc(int ch) #define ez80_txready() ((ez80_inp(EZ80_UART_LSR) & EZ80_UARTLSR_THRE) != 0) #define ez80_send(ch) ez80_outp(EZ80_UART_THR, ch) -/**************************************************************************** - * Private Function Prototypes - ****************************************************************************/ - -/**************************************************************************** - * Private Data - ****************************************************************************/ - /**************************************************************************** * Private Functions ****************************************************************************/ diff --git a/arch/z80/src/ez80/ez80_spi.c b/arch/z80/src/ez80/ez80_spi.c index 734068d9c4..553f70d5c3 100644 --- a/arch/z80/src/ez80/ez80_spi.c +++ b/arch/z80/src/ez80/ez80_spi.c @@ -45,6 +45,7 @@ #include #include #include +#include #include #include @@ -62,11 +63,19 @@ ****************************************************************************/ #ifdef CONFIG_ARCH_CHIP_EZ80F91 -# define GPIOB_SPI_PINSET 0x38 /* MISO+MSOI+SCK. Excludes SS */ +# define GPIOB_SPI_SS (1 << 2) /* Pin 2: /SS (not used by driver) */ +# define GPIOB_SPI_SCK (1 << 3) /* Pin 3: SCK */ +# define GPIOB_SPI_MISO (1 << 6) /* Pin 6: MISO */ +# define GPIOB_SPI_MOSI (1 << 7) /* Pin 7: MOSI */ + +# define GPIOB_SPI_PINSET (GPIOB_SPI_SS | GPIOB_SPI_SCK | GPIOB_SPI_MISO | \ + GPIOB_SPI_MOSI) #else # error "Check GPIO initialization for this chip" #endif +#define SPIF_RETRIES 1000 + /**************************************************************************** * Private Function Prototypes ****************************************************************************/ @@ -178,7 +187,7 @@ static int spi_lock(FAR struct spi_dev_s *dev, bool lock) * was awakened by a signal. */ - DEBUGASSERT(ret == OK || ret == -EINTR); + DEBUGASSERT(ret == OK || ret == -EINTR || ret == -ECANCELED); } while (ret == -EINTR); } @@ -209,6 +218,10 @@ static int spi_lock(FAR struct spi_dev_s *dev, bool lock) static uint32_t spi_setfrequency(FAR struct spi_dev_s *dev, uint32_t frequency) { + uint32_t brg; + + spiinfo("frequency: %lu\n", (unsigned long)frequency); + /* We want select divisor to provide the highest frequency (SPIR) that does * NOT exceed the requested frequency.: * @@ -219,7 +232,7 @@ static uint32_t spi_setfrequency(FAR struct spi_dev_s *dev, * BRG >= System Clock Frequency / (2 * SPIR) */ - uint32_t brg = ((EZ80_SYS_CLK_FREQ + 1) / 2 + frequency - 1) / frequency; + brg = ((EZ80_SYS_CLK_FREQ + 1) / 2 + frequency - 1) / frequency; /* "When configured as a Master, the 16-bit divisor value must be between * 0003h and FFFFh, inclusive. When configured as a Slave, the 16-bit @@ -232,11 +245,11 @@ static uint32_t spi_setfrequency(FAR struct spi_dev_s *dev, } else if (brg > 0xffff) { - brg = 0xfff; + brg = 0xffff; } outp(EZ80_SPI_BRG_L, brg & 0xff); - outp(EZ80_SPI_BRG_L, (brg >> 8) & 0xff); + outp(EZ80_SPI_BRG_H, (brg >> 8) & 0xff); return ((EZ80_SYS_CLK_FREQ + 1) / 2 + brg - 1) / brg; } @@ -261,6 +274,8 @@ static void spi_setmode(FAR struct spi_dev_s *dev, enum spi_mode_e mode) uint8_t modebits; uint8_t regval; + spiinfo("mode: %d\n", (int)mode); + /* Select the CTL register bits based on the selected mode */ switch (mode) @@ -304,25 +319,34 @@ static void spi_setmode(FAR struct spi_dev_s *dev, enum spi_mode_e mode) * None * * Returned Value: - * Status register mode bits + * OK if the transferred completed without error. Otherwise, a negated + * errno value is returned indicating the nature of the error. * ****************************************************************************/ -static uint8_t spi_waitspif(void) +static int spi_waitspif(void) { uint8_t status; + int retries; /* Wait for the device to be ready to accept another byte (or for an error - * to be reported + * to be reported or for a timeout to occur). */ - do + for (retries = 0; retries < SPIF_RETRIES; retries++) { - status = inp(EZ80_SPI_SR) & (SPI_SR_SPIF | SPI_SR_WCOL | SPI_SR_MODF); + status = inp(EZ80_SPI_SR); + if ((status & (SPI_SR_WCOL | SPI_SR_MODF)) != 0) + { + return -EIO; + } + else if ((status & SPI_SR_SPIF) != 0) + { + return OK; + } } - while (status == 0); - return status; + return -ETIMEDOUT; } /**************************************************************************** @@ -332,29 +356,41 @@ static uint8_t spi_waitspif(void) * Send one byte on SPI, return the response * * Input Parameters: - * ch - the byte to send + * chout - The byte to send + * chin - The location to save the returned byte (may be NULL) * * Returned Value: * response * ****************************************************************************/ -static uint8_t spi_transfer(uint8_t ch) +static int spi_transfer(uint8_t chout, FAR uint8_t *chin) { - uint8_t status; + uint8_t response; + int ret; + + spiinfo("chout: %02x\n", chout); /* Send the byte, repeating if some error occurs */ for (; ; ) { - outp(EZ80_SPI_TSR, ch); + outp(EZ80_SPI_TSR, chout); /* Wait for the device to be ready to accept another byte */ - status = spi_waitspif(); - if ((status & SPI_SR_SPIF) != 0) + ret = spi_waitspif(); + if (ret < 0) { - return inp(EZ80_SPI_RBR); + spierr("ERROR: spi_waitspif returned %d\n", ret); + return ret; + } + + response = inp(EZ80_SPI_RBR); + if (chin != NULL) + { + *chin = response; + return OK; } } } @@ -377,7 +413,19 @@ static uint8_t spi_transfer(uint8_t ch) static uint16_t spi_send(FAR struct spi_dev_s *dev, uint16_t wd) { - return spi_transfer((uint8_t)wd); + uint8_t response; + int ret; + + spiinfo("ch: %04x\n", wd); + + ret = spi_transfer((uint8_t)wd, &response); + if (ret < 0) + { + spierr("ERROR: spi_waitspif returned %d\n", ret); + return (uint16_t)0xff; + } + + return (uint16_t)response; } /**************************************************************************** @@ -409,23 +457,34 @@ static void spi_exchange(FAR struct spi_dev_s *dev, FAR const uint8_t *inptr = (FAR const uint8_t *)txbuffer; FAR uint8_t *outptr = (FAR const uint8_t *)rxbuffer; + spiinfo("txbuffer: %p rxbuffer: %p nwords: %lu\n", + txbuffer, rxbuffer, (unsigned long)nwords); + /* Loop while there are bytes remaining to be sent */ while (nwords-- > 0) { + uint8_t outword; + int ret; + /* Send 0xff if there is no outgoing TX stream */ - uint8_t outword = (inptr == NULL) ? 0xff : *inptr++; + outword = (inptr == NULL) ? 0xff : *inptr++; - /* Send the outgoing word and obtain the respoonse */ + /* Send the outgoing word and obtain the response */ - uint8_t inword = spi_transfer(outword); + ret = spi_transfer(outword, outptr); + if (ret < 0) + { + spierr("ERROR: spi_waitspif returned %d\n", ret); + break; + } - /* Save the response if there is an incoming RX stream */ + /* Conditionally increment the output buffer pointer. */ if (outptr != NULL) { - *outptr++ = inword; + outptr++; } } } @@ -456,12 +515,20 @@ static void spi_sndblock(FAR struct spi_dev_s *dev, FAR const void *buffer, size_t buflen) { FAR const uint8_t *ptr = (FAR const uint8_t *)buffer; + int ret; + + spiinfo("buffer: %p buflen: %lu\n", buffer, (unsigned long)nwords); /* Loop while there are bytes remaining to be sent */ while (buflen-- > 0) { - (void)spi_transfer(*ptr++); + ret = spi_transfer(*ptr++, NULL); + if (ret < 0) + { + spierr("ERROR: spi_waitspif returned %d\n", ret); + break; + } } } #endif @@ -492,11 +559,18 @@ static void spi_recvblock(FAR struct spi_dev_s *dev, FAR void *buffer, { FAR uint8_t *ptr = (FAR uint8_t *)buffer; - /* Loop while thre are bytes remaining to be sent */ + spiinfo("buffer: %p buflen: %lu\n", buffer, (unsigned long)nwords); + + /* Loop while there are bytes remaining to be sent */ while (buflen-- > 0) { - *ptr++ = spi_transfer(0xff); + ret = spi_transfer(0xff, ptr++); + if (ret < 0) + { + spierr("ERROR: spi_waitspif returned %d\n", ret); + break; + } } } #endif @@ -516,14 +590,14 @@ static void spi_recvblock(FAR struct spi_dev_s *dev, FAR void *buffer, * * One GPIO, SS (PB2 on the eZ8F091) is reserved as a chip select. However, * If multiple devices on on the bus, then multiple chip selects will be - * required. Theregore, all GPIO chip management is deferred to board- + * required. Therefore, all GPIO chip management is deferred to board- * specific logic. * * Input Parameters: - * Port number (for hardware that has mutiple SPI interfaces) + * Port number (for hardware that has multiple SPI interfaces) * * Returned Value: - * Valid SPI device structre reference on succcess; a NULL on failure + * Valid SPI device structure reference on success; a NULL on failure * ****************************************************************************/ @@ -549,12 +623,12 @@ FAR struct spi_dev_s *ez80_spibus_initialize(int port) * * GPIO ALT MASTER SLAVE COMMENT * ---- ----- ------- ------- --------------------------------- - * PB2 SS INPUT INPUT Managed by board specific logic - * PB3 SCLK OUTPUT INPUT - * PB4 MISO INPUT OUTPUT - * PB5 MOSI OUTPUT INPUT + * PB2 SS INPUT INPUT Managed by board specific logic + * PB3 SCLK OUTPUT INPUT + * PB6 MISO INPUT OUTPUT + * PB7 MOSI OUTPUT INPUT * - * Select the alternate function for PB2-5: + * Select the alternate function for PB2-3,6-7: */ #ifdef CONFIG_ARCH_CHIP_EZ80F91 @@ -579,7 +653,7 @@ FAR struct spi_dev_s *ez80_spibus_initialize(int port) /* Enable the SPI. * NOTE 1: Interrupts are not used in this driver version. - * NOTE 2: Initial mode is mode=0. + * NOTE 2: Initial mode is mode=0 */ outp(EZ80_SPI_CTL, SPI_CTL_SPIEN | SPI_CTL_MASTEREN); diff --git a/configs/makerlisp/README.txt b/configs/makerlisp/README.txt index 3e530dc159..7641644c8f 100644 --- a/configs/makerlisp/README.txt +++ b/configs/makerlisp/README.txt @@ -313,11 +313,19 @@ Configuration Subdirectories placed in the card slot before the system is started. STATUS: - 2109-06-16: The basic NSH configuration appears to be fully functional + 2019-06-16: The basic NSH configuration appears to be fully functional using only the CPU and I/O expansion card. Console is provided over USB. Added support for SPI-based SD cards, the RTC and procFS. There are - still a few issues at the end-of-the-day: (1) the SD card block driver - is not being registered, and (2) RTC does not preserve time across a + still a few issues at the end-of-the-day: (1) the SD card initialization + hangs and prevents booting, and (2) RTC does not preserve time across a power cycle. + + 2019-06-17: The SD initialization is due to some error in the SPI driver: + It waits for a byte transfer to complete but it never receives the + indication that the transfer completed. The SPI problem has not been + fixed, but timeout logic was added to avoid the hang. + + The MMC/SD start-up failures do effect the boot-up time. You might want + to disable SPI to avoid start-up delays. diff --git a/configs/makerlisp/include/board.h b/configs/makerlisp/include/board.h index f4250af0a3..9386cfdf95 100644 --- a/configs/makerlisp/include/board.h +++ b/configs/makerlisp/include/board.h @@ -76,7 +76,7 @@ #define LED_STACKCREATED 0 #define LED_IDLE 0 #define LED_INIRQ 0 -#define LED_ASSERTION 1 +#define LED_ASSERTION 0 #define LED_SIGNAL 0 #define LED_PANIC 1 diff --git a/configs/makerlisp/nsh/defconfig b/configs/makerlisp/nsh/defconfig index 257631ec93..d1d294618b 100644 --- a/configs/makerlisp/nsh/defconfig +++ b/configs/makerlisp/nsh/defconfig @@ -14,6 +14,7 @@ CONFIG_ARCH_BOARD="makerlisp" CONFIG_ARCH_BOARD_MAKERLISP=y CONFIG_ARCH_CHIP_EZ80=y CONFIG_ARCH_CHIP_EZ80F91=y +CONFIG_ARCH_STACKDUMP=y CONFIG_ARCH_Z80=y CONFIG_BOARD_LOOPSPERMSEC=1250 CONFIG_DISABLE_MQUEUE=y diff --git a/configs/makerlisp/src/ez80_bringup.c b/configs/makerlisp/src/ez80_bringup.c index 7ccf0cc263..8d26895aea 100644 --- a/configs/makerlisp/src/ez80_bringup.c +++ b/configs/makerlisp/src/ez80_bringup.c @@ -43,6 +43,8 @@ #include #include +#include "makerlisp.h" + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -78,7 +80,7 @@ int ez80_bringup(void) #ifdef HAVE_MMCSD /* Initialize SPI-based SD card slot */ - ret = ez80_mmcsd_initialize(void); + ret = ez80_mmcsd_initialize(); if (ret < 0) { syslog(LOG_ERR, "ERROR: Failed to initialize SD card: %d\n", ret); diff --git a/configs/makerlisp/src/ez80_spi.c b/configs/makerlisp/src/ez80_spi.c index 2fd6493fcd..4cfcdd9643 100644 --- a/configs/makerlisp/src/ez80_spi.c +++ b/configs/makerlisp/src/ez80_spi.c @@ -145,7 +145,7 @@ uint8_t ez80_spistatus(FAR struct spi_dev_s *dev, uint32_t devid) { uint8_t status = 0; -#ifdef HAVE_MMCSD_SPI +#ifdef HAVE_MMCSD if (devid == SPIDEV_MMCSD(0)) { /* No card detect pin.. Always claim that the card is present in