SPI HAL implementation for CC2538
This commit is contained in:
parent
5e79f0a922
commit
2a7e9f0835
@ -16,6 +16,7 @@ CONTIKI_CPU_DIRS = . dev usb usb/common usb/common/cdc-acm
|
||||
### CPU-dependent source files
|
||||
CONTIKI_CPU_SOURCEFILES += soc.c clock.c rtimer-arch.c uart.c watchdog.c
|
||||
CONTIKI_CPU_SOURCEFILES += nvic.c sys-ctrl.c gpio.c ioc.c spi.c adc.c
|
||||
CONTIKI_CPU_SOURCEFILES += spi-hal-arch.c
|
||||
CONTIKI_CPU_SOURCEFILES += crypto.c aes.c ecb.c cbc.c ctr.c cbc-mac.c gcm.c
|
||||
CONTIKI_CPU_SOURCEFILES += ccm.c sha256.c gpio-hal-arch.c
|
||||
CONTIKI_CPU_SOURCEFILES += cc2538-aes-128.c cc2538-ccm-star.c
|
||||
|
@ -325,6 +325,9 @@
|
||||
#endif
|
||||
/** @} */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* SPI HAL: Path to arch-specific implementation */
|
||||
#define SPI_HAL_CONF_ARCH_HDR_PATH "dev/spi-hal-arch.h"
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#endif /* CC2538_CONF_H_ */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @} */
|
||||
|
359
arch/cpu/cc2538/dev/spi-hal-arch.c
Normal file
359
arch/cpu/cc2538/dev/spi-hal-arch.c
Normal file
@ -0,0 +1,359 @@
|
||||
/*
|
||||
* Copyright (c) 2016-2017, Yanzi Networks.
|
||||
* Copyright (c) 2018, University of Bristol.
|
||||
* 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 HOLDER AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include "contiki.h"
|
||||
#include "reg.h"
|
||||
#include "spi-hal.h"
|
||||
#include "spi-hal-arch.h"
|
||||
#include "gpio-hal-arch.h"
|
||||
#include "sys/cc.h"
|
||||
#include "ioc.h"
|
||||
#include "sys-ctrl.h"
|
||||
#include "spi.h"
|
||||
#include "ssi.h"
|
||||
#include "gpio.h"
|
||||
#include "sys/log.h"
|
||||
#include "sys/mutex.h"
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Log configuration */
|
||||
#define LOG_MODULE "spi-hal-arch"
|
||||
#define LOG_LEVEL LOG_LEVEL_NONE
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#if (SPI0_CPRS_CPSDVSR & 1) == 1 || SPI0_CPRS_CPSDVSR < 2 || SPI0_CPRS_CPSDVSR > 254
|
||||
#error SPI0_CPRS_CPSDVSR must be an even number between 2 and 254
|
||||
#endif
|
||||
|
||||
#if (SPI1_CPRS_CPSDVSR & 1) == 1 || SPI1_CPRS_CPSDVSR < 2 || SPI1_CPRS_CPSDVSR > 254
|
||||
#error SPI1_CPRS_CPSDVSR must be an even number between 2 and 254
|
||||
#endif
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/*
|
||||
* Clock source from which the baud clock is determined for the SSI, according
|
||||
* to SSI_CC.CS.
|
||||
*/
|
||||
#define SSI_SYS_CLOCK SYS_CTRL_SYS_CLOCK
|
||||
/*---------------------------------------------------------------------------*/
|
||||
typedef struct {
|
||||
uint32_t base;
|
||||
uint32_t ioc_ssirxd_ssi;
|
||||
uint32_t ioc_pxx_sel_ssi_clkout;
|
||||
uint32_t ioc_pxx_sel_ssi_txd;
|
||||
uint8_t ssi_cprs_cpsdvsr;
|
||||
} spi_regs_t;
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static const spi_regs_t spi_regs[SSI_INSTANCE_COUNT] = {
|
||||
{
|
||||
.base = SSI0_BASE,
|
||||
.ioc_ssirxd_ssi = IOC_SSIRXD_SSI0,
|
||||
.ioc_pxx_sel_ssi_clkout = IOC_PXX_SEL_SSI0_CLKOUT,
|
||||
.ioc_pxx_sel_ssi_txd = IOC_PXX_SEL_SSI0_TXD,
|
||||
.ssi_cprs_cpsdvsr = SPI0_CPRS_CPSDVSR,
|
||||
}, {
|
||||
.base = SSI1_BASE,
|
||||
.ioc_ssirxd_ssi = IOC_SSIRXD_SSI1,
|
||||
.ioc_pxx_sel_ssi_clkout = IOC_PXX_SEL_SSI1_CLKOUT,
|
||||
.ioc_pxx_sel_ssi_txd = IOC_PXX_SEL_SSI1_TXD,
|
||||
.ssi_cprs_cpsdvsr = SPI1_CPRS_CPSDVSR,
|
||||
}
|
||||
};
|
||||
|
||||
typedef struct spi_locks_s {
|
||||
mutex_t lock;
|
||||
spi_device_t *owner;
|
||||
} spi_locks_t;
|
||||
|
||||
/* One lock per SPI controller */
|
||||
spi_locks_t board_spi_locks_spi[BOARD_SPI_CONTROLLERS] = { { MUTEX_STATUS_UNLOCKED, NULL } };
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
spix_wait_tx_ready(spi_device_t *dev)
|
||||
{
|
||||
/* Infinite loop until SR_TNF - Transmit FIFO Not Full */
|
||||
while(!(REG(spi_regs[dev->spi_controller].base + SSI_SR) & SSI_SR_TNF));
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static int
|
||||
spix_read_buf(spi_device_t *dev)
|
||||
{
|
||||
return REG(spi_regs[dev->spi_controller].base + SSI_DR);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
spix_write_buf(spi_device_t *dev, int data)
|
||||
{
|
||||
REG(spi_regs[dev->spi_controller].base + SSI_DR) = data;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
spix_wait_eotx(spi_device_t *dev)
|
||||
{
|
||||
/* wait until not busy */
|
||||
while(REG(spi_regs[dev->spi_controller].base + SSI_SR) & SSI_SR_BSY);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
spix_wait_eorx(spi_device_t *dev)
|
||||
{
|
||||
/* wait as long as receive is empty */
|
||||
while(!(REG(spi_regs[dev->spi_controller].base + SSI_SR) & SSI_SR_RNE));
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
spi_status_t
|
||||
spi_arch_lock(spi_device_t *dev)
|
||||
{
|
||||
if(mutex_try_lock(&board_spi_locks_spi[dev->spi_controller].lock) == false) {
|
||||
return SPI_DEV_STATUS_BUS_LOCKED;
|
||||
}
|
||||
|
||||
board_spi_locks_spi[dev->spi_controller].owner = dev;
|
||||
|
||||
return SPI_DEV_STATUS_OK;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
bool
|
||||
spi_arch_has_lock(spi_device_t *dev)
|
||||
{
|
||||
if(board_spi_locks_spi[dev->spi_controller].owner == dev) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
bool
|
||||
spi_arch_is_bus_locked(spi_device_t *dev)
|
||||
{
|
||||
if(board_spi_locks_spi[dev->spi_controller].lock == MUTEX_STATUS_LOCKED) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
spi_status_t
|
||||
spi_arch_unlock(spi_device_t *dev)
|
||||
{
|
||||
if(!spi_arch_has_lock(dev)) {
|
||||
return SPI_DEV_STATUS_BUS_NOT_OWNED;
|
||||
}
|
||||
|
||||
board_spi_locks_spi[dev->spi_controller].owner = NULL;
|
||||
mutex_unlock(&board_spi_locks_spi[dev->spi_controller].lock);
|
||||
|
||||
return SPI_DEV_STATUS_OK;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
spi_status_t
|
||||
spi_arch_open(spi_device_t *dev)
|
||||
{
|
||||
uint32_t scr;
|
||||
uint64_t div;
|
||||
|
||||
uint32_t cs_port = PIN_TO_PORT(dev->pin_spi_cs);
|
||||
uint32_t cs_pin = PIN_TO_NUM(dev->pin_spi_cs);
|
||||
|
||||
uint32_t clk_port = PIN_TO_PORT(dev->pin_spi_sck);
|
||||
uint32_t clk_pin = PIN_TO_NUM(dev->pin_spi_sck);
|
||||
|
||||
uint32_t miso_port = PIN_TO_PORT(dev->pin_spi_miso);
|
||||
uint32_t miso_pin = PIN_TO_NUM(dev->pin_spi_miso);
|
||||
|
||||
uint32_t mosi_port = PIN_TO_PORT(dev->pin_spi_mosi);
|
||||
uint32_t mosi_pin = PIN_TO_NUM(dev->pin_spi_mosi);
|
||||
|
||||
uint32_t mode = 0;
|
||||
|
||||
if(!spi_arch_has_lock(dev)) {
|
||||
return SPI_DEV_STATUS_BUS_NOT_OWNED;
|
||||
}
|
||||
|
||||
/* Set SPI phase */
|
||||
if(dev->spi_pha != 0){
|
||||
mode = mode | SSI_CR0_SPH;
|
||||
}
|
||||
|
||||
/* Set SPI polarity */
|
||||
if(dev->spi_pol !=0){
|
||||
mode = mode | SSI_CR0_SPO;
|
||||
}
|
||||
|
||||
/* CS pin configuration */
|
||||
GPIO_SOFTWARE_CONTROL(GPIO_PORT_TO_BASE(cs_port),
|
||||
GPIO_PIN_MASK(cs_pin));
|
||||
ioc_set_over(cs_port, cs_pin, IOC_OVERRIDE_DIS);
|
||||
GPIO_SET_OUTPUT(GPIO_PORT_TO_BASE(cs_port), GPIO_PIN_MASK(cs_pin));
|
||||
GPIO_SET_PIN(GPIO_PORT_TO_BASE(cs_port), GPIO_PIN_MASK(cs_pin));
|
||||
|
||||
const spi_regs_t *regs;
|
||||
|
||||
regs = &spi_regs[dev->spi_controller];
|
||||
|
||||
/* SSI Enable */
|
||||
REG(SYS_CTRL_RCGCSSI) |= (1 << dev->spi_controller);
|
||||
|
||||
/* Start by disabling the peripheral before configuring it */
|
||||
REG(regs->base + SSI_CR1) = 0;
|
||||
|
||||
/* Set the system clock as the SSI clock */
|
||||
REG(regs->base + SSI_CC) = 0;
|
||||
|
||||
/* Set the mux correctly to connect the SSI pins to the correct GPIO pins */
|
||||
ioc_set_sel(clk_port, clk_pin, regs->ioc_pxx_sel_ssi_clkout);
|
||||
ioc_set_sel(mosi_port, mosi_pin, regs->ioc_pxx_sel_ssi_txd);
|
||||
REG(regs->ioc_ssirxd_ssi) = dev->pin_spi_miso;
|
||||
|
||||
/* Put all the SSI gpios into peripheral mode */
|
||||
GPIO_PERIPHERAL_CONTROL(GPIO_PORT_TO_BASE(clk_port),
|
||||
GPIO_PIN_MASK(clk_pin));
|
||||
GPIO_PERIPHERAL_CONTROL(GPIO_PORT_TO_BASE(mosi_port),
|
||||
GPIO_PIN_MASK(mosi_pin));
|
||||
GPIO_PERIPHERAL_CONTROL(GPIO_PORT_TO_BASE(miso_port),
|
||||
GPIO_PIN_MASK(miso_pin));
|
||||
|
||||
/* Disable any pull ups or the like */
|
||||
ioc_set_over(clk_port, clk_pin, IOC_OVERRIDE_DIS);
|
||||
ioc_set_over(mosi_port, mosi_pin, IOC_OVERRIDE_DIS);
|
||||
ioc_set_over(miso_port, miso_pin, IOC_OVERRIDE_DIS);
|
||||
|
||||
/* Configure the clock */
|
||||
REG(regs->base + SSI_CPSR) = regs->ssi_cprs_cpsdvsr;
|
||||
|
||||
/* Configure the mode */
|
||||
REG(regs->base + SSI_CR0) = mode | (0x07);
|
||||
|
||||
/* Configure the SSI serial clock rate */
|
||||
if(!dev->spi_bit_rate) {
|
||||
scr = 255;
|
||||
} else {
|
||||
div = (uint64_t)regs->ssi_cprs_cpsdvsr * dev->spi_bit_rate;
|
||||
scr = (SSI_SYS_CLOCK + div - 1) / div;
|
||||
scr = MIN(MAX(scr, 1), 256) - 1;
|
||||
}
|
||||
REG(regs->base + SSI_CR0) = (REG(regs->base + SSI_CR0) & ~SSI_CR0_SCR_M) |
|
||||
scr << SSI_CR0_SCR_S;
|
||||
|
||||
/* Enable the SSI */
|
||||
REG(regs->base + SSI_CR1) |= SSI_CR1_SSE;
|
||||
|
||||
return SPI_DEV_STATUS_OK;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
spi_status_t
|
||||
spi_arch_close(spi_device_t *dev)
|
||||
{
|
||||
if(!spi_arch_has_lock(dev)) {
|
||||
return SPI_DEV_STATUS_BUS_NOT_OWNED;
|
||||
}
|
||||
|
||||
/* Disable SSI */
|
||||
REG(SYS_CTRL_RCGCSSI) &= ~(1 << dev->spi_controller);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
SPIX_CS_CLR(PIN_TO_PORT(dev->pin_spi_cs), PIN_TO_NUM(dev->pin_spi_cs));
|
||||
|
||||
return SPI_DEV_STATUS_OK;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
spi_status_t
|
||||
spi_arch_deselect(spi_device_t *dev)
|
||||
{
|
||||
SPIX_CS_SET(PIN_TO_PORT(dev->pin_spi_cs), PIN_TO_NUM(dev->pin_spi_cs));
|
||||
|
||||
return SPI_DEV_STATUS_OK;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Assumes that checking dev and bus is not NULL before calling this */
|
||||
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)
|
||||
{
|
||||
int i;
|
||||
int totlen;
|
||||
uint8_t c;
|
||||
|
||||
if(!spi_arch_has_lock(dev)) {
|
||||
return SPI_DEV_STATUS_BUS_NOT_OWNED;
|
||||
}
|
||||
|
||||
LOG_DBG("SPI: transfer (r:%d,w:%d) ", rlen, wlen);
|
||||
|
||||
if(write_buf == NULL && wlen > 0) {
|
||||
return SPI_DEV_STATUS_EINVAL;
|
||||
}
|
||||
if(inbuf == NULL && rlen > 0) {
|
||||
return SPI_DEV_STATUS_EINVAL;
|
||||
}
|
||||
|
||||
totlen = MAX(rlen + ignore_len, wlen);
|
||||
|
||||
if(totlen == 0) {
|
||||
/* Nothing to do */
|
||||
return SPI_DEV_STATUS_OK;
|
||||
}
|
||||
|
||||
LOG_DBG("%c%c%c: %u ", rlen > 0 ? 'R' : '-', wlen > 0 ? 'W' : '-',
|
||||
ignore_len > 0 ? 'S' : '-', totlen);
|
||||
|
||||
for(i = 0; i < totlen; i++) {
|
||||
spix_wait_tx_ready(dev);
|
||||
c = i < wlen ? write_buf[i] : 0;
|
||||
spix_write_buf(dev, c);
|
||||
LOG_DBG("%c%02x->", i < rlen ? ' ' : '#', c);
|
||||
spix_wait_eotx(dev);
|
||||
spix_wait_eorx(dev);
|
||||
c = spix_read_buf(dev);
|
||||
if(i < rlen) {
|
||||
inbuf[i] = c;
|
||||
}
|
||||
LOG_DBG("%02x", c);
|
||||
}
|
||||
LOG_DBG("\n");
|
||||
|
||||
return SPI_DEV_STATUS_OK;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
84
arch/cpu/cc2538/dev/spi-hal-arch.h
Normal file
84
arch/cpu/cc2538/dev/spi-hal-arch.h
Normal file
@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright (c) 2013, University of Michigan.
|
||||
*
|
||||
* Copyright (c) 2015, Weptech elektronik GmbH
|
||||
* Author: Ulf Knoblich, ulf.knoblich@weptech.de
|
||||
*
|
||||
* Copyright (c) 2018, University of Bristol.
|
||||
*
|
||||
* 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 University 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 INSTITUTE 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 INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef SPI_ARCH_H_
|
||||
#define SPI_ARCH_H_
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#define BOARD_SPI_CONTROLLERS 2
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#define BOARD_SPI_CONTROLLER_SPI0 0
|
||||
#define BOARD_SPI_CONTROLLER_SPI1 1
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Default values for the clock rate divider */
|
||||
#ifdef SPI0_CONF_CPRS_CPSDVSR
|
||||
#define SPI0_CPRS_CPSDVSR SPI0_CONF_CPRS_CPSDVSR
|
||||
#else
|
||||
#define SPI0_CPRS_CPSDVSR 2
|
||||
#endif
|
||||
|
||||
#ifdef SPI1_CONF_CPRS_CPSDVSR
|
||||
#define SPI1_CPRS_CPSDVSR SPI1_CONF_CPRS_CPSDVSR
|
||||
#else
|
||||
#define SPI1_CPRS_CPSDVSR 2
|
||||
#endif
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* New API macros */
|
||||
#define SPIX_WAITFORTxREADY(spi) do { \
|
||||
while(!(REG(SSI_BASE(spi) + SSI_SR) & SSI_SR_TNF)) ; \
|
||||
} while(0)
|
||||
#define SPIX_BUF(spi) REG(SSI_BASE(spi) + SSI_DR)
|
||||
#define SPIX_WAITFOREOTx(spi) do { \
|
||||
while(REG(SSI_BASE(spi) + SSI_SR) & SSI_SR_BSY) ; \
|
||||
} while(0)
|
||||
#define SPIX_WAITFOREORx(spi) do { \
|
||||
while(!(REG(SSI_BASE(spi) + SSI_SR) & SSI_SR_RNE)) ; \
|
||||
} while(0)
|
||||
#define SPIX_FLUSH(spi) do { \
|
||||
while(REG(SSI_BASE(spi) + SSI_SR) & SSI_SR_RNE) { \
|
||||
SPIX_BUF(spi); \
|
||||
} \
|
||||
} while(0)
|
||||
#define SPIX_CS_CLR(port, pin) do { \
|
||||
GPIO_CLR_PIN(GPIO_PORT_TO_BASE(port), GPIO_PIN_MASK(pin)); \
|
||||
} while(0)
|
||||
#define SPIX_CS_SET(port, pin) do { \
|
||||
GPIO_SET_PIN(GPIO_PORT_TO_BASE(port), GPIO_PIN_MASK(pin)); \
|
||||
} while(0)
|
||||
|
||||
#endif /* SPI_ARCH_H_ */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
Loading…
Reference in New Issue
Block a user