Implented SPI HAL for CC13xx/CC26xx

This commit is contained in:
Edvard Pettersen 2018-07-25 15:05:08 +02:00
parent 972502b3e2
commit 813543b569
8 changed files with 333 additions and 3 deletions

View File

@ -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

View File

@ -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
*

View File

@ -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 <e.pettersen@ti.com>
*/
/*---------------------------------------------------------------------------*/
#include "contiki.h"
#include "sys/cc.h"
#include "dev/spi.h"
/*---------------------------------------------------------------------------*/
#include <ti/drivers/SPI.h>
#include <ti/drivers/dpl/HwiP.h>
#include <ti/drivers/pin/PINCC26XX.h>
/*---------------------------------------------------------------------------*/
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
/*---------------------------------------------------------------------------*/
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;
}
/*---------------------------------------------------------------------------*/
/**
* @}
* @}
*/

View File

@ -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

View File

@ -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_ */
/*---------------------------------------------------------------------------*/
/**

View File

@ -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_ */
/*---------------------------------------------------------------------------*/
/**

View File

@ -1,7 +1,7 @@
################################################################################
# SimpleLink LaunchPad makefile
BOARD_TYPE = BOARD_SRF06
BOARD_TYPE = BOARD_SMARTRF06EB
# leds-arch.c etc.
BOARD_SOURCEFILES += srf06-sensors.c

View File

@ -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 */