From 813543b5694b22afaa2b5e411c68e25865e69874 Mon Sep 17 00:00:00 2001 From: Edvard Pettersen Date: Wed, 25 Jul 2018 15:05:08 +0200 Subject: [PATCH] Implented SPI HAL for CC13xx/CC26xx --- arch/cpu/cc13xx-cc26xx/Makefile.cc13xx-cc26xx | 1 + arch/cpu/cc13xx-cc26xx/cc13xx-cc26xx-conf.h | 41 +++ arch/cpu/cc13xx-cc26xx/dev/spi-arch.c | 265 ++++++++++++++++++ .../cc13xx-cc26xx/Makefile.cc13xx-cc26xx | 4 +- .../cc13xx-cc26xx/launchpad/board-conf.h | 11 + .../cc13xx-cc26xx/sensortag/board-conf.h | 11 + .../cc13xx-cc26xx/srf06/Makefile.srf06 | 2 +- os/dev/spi.h | 1 + 8 files changed, 333 insertions(+), 3 deletions(-) create mode 100644 arch/cpu/cc13xx-cc26xx/dev/spi-arch.c diff --git a/arch/cpu/cc13xx-cc26xx/Makefile.cc13xx-cc26xx b/arch/cpu/cc13xx-cc26xx/Makefile.cc13xx-cc26xx index 6322e9a1b..581422d56 100644 --- a/arch/cpu/cc13xx-cc26xx/Makefile.cc13xx-cc26xx +++ b/arch/cpu/cc13xx-cc26xx/Makefile.cc13xx-cc26xx @@ -73,6 +73,7 @@ CONTIKI_CPU_SOURCEFILES += watchdog-arch.c dbg-arch.c CONTIKI_CPU_SOURCEFILES += uart0-arch.c slip-arch.c CONTIKI_CPU_SOURCEFILES += gpio-hal-arch.c int-master-arch.c CONTIKI_CPU_SOURCEFILES += random.c trng-arch.c +CONTIKI_CPU_SOURCEFILES += spi-arch.c # RF source files CONTIKI_CPU_SOURCEFILES += sched.c data-queue.c diff --git a/arch/cpu/cc13xx-cc26xx/cc13xx-cc26xx-conf.h b/arch/cpu/cc13xx-cc26xx/cc13xx-cc26xx-conf.h index fad5bcf5e..09790cebc 100644 --- a/arch/cpu/cc13xx-cc26xx/cc13xx-cc26xx-conf.h +++ b/arch/cpu/cc13xx-cc26xx/cc13xx-cc26xx-conf.h @@ -410,6 +410,47 @@ #endif /** @} */ /*---------------------------------------------------------------------------*/ +/** + * \name SPI HAL configuration. + * + * CC13x0/CC26x0 has one SPI interface, while CC13x2/CC26x2 has two + * SPI interfaces. Some additional checks has to be made for the + * SPI_CONF_CONTROLLER_COUNT configuration, as this relies on whether the + * available SPI interfaces are enabled or not, as well as if the SPI driver + * is enabled at all. + * + * @{ + */ +#if TI_SPI_CONF_ENABLE +/* + * The SPI driver is enabled. Therefore, the number of SPI interfaces depends + * on which Device family parent the device falls under and if any of its + * corresponding SPI interfaces are enabled or not. + */ + +#define SPI0_IS_ENABLED ((TI_SPI_CONF_SPI0_ENABLE) ? 1 : 0) +#define SPI1_IS_ENABLED ((TI_SPI_CONF_SPI1_ENABLE) ? 1 : 0) + +#if (DeviceFamily_PARENT == DeviceFamily_PARENT_CC13X0_CC26X0) + +/* CC13x0/CC26x0 only has one SPI interface: SPI0. */ +#define SPI_CONF_CONTROLLER_COUNT (SPI0_IS_ENABLED) + +#elif (DeviceFamily_PARENT == DeviceFamily_PARENT_CC13X2_CC26X2) + +/* CC13x0/CC26x0 only has two SPI interface: SPI0 and SPI1. */ +#define SPI_CONF_CONTROLLER_COUNT (SPI0_ENABLED + SPI1_IS_ENABLED) + +#endif /* DeviceFamily_PARENT */ + +#else /* TI_SPI_CONF_ENABLE */ +/* + * If the SPI driver is disabled then there are 0 available + * SPI interfaces. */ +#define SPI_CONF_CONTROLLER_COUNT 0 +#endif /* TI_SPI_CONF_ENABLE */ +/** @} */ +/*---------------------------------------------------------------------------*/ /** * \name Slip configuration * diff --git a/arch/cpu/cc13xx-cc26xx/dev/spi-arch.c b/arch/cpu/cc13xx-cc26xx/dev/spi-arch.c new file mode 100644 index 000000000..7fe41762b --- /dev/null +++ b/arch/cpu/cc13xx-cc26xx/dev/spi-arch.c @@ -0,0 +1,265 @@ +/* + * Copyright (c) 2018, Texas Instruments Incorporated - http://www.ti.com/ + * All rights reserved. + * + * 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 of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/** + * \addtogroup cc13xx-cc26xx-cpu + * @{ + * + * \defgroup cc13xx-cc26xx-spi CC13xx/CC26xx SPI HAL + * + * @{ + * \file + * Implementation of the SPI HAL driver for CC13xx/CC26xx. + * \author + * Edvard Pettersen + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "sys/cc.h" +#include "dev/spi.h" +/*---------------------------------------------------------------------------*/ +#include +#include +#include +/*---------------------------------------------------------------------------*/ +#include +#include +#include +/*---------------------------------------------------------------------------*/ +typedef struct { + SPI_Handle handle; + spi_device_t *owner; +} spi_arch_t; +/*---------------------------------------------------------------------------*/ +#if (SPI_CONTROLLER_COUNT > 0) +static spi_arch_t spi_arches[SPI_CONTROLLER_COUNT]; +#else +static spi_arch_t *spi_arches = NULL; +#endif +/*---------------------------------------------------------------------------*/ +static inline spi_arch_t* +get_handle(uint8_t spi_controller) +{ + if(spi_controller < SPI_CONTROLLER_COUNT) { + return &spi_arches[spi_controller]; + } else { + return NULL; + } +} +/*---------------------------------------------------------------------------*/ +static SPI_FrameFormat +convert_frame_format(uint8_t pol, uint8_t pha) +{ + pol = (pol) ? 1 : 0; + pha = (pha) ? 1 : 0; + /* + * Convert pol/pha to a single byte on the following format: + * xxxA xxxB + * where A is the polarity bit and B is the phase bit. + * Note that any other value deviating from this format will + * default to the SPI_POL1_PHA1 format. + */ + uint8_t pol_pha = (pol << 4) | (pha << 0); + switch(pol_pha) { + case 0x00: return SPI_POL0_PHA0; + case 0x01: return SPI_POL0_PHA1; + case 0x10: return SPI_POL1_PHA0; + default: /* fallthrough */ + case 0x11: return SPI_POL1_PHA1; + } +} +/*---------------------------------------------------------------------------*/ +bool +spi_arch_has_lock(spi_device_t *dev) +{ + /* + * The SPI device is the owner if the SPI controller returns a valid + * SPI arch object and the SPI device is owner of that object. + */ + spi_arch_t *spi_arch = get_handle(dev->spi_controller); + return (spi_arch != NULL) && (spi_arch->owner == dev); +} +/*---------------------------------------------------------------------------*/ +bool +spi_arch_is_bus_locked(spi_device_t *dev) +{ + /* + * The SPI controller is locked by any device if the SPI controller returns + * a valid SPI arch object and the SPI handle of that object is valid. + */ + spi_arch_t *spi_arch = get_handle(dev->spi_controller); + return (spi_arch != NULL) && (spi_arch->handle != NULL); +} +/*---------------------------------------------------------------------------*/ +spi_status_t +spi_arch_lock_and_open(spi_device_t *dev) +{ + uint_least8_t spi_index; + spi_arch_t *spi_arch; + SPI_Params spi_params; + + const uintptr_t hwi_key = HwiP_disable(); + + spi_index = dev->spi_controller; + spi_arch = get_handle(spi_index); + + /* Ensure the provided SPI index is valid. */ + if(spi_arch == NULL) { + HwiP_restore(hwi_key); + return SPI_DEV_STATUS_EINVAL; + } + + /* Ensure the corresponding SPI interface is not already locked. */ + if(spi_arch_is_bus_locked(dev)) { + HwiP_restore(hwi_key); + return SPI_DEV_STATUS_BUS_LOCKED; + } + + SPI_Params_init(&spi_params); + + spi_params.transferMode = SPI_MODE_BLOCKING; + spi_params.mode = SPI_MASTER; + spi_params.bitRate = dev->spi_bit_rate; + spi_params.dataSize = 8; + spi_params.frameFormat = convert_frame_format(dev->spi_pol, dev->spi_pha); + + /* + * Try to open the SPI driver. Accessing the SPI driver also ensures + * atomic access to the SPI interface. + */ + spi_arch->handle = SPI_open(spi_index, &spi_params); + + if(spi_arch->handle == NULL) { + HwiP_restore(hwi_key); + return SPI_DEV_STATUS_BUS_LOCKED; + } + + spi_arch->owner = dev; + + HwiP_restore(hwi_key); + return SPI_DEV_STATUS_OK; +} +/*---------------------------------------------------------------------------*/ +spi_status_t +spi_arch_close_and_unlock(spi_device_t *dev) +{ + spi_arch_t *spi_arch; + + const uintptr_t hwi_key = HwiP_disable(); + + /* Ensure the provided SPI index is valid. */ + spi_arch = get_handle(dev->spi_controller); + if(spi_arch == NULL) { + HwiP_restore(hwi_key); + return SPI_DEV_STATUS_EINVAL; + } + + /* Ensure the corresponding SPI device owns the SPI controller. */ + if(!spi_arch_has_lock(dev)) { + HwiP_restore(hwi_key); + return SPI_DEV_STATUS_BUS_NOT_OWNED; + } + + SPI_close(spi_arch->handle); + + spi_arch->handle = NULL; + spi_arch->owner = NULL; + + HwiP_restore(hwi_key); + return SPI_DEV_STATUS_OK; +} +/*---------------------------------------------------------------------------*/ +spi_status_t +spi_arch_transfer(spi_device_t *dev, + const uint8_t *write_buf, int wlen, + uint8_t *inbuf, int rlen, int ignore_len) +{ + spi_arch_t *spi_arch; + size_t totlen; + SPI_Transaction spi_transaction; + bool transfer_ok; + + /* Ensure the provided SPI index is valid. */ + spi_arch = get_handle(dev->spi_controller); + if(spi_arch == NULL) { + return SPI_DEV_STATUS_EINVAL; + } + + if(!spi_arch_has_lock(dev)) { + return SPI_DEV_STATUS_BUS_NOT_OWNED; + } + + totlen = MAX((size_t)(rlen + ignore_len), (size_t)wlen); + + if(totlen == 0) { + /* Nothing to do */ + return SPI_DEV_STATUS_OK; + } + + spi_transaction.count = totlen; + spi_transaction.txBuf = (void *)write_buf; + spi_transaction.rxBuf = (void *)inbuf; + + transfer_ok = SPI_transfer(spi_arch->handle, &spi_transaction); + + if(!transfer_ok) { + return SPI_DEV_STATUS_TRANSFER_ERR; + } + + return SPI_DEV_STATUS_OK; +} +/*---------------------------------------------------------------------------*/ +spi_status_t +spi_arch_select(spi_device_t *dev) +{ + if(!spi_arch_has_lock(dev)) { + return SPI_DEV_STATUS_BUS_NOT_OWNED; + } + + PINCC26XX_setOutputValue(dev->pin_spi_cs, 0); + + return SPI_DEV_STATUS_OK; +} +/*---------------------------------------------------------------------------*/ +spi_status_t +spi_arch_deselect(spi_device_t *dev) +{ + if(!spi_arch_has_lock(dev)) { + return SPI_DEV_STATUS_BUS_NOT_OWNED; + } + + PINCC26XX_setOutputValue(dev->pin_spi_cs, 1); + + return SPI_DEV_STATUS_OK; +} +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ \ No newline at end of file diff --git a/arch/platform/simplelink/cc13xx-cc26xx/Makefile.cc13xx-cc26xx b/arch/platform/simplelink/cc13xx-cc26xx/Makefile.cc13xx-cc26xx index dc681a5eb..959e19105 100644 --- a/arch/platform/simplelink/cc13xx-cc26xx/Makefile.cc13xx-cc26xx +++ b/arch/platform/simplelink/cc13xx-cc26xx/Makefile.cc13xx-cc26xx @@ -6,8 +6,8 @@ BOARD_PLATFORMS = launchpad sensortag srf06 # All supported boards for this SimpleLink family -BOARDS := $(foreach BOARD_TYPE, $(BOARD_PLATFORMS), \ - $(shell cd $(FAMILY_PATH); find $(BOARD_TYPE)/* -type d -print)) +BOARDS := $(foreach BOARD, $(BOARD_PLATFORMS), \ + $(shell cd $(FAMILY_PATH); find $(BOARD)/* -type d -print)) ################################################################################ # Directory and source configurations diff --git a/arch/platform/simplelink/cc13xx-cc26xx/launchpad/board-conf.h b/arch/platform/simplelink/cc13xx-cc26xx/launchpad/board-conf.h index f700baa08..a096f0072 100644 --- a/arch/platform/simplelink/cc13xx-cc26xx/launchpad/board-conf.h +++ b/arch/platform/simplelink/cc13xx-cc26xx/launchpad/board-conf.h @@ -50,6 +50,8 @@ #ifndef BOARD_CONF_H_ #define BOARD_CONF_H_ /*---------------------------------------------------------------------------*/ +#include "contiki-conf.h" +/*---------------------------------------------------------------------------*/ /** * \name LED configurations for the dev/leds.h API. * @@ -83,6 +85,15 @@ #define BOARD_CONF_HAS_SENSORS 0 /** @} */ /*---------------------------------------------------------------------------*/ +/** + * \name The external flash SPI CS pin, defined in Board.h. + * + * Those values are not meant to be modified by the user + * @{ + */ +#define EXT_FLASH_SPI_PIN_CS Board_SPI_FLASH_CS +/** @} */ +/*---------------------------------------------------------------------------*/ #endif /* BOARD_CONF_H_ */ /*---------------------------------------------------------------------------*/ /** diff --git a/arch/platform/simplelink/cc13xx-cc26xx/sensortag/board-conf.h b/arch/platform/simplelink/cc13xx-cc26xx/sensortag/board-conf.h index fa3c4e406..d676f3375 100644 --- a/arch/platform/simplelink/cc13xx-cc26xx/sensortag/board-conf.h +++ b/arch/platform/simplelink/cc13xx-cc26xx/sensortag/board-conf.h @@ -50,6 +50,8 @@ #ifndef BOARD_CONF_H_ #define BOARD_CONF_H_ /*---------------------------------------------------------------------------*/ +#include "contiki-conf.h" +/*---------------------------------------------------------------------------*/ #include "leds-arch.h" /*---------------------------------------------------------------------------*/ /** @@ -81,6 +83,15 @@ #define BOARD_SENSORS_ENABLE (!(BOARD_CONF_SENSORS_DISABLE)) /** @} */ /*---------------------------------------------------------------------------*/ +/** + * \name The external flash SPI CS pin, defined in Board.h. + * + * Those values are not meant to be modified by the user + * @{ + */ +#define EXT_FLASH_SPI_PIN_CS Board_SPI_FLASH_CS +/** @} */ +/*---------------------------------------------------------------------------*/ #endif /* BOARD_CONF_H_ */ /*---------------------------------------------------------------------------*/ /** diff --git a/arch/platform/simplelink/cc13xx-cc26xx/srf06/Makefile.srf06 b/arch/platform/simplelink/cc13xx-cc26xx/srf06/Makefile.srf06 index 500b8414d..d6686e10a 100644 --- a/arch/platform/simplelink/cc13xx-cc26xx/srf06/Makefile.srf06 +++ b/arch/platform/simplelink/cc13xx-cc26xx/srf06/Makefile.srf06 @@ -1,7 +1,7 @@ ################################################################################ # SimpleLink LaunchPad makefile -BOARD_TYPE = BOARD_SRF06 +BOARD_TYPE = BOARD_SMARTRF06EB # leds-arch.c etc. BOARD_SOURCEFILES += srf06-sensors.c diff --git a/os/dev/spi.h b/os/dev/spi.h index 0c9aadc73..70faa6b5b 100644 --- a/os/dev/spi.h +++ b/os/dev/spi.h @@ -80,6 +80,7 @@ typedef enum { SPI_DEV_STATUS_OK, /* Everything OK */ SPI_DEV_STATUS_EINVAL, /* Erroneous input value */ + SPI_DEV_STATUS_TRANSFER_ERR, /* Error during SPI transfer */ SPI_DEV_STATUS_BUS_LOCKED, /* SPI bus is already locked */ SPI_DEV_STATUS_BUS_NOT_OWNED, /* SPI bus is locked by someone else */ SPI_DEV_STATUS_CLOSED /* SPI bus has not opened properly */