Merge branch 'contiki' into osd

This commit is contained in:
Harald Pichler 2015-05-19 10:54:55 +02:00
commit 6a0d407806
84 changed files with 2097 additions and 1029 deletions

View file

@ -106,6 +106,7 @@ env:
## of environment variable defined below
- BUILD_TYPE='doxygen' BUILD_CATEGORY='doxygen'
- BUILD_TYPE='compile-base' BUILD_CATEGORY='compile'
- BUILD_TYPE='compile-tools' BUILD_CATEGORY='compile'
- BUILD_TYPE='collect'
- BUILD_TYPE='collect-lossy'
- BUILD_TYPE='rpl'

View file

@ -36,6 +36,7 @@
* Matthias Kovatsch <kovatsch@inf.ethz.ch>
*/
#include "sys/cc.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

View file

@ -36,6 +36,7 @@
* Matthias Kovatsch <kovatsch@inf.ethz.ch>
*/
#include "sys/cc.h"
#include <stdio.h>
#include <string.h>
#include "er-coap-separate.h"

View file

@ -39,6 +39,7 @@
#include <string.h>
#include <stdio.h>
#include "contiki.h"
#include "sys/cc.h"
#include "contiki-net.h"
#include "er-coap.h"

View file

@ -79,10 +79,6 @@ enum { OPTION_MAP_SIZE = sizeof(uint8_t) * 8 };
#define SET_OPTION(packet, opt) ((packet)->options[opt / OPTION_MAP_SIZE] |= 1 << (opt % OPTION_MAP_SIZE))
#define IS_OPTION(packet, opt) ((packet)->options[opt / OPTION_MAP_SIZE] & (1 << (opt % OPTION_MAP_SIZE)))
#ifndef MIN
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#endif /* MIN */
/* parsed message struct */
typedef struct {
uint8_t *buffer; /* pointer to CoAP header / incoming packet buffer / memory to serialize packet */

View file

@ -57,13 +57,12 @@
#include "lib/assert.h"
#include "lib/list.h"
#include "sys/cc.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
/*---------------------------------------------------------------------------*/
#define MIN(a, b) ((a) < (b) ? (a) : (b))
/*---------------------------------------------------------------------------*/
#define DEBUG 0
#if DEBUG
#define PRINTF(...) PRINTF(__VA_ARGS__)

View file

@ -62,10 +62,6 @@
#define REST_MAX_CHUNK_SIZE 64
#endif
#ifndef MIN
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#endif /* MIN */
struct resource_s;
struct periodic_resource_s;

View file

@ -42,6 +42,7 @@
#include "sys/energest.h"
#include <stdio.h>
#include "sys/cc.h"
struct power_msg {
uint16_t len;

View file

@ -38,6 +38,7 @@
*/
#include "contiki.h"
#include "sys/cc.h"
#include "shell-sky.h"
#include "dev/watchdog.h"
@ -84,8 +85,6 @@ SHELL_COMMAND(rfchannel_command,
"rfchannel <channel>: change CC2420 radio channel (11 - 26)",
&shell_rfchannel_process);
/*---------------------------------------------------------------------------*/
#define MAX(a, b) ((a) > (b)? (a): (b))
#define MIN(a, b) ((a) < (b)? (a): (b))
struct spectrum {
int channel[16];
};

View file

@ -36,13 +36,10 @@
#include <stddef.h>
#include "contiki.h"
#include "sys/cc.h"
#include "shell.h"
#include "telnet.h"
#ifndef MIN
#define MIN(a, b) ((a) < (b)? (a) : (b))
#endif /* MIN */
/*---------------------------------------------------------------------------*/
PROCESS(shell_tcpsend_process, "tcpsend");
SHELL_COMMAND(tcpsend_command,

View file

@ -38,6 +38,7 @@
*/
#include "contiki.h"
#include "sys/cc.h"
#include "shell-time.h"
#include "sys/clock.h"
@ -51,11 +52,6 @@
#define MAX_COMMANDLENGTH 64
#define PERIOD_INTERVAL 60
#ifndef MIN
#define MIN(a, b) ((a) < (b)? (a) : (b))
#endif /* MIN */
/*---------------------------------------------------------------------------*/
PROCESS(shell_time_process, "time");
SHELL_COMMAND(time_command,

View file

@ -33,6 +33,7 @@
#include <string.h>
#include "sys/cc.h"
#include "contiki-lib.h"
#include "contiki-net.h"
#include "lib/petsciiconv.h"
@ -103,7 +104,6 @@ static uint8_t connected;
#define MAX_SILENCE_TIME (CLOCK_SECOND * 30)
#define MIN(a, b) ((a) < (b)? (a): (b))
/*---------------------------------------------------------------------------*/
static void
buf_init(struct telnetd_buf *buf)

View file

@ -57,36 +57,36 @@ extern unsigned char spi_busy;
void spi_init(void);
/* Write one character to SPI */
#define SPI_WRITE(data) \
do { \
SPI_WAITFORTx_BEFORE(); \
SPI_TXBUF = data; \
SPI_WAITFOREOTx(); \
#define SPI_WRITE(data) \
do { \
SPI_WAITFORTx_BEFORE(); \
SPI_TXBUF = data; \
SPI_WAITFOREOTx(); \
} while(0)
/* Write one character to SPI - will not wait for end
useful for multiple writes with wait after final */
#define SPI_WRITE_FAST(data) \
do { \
SPI_WAITFORTx_BEFORE(); \
SPI_TXBUF = data; \
SPI_WAITFORTx_AFTER(); \
#define SPI_WRITE_FAST(data) \
do { \
SPI_WAITFORTx_BEFORE(); \
SPI_TXBUF = data; \
SPI_WAITFORTx_AFTER(); \
} while(0)
/* Read one character from SPI */
#define SPI_READ(data) \
do { \
SPI_TXBUF = 0; \
SPI_WAITFOREORx(); \
data = SPI_RXBUF; \
#define SPI_READ(data) \
do { \
SPI_TXBUF = 0; \
SPI_WAITFOREORx(); \
data = SPI_RXBUF; \
} while(0)
/* Flush the SPI read register */
#ifndef SPI_FLUSH
#define SPI_FLUSH() \
do { \
SPI_RXBUF; \
} while(0);
do { \
SPI_RXBUF; \
} while(0)
#endif
#endif /* SPI_H_ */

View file

@ -65,10 +65,6 @@
#define SETTINGS_BOTTOM_ADDR (SETTINGS_TOP_ADDR + 1 - SETTINGS_MAX_SIZE)
#endif
#ifndef MIN
#define MIN(a,b) ((a)<(b)?a:b)
#endif
typedef struct {
#if SETTINGS_CONF_SUPPORT_LARGE_VALUES
uint8_t size_extra;

View file

@ -30,6 +30,7 @@
*/
#include "contiki.h"
#include "sys/cc.h"
#include "contiki-net.h"
#include "lib/list.h"
@ -39,7 +40,6 @@
#include <stdio.h>
#include <string.h>
#define MIN(a, b) ((a) < (b) ? (a) : (b))
static void relisten(struct tcp_socket *s);

View file

@ -78,6 +78,8 @@
#include "net/ipv4/uip-neighbor.h"
#include <string.h>
#include "sys/cc.h"
/*---------------------------------------------------------------------------*/
/* Variable definitions. */
@ -1953,7 +1955,6 @@ void
uip_send(const void *data, int len)
{
int copylen;
#define MIN(a,b) ((a) < (b)? (a): (b))
copylen = MIN(len, UIP_BUFSIZE - UIP_LLH_LEN - UIP_TCPIP_HLEN -
(int)((char *)uip_sappdata - (char *)&uip_buf[UIP_LLH_LEN + UIP_TCPIP_HLEN]));
if(copylen > 0) {

View file

@ -71,6 +71,7 @@
* the packet back to the peer.
*/
#include "sys/cc.h"
#include "net/ip/uip.h"
#include "net/ip/uipopt.h"
#include "net/ipv6/uip-icmp6.h"
@ -2332,7 +2333,6 @@ void
uip_send(const void *data, int len)
{
int copylen;
#define MIN(a,b) ((a) < (b)? (a): (b))
if(uip_sappdata != NULL) {
copylen = MIN(len, UIP_BUFSIZE - UIP_LLH_LEN - UIP_TCPIP_HLEN -

View file

@ -229,10 +229,6 @@ static struct compower_activity current_packet;
#define DEFAULT_STREAM_TIME (4 * CYCLE_TIME)
#ifndef MIN
#define MIN(a, b) ((a) < (b)? (a) : (b))
#endif /* MIN */
#if CONTIKIMAC_CONF_BROADCAST_RATE_LIMIT
static struct timer broadcast_rate_timer;
static int broadcast_rate_counter;

View file

@ -52,6 +52,7 @@
#include "sys/rtimer.h"
#include "contiki-conf.h"
#include "sys/cc.h"
#ifdef EXPERIMENT_SETUP
#include "experiment-setup.h"
@ -215,10 +216,6 @@ static linkaddr_t is_streaming_to, is_streaming_to_too;
static rtimer_clock_t stream_until;
#define DEFAULT_STREAM_TIME (RTIMER_ARCH_SECOND)
#ifndef MIN
#define MIN(a, b) ((a) < (b)? (a) : (b))
#endif /* MIN */
/*---------------------------------------------------------------------------*/
static void
on(void)

View file

@ -92,8 +92,6 @@ static struct broadcast_announcement_state {
#define PRINTF(...)
#endif
#define MIN(a, b) ((a)<(b)?(a):(b))
/*---------------------------------------------------------------------------*/
static void
send_adv(void *ptr)

View file

@ -42,20 +42,13 @@
* @{
*/
#include "sys/cc.h"
#include "net/rime/rime.h"
#include "net/rime/ipolite.h"
#include "lib/random.h"
#include <string.h>
#ifndef MAX
#define MAX(a, b) ((a) > (b)? (a) : (b))
#endif /* MAX */
#ifndef MIN
#define MIN(a, b) ((a) < (b)? (a) : (b))
#endif /* MIN */
#define DEBUG 0
#if DEBUG
#include <stdio.h>

View file

@ -43,7 +43,7 @@
*/
#include "contiki.h"
#include "sys/cc.h"
#include "lib/list.h"
#include "net/rime/rime.h"
#include "net/rime/announcement.h"
@ -90,8 +90,6 @@ static struct polite_announcement_state {
#define PRINTF(...)
#endif
#define MIN(a, b) ((a)<(b)?(a):(b))
/*---------------------------------------------------------------------------*/
static void
send_adv(clock_time_t interval)

View file

@ -42,21 +42,13 @@
* @{
*/
#include "sys/cc.h"
#include "net/rime/rime.h"
#include "net/rime/polite.h"
#include "lib/random.h"
#include <string.h>
#ifndef MAX
#define MAX(a,b) ((a) > (b)? (a) : (b))
#endif /* MAX */
#ifndef MIN
#define MIN(a, b) ((a) < (b)? (a) : (b))
#endif /* MIN */
/*---------------------------------------------------------------------------*/
static void
recv(struct abc_conn *abc)

View file

@ -127,14 +127,33 @@
#define NULL 0
#endif /* NULL */
#ifndef MAX
#define MAX(n, m) (((n) < (m)) ? (m) : (n))
#endif
#ifndef MIN
#define MIN(n, m) (((n) < (m)) ? (n) : (m))
#endif
#ifndef ABS
#define ABS(n) (((n) < 0) ? -(n) : (n))
#endif
#define CC_CONCAT2(s1, s2) s1##s2
/**
* A C preprocessing macro for concatenating to
* strings.
* A C preprocessing macro for concatenating two preprocessor tokens.
*
* We need use two macros (CC_CONCAT and CC_CONCAT2) in order to allow
* concatenation of two \#defined macros.
*/
#define CC_CONCAT(s1, s2) CC_CONCAT2(s1, s2)
#define CC_CONCAT_EXT_2(s1, s2) CC_CONCAT2(s1, s2)
/**
* A C preprocessing macro for concatenating three preprocessor tokens.
*/
#define CC_CONCAT3(s1, s2, s3) s1##s2##s3
#define CC_CONCAT_EXT_3(s1, s2, s3) CC_CONCAT3(s1, s2, s3)
#endif /* CC_H_ */

View file

@ -280,9 +280,6 @@ typedef char r_uart_ptchar;
#define OUT_X(addrx,value) (*addrx = value)
#define IN_X(addrx) (*addrx)
# define Max(a, b) ( (a)>(b) ? (a) : (b) ) // Take the max between a and b
# define Min(a, b) ( (a)<(b) ? (a) : (b) ) // Take the min between a and b
// Align on the upper value <val> on a <n> boundary
// i.e. Upper(0, 4)= 4
// Upper(1, 4)= 4

View file

@ -1,5 +1,9 @@
/*
* Copyright (c) 2013, University of Michigan.
*
* Copyright (c) 2015, Weptech elektronik GmbH
* Author: Ulf Knoblich, ulf.knoblich@weptech.de
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -41,102 +45,281 @@
#include "dev/spi.h"
#include "dev/ssi.h"
#include "dev/gpio.h"
/*---------------------------------------------------------------------------*/
/* Check port / pin settings for SPI0 and provide default values for spi_cfg */
#ifndef SPI0_CLK_PORT
#define SPI0_CLK_PORT (-1)
#endif
#ifndef SPI0_CLK_PIN
#define SPI0_CLK_PIN (-1)
#endif
#if SPI0_CLK_PORT >= 0 && SPI0_CLK_PIN < 0 || \
SPI0_CLK_PORT < 0 && SPI0_CLK_PIN >= 0
#error Both SPI0_CLK_PORT and SPI0_CLK_PIN must be valid or invalid
#endif
#define SPI_CLK_PORT_BASE GPIO_PORT_TO_BASE(SPI_CLK_PORT)
#define SPI_CLK_PIN_MASK GPIO_PIN_MASK(SPI_CLK_PIN)
#define SPI_MOSI_PORT_BASE GPIO_PORT_TO_BASE(SPI_MOSI_PORT)
#define SPI_MOSI_PIN_MASK GPIO_PIN_MASK(SPI_MOSI_PIN)
#define SPI_MISO_PORT_BASE GPIO_PORT_TO_BASE(SPI_MISO_PORT)
#define SPI_MISO_PIN_MASK GPIO_PIN_MASK(SPI_MISO_PIN)
#ifndef SPI0_TX_PORT
#define SPI0_TX_PORT (-1)
#endif
#ifndef SPI0_TX_PIN
#define SPI0_TX_PIN (-1)
#endif
#if SPI0_TX_PORT >= 0 && SPI0_TX_PIN < 0 || \
SPI0_TX_PORT < 0 && SPI0_TX_PIN >= 0
#error Both SPI0_TX_PORT and SPI0_TX_PIN must be valid or invalid
#endif
/**
* \brief Initialize the SPI bus.
*
* This SPI init() function uses the following defines to set the pins:
* SPI_CLK_PORT SPI_CLK_PIN
* SPI_MOSI_PORT SPI_MOSI_PIN
* SPI_MISO_PORT SPI_MISO_PIN
*
* This sets the mode to Motorola SPI with the following format options:
* Clock phase: 1; data captured on second (rising) edge
* Clock polarity: 1; clock is high when idle
* Data size: 8 bits
*/
#ifndef SPI0_RX_PORT
#define SPI0_RX_PORT (-1)
#endif
#ifndef SPI0_RX_PIN
#define SPI0_RX_PIN (-1)
#endif
#if SPI0_RX_PORT >= 0 && SPI0_RX_PIN < 0 || \
SPI0_RX_PORT < 0 && SPI0_RX_PIN >= 0
#error Both SPI0_RX_PORT and SPI0_RX_PIN must be valid or invalid
#endif
/* Here we check that either all or none of the ports are defined. As
we did already check that both ports + pins are either defined or
not for every pin, this means that we can check for an incomplete
configuration by only looking at the port defines */
/* If some SPI0 pads are valid */
#if SPI0_CLK_PORT >= 0 || SPI0_TX_PORT >= 0 || SPI0_RX_PORT >= 0
/* but not all */
#if SPI0_CLK_PORT < 0 || SPI0_TX_PORT < 0 || SPI0_RX_PORT < 0
#error Some SPI0 pad definitions are invalid
#endif
#define SPI0_PADS_VALID
#endif
/*---------------------------------------------------------------------------*/
/* Check port / pin settings for SPI1 and provide default values for spi_cfg */
#ifndef SPI1_CLK_PORT
#define SPI1_CLK_PORT (-1)
#endif
#ifndef SPI1_CLK_PIN
#define SPI1_CLK_PIN (-1)
#endif
#if SPI1_CLK_PORT >= 0 && SPI1_CLK_PIN < 0 || \
SPI1_CLK_PORT < 0 && SPI1_CLK_PIN >= 0
#error Both SPI1_CLK_PORT and SPI1_CLK_PIN must be valid or invalid
#endif
#ifndef SPI1_TX_PORT
#define SPI1_TX_PORT (-1)
#endif
#ifndef SPI1_TX_PIN
#define SPI1_TX_PIN (-1)
#endif
#if SPI1_TX_PORT >= 0 && SPI1_TX_PIN < 0 || \
SPI1_TX_PORT < 0 && SPI1_TX_PIN >= 0
#error Both SPI1_TX_PORT and SPI1_TX_PIN must be valid or invalid
#endif
#ifndef SPI1_RX_PORT
#define SPI1_RX_PORT (-1)
#endif
#ifndef SPI1_RX_PIN
#define SPI1_RX_PIN (-1)
#endif
#if SPI1_RX_PORT >= 0 && SPI1_RX_PIN < 0 || \
SPI1_RX_PORT < 0 && SPI1_RX_PIN >= 0
#error Both SPI1_RX_PORT and SPI1_RX_PIN must be valid or invalid
#endif
/* If some SPI1 pads are valid */
#if SPI1_CLK_PORT >= 0 || SPI1_TX_PORT >= 0 || SPI1_RX_PORT >= 0
/* but not all */
#if SPI1_CLK_PORT < 0 || SPI1_TX_PORT < 0 || SPI1_RX_PORT < 0
#error Some SPI1 pad definitions are invalid
#endif
#define SPI1_PADS_VALID
#endif
#ifdef SPI_DEFAULT_INSTANCE
#if SPI_DEFAULT_INSTANCE == 0
#ifndef SPI0_PADS_VALID
#error SPI_DEFAULT_INSTANCE is set to SPI0, but its pads are not valid
#endif
#elif SPI_DEFAULT_INSTANCE == 1
#ifndef SPI1_PADS_VALID
#error SPI_DEFAULT_INSTANCE is set to SPI1, but its pads are not valid
#endif
#endif
#endif
#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
/*---------------------------------------------------------------------------*/
typedef struct {
int8_t port;
int8_t pin;
} spi_pad_t;
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_pad_t clk;
spi_pad_t tx;
spi_pad_t rx;
} 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,
.clk = { SPI0_CLK_PORT, SPI0_CLK_PIN },
.tx = { SPI0_TX_PORT, SPI0_TX_PIN },
.rx = { SPI0_RX_PORT, SPI0_RX_PIN }
}, {
.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,
.clk = { SPI1_CLK_PORT, SPI1_CLK_PIN },
.tx = { SPI1_TX_PORT, SPI1_TX_PIN },
.rx = { SPI1_RX_PORT, SPI1_RX_PIN }
}
};
/*---------------------------------------------------------------------------*/
/* Deprecated function call provided for compatibility reasons */
#ifdef SPI_DEFAULT_INSTANCE
void
spi_init(void)
{
spi_enable();
spix_init(SPI_DEFAULT_INSTANCE);
}
#endif /* #ifdef SPI_DEFAULT_INSTANCE */
/*---------------------------------------------------------------------------*/
void
spix_init(uint8_t spi)
{
const spi_regs_t *regs;
if(spi >= SSI_INSTANCE_COUNT) {
return;
}
regs = &spi_regs[spi];
if(regs->clk.port < 0) {
/* Port / pin configuration invalid. We checked for completeness
above. If clk.port is < 0, this means that all other defines are
< 0 as well */
return;
}
spix_enable(spi);
/* Start by disabling the peripheral before configuring it */
REG(SSI0_BASE + SSI_CR1) = 0;
REG(regs->base + SSI_CR1) = 0;
/* Set the IO clock as the SSI clock */
REG(SSI0_BASE + SSI_CC) = 1;
REG(regs->base + SSI_CC) = 1;
/* Set the mux correctly to connect the SSI pins to the correct GPIO pins */
ioc_set_sel(SPI_CLK_PORT, SPI_CLK_PIN, IOC_PXX_SEL_SSI0_CLKOUT);
ioc_set_sel(SPI_MOSI_PORT, SPI_MOSI_PIN, IOC_PXX_SEL_SSI0_TXD);
REG(IOC_SSIRXD_SSI0) = (SPI_MISO_PORT * 8) + SPI_MISO_PIN;
ioc_set_sel(regs->clk.port,
regs->clk.pin,
regs->ioc_pxx_sel_ssi_clkout);
ioc_set_sel(regs->tx.port,
regs->tx.pin,
regs->ioc_pxx_sel_ssi_txd);
REG(regs->ioc_ssirxd_ssi) = (regs->rx.port * 8) + regs->rx.pin;
/* Put all the SSI gpios into peripheral mode */
GPIO_PERIPHERAL_CONTROL(SPI_CLK_PORT_BASE, SPI_CLK_PIN_MASK);
GPIO_PERIPHERAL_CONTROL(SPI_MOSI_PORT_BASE, SPI_MOSI_PIN_MASK);
GPIO_PERIPHERAL_CONTROL(SPI_MISO_PORT_BASE, SPI_MISO_PIN_MASK);
GPIO_PERIPHERAL_CONTROL(GPIO_PORT_TO_BASE(regs->clk.port),
GPIO_PIN_MASK(regs->clk.pin));
GPIO_PERIPHERAL_CONTROL(GPIO_PORT_TO_BASE(regs->tx.port),
GPIO_PIN_MASK(regs->tx.pin));
GPIO_PERIPHERAL_CONTROL(GPIO_PORT_TO_BASE(regs->rx.port),
GPIO_PIN_MASK(regs->rx.pin));
/* Disable any pull ups or the like */
ioc_set_over(SPI_CLK_PORT, SPI_CLK_PIN, IOC_OVERRIDE_DIS);
ioc_set_over(SPI_MOSI_PORT, SPI_MOSI_PIN, IOC_OVERRIDE_DIS);
ioc_set_over(SPI_MISO_PORT, SPI_MISO_PIN, IOC_OVERRIDE_DIS);
ioc_set_over(regs->clk.port, regs->clk.pin, IOC_OVERRIDE_DIS);
ioc_set_over(regs->tx.port, regs->tx.pin, IOC_OVERRIDE_DIS);
ioc_set_over(regs->rx.port, regs->rx.pin, IOC_OVERRIDE_DIS);
/* Configure the clock */
REG(SSI0_BASE + SSI_CPSR) = 2;
REG(regs->base + SSI_CPSR) = regs->ssi_cprs_cpsdvsr;
/* Configure the default SPI options.
/*
* Configure the default SPI options.
* mode: Motorola frame format
* clock: High when idle
* data: Valid on rising edges of the clock
* bits: 8 byte data
*/
REG(SSI0_BASE + SSI_CR0) = SSI_CR0_SPH | SSI_CR0_SPO | (0x07);
REG(regs->base + SSI_CR0) = SSI_CR0_SPH | SSI_CR0_SPO | (0x07);
/* Enable the SSI */
REG(SSI0_BASE + SSI_CR1) |= SSI_CR1_SSE;
REG(regs->base + SSI_CR1) |= SSI_CR1_SSE;
}
/*---------------------------------------------------------------------------*/
void
spi_cs_init(uint8_t port, uint8_t pin)
spix_enable(uint8_t spi)
{
GPIO_SOFTWARE_CONTROL(GPIO_PORT_TO_BASE(port), GPIO_PIN_MASK(pin));
if(spi >= SSI_INSTANCE_COUNT) {
return;
}
REG(SYS_CTRL_RCGCSSI) |= (1 << spi);
}
/*---------------------------------------------------------------------------*/
void
spix_disable(uint8_t spi)
{
if(spi >= SSI_INSTANCE_COUNT) {
return;
}
REG(SYS_CTRL_RCGCSSI) &= ~(1 << spi);
}
/*---------------------------------------------------------------------------*/
void
spix_set_mode(uint8_t spi,
uint32_t frame_format,
uint32_t clock_polarity,
uint32_t clock_phase,
uint32_t data_size)
{
const spi_regs_t *regs;
if(spi >= SSI_INSTANCE_COUNT) {
return;
}
regs = &spi_regs[spi];
/* Disable the SSI peripheral to configure it */
REG(regs->base + SSI_CR1) = 0;
/* Configure the SSI options */
REG(regs->base + SSI_CR0) = clock_phase |
clock_polarity |
frame_format |
(data_size - 1);
/* Re-enable the SSI */
REG(regs->base + SSI_CR1) |= SSI_CR1_SSE;
}
/*---------------------------------------------------------------------------*/
void
spix_cs_init(uint8_t port, uint8_t pin)
{
GPIO_SOFTWARE_CONTROL(GPIO_PORT_TO_BASE(port),
GPIO_PIN_MASK(pin));
ioc_set_over(port, pin, IOC_OVERRIDE_DIS);
GPIO_SET_OUTPUT(GPIO_PORT_TO_BASE(port), GPIO_PIN_MASK(pin));
GPIO_SET_PIN(GPIO_PORT_TO_BASE(port), GPIO_PIN_MASK(pin));
}
/*---------------------------------------------------------------------------*/
void
spi_enable(void)
{
/* Enable the clock for the SSI peripheral */
REG(SYS_CTRL_RCGCSSI) |= 1;
}
/*---------------------------------------------------------------------------*/
void
spi_disable(void)
{
/* Gate the clock for the SSI peripheral */
REG(SYS_CTRL_RCGCSSI) &= ~1;
}
/*---------------------------------------------------------------------------*/
void
spi_set_mode(uint32_t frame_format, uint32_t clock_polarity,
uint32_t clock_phase, uint32_t data_size)
{
/* Disable the SSI peripheral to configure it */
REG(SSI0_BASE + SSI_CR1) = 0;
/* Configure the SSI options */
REG(SSI0_BASE + SSI_CR0) = clock_phase | clock_polarity | frame_format | (data_size - 1);
/* Re-enable the SSI */
REG(SSI0_BASE + SSI_CR1) |= SSI_CR1_SSE;
}
/** @} */

View file

@ -45,6 +45,12 @@
#ifndef SSI_H_
#define SSI_H_
/*---------------------------------------------------------------------------*/
/** \name Number of SSI instances supported by this CPU.
* @{
*/
#define SSI_INSTANCE_COUNT 2
/** @} */
/*---------------------------------------------------------------------------*/
/** \name Base register memory locations.
* @{

View file

@ -1,5 +1,9 @@
/*
* Copyright (c) 2013, University of Michigan.
*
* Copyright (c) 2015, Weptech elektronik GmbH
* Author: Ulf Knoblich, ulf.knoblich@weptech.de
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -34,66 +38,144 @@
* Header file for the cc2538 SPI driver, including macros for the
* implementation of the low-level SPI primitives such as waiting for the TX
* FIFO to be ready, inserting into the TX FIFO, etc.
*
* It supports the usage of SSI_NUM_INSTANCES instances by providing new
* functions calls like
*
* - spix_init(uint8_t instance)
* - spix_enable(uint8_t instance)
* - spix_disable(uint8_t instance)
* - spix_set_mode(unit8_t instance, ...)
*
* and new macros like
*
* - SPIX_WAITFORTxREADY(x)
* - SPIX_WAITFOREOTx(x)
* - SPIX_WAITFOREORx(x)
* - SPIX_FLUSH(x)
*
* Some of the old functions and macros are still supported.
* When using these deprecated functions, the SSI module to use
* has to be be selected by means of the macro SPI_CONF_DEFAULT_INSTANCE.
*
* This SPI driver depends on the following defines:
*
* For the SSI0 module:
*
* - SPI0_CKL_PORT
* - SPI0_CLK_PIN
* - SPI0_TX_PORT
* - SPI0_TX_PIN
* - SPI0_RX_PORT
* - SPI0_RX_PIN
*
* For the SSI1 module:
*
* - SPI1_CKL_PORT
* - SPI1_CLK_PIN
* - SPI1_TX_PORT
* - SPI1_TX_PIN
* - SPI1_RX_PORT
* - SPI1_RX_PIN
*/
#ifndef SPI_ARCH_H_
#define SPI_ARCH_H_
#include "contiki.h"
#include "dev/ssi.h"
#define SPI_WAITFORTxREADY() do { \
while(!(REG(SSI0_BASE + SSI_SR) & SSI_SR_TNF)); \
} while(0)
#define SPI_TXBUF REG(SSI0_BASE + SSI_DR)
#define SPI_RXBUF REG(SSI0_BASE + SSI_DR)
#define SPI_WAITFOREOTx() do { \
while(REG(SSI0_BASE + SSI_SR) & SSI_SR_BSY); \
} while(0)
#define SPI_WAITFOREORx() do { \
while(!(REG(SSI0_BASE + SSI_SR) & SSI_SR_RNE)); \
} while(0)
#ifdef SPI_FLUSH
#error "You must include spi-arch.h before spi.h for the CC2538."
/*---------------------------------------------------------------------------*/
/* The SPI instance to use when using the deprecated SPI API. */
#ifdef SPI_CONF_DEFAULT_INSTANCE
#if SPI_CONF_DEFAULT_INSTANCE > (SSI_INSTANCE_COUNT - 1)
#error Invalid SPI_CONF_DEFAULT_INSTANCE: valid values are 0 and 1
#else
#define SPI_DEFAULT_INSTANCE SPI_CONF_DEFAULT_INSTANCE
#endif
#endif
/*---------------------------------------------------------------------------*/
/* 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
#define SPI_FLUSH() do { \
SPI_WAITFOREORx(); \
while (REG(SSI0_BASE + SSI_SR) & SSI_SR_RNE) { \
SPI_RXBUF; \
} \
} while(0)
#define SPI_CS_CLR(port, pin) do { \
GPIO_CLR_PIN(GPIO_PORT_TO_BASE(port), GPIO_PIN_MASK(pin)); \
#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(CC_CONCAT3(SSI, spi, _BASE) + SSI_SR) & SSI_SR_TNF)) ; \
} while(0)
#define SPI_CS_SET(port, pin) do { \
GPIO_SET_PIN(GPIO_PORT_TO_BASE(port), GPIO_PIN_MASK(pin)); \
#define SPIX_BUF(spi) REG(CC_CONCAT3(SSI, spi, _BASE) + SSI_DR)
#define SPIX_WAITFOREOTx(spi) do { \
while(REG(CC_CONCAT3(SSI, spi, _BASE) + SSI_SR) & SSI_SR_BSY) ; \
} while(0)
#define SPIX_WAITFOREORx(spi) do { \
while(!(REG(CC_CONCAT3(SSI, spi, _BASE) + SSI_SR) & SSI_SR_RNE)) ; \
} while(0)
#define SPIX_FLUSH(spi) do { \
while(REG(CC_CONCAT3(SSI, spi, _BASE) + 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)
/*---------------------------------------------------------------------------*/
/* Deprecated macros provided for compatibility reasons */
#ifdef SPI_DEFAULT_INSTANCE
#define SPI_WAITFORTxREADY() SPIX_WAITFORTxREADY(SPI_DEFAULT_INSTANCE)
#define SPI_TXBUF SPIX_BUF(SPI_DEFAULT_INSTANCE)
#define SPI_RXBUF SPI_TXBUF
#define SPI_WAITFOREOTx() SPIX_WAITFOREOTx(SPI_DEFAULT_INSTANCE)
#define SPI_WAITFOREORx() SPIX_WAITFOREORx(SPI_DEFAULT_INSTANCE)
#ifdef SPI_FLUSH
#error You must include spi-arch.h before spi.h for the CC2538
#else
#define SPI_FLUSH() SPIX_FLUSH(SPI_DEFAULT_INSTANCE)
#endif
#define SPI_CS_CLR(port, pin) SPIX_CS_CLR(port, pin)
#define SPI_CS_SET(port, pin) SPIX_CS_SET(port, pin)
#endif /* #ifdef SPI_DEFAULT_INSTANCE */
/*---------------------------------------------------------------------------*/
/** \name Arch-specific SPI functions
* @{
*/
/**
* \brief Configure a GPIO to be the chip select pin
* \brief Initialize the SPI bus for the instance given
*
* This sets the mode to Motorola SPI with the following format options:
* Clock phase: 1; data captured on second (rising) edge
* Clock polarity: 1; clock is high when idle
* Data size: 8 bits
*
* Use spix_set_mode() to change the spi mode.
*/
void spi_cs_init(uint8_t port, uint8_t pin);
/** \brief Enables the SPI peripheral
*/
void spi_enable(void);
/** \brief Disables the SPI peripheral
* \note Call this function to save power when the SPI is unused.
*/
void spi_disable(void);
void spix_init(uint8_t spi);
/**
* \brief Configure the SPI data and clock polarity and the data size.
* \brief Enables the SPI peripheral for the instance given
*/
void spix_enable(uint8_t spi);
/**
* \brief Disables the SPI peripheral for the instance given
* \note Call this function to save power when the SPI is unused.
*/
void spix_disable(uint8_t spi);
/**
* \brief Configure the SPI data and clock polarity and the data size for the
* instance given
*
* This function configures the SSI peripheral to use a particular SPI
* configuration that a slave device requires. It should always be called
@ -101,6 +183,7 @@ void spi_disable(void);
*
* See section 19.4.4 in the CC2538 user guide for more information.
*
* \param spi The SSI instance to use.
* \param frame_format Set the SSI frame format. Use SSI_CR0_FRF_MOTOROLA,
* SSI_CR0_FRF_TI, or SSI_CR0_FRF_MICROWIRE.
* \param clock_polarity In Motorola mode, set whether the clock is high or low
@ -110,8 +193,17 @@ void spi_disable(void);
* \param data_size The number of bits in each "byte" of data. Must be
* between 4 and 16, inclusive.
*/
void spi_set_mode(uint32_t frame_format, uint32_t clock_polarity,
uint32_t clock_phase, uint32_t data_size);
void spix_set_mode(uint8_t spi, uint32_t frame_format,
uint32_t clock_polarity, uint32_t clock_phase,
uint32_t data_size);
/**
* \brief Configure a GPIO to be the chip select pin.
*
* Even if this function does not depend on the SPI instance used, we rename
* it to reflect the new naming convention.
*/
void spix_cs_init(uint8_t port, uint8_t pin);
/** @} */

View file

@ -81,7 +81,7 @@ CONTIKI_CPU_SOURCEFILES += clock.c rtimer-arch.c cc26xx-rtc.c uart.c
CONTIKI_CPU_SOURCEFILES += cc26xx-rf.c contiki-watchdog.c
CONTIKI_CPU_SOURCEFILES += putchar.c ieee-addr.c batmon-sensor.c
CONTIKI_CPU_SOURCEFILES += slip-arch.c slip.c cc26xx-uart.c lpm.c
CONTIKI_CPU_SOURCEFILES += gpio-interrupt.c
CONTIKI_CPU_SOURCEFILES += gpio-interrupt.c oscillators.c
DEBUG_IO_SOURCEFILES += dbg-printf.c dbg-snprintf.c dbg-sprintf.c strformat.c

View file

@ -79,8 +79,14 @@ clock_init(void)
* Here, we configure GPT0 Timer A, which we subsequently use in
* clock_delay_usec
*
* First, enable GPT0 in run mode. We don't need it in sleep mode
* We need to access registers, so firstly power up the PD and then enable
* the clock to GPT0.
*/
if(ti_lib_prcm_power_domain_status(PRCM_DOMAIN_PERIPH) !=
PRCM_DOMAIN_POWER_ON) {
power_domain_on();
}
ti_lib_prcm_peripheral_run_enable(PRCM_PERIPH_TIMER0);
ti_lib_prcm_load_set();
while(!ti_lib_prcm_load_get());
@ -155,11 +161,19 @@ clock_wait(clock_time_t i)
void
clock_delay_usec(uint16_t len)
{
uint32_t clock_status;
if(ti_lib_prcm_power_domain_status(PRCM_DOMAIN_PERIPH) !=
PRCM_DOMAIN_POWER_ON) {
power_domain_on();
}
clock_status = HWREG(PRCM_BASE + PRCM_O_GPTCLKGR) & PRCM_GPIOCLKGR_CLK_EN;
ti_lib_prcm_peripheral_run_enable(PRCM_PERIPH_TIMER0);
ti_lib_prcm_load_set();
while(!ti_lib_prcm_load_get());
ti_lib_timer_load_set(GPT0_BASE, TIMER_B, len);
ti_lib_timer_enable(GPT0_BASE, TIMER_B);
@ -168,6 +182,12 @@ clock_delay_usec(uint16_t len)
* function, hence the direct register access here
*/
while(HWREG(GPT0_BASE + GPT_O_CTL) & GPT_CTL_TBEN);
if(clock_status == 0) {
ti_lib_prcm_peripheral_run_disable(PRCM_PERIPH_TIMER0);
ti_lib_prcm_load_set();
while(!ti_lib_prcm_load_get());
}
}
/*---------------------------------------------------------------------------*/
/**

View file

@ -39,6 +39,7 @@
#include "contiki.h"
#include "dev/radio.h"
#include "dev/cc26xx-rf.h"
#include "dev/oscillators.h"
#include "net/packetbuf.h"
#include "net/rime/rimestats.h"
#include "net/linkaddr.h"
@ -46,6 +47,7 @@
#include "sys/energest.h"
#include "sys/clock.h"
#include "sys/rtimer.h"
#include "sys/cc.h"
#include "lpm.h"
#include "ti-lib.h"
/*---------------------------------------------------------------------------*/
@ -68,6 +70,7 @@
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include <stdbool.h>
/*---------------------------------------------------------------------------*/
#define BUSYWAIT_UNTIL(cond, max_time) \
do { \
@ -76,10 +79,6 @@
while(!(cond) && RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + (max_time))); \
} while(0)
/*---------------------------------------------------------------------------*/
#ifndef MIN
#define MIN(n, m) (((n) < (m)) ? (n) : (m))
#endif
/*---------------------------------------------------------------------------*/
#ifdef __GNUC__
#define CC_ALIGN_ATTR(n) __attribute__ ((aligned(n)))
#else
@ -393,74 +392,6 @@ static int on(void);
static int off(void);
static void setup_interrupts(void);
/*---------------------------------------------------------------------------*/
/* Select the HF XOSC as the source for the HF clock, but don't switch yet */
static void
request_hf_xosc(void)
{
/* Enable OSC DIG interface to change clock sources */
ti_lib_osc_interface_enable();
/* Make sure the SMPH clock within AUX is enabled */
ti_lib_aux_wuc_clock_enable(AUX_WUC_SMPH_CLOCK);
while(ti_lib_aux_wuc_clock_status(AUX_WUC_SMPH_CLOCK) != AUX_WUC_CLOCK_READY);
if(ti_lib_osc_clock_source_get(OSC_SRC_CLK_HF) != OSC_XOSC_HF) {
/*
* Request to switch to the crystal to enable radio operation. It takes a
* while for the XTAL to be ready so instead of performing the actual
* switch, we return and we do other stuff while the XOSC is getting ready.
*/
ti_lib_osc_clock_source_set(OSC_SRC_CLK_MF | OSC_SRC_CLK_HF, OSC_XOSC_HF);
}
/* Disable OSC DIG interface */
ti_lib_osc_interface_disable();
}
/*---------------------------------------------------------------------------*/
/*
* Switch to the XOSC. This will block until the XOSC is ready, so this must
* be preceded by a call to select_hf_xosc()
*/
static void
switch_to_hf_xosc(void)
{
/* Enable OSC DIG interface to change clock sources */
ti_lib_osc_interface_enable();
/* Make sure the SMPH clock within AUX is enabled */
ti_lib_aux_wuc_clock_enable(AUX_WUC_SMPH_CLOCK);
while(ti_lib_aux_wuc_clock_status(AUX_WUC_SMPH_CLOCK) != AUX_WUC_CLOCK_READY);
if(ti_lib_osc_clock_source_get(OSC_SRC_CLK_HF) != OSC_XOSC_HF) {
/* Switch the HF clock source (cc26xxware executes this from ROM) */
ti_lib_osc_hf_source_switch();
}
/* Disable OSC DIG interface */
ti_lib_osc_interface_disable();
}
/*---------------------------------------------------------------------------*/
static void
switch_to_hf_rc_osc(void)
{
/* Enable OSC DIG interface to change clock sources */
ti_lib_osc_interface_enable();
/* Make sure the SMPH clock within AUX is enabled */
ti_lib_aux_wuc_clock_enable(AUX_WUC_SMPH_CLOCK);
while(ti_lib_aux_wuc_clock_status(AUX_WUC_SMPH_CLOCK) != AUX_WUC_CLOCK_READY);
/* Set all clock sources to the HF RC Osc */
ti_lib_osc_clock_source_set(OSC_SRC_CLK_MF | OSC_SRC_CLK_HF, OSC_RCOSC_HF);
/* Check to not enable HF RC oscillator if already enabled */
if(ti_lib_osc_clock_source_get(OSC_SRC_CLK_HF) != OSC_RCOSC_HF) {
/* Switch the HF clock source (cc26xxware executes this from ROM) */
ti_lib_osc_hf_source_switch();
}
ti_lib_osc_interface_disable();
}
/*---------------------------------------------------------------------------*/
static uint8_t
rf_is_accessible(void)
{
@ -498,16 +429,19 @@ static uint_fast8_t
rf_send_cmd(uint32_t cmd, uint32_t *status)
{
uint32_t timeout_count = 0;
bool interrupts_disabled;
/*
* Make sure ContikiMAC doesn't turn us off from within an interrupt while
* we are accessing RF Core registers
*/
ti_lib_int_master_disable();
interrupts_disabled = ti_lib_int_master_disable();
if(!rf_is_accessible()) {
PRINTF("rf_send_cmd: RF was off\n");
ti_lib_int_master_enable();
if(!interrupts_disabled) {
ti_lib_int_master_enable();
}
return RF_CMD_ERROR;
}
@ -516,12 +450,16 @@ rf_send_cmd(uint32_t cmd, uint32_t *status)
*status = HWREG(RFC_DBELL_BASE + RFC_DBELL_O_CMDSTA);
if(++timeout_count > 50000) {
PRINTF("rf_send_cmd: Timeout\n");
ti_lib_int_master_enable();
if(!interrupts_disabled) {
ti_lib_int_master_enable();
}
return RF_CMD_ERROR;
}
} while(*status == RF_CMD_STATUS_PENDING);
ti_lib_int_master_enable();
if(!interrupts_disabled) {
ti_lib_int_master_enable();
}
/*
* If we reach here the command is no longer pending. It is either completed
@ -978,8 +916,8 @@ static int
power_up(void)
{
uint32_t cmd_status;
bool interrupts_disabled = ti_lib_int_master_disable();
ti_lib_int_master_disable();
ti_lib_int_pend_clear(INT_RF_CPE0);
ti_lib_int_pend_clear(INT_RF_CPE1);
ti_lib_int_disable(INT_RF_CPE0);
@ -1002,7 +940,10 @@ power_up(void)
HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIEN) = 0x0;
ti_lib_int_enable(INT_RF_CPE0);
ti_lib_int_enable(INT_RF_CPE1);
ti_lib_int_master_enable();
if(!interrupts_disabled) {
ti_lib_int_master_enable();
}
/* Let CPE boot */
HWREG(RFC_PWR_NONBUF_BASE + RFC_PWR_O_PWMCLKEN) = RF_CORE_CLOCKS_MASK;
@ -1022,7 +963,7 @@ power_up(void)
static void
power_down(void)
{
ti_lib_int_master_disable();
bool interrupts_disabled = ti_lib_int_master_disable();
ti_lib_int_disable(INT_RF_CPE0);
ti_lib_int_disable(INT_RF_CPE1);
@ -1045,7 +986,9 @@ power_down(void)
ti_lib_int_pend_clear(INT_RF_CPE1);
ti_lib_int_enable(INT_RF_CPE0);
ti_lib_int_enable(INT_RF_CPE1);
ti_lib_int_master_enable();
if(!interrupts_disabled) {
ti_lib_int_master_enable();
}
}
/*---------------------------------------------------------------------------*/
static int
@ -1160,6 +1103,8 @@ cc26xx_rf_cpe0_isr(void)
static void
setup_interrupts(void)
{
bool interrupts_disabled;
/* We are already turned on by the caller, so this should not happen */
if(!rf_is_accessible()) {
PRINTF("setup_interrupts: No access\n");
@ -1167,7 +1112,7 @@ setup_interrupts(void)
}
/* Disable interrupts */
ti_lib_int_master_disable();
interrupts_disabled = ti_lib_int_master_disable();
/* Set all interrupt channels to CPE0 channel, error to CPE1 */
HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEISL) = ERROR_IRQ;
@ -1182,7 +1127,10 @@ setup_interrupts(void)
ti_lib_int_pend_clear(INT_RF_CPE1);
ti_lib_int_enable(INT_RF_CPE0);
ti_lib_int_enable(INT_RF_CPE1);
ti_lib_int_master_enable();
if(!interrupts_disabled) {
ti_lib_int_master_enable();
}
}
/*---------------------------------------------------------------------------*/
static uint8_t
@ -1199,7 +1147,7 @@ request(void)
return LPM_MODE_MAX_SUPPORTED;
}
/*---------------------------------------------------------------------------*/
LPM_MODULE(cc26xx_rf_lpm_module, request, NULL, NULL);
LPM_MODULE(cc26xx_rf_lpm_module, request, NULL, NULL, LPM_DOMAIN_NONE);
/*---------------------------------------------------------------------------*/
static int
init(void)
@ -1530,7 +1478,7 @@ on(void)
* Request the HF XOSC as the source for the HF clock. Needed before we can
* use the FS. This will only request, it will _not_ perform the switch.
*/
request_hf_xosc();
oscillators_request_hf_xosc();
/*
* If we are in the middle of a BLE operation, we got called by ContikiMAC
@ -1568,7 +1516,7 @@ on(void)
* This will block until the XOSC is actually ready, but give how we
* requested it early on, this won't be too long a wait/
*/
switch_to_hf_xosc();
oscillators_switch_to_hf_xosc();
if(rf_radio_setup(RF_MODE_IEEE) != RF_CMD_OK) {
PRINTF("on: radio_setup() failed\n");
@ -1597,7 +1545,7 @@ off(void)
power_down();
/* Switch HF clock source to the RCOSC to preserve power */
switch_to_hf_rc_osc();
oscillators_switch_to_hf_rc();
/* We pulled the plug, so we need to restore the status manually */
GET_FIELD(cmd_ieee_rx_buf, radioOp, status) = IDLE;
@ -1993,6 +1941,7 @@ PROCESS_THREAD(cc26xx_rf_ble_beacon_process, ev, data)
uint8_t was_on;
int j;
uint32_t cmd_status;
bool interrupts_disabled;
PROCESS_BEGIN();
@ -2023,9 +1972,11 @@ PROCESS_THREAD(cc26xx_rf_ble_beacon_process, ev, data)
* Under ContikiMAC, some IEEE-related operations will be called from an
* interrupt context. We need those to see that we are in BLE mode.
*/
ti_lib_int_master_disable();
interrupts_disabled = ti_lib_int_master_disable();
ble_mode_on = 1;
ti_lib_int_master_enable();
if(!interrupts_disabled) {
ti_lib_int_master_enable();
}
/*
* Send BLE_ADV_MESSAGES beacon bursts. Each burst on all three
@ -2061,7 +2012,7 @@ PROCESS_THREAD(cc26xx_rf_ble_beacon_process, ev, data)
}
} else {
/* Request the HF XOSC to source the HF clock. */
request_hf_xosc();
oscillators_request_hf_xosc();
/* We were off: Boot the CPE */
if(power_up() != RF_CMD_OK) {
@ -2079,7 +2030,7 @@ PROCESS_THREAD(cc26xx_rf_ble_beacon_process, ev, data)
}
/* Trigger a switch to the XOSC, so that we can use the FS */
switch_to_hf_xosc();
oscillators_switch_to_hf_xosc();
}
/* Enter BLE mode */
@ -2118,13 +2069,17 @@ PROCESS_THREAD(cc26xx_rf_ble_beacon_process, ev, data)
power_down();
/* Switch HF clock source to the RCOSC to preserve power */
switch_to_hf_rc_osc();
oscillators_switch_to_hf_rc();
}
etimer_set(&ble_adv_et, BLE_ADV_DUTY_CYCLE);
ti_lib_int_master_disable();
interrupts_disabled = ti_lib_int_master_disable();
ble_mode_on = 0;
ti_lib_int_master_enable();
if(!interrupts_disabled) {
ti_lib_int_master_enable();
}
/* Wait unless this is the last burst */
if(i < BLE_ADV_MESSAGES - 1) {
@ -2132,9 +2087,13 @@ PROCESS_THREAD(cc26xx_rf_ble_beacon_process, ev, data)
}
}
ti_lib_int_master_disable();
interrupts_disabled = ti_lib_int_master_disable();
ble_mode_on = 0;
ti_lib_int_master_enable();
if(!interrupts_disabled) {
ti_lib_int_master_enable();
}
}
PROCESS_END();
}

View file

@ -44,6 +44,7 @@
#include "ti-lib.h"
#include <stdint.h>
#include <stdbool.h>
/*---------------------------------------------------------------------------*/
#define cc26xx_rtc_isr(...) AONRTCIntHandler(__VA_ARGS__)
/*---------------------------------------------------------------------------*/
@ -54,9 +55,11 @@ void
cc26xx_rtc_init(void)
{
uint32_t compare_value;
bool interrupts_disabled;
/* Disable and clear interrupts */
ti_lib_int_master_disable();
interrupts_disabled = ti_lib_int_master_disable();
ti_lib_aon_rtc_disable();
ti_lib_aon_rtc_event_clear(AON_RTC_CH0);
@ -65,22 +68,25 @@ cc26xx_rtc_init(void)
/* Setup the wakeup event */
ti_lib_aon_event_mcu_wake_up_set(AON_EVENT_MCU_WU0, AON_EVENT_RTC0);
ti_lib_aon_event_mcu_wake_up_set(AON_EVENT_MCU_WU1, AON_EVENT_RTC2);
ti_lib_aon_rtc_combined_event_config(AON_RTC_CH0 | AON_RTC_CH2);
/* Configure channel 2 in continuous compare, 128 ticks / sec */
ti_lib_aon_rtc_inc_value_ch2_set(RTIMER_SECOND / CLOCK_SECOND);
ti_lib_aon_rtc_mode_ch2_set(AON_RTC_MODE_CH2_CONTINUOUS);
compare_value = (RTIMER_SECOND / CLOCK_SECOND) +
ti_lib_aon_rtc_current_compare_value_get();
ti_lib_aon_rtc_compare_value_set(AON_RTC_CH2, compare_value);
ti_lib_aon_rtc_inc_value_ch2_set(RTIMER_SECOND / CLOCK_SECOND);
ti_lib_aon_rtc_mode_ch2_set(AON_RTC_MODE_CH2_CONTINUOUS);
/* Enable event generation for channels 0 and 2 and enable the RTC */
ti_lib_aon_rtc_combined_event_config(AON_RTC_CH0 | AON_RTC_CH2);
/* Enable channel 2 and the RTC */
ti_lib_aon_rtc_channel_enable(AON_RTC_CH2);
ti_lib_aon_rtc_enable();
ti_lib_int_enable(INT_AON_RTC);
ti_lib_int_master_enable();
/* Re-enable interrupts */
if(!interrupts_disabled) {
ti_lib_int_master_enable();
}
}
/*---------------------------------------------------------------------------*/
rtimer_clock_t

View file

@ -40,6 +40,7 @@
#include "sys/energest.h"
#include <stdint.h>
#include <stdbool.h>
/*---------------------------------------------------------------------------*/
/* Which events to trigger a UART interrupt */
#define CC26XX_UART_RX_INTERRUPT_TRIGGERS (UART_INT_RX | UART_INT_RT)
@ -53,35 +54,98 @@
/*---------------------------------------------------------------------------*/
static int (*input_handler)(unsigned char c);
/*---------------------------------------------------------------------------*/
static void
power_domain_on(void)
static bool
usable(void)
{
if(BOARD_IOID_UART_RX == IOID_UNUSED ||
BOARD_IOID_UART_TX == IOID_UNUSED ||
CC26XX_UART_CONF_ENABLE == 0) {
return false;
}
return true;
}
/*---------------------------------------------------------------------------*/
static void
power_and_clock(void)
{
/* Power on the SERIAL PD */
ti_lib_prcm_power_domain_on(PRCM_DOMAIN_SERIAL);
while(ti_lib_prcm_power_domain_status(PRCM_DOMAIN_SERIAL)
!= PRCM_DOMAIN_POWER_ON);
/* Enable UART clock in active mode */
ti_lib_prcm_peripheral_run_enable(PRCM_PERIPH_UART0);
ti_lib_prcm_load_set();
while(!ti_lib_prcm_load_get());
}
/*---------------------------------------------------------------------------*/
/*
* Returns 0 if either the SERIAL PD is off, or the PD is on but the run mode
* clock is gated. If this function would return 0, accessing UART registers
* will return a precise bus fault. If this function returns 1, it is safe to
* access UART registers.
*
* This function only checks the 'run mode' clock gate, since it can only ever
* be called with the MCU in run mode.
*/
static bool
accessible(void)
{
/* First, check the PD */
if(ti_lib_prcm_power_domain_status(PRCM_DOMAIN_SERIAL)
!= PRCM_DOMAIN_POWER_ON) {
return false;
}
/* Then check the 'run mode' clock gate */
if(!(HWREG(PRCM_BASE + PRCM_O_UARTCLKGR) & PRCM_UARTCLKGR_CLK_EN)) {
return false;
}
return true;
}
/*---------------------------------------------------------------------------*/
static void
configure_baud_rate(void)
disable_interrupts(void)
{
/* Acknowledge UART interrupts */
ti_lib_int_disable(INT_UART0);
/* Disable all UART module interrupts */
ti_lib_uart_int_disable(UART0_BASE, CC26XX_UART_INTERRUPT_ALL);
/* Clear all UART interrupts */
ti_lib_uart_int_clear(UART0_BASE, CC26XX_UART_INTERRUPT_ALL);
}
/*---------------------------------------------------------------------------*/
static void
enable_interrupts(void)
{
/* Clear all UART interrupts */
ti_lib_uart_int_clear(UART0_BASE, CC26XX_UART_INTERRUPT_ALL);
/* Enable RX-related interrupts only if we have an input handler */
if(input_handler) {
/* Configure which interrupts to generate: FIFO level or after RX timeout */
ti_lib_uart_int_enable(UART0_BASE, CC26XX_UART_RX_INTERRUPT_TRIGGERS);
/* Acknowledge UART interrupts */
ti_lib_int_enable(INT_UART0);
}
}
/*---------------------------------------------------------------------------*/
static void
configure(void)
{
uint32_t ctl_val = UART_CTL_UARTEN | UART_CTL_TXE;
/*
* Configure the UART for 115,200, 8-N-1 operation.
* This function uses SysCtrlClockGet() to get the system clock
* frequency. This could be also be a variable or hard coded value
* instead of a function call.
* Make sure the TX pin is output / high before assigning it to UART control
* to avoid falling edge glitches
*/
ti_lib_uart_config_set_exp_clk(UART0_BASE,
ti_lib_sys_ctrl_peripheral_clock_get(
PRCM_PERIPH_UART0,
SYSCTRL_SYSBUS_ON),
CC26XX_UART_CONF_BAUD_RATE,
(UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE |
UART_CONFIG_PAR_NONE));
}
/*---------------------------------------------------------------------------*/
static void
configure_registers(void)
{
ti_lib_ioc_pin_type_gpio_output(BOARD_IOID_UART_TX);
ti_lib_gpio_pin_write(BOARD_UART_TX, 1);
/*
* Map UART signals to the correct GPIO pins and configure them as
* hardware controlled.
@ -89,7 +153,14 @@ configure_registers(void)
ti_lib_ioc_pin_type_uart(UART0_BASE, BOARD_IOID_UART_RX, BOARD_IOID_UART_TX,
BOARD_IOID_UART_CTS, BOARD_IOID_UART_RTS);
configure_baud_rate();
/* Configure the UART for 115,200, 8-N-1 operation. */
ti_lib_uart_config_set_exp_clk(UART0_BASE,
ti_lib_sys_ctrl_peripheral_clock_get(
PRCM_PERIPH_UART0,
SYSCTRL_SYSBUS_ON),
CC26XX_UART_CONF_BAUD_RATE,
(UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE |
UART_CONFIG_PAR_NONE));
/*
* Generate an RX interrupt at FIFO 1/2 full.
@ -97,116 +168,138 @@ configure_registers(void)
*/
ti_lib_uart_fifo_level_set(UART0_BASE, UART_FIFO_TX7_8, UART_FIFO_RX4_8);
/* Configure which interrupts to generate: FIFO level or after RX timeout */
ti_lib_uart_int_enable(UART0_BASE, CC26XX_UART_RX_INTERRUPT_TRIGGERS);
}
/*---------------------------------------------------------------------------*/
static void
uart_on(void)
{
power_domain_on();
/* Enable FIFOs */
HWREG(UART0_BASE + UART_O_LCRH) |= UART_LCRH_FEN;
/* Configure baud rate and enable */
if((HWREG(UART0_BASE + UART_O_CTL) & UART_CTL_UARTEN) == 0) {
configure_registers();
/* Enable UART */
ti_lib_uart_enable(UART0_BASE);
if(input_handler) {
ctl_val += UART_CTL_RXE;
}
}
/*---------------------------------------------------------------------------*/
static uint8_t
lpm_permit_max_pm_handler(void)
{
return LPM_MODE_MAX_SUPPORTED;
/* Enable TX, RX (conditionally), and the UART. */
HWREG(UART0_BASE + UART_O_CTL) = ctl_val;
}
/*---------------------------------------------------------------------------*/
static void
lpm_drop_handler(uint8_t mode)
{
/* Do nothing if the PD is off */
if(ti_lib_prcm_power_domain_status(PRCM_DOMAIN_SERIAL)
!= PRCM_DOMAIN_POWER_ON) {
return;
/*
* First, wait for any outstanding TX to complete. If we have an input
* handler, the SERIAL PD will be kept on and the UART module clock will
* be enabled under sleep as well as deep sleep. In theory, this means that
* we shouldn't lose any outgoing bytes, but we actually do on occasion.
* This byte loss may (or may not) be related to the freezing of IO latches
* between MCU and AON when we drop to deep sleep. This here is essentially a
* workaround
*/
if(accessible() == true) {
while(ti_lib_uart_busy(UART0_BASE));
}
/* Wait for outstanding TX to complete */
while(ti_lib_uart_busy(UART0_BASE));
/*
* Check our clock gate under Deep Sleep. If it's off, we can shut down. If
* it's on, this means that some other code module wants UART functionality
* during deep sleep, so we stay enabled
* If we have a registered input_handler then we need to retain RX
* capability. Thus, if this is not a shutdown notification and we have an
* input handler, we do nothing
*/
if((HWREG(PRCM_BASE + PRCM_O_UARTCLKGDS) & 1) == 0) {
ti_lib_ioc_pin_type_gpio_input(BOARD_IOID_UART_RX);
ti_lib_ioc_pin_type_gpio_input(BOARD_IOID_UART_TX);
ti_lib_uart_disable(UART0_BASE);
}
}
/*---------------------------------------------------------------------------*/
static void
lpm_wakeup_handler(void)
{
uart_on();
}
/*---------------------------------------------------------------------------*/
/* Declare a data structure to register with LPM. */
LPM_MODULE(uart_module, lpm_permit_max_pm_handler,
lpm_drop_handler, lpm_wakeup_handler);
/*---------------------------------------------------------------------------*/
void
cc26xx_uart_init()
{
/* Exit without initialising if ports are misconfigured */
if(BOARD_IOID_UART_RX == IOID_UNUSED ||
BOARD_IOID_UART_TX == IOID_UNUSED) {
if((mode != LPM_MODE_SHUTDOWN) && (input_handler != NULL)) {
return;
}
/* Enable the serial domain and wait for domain to be on */
power_domain_on();
/*
* If we reach here, we either don't care about staying awake or we have
* received a shutdown notification
*
* Only touch UART registers if the module is powered and clocked
*/
if(accessible() == true) {
/* Disable the module */
ti_lib_uart_disable(UART0_BASE);
/* Enable the UART clock when running and sleeping */
ti_lib_prcm_peripheral_run_enable(PRCM_PERIPH_UART0);
/* Disable all UART interrupts and clear all flags */
disable_interrupts();
}
/* Apply clock settings and wait for them to take effect */
/*
* Always stop the clock in run mode. Also stop in Sleep and Deep Sleep if
* this is a request for full shutdown
*/
ti_lib_prcm_peripheral_run_disable(PRCM_PERIPH_UART0);
if(mode == LPM_MODE_SHUTDOWN) {
ti_lib_prcm_peripheral_sleep_disable(PRCM_PERIPH_UART0);
ti_lib_prcm_peripheral_deep_sleep_disable(PRCM_PERIPH_UART0);
}
ti_lib_prcm_load_set();
while(!ti_lib_prcm_load_get());
/* Disable Interrupts */
ti_lib_int_master_disable();
/* Set pins to low leakage configuration in preparation for deep sleep */
lpm_pin_set_default_state(BOARD_IOID_UART_TX);
lpm_pin_set_default_state(BOARD_IOID_UART_RX);
lpm_pin_set_default_state(BOARD_IOID_UART_CTS);
lpm_pin_set_default_state(BOARD_IOID_UART_RTS);
}
/*---------------------------------------------------------------------------*/
/* Declare a data structure to register with LPM. */
LPM_MODULE(uart_module, NULL, lpm_drop_handler, NULL, LPM_DOMAIN_NONE);
/*---------------------------------------------------------------------------*/
static void
enable(void)
{
power_and_clock();
/* Make sure the peripheral is disabled */
ti_lib_uart_disable(UART0_BASE);
/* Disable all UART module interrupts */
ti_lib_uart_int_disable(UART0_BASE, CC26XX_UART_INTERRUPT_ALL);
/* Disable all UART interrupts and clear all flags */
disable_interrupts();
configure_registers();
/* Setup pins, Baud rate and FIFO levels */
configure();
/* Acknowledge UART interrupts */
ti_lib_int_enable(INT_UART0);
/* Enable UART interrupts */
enable_interrupts();
}
/*---------------------------------------------------------------------------*/
void
cc26xx_uart_init()
{
bool interrupts_disabled;
/* Re-enable processor interrupts */
ti_lib_int_master_enable();
/* Return early if disabled by user conf or if ports are misconfigured */
if(usable() == false) {
return;
}
/* Enable UART */
ti_lib_uart_enable(UART0_BASE);
/* Disable Interrupts */
interrupts_disabled = ti_lib_int_master_disable();
/* Register ourselves with the LPM module */
lpm_register_module(&uart_module);
/* Only TX and EN to start with. RX will be enabled only if needed */
input_handler = NULL;
/*
* init() won't actually fire up the UART. We turn it on only when (and if)
* it gets requested, either to enable input or to send out a character
*
* Thus, we simply re-enable processor interrupts here
*/
if(!interrupts_disabled) {
ti_lib_int_master_enable();
}
}
/*---------------------------------------------------------------------------*/
void
cc26xx_uart_write_byte(uint8_t c)
{
if(ti_lib_prcm_power_domain_status(PRCM_DOMAIN_SERIAL)
!= PRCM_DOMAIN_POWER_ON) {
/* Return early if disabled by user conf or if ports are misconfigured */
if(usable() == false) {
return;
}
if(accessible() == false) {
enable();
}
ti_lib_uart_char_put(UART0_BASE, c);
}
/*---------------------------------------------------------------------------*/
@ -214,9 +307,52 @@ void
cc26xx_uart_set_input(int (*input)(unsigned char c))
{
input_handler = input;
/* Return early if disabled by user conf or if ports are misconfigured */
if(usable() == false) {
return;
}
if(input == NULL) {
/* Let the SERIAL PD power down */
uart_module.domain_lock = LPM_DOMAIN_NONE;
/* Disable module clocks under sleep and deep sleep */
ti_lib_prcm_peripheral_sleep_disable(PRCM_PERIPH_UART0);
ti_lib_prcm_peripheral_deep_sleep_disable(PRCM_PERIPH_UART0);
} else {
/* Request the SERIAL PD to stay on during deep sleep */
uart_module.domain_lock = LPM_DOMAIN_SERIAL;
/* Enable module clocks under sleep and deep sleep */
ti_lib_prcm_peripheral_sleep_enable(PRCM_PERIPH_UART0);
ti_lib_prcm_peripheral_deep_sleep_enable(PRCM_PERIPH_UART0);
}
ti_lib_prcm_load_set();
while(!ti_lib_prcm_load_get());
enable();
return;
}
/*---------------------------------------------------------------------------*/
uint8_t
cc26xx_uart_busy(void)
{
/* Return early if disabled by user conf or if ports are misconfigured */
if(usable() == false) {
return UART_IDLE;
}
/* If the UART is not accessible, it is not busy */
if(accessible() == false) {
return UART_IDLE;
}
return ti_lib_uart_busy(UART0_BASE);
}
/*---------------------------------------------------------------------------*/
void
cc26xx_uart_isr(void)
{
@ -225,6 +361,8 @@ cc26xx_uart_isr(void)
ENERGEST_ON(ENERGEST_TYPE_IRQ);
power_and_clock();
/* Read out the masked interrupt status */
flags = ti_lib_uart_int_status(UART0_BASE, true);

View file

@ -63,9 +63,32 @@ void cc26xx_uart_write_byte(uint8_t b);
/**
* \brief Assigns a callback to be called when the UART receives a byte
* \param input A pointer to the function
*
* If \e input is NULL, the UART driver will assume that RX functionality is
* not required and it will be disabled. It will also disable the module's
* clocks under sleep and deep sleep and allow the SERIAL PD to be powered off.
*
* If \e input is not NULL, the UART driver will assume that RX is in fact
* required and it will be enabled. The module's clocks will be enabled under
* sleep and deep sleep and the driver will not allow the SERIAL PD to turn
* off during deep sleep, so that the UART can still receive bytes.
*
* \note This has a significant impact on overall energy consumption, so you
* should only enabled UART RX input when it's actually required.
*/
void cc26xx_uart_set_input(int (*input)(unsigned char c));
/**
* \brief Returns the UART busy status
* \return UART_IDLE or UART_BUSY
*
* ti_lib_uart_busy() will access UART registers. It is our responsibility
* to first make sure the UART is accessible before calling it. Hence this
* wrapper.
*
* Return values are defined in CC26xxware's uart.h
*/
uint8_t cc26xx_uart_busy(void);
/** @} */
/*---------------------------------------------------------------------------*/
#endif /* CC26XX_UART_H_ */

View file

@ -0,0 +1,172 @@
/*
* Copyright (c) 2015, 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 cc26xx-oscillators
* @{
*
* \file
* Implementation of CC26xxware oscillator control wrappers.
*/
/*---------------------------------------------------------------------------*/
#include "ti-lib.h"
#include <stdint.h>
/*---------------------------------------------------------------------------*/
static uint32_t
osc_interface_en(void)
{
uint32_t smph_clk_state;
/* Enable OSC DIG interface to change clock sources */
ti_lib_osc_interface_enable();
/* Save the state of the SMPH clock within AUX */
smph_clk_state = ti_lib_aux_wuc_clock_status(AUX_WUC_SMPH_CLOCK);
/* Make sure the SMPH clock within AUX is enabled */
ti_lib_aux_wuc_clock_enable(AUX_WUC_SMPH_CLOCK);
while(ti_lib_aux_wuc_clock_status(AUX_WUC_SMPH_CLOCK) != AUX_WUC_CLOCK_READY);
return smph_clk_state;
}
/*---------------------------------------------------------------------------*/
static void
osc_interface_dis(uint32_t smph_clk_state)
{
/* If the SMPH clock was off, turn it back off */
if(smph_clk_state == AUX_WUC_CLOCK_OFF) {
ti_lib_aux_wuc_clock_disable(AUX_WUC_SMPH_CLOCK);
}
/* Disable OSC DIG interface */
ti_lib_osc_interface_disable();
}
/*---------------------------------------------------------------------------*/
void
oscillators_select_lf_xosc(void)
{
/* Enable the Osc interface and remember the state of the SMPH clock */
uint32_t smph_clk_state = osc_interface_en();
/* Switch LF clock source to the LF XOSC if required */
if(ti_lib_osc_clock_source_get(OSC_SRC_CLK_LF) != OSC_XOSC_LF) {
ti_lib_osc_clock_source_set(OSC_SRC_CLK_LF, OSC_XOSC_LF);
/* Wait for LF clock source to become XOSC_LF */
while(ti_lib_osc_clock_source_get(OSC_SRC_CLK_LF) != OSC_XOSC_LF);
/* Disable the LF clock qualifiers */
ti_lib_ddi_16_bit_field_write(AUX_DDI0_OSC_BASE, DDI_0_OSC_O_CTL0,
DDI_0_OSC_CTL0_BYPASS_XOSC_LF_CLK_QUAL_M |
DDI_0_OSC_CTL0_BYPASS_RCOSC_LF_CLK_QUAL_M,
DDI_0_OSC_CTL0_BYPASS_RCOSC_LF_CLK_QUAL_S,
0x3);
}
/* Restore the SMPH clock and disable the OSC interface */
osc_interface_dis(smph_clk_state);
}
/*---------------------------------------------------------------------------*/
void
oscillators_select_lf_rcosc(void)
{
/* Enable the Osc interface and remember the state of the SMPH clock */
uint32_t smph_clk_state = osc_interface_en();
/* Switch LF clock source to the LF XOSC if required */
if(ti_lib_osc_clock_source_get(OSC_SRC_CLK_LF) != OSC_RCOSC_LF) {
ti_lib_osc_clock_source_set(OSC_SRC_CLK_LF, OSC_RCOSC_LF);
/* Wait for LF clock source to become XOSC_LF */
while(ti_lib_osc_clock_source_get(OSC_SRC_CLK_LF) != OSC_RCOSC_LF);
}
/* Restore the SMPH clock and disable the OSC interface */
osc_interface_dis(smph_clk_state);
}
/*---------------------------------------------------------------------------*/
void
oscillators_request_hf_xosc(void)
{
/* Enable the Osc interface and remember the state of the SMPH clock */
uint32_t smph_clk_state = osc_interface_en();
if(ti_lib_osc_clock_source_get(OSC_SRC_CLK_HF) != OSC_XOSC_HF) {
/*
* Request to switch to the crystal to enable radio operation. It takes a
* while for the XTAL to be ready so instead of performing the actual
* switch, we return and we do other stuff while the XOSC is getting ready.
*/
ti_lib_osc_clock_source_set(OSC_SRC_CLK_MF | OSC_SRC_CLK_HF, OSC_XOSC_HF);
}
/* Restore the SMPH clock and disable the OSC interface */
osc_interface_dis(smph_clk_state);
}
/*---------------------------------------------------------------------------*/
void
oscillators_switch_to_hf_xosc(void)
{
/* Enable the Osc interface and remember the state of the SMPH clock */
uint32_t smph_clk_state = osc_interface_en();
if(ti_lib_osc_clock_source_get(OSC_SRC_CLK_HF) != OSC_XOSC_HF) {
/* Switch the HF clock source (cc26xxware executes this from ROM) */
ti_lib_osc_hf_source_switch();
}
/* Restore the SMPH clock and disable the OSC interface */
osc_interface_dis(smph_clk_state);
}
/*---------------------------------------------------------------------------*/
void
oscillators_switch_to_hf_rc(void)
{
/* Enable the Osc interface and remember the state of the SMPH clock */
uint32_t smph_clk_state = osc_interface_en();
/* Set all clock sources to the HF RC Osc */
ti_lib_osc_clock_source_set(OSC_SRC_CLK_MF | OSC_SRC_CLK_HF, OSC_RCOSC_HF);
/* Check to not enable HF RC oscillator if already enabled */
if(ti_lib_osc_clock_source_get(OSC_SRC_CLK_HF) != OSC_RCOSC_HF) {
/* Switch the HF clock source (cc26xxware executes this from ROM) */
ti_lib_osc_hf_source_switch();
}
/* Restore the SMPH clock and disable the OSC interface */
osc_interface_dis(smph_clk_state);
}
/*---------------------------------------------------------------------------*/
/**
* @}
* @}
*/

View file

@ -0,0 +1,101 @@
/*
* Copyright (c) 2015, 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 cc26xx
* @{
*
* \defgroup cc26xx-oscillators CC26XX oscillator control
*
* Wrapper around those CC26xxware OSC functions that we need in Contiki.
*
* All CC26xxware OSC control requires access to the semaphore module within
* AUX. Thus, in addition to enabling the oscillator interface, we need to
* start the clock to SMPH and restore it to its previous state when we are
* done.
* @{
*
* \file
* Header file for the CC26XX oscillator control
*/
/*---------------------------------------------------------------------------*/
#ifndef OSCILLATORS_H_
#define OSCILLATORS_H_
/*---------------------------------------------------------------------------*/
/**
* \brief Set the LF clock source to be the LF XOSC
*
* This function is only called once as soon as the system starts.
*
* Do not switch the LF clock source to the RC OSC for normal system operation
* See CC26xx Errata (swrz058)
*/
void oscillators_select_lf_xosc(void);
/**
* \brief Set the LF clock source to be the LF RCOSC
*
* This function is only called once, when the systen transitions to a full
* shutdown
*
* Do not switch the LF clock source to the RC OSC for normal system operation
* See CC26xx Errata (swrz058)
*/
void oscillators_select_lf_rcosc(void);
/**
* \brief Requests the HF XOSC as the source for the HF clock, but does not
* perform the actual switch.
*
* This triggers the startup sequence of the HF XOSC and returns so the CPU
* can perform other tasks while the XOSC is starting.
*
* The XOSC is requested as the source for the HF as well as the MF clock.
*/
void oscillators_request_hf_xosc(void);
/**
* \brief Performs the switch to the XOSC
*
* This function must be preceded by a call to oscillators_request_hf_xosc()
*/
void oscillators_switch_to_hf_xosc(void);
/**
* \brief Switches MF and HF clock source to be the HF RC OSC
*/
void oscillators_switch_to_hf_rc(void);
/*---------------------------------------------------------------------------*/
#endif /* OSCILLATORS_H_ */
/*---------------------------------------------------------------------------*/
/**
* @}
* @}
*/

View file

@ -49,6 +49,7 @@
#include "dev/leds.h"
#include "dev/watchdog.h"
#include "dev/cc26xx-rtc.h"
#include "dev/oscillators.h"
/*---------------------------------------------------------------------------*/
#if ENERGEST_CONF_ON
static unsigned long irq_energest = 0;
@ -64,9 +65,6 @@ static unsigned long irq_energest = 0;
/*---------------------------------------------------------------------------*/
LIST(modules_list);
/*---------------------------------------------------------------------------*/
/* Control what power domains we are allow to run under what mode */
LIST(power_domain_locks_list);
/* PDs that may stay on in deep sleep */
#define LOCKABLE_DOMAINS ((uint32_t)(PRCM_DOMAIN_SERIAL | PRCM_DOMAIN_PERIPH))
/*---------------------------------------------------------------------------*/
@ -76,49 +74,48 @@ LIST(power_domain_locks_list);
*/
#define STANDBY_MIN_DURATION (RTIMER_SECOND >> 8)
/*---------------------------------------------------------------------------*/
/* Variables used by the power on/off (Power mode: SHUTDOWN) functionality */
static uint8_t shutdown_requested;
static uint32_t pin;
/*---------------------------------------------------------------------------*/
void
lpm_pd_lock_obtain(lpm_power_domain_lock_t *lock, uint32_t domains)
{
/* We only accept locks for specific PDs */
domains &= LOCKABLE_DOMAINS;
if(domains == 0) {
return;
}
lock->domains = domains;
list_add(power_domain_locks_list, lock);
}
/*---------------------------------------------------------------------------*/
void
lpm_pd_lock_release(lpm_power_domain_lock_t *lock)
{
lock->domains = 0;
list_remove(power_domain_locks_list, lock);
}
/*---------------------------------------------------------------------------*/
void
lpm_shutdown(uint32_t wakeup_pin)
{
shutdown_requested = 1;
pin = wakeup_pin;
}
/*---------------------------------------------------------------------------*/
static void
shutdown_now(void)
lpm_shutdown(uint32_t wakeup_pin, uint32_t io_pull, uint32_t wake_on)
{
lpm_registered_module_t *module;
int i;
rtimer_clock_t t0;
uint32_t io_cfg = (IOC_STD_INPUT & ~IOC_IOPULL_M) | IOC_IOPULL_UP |
IOC_WAKE_ON_LOW;
int i, j;
uint32_t io_cfg = (IOC_STD_INPUT & ~IOC_IOPULL_M) | io_pull |
wake_on;
/* This procedure may not be interrupted */
ti_lib_int_master_disable();
/* Disable the RTC */
ti_lib_aon_rtc_disable();
ti_lib_aon_rtc_event_clear(AON_RTC_CH0);
ti_lib_aon_rtc_event_clear(AON_RTC_CH1);
ti_lib_aon_rtc_event_clear(AON_RTC_CH2);
/* Reset AON even fabric to default wakeup sources */
for(i = AON_EVENT_MCU_WU0; i <= AON_EVENT_MCU_WU3; i++) {
ti_lib_aon_event_mcu_wake_up_set(i, AON_EVENT_NULL);
}
for(i = AON_EVENT_AUX_WU0; i <= AON_EVENT_AUX_WU2; i++) {
ti_lib_aon_event_aux_wake_up_set(i, AON_EVENT_NULL);
}
ti_lib_sys_ctrl_aon_sync();
watchdog_periodic();
/* fade away....... */
j = 1000;
for(i = j; i > 0; --i) {
leds_on(LEDS_ALL);
clock_delay_usec(i);
leds_off(LEDS_ALL);
clock_delay_usec(j - i);
}
leds_off(LEDS_ALL);
/* Notify all modules that we're shutting down */
for(module = list_head(modules_list); module != NULL;
module = module->next) {
if(module->shutdown) {
@ -126,34 +123,76 @@ shutdown_now(void)
}
}
leds_off(LEDS_ALL);
/* Configure the wakeup trigger */
ti_lib_gpio_dir_mode_set((1 << wakeup_pin), GPIO_DIR_MODE_IN);
ti_lib_ioc_port_configure_set(wakeup_pin, IOC_PORT_GPIO, io_cfg);
for(i = 0; i < 5; i++) {
t0 = RTIMER_NOW();
leds_toggle(LEDS_ALL);
while(RTIMER_CLOCK_LT(RTIMER_NOW(), (t0 + (RTIMER_SECOND >> 3))));
}
/* Freeze I/O latches in AON */
ti_lib_aon_ioc_freeze_enable();
leds_off(LEDS_ALL);
/* Turn off RFCORE, SERIAL and PERIPH PDs. This will happen immediately */
ti_lib_prcm_power_domain_off(PRCM_DOMAIN_RFCORE | PRCM_DOMAIN_SERIAL |
PRCM_DOMAIN_PERIPH);
ti_lib_gpio_dir_mode_set((1 << pin), GPIO_DIR_MODE_IN);
ti_lib_ioc_port_configure_set(pin, IOC_PORT_GPIO, io_cfg);
oscillators_switch_to_hf_rc();
oscillators_select_lf_rcosc();
ti_lib_pwr_ctrl_state_set(LPM_MODE_SHUTDOWN);
/* Configure clock sources for MCU and AUX: No clock */
ti_lib_aon_wuc_mcu_power_down_config(AONWUC_NO_CLOCK);
ti_lib_aon_wuc_aux_power_down_config(AONWUC_NO_CLOCK);
/* Disable retentions: SRAM, CPU, AUX, RFCORE - possibly not required */
ti_lib_aon_wuc_mcu_sram_config(0);
ti_lib_prcm_retention_disable(PRCM_DOMAIN_CPU);
ti_lib_aon_wuc_aux_sram_config(false);
ti_lib_prcm_retention_disable(PRCM_DOMAIN_RFCORE);
/*
* Request CPU, SYSBYS and VIMS PD off.
* This will only happen when the CM3 enters deep sleep
*/
ti_lib_prcm_power_domain_off(PRCM_DOMAIN_CPU | PRCM_DOMAIN_VIMS |
PRCM_DOMAIN_SYSBUS);
/* Request JTAG domain power off */
ti_lib_aon_wuc_jtag_power_off();
/* Turn off AUX */
ti_lib_aux_wuc_power_ctrl(AUX_WUC_POWER_OFF);
ti_lib_aon_wuc_domain_power_down_enable();
while(ti_lib_aon_wuc_power_status() & AONWUC_AUX_POWER_ON);
/*
* Request MCU VD power off.
* This will only happen when the CM3 enters deep sleep
*/
ti_lib_prcm_mcu_power_off();
/* Set MCU wakeup to immediate and disable virtual power off */
ti_lib_aon_wuc_mcu_wake_up_config(MCU_IMM_WAKE_UP);
ti_lib_aon_wuc_mcu_power_off_config(MCU_VIRT_PWOFF_DISABLE);
/* Latch the IOs in the padring and enable I/O pad sleep mode */
ti_lib_pwr_ctrl_io_freeze_enable();
/* Turn off VIMS cache, CRAM and TRAM - possibly not required */
ti_lib_prcm_retention_disable(PRCM_DOMAIN_VIMS);
ti_lib_vims_mode_set(VIMS_BASE, VIMS_MODE_OFF);
/* Enable shutdown and sync AON */
ti_lib_aon_wuc_shut_down_enable();
ti_lib_sys_ctrl_aon_sync();
/* Deep Sleep */
ti_lib_prcm_deep_sleep();
}
/*---------------------------------------------------------------------------*/
/*
* We'll get called on three occasions:
* - While running
* - While sleeping
* - While deep sleeping
*
* For the former two, we don't need to do anything. For the latter, we
* notify all modules that we're back on and rely on them to restore clocks
* Notify all modules that we're back on and rely on them to restore clocks
* and power domains as required.
*/
void
lpm_wake_up()
static void
wake_up(void)
{
lpm_registered_module_t *module;
@ -182,8 +221,8 @@ lpm_wake_up()
ti_lib_aon_ioc_freeze_disable();
ti_lib_sys_ctrl_aon_sync();
/* Power up AUX and allow it to go to sleep */
ti_lib_aon_wuc_aux_wakeup_event(AONWUC_AUX_ALLOW_SLEEP);
/* Check operating conditions, optimally choose DCDC versus GLDO */
ti_lib_sys_ctrl_dcdc_voltage_conditional_control();
/* Notify all registered modules that we've just woken up */
for(module = list_head(modules_list); module != NULL;
@ -198,16 +237,11 @@ void
lpm_drop()
{
lpm_registered_module_t *module;
lpm_power_domain_lock_t *lock;
uint8_t max_pm = LPM_MODE_MAX_SUPPORTED;
uint8_t module_pm;
uint32_t domains = LOCKABLE_DOMAINS;
if(shutdown_requested) {
shutdown_now();
}
if(RTIMER_CLOCK_LT(cc26xx_rtc_get_next_trigger(),
RTIMER_NOW() + STANDBY_MIN_DURATION)) {
lpm_sleep();
@ -244,26 +278,21 @@ lpm_drop()
* This is a chance for modules to delay us a little bit until an ongoing
* operation has finished (e.g. uart TX) or to configure themselves for
* deep sleep.
*
* At this stage, we also collect power domain locks, if any.
* The argument to PRCMPowerDomainOff() is a bitwise OR, so every time
* we encounter a lock we just clear the respective bits in the 'domains'
* variable as required by the lock. In the end the domains variable will
* just hold whatever has not been cleared
*/
for(module = list_head(modules_list); module != NULL;
module = module->next) {
if(module->shutdown) {
module->shutdown(max_pm);
}
}
/*
* Iterate PD locks to see what we can and cannot turn off.
*
* The argument to PRCMPowerDomainOff() is a bitwise OR, so every time
* we encounter a lock we just clear the respective bits in the 'domains'
* variable as required by the lock. In the end the domains variable will
* just hold whatever has not been cleared
*/
for(lock = list_head(power_domain_locks_list); lock != NULL;
lock = lock->next) {
/* Clear the bits specified in the lock */
domains &= ~lock->domains;
domains &= ~module->domain_lock;
}
/* Pat the dog: We don't want it to shout right after we wake up */
@ -289,6 +318,20 @@ lpm_drop()
ti_lib_prcm_power_domain_off(domains);
}
/*
* Before entering Deep Sleep, we must switch off the HF XOSC. The HF XOSC
* is predominantly controlled by the RF driver. In a build with radio
* cycling (e.g. ContikiMAC), the RF driver will request the XOSC before
* using the Freq. Synth, and switch back to the RC when it is about to
* turn back off.
*
* If the radio is on, we won't even reach here, and if it's off the HF
* clock source should already be the HF RC.
*
* Nevertheless, request the switch to the HF RC explicitly here.
*/
oscillators_switch_to_hf_rc();
/* Configure clock sources for MCU and AUX: No clock */
ti_lib_aon_wuc_mcu_power_down_config(AONWUC_NO_CLOCK);
ti_lib_aon_wuc_aux_power_down_config(AONWUC_NO_CLOCK);
@ -304,11 +347,7 @@ lpm_drop()
ti_lib_aon_wuc_aux_sram_config(false);
/* Disable retention in the RFCORE RAM */
HWREG(PRCM_BASE + PRCM_O_RAMRETEN) &= ~PRCM_RAMRETEN_RFC;
/* Disable retention of VIMS RAM (TRAM and CRAM) */
//TODO: This can probably be removed, we are calling ti_lib_prcm_retention_disable(PRCM_DOMAIN_VIMS); further down
HWREG(PRCM_BASE + PRCM_O_RAMRETEN) &= ~PRCM_RAMRETEN_VIMS_M;
ti_lib_prcm_retention_disable(PRCM_DOMAIN_RFCORE);
/*
* Always turn off RFCORE, CPU, SYSBUS and VIMS. RFCORE should be off
@ -329,7 +368,7 @@ lpm_drop()
ti_lib_sys_ctrl_set_recharge_before_power_down(false);
/*
* If both PERIPH and SERIAL PDs are off, request the uLDO for as the power
* If both PERIPH and SERIAL PDs are off, request the uLDO as the power
* source while in deep sleep.
*/
if(domains == LOCKABLE_DOMAINS) {
@ -362,7 +401,7 @@ lpm_drop()
* the chip properly, and then we will enable the global interrupt without
* unpending events so the handlers can fire
*/
lpm_wake_up();
wake_up();
ti_lib_int_master_enable();
}
@ -396,10 +435,26 @@ lpm_register_module(lpm_registered_module_t *module)
}
/*---------------------------------------------------------------------------*/
void
lpm_unregister_module(lpm_registered_module_t *module)
{
list_remove(modules_list, module);
}
/*---------------------------------------------------------------------------*/
void
lpm_init()
{
list_init(modules_list);
list_init(power_domain_locks_list);
}
/*---------------------------------------------------------------------------*/
void
lpm_pin_set_default_state(uint32_t ioid)
{
if(ioid == IOID_UNUSED) {
return;
}
ti_lib_ioc_port_configure_set(ioid, IOC_PORT_GPIO, IOC_STD_OUTPUT);
ti_lib_gpio_dir_mode_set((1 << ioid), GPIO_DIR_MODE_IN);
}
/*---------------------------------------------------------------------------*/
/**

View file

@ -49,17 +49,22 @@
#include <stdint.h>
/*---------------------------------------------------------------------------*/
#define LPM_MODE_SLEEP PWRCTRL_ACTIVE
#define LPM_MODE_DEEP_SLEEP PWRCTRL_POWER_DOWN
#define LPM_MODE_SHUTDOWN PWRCTRL_SHUTDOWN
#define LPM_MODE_SLEEP 1
#define LPM_MODE_DEEP_SLEEP 2
#define LPM_MODE_SHUTDOWN 3
#define LPM_MODE_MAX_SUPPORTED LPM_MODE_DEEP_SLEEP
/*---------------------------------------------------------------------------*/
#define LPM_DOMAIN_NONE 0
#define LPM_DOMAIN_SERIAL PRCM_DOMAIN_SERIAL
#define LPM_DOMAIN_PERIPH PRCM_DOMAIN_PERIPH
/*---------------------------------------------------------------------------*/
typedef struct lpm_registered_module {
struct lpm_registered_module *next;
uint8_t (*request_max_pm)(void);
void (*shutdown)(uint8_t mode);
void (*wakeup)(void);
uint32_t domain_lock;
} lpm_registered_module_t;
/*---------------------------------------------------------------------------*/
/**
@ -78,46 +83,14 @@ typedef struct lpm_registered_module {
* woken up. This can be used to e.g. turn a peripheral back on. This
* function is in charge of turning power domains back on. This
* function will normally be called within an interrupt context.
* \param l Power domain locks, if any are required. The module can request
* that the SERIAL or PERIPH PD be kept powered up at the transition
* to deep sleep. This field can be a bitwise OR of LPM_DOMAIN_x, so
* if required multiple domains can be kept powered.
*/
#define LPM_MODULE(n, m, s, w) static lpm_registered_module_t n = \
{ NULL, m, s, w }
#define LPM_MODULE(n, m, s, w, l) static lpm_registered_module_t n = \
{ NULL, m, s, w, l }
/*---------------------------------------------------------------------------*/
/**
*
* \brief Data type used to control whether a PD will get shut down when the
* CM3 drops to deep sleep
*
* Modules using these facilities must allocate a variable of this type, but
* they must not try to manipulate it directly. Instead, the respective
* functions must be used
*
* \sa lpm_pd_lock_obtain(), lpm_pd_lock_release()
*/
typedef struct lpm_power_domain_lock {
struct lpm_power_domain_lock *next;
uint32_t domains;
} lpm_power_domain_lock_t;
/*---------------------------------------------------------------------------*/
/**
* \brief Prohibit a PD from turning off in standby mode
* \param lock A pointer to a lpm_power_domain_lock_t
* \param domains Bitwise OR from PRCM_DOMAIN_PERIPH, PRCM_DOMAIN_SERIAL
*
* The caller is responsible for allocating lpm_power_domain_lock_t
*
* Only the domains listed above can be locked / released, but a single lock
* can be used for multiple domains
*/
void lpm_pd_lock_obtain(lpm_power_domain_lock_t *lock, uint32_t domains);
/**
* \brief Permit a PD to turn off in standby mode
* \param pd A pointer to a previously used lock
*
* \sa lpm_pd_lock_obtain()
*/
void lpm_pd_lock_release(lpm_power_domain_lock_t *pd);
/**
* \brief Drop the cortex to sleep / deep sleep and shut down peripherals
*
@ -134,17 +107,11 @@ void lpm_sleep(void);
/**
* \brief Put the chip in shutdown power mode
* \param wakeup_pin The GPIO pin which will wake us up. Must be IOID_0 etc...
* \param io_pull Pull configuration for the shutdown pin: IOC_NO_IOPULL,
* IOC_IOPULL_UP or IOC_IOPULL_DOWN
* \param wake_on High or Low (IOC_WAKE_ON_LOW or IOC_WAKE_ON_HIGH)
*/
void lpm_shutdown(uint32_t wakeup_pin);
/**
* \brief Wake up from sleep mode
*
* This function must be called at the start of any interrupt context which
* may bring us out of sleep. Current interrupts do this already, but make sure
* to do the same when adding new ISRs
*/
void lpm_wake_up(void);
void lpm_shutdown(uint32_t wakeup_pin, uint32_t io_pull, uint32_t wake_on);
/**
* \brief Register a module for LPM notifications.
@ -159,10 +126,31 @@ void lpm_wake_up(void);
*/
void lpm_register_module(lpm_registered_module_t *module);
/**
* \brief Unregister a module from LPM notifications.
* \param module A pointer to the data structure with the module definition
*
* When a previously registered module is no longer interested in LPM
* notifications, this function can be used to unregister it.
*/
void lpm_unregister_module(lpm_registered_module_t *module);
/**
* \brief Initialise the low-power mode management module
*/
void lpm_init(void);
/**
* \brief Sets an IOID to a default state
* \param ioid IOID_0...
*
* This will set ioid to sw control, input, no pull. Input buffer and output
* driver will both be disabled
*
* The function will do nothing if ioid == IOID_UNUSED, so the caller does not
* have to check board configuration before calling this.
*/
void lpm_pin_set_default_state(uint32_t ioid);
/*---------------------------------------------------------------------------*/
#endif /* LPM_H_ */
/*---------------------------------------------------------------------------*/

View file

@ -29,6 +29,7 @@
*/
/*---------------------------------------------------------------------------*/
#include "cc26xx-uart.h"
#include "ti-lib.h"
#include <string.h>
/*---------------------------------------------------------------------------*/
@ -47,9 +48,16 @@ puts(const char *str)
return 0;
}
for(i = 0; i < strlen(str); i++) {
putchar(str[i]);
cc26xx_uart_write_byte(str[i]);
}
putchar('\n');
cc26xx_uart_write_byte('\n');
/*
* Wait for the line to go out. This is to prevent garbage when used between
* UART on/off cycles
*/
while(cc26xx_uart_busy() == UART_BUSY);
return i;
}
/*---------------------------------------------------------------------------*/
@ -62,9 +70,16 @@ dbg_send_bytes(const unsigned char *s, unsigned int len)
if(i >= len) {
break;
}
putchar(*s++);
cc26xx_uart_write_byte(*s++);
i++;
}
/*
* Wait for the buffer to go out. This is to prevent garbage when used
* between UART on/off cycles
*/
while(cc26xx_uart_busy() == UART_BUSY);
return i;
}
/*---------------------------------------------------------------------------*/

View file

@ -58,6 +58,10 @@ slip_arch_writeb(unsigned char c)
void
slip_arch_init(unsigned long ubr)
{
/*
* Enable an input handler. In doing so, the driver will make sure that UART
* RX stays operational during deep sleep
*/
cc26xx_uart_set_input(slip_input_byte);
}
/*---------------------------------------------------------------------------*/

View file

@ -148,7 +148,7 @@
#include "driverlib/aux_wuc.h"
#define ti_lib_aux_wuc_clock_enable(...) AUXWUCClockEnable(__VA_ARGS__)
#define ti_lib_aux_wuc_clock_disble(...) AUXWUCClockDisable(__VA_ARGS__)
#define ti_lib_aux_wuc_clock_disable(...) AUXWUCClockDisable(__VA_ARGS__)
#define ti_lib_aux_wuc_clock_status(...) AUXWUCClockStatus(__VA_ARGS__)
#define ti_lib_aux_wuc_clock_freq_req(...) AUXWUCClockFreqReq(__VA_ARGS__)
#define ti_lib_aux_wuc_power_ctrl(...) AUXWUCPowerCtrl(__VA_ARGS__)
@ -531,6 +531,8 @@
#define ti_lib_sys_ctrl_aon_update(...) SysCtrlAonUpdate(__VA_ARGS__)
#define ti_lib_sys_ctrl_set_recharge_before_power_down(...) SysCtrlSetRechargeBeforePowerDown(__VA_ARGS__)
#define ti_lib_sys_ctrl_adjust_recharge_after_power_down(...) SysCtrlAdjustRechargeAfterPowerDown(__VA_ARGS__)
#define ti_lib_sys_ctrl_dcdc_voltage_conditional_control(...) SysCtrl_DCDC_VoltageConditionalControl(__VA_ARGS__)
#define ti_lib_sys_ctrl_reset_source_get(...) SysCtrlResetSourceGet(__VA_ARGS__)
/*---------------------------------------------------------------------------*/
/* ssi.h */
#include "driverlib/ssi.h"

View file

@ -4,6 +4,8 @@ ifdef nodeid
CFLAGS += -DNODEID=$(nodeid)
endif
CFLAGS += -gstabs+
.SUFFIXES:
### Define the CPU directory

View file

@ -45,6 +45,7 @@
#include "sfrs-ext.h"
#include "contiki.h" /* for clock_wait() and CLOCK_SECOND. */
#include "sys/cc.h"
/******************************************************************************/
/*************************** Macros Definitions *******************************/
@ -91,9 +92,6 @@
while(condition) { body; break_loop(); } \
} while(0)
#undef MIN
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
/******************************************************************************/
/************************ Variables Definitions *******************************/
/******************************************************************************/

View file

@ -6,8 +6,6 @@ boards. More specifically, the example demonstrates:
* How to take sensor readings
* How to use buttons and the reed relay (triggered by holding a magnet near S3
on the SensorTag).
* How to keep a power domain powered and a peripheral clocked under low power
operation
* How to send out BLE advertisements. The device will periodically send out BLE
beacons with the platform name as payload. Those beacons/BLE ADV packets can
be captured with any BLE capable device. Two such applications for iOS are the

View file

@ -77,12 +77,6 @@
* - The example also shows how to retrieve the duration of a
* button press (in ticks). The driver will generate a
* sensors_changed event upon button release
* - UART : Receiving an entire line of text over UART (ending
* in \\r) will cause CC26XX_DEMO_LEDS_SERIAL_IN to toggle
* This also demonstrates how a code module can influence
* low-power operation: In this example we keep the UART on
* and capable to RX even with the chip in deep sleep.
* see keep_uart_on() and the UART driver
* - Reed Relay : Will toggle the sensortag buzzer on/off
*
* @{
@ -100,7 +94,6 @@
#include "button-sensor.h"
#include "batmon-sensor.h"
#include "board-peripherals.h"
#include "lpm.h"
#include "cc26xx-rf.h"
#include "ti-lib.h"
@ -251,8 +244,7 @@ get_light_reading()
printf("OPT: Light Read Error\n");
}
SENSORS_DEACTIVATE(opt_3001_sensor);
/* The OPT will turn itself off, so we don't need to call its DEACTIVATE */
ctimer_set(&opt_timer, next, init_opt_reading, NULL);
}
/*---------------------------------------------------------------------------*/
@ -369,26 +361,6 @@ init_sensor_readings(void)
#endif
}
/*---------------------------------------------------------------------------*/
static lpm_power_domain_lock_t lock;
/*---------------------------------------------------------------------------*/
/*
* In order to maintain UART input operation:
* - Keep the uart clocked in sleep and deep sleep
* - Keep the serial PD on in deep sleep
*/
static void
keep_uart_on(void)
{
/* Keep the serial PD on */
lpm_pd_lock_obtain(&lock, PRCM_DOMAIN_SERIAL);
/* Keep the UART clock on during Sleep and Deep Sleep */
ti_lib_prcm_peripheral_sleep_enable(PRCM_PERIPH_UART0);
ti_lib_prcm_peripheral_deep_sleep_enable(PRCM_PERIPH_UART0);
ti_lib_prcm_load_set();
while(!ti_lib_prcm_load_get());
}
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(cc26xx_demo_process, ev, data)
{
@ -406,8 +378,6 @@ PROCESS_THREAD(cc26xx_demo_process, ev, data)
get_sync_sensor_readings();
init_sensor_readings();
keep_uart_on();
while(1) {
PROCESS_YIELD();
@ -462,8 +432,6 @@ PROCESS_THREAD(cc26xx_demo_process, ev, data)
button_select_sensor.value(BUTTON_SENSOR_VALUE_DURATION));
#endif
}
} else if(ev == serial_line_event_message) {
leds_toggle(CC26XX_DEMO_LEDS_SERIAL_IN);
}
}

View file

@ -574,8 +574,6 @@ get_light_reading()
value = opt_3001_sensor.value(0);
SENSORS_DEACTIVATE(opt_3001_sensor);
if(value != CC26XX_SENSOR_READING_ERROR) {
opt_reading.raw = value;
@ -587,6 +585,7 @@ get_light_reading()
value % 100);
}
/* The OPT will turn itself off, so we don't need to call its DEACTIVATE */
ctimer_set(&opt_timer, next, init_light_reading, NULL);
}
/*---------------------------------------------------------------------------*/

View file

@ -59,12 +59,13 @@
#include "contiki-conf.h"
#include "sys/process.h"
#include "dev/serial-line.h"
#include "dev/cc26xx-uart.h"
#include "net/ip/uip.h"
#include "net/ip/uip-udp-packet.h"
#include "net/ip/uiplib.h"
#include "lpm.h"
#include "net-uart.h"
#include "httpd-simple.h"
#include "sys/cc.h"
#include "ti-lib.h"
@ -86,10 +87,6 @@
#define ADDRESS_CONVERSION_OK 1
#define ADDRESS_CONVERSION_ERROR 0
/*---------------------------------------------------------------------------*/
#ifndef MIN
#define MIN(n, m) (((n) < (m)) ? (n) : (m))
#endif
/*---------------------------------------------------------------------------*/
static struct uip_udp_conn *udp_conn = NULL;
static uint8_t buffer[MAX_MSG_SIZE];
@ -148,37 +145,16 @@ net_input(void)
return;
}
/*---------------------------------------------------------------------------*/
/*
* In order to maintain UART input operation:
* - Keep the uart clocked in sleep and deep sleep
* - Keep the serial PD on in deep sleep
*/
static lpm_power_domain_lock_t lock;
/*---------------------------------------------------------------------------*/
static void
release_uart(void)
{
/* Release serial PD lock */
lpm_pd_lock_release(&lock);
/* Let the UART turn off during Sleep and Deep Sleep */
ti_lib_prcm_peripheral_sleep_disable(PRCM_PERIPH_UART0);
ti_lib_prcm_peripheral_deep_sleep_disable(PRCM_PERIPH_UART0);
ti_lib_prcm_load_set();
while(!ti_lib_prcm_load_get());
cc26xx_uart_set_input(NULL);
}
/*---------------------------------------------------------------------------*/
static void
keep_uart_on(void)
{
/* Keep the serial PD on */
lpm_pd_lock_obtain(&lock, PRCM_DOMAIN_SERIAL);
/* Keep the UART clock on during Sleep and Deep Sleep */
ti_lib_prcm_peripheral_sleep_enable(PRCM_PERIPH_UART0);
ti_lib_prcm_peripheral_deep_sleep_enable(PRCM_PERIPH_UART0);
ti_lib_prcm_load_set();
while(!ti_lib_prcm_load_get());
cc26xx_uart_set_input(serial_line_input_byte);
}
/*---------------------------------------------------------------------------*/
static int

View file

@ -37,6 +37,7 @@
*/
#include <string.h>
#include "sys/cc.h"
#include "rest-engine.h"
#include "er-coap.h"
#include "er-plugtest.h"

View file

@ -38,6 +38,7 @@
*/
#include "contiki.h"
#include "sys/cc.h"
#include "net/netstack.h"
#include "net/rime/rime.h"
#include "net/rime/collect.h"
@ -120,8 +121,6 @@ PROCESS_THREAD(depth_blink_process, ev, data)
PROCESS_END();
}
/*---------------------------------------------------------------------------*/
#define MAX(a, b) ((a) > (b)? (a): (b))
#define MIN(a, b) ((a) < (b)? (a): (b))
struct spectrum {
int channel[16];
};

View file

@ -30,6 +30,7 @@
*/
#include "contiki-net.h"
#include "sys/cc.h"
#include <stdio.h>
#include <stdlib.h>
@ -104,7 +105,6 @@ PROCESS_THREAD(tcp_server_process, ev, data)
while(bytes_to_send > 0) {
PROCESS_PAUSE();
int len, tosend;
#define MIN(a,b) ((a)<(b)?(a):(b))
tosend = MIN(bytes_to_send, sizeof(outputbuf));
len = tcp_socket_send(&socket, (uint8_t *)"", tosend);
bytes_to_send -= len;

View file

@ -411,7 +411,7 @@ lcd_num_putdec(int numb, lcd_padding_t padding)
}
/* Convert to BCD */
bcd = itobcd(abs(numb));
bcd = itobcd(ABS(numb));
/* Print */
return lcd_num_print(bcd, (bool)(numb<0), padding);

View file

@ -48,6 +48,7 @@
#include "contiki.h"
#include "sys/cc.h"
#include "usb_drv.h"
#include "usb_descriptors.h"
#include "usb_specific_request.h"
@ -753,7 +754,7 @@ uint16_t p=(uint16_t)&__bss_end;
radio_get_rssi_value(&RSSI);
RSSI*=3;
#endif
maxRSSI[i-11]=Max(maxRSSI[i-11],RSSI);
maxRSSI[i-11]=MAX(maxRSSI[i-11],RSSI);
accRSSI[i-11]+=RSSI;
}
if(j&(1<<7)) {
@ -774,7 +775,7 @@ uint16_t p=(uint16_t)&__bss_end;
#endif
PRINTF_P(PSTR("\n"));
for(i=11;i<=26;i++) {
uint8_t activity=Min(maxRSSI[i-11],accRSSI[i-11]/(1<<7));
uint8_t activity=MIN(maxRSSI[i-11],accRSSI[i-11]/(1<<7));
PRINTF_P(PSTR(" %d: %02ddB "),i, -91+(maxRSSI[i-11]-1));
for(;activity--;maxRSSI[i-11]--) {
PRINTF_P(PSTR("#"));

View file

@ -76,7 +76,7 @@ The toolchain used to build contiki is arm-gcc, also used by other arm-based Con
The platform is currently being used/tested with "GNU Tools for ARM Embedded Processors". This is the recommended version and the one being used by Contiki's regression tests on Travis. <https://launchpad.net/gcc-arm-embedded>
The older version (Sourcery G++ Lite 2008q3-66) shown above should still work, but the port is no longer being tested with it.
The older version (Sourcery G++ Lite 2008q3-66) shown above should still work, but the port is no longer being tested with it. <http://sourcery.mentor.com/public/gnu_toolchain/arm-none-eabi>
Drivers
-------

View file

@ -28,7 +28,7 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
/**
* \addtogroup cc2538dk
* @{
*
@ -78,28 +78,28 @@
#undef LEDS_RED
#undef LEDS_CONF_ALL
#define LEDS_YELLOW 2 /**< LED2 (Yellow) -> PC1 */
#define LEDS_GREEN 4 /**< LED3 (Green) -> PC2 */
#define LEDS_ORANGE 8 /**< LED4 (Orange) -> PC3 */
#define LEDS_YELLOW 2 /**< LED2 (Yellow) -> PC1 */
#define LEDS_GREEN 4 /**< LED3 (Green) -> PC2 */
#define LEDS_ORANGE 8 /**< LED4 (Orange) -> PC3 */
#if USB_SERIAL_CONF_ENABLE
#define LEDS_CONF_ALL 14
#define LEDS_RED LEDS_ORANGE
#define LEDS_CONF_ALL 14
#define LEDS_RED LEDS_ORANGE
#else
#define LEDS_CONF_ALL 15
#define LEDS_RED 1 /**< LED1 (Red) -> PC0 */
#define LEDS_CONF_ALL 15
#define LEDS_RED 1 /**< LED1 (Red) -> PC0 */
#endif
/* Notify various examples that we have LEDs */
#define PLATFORM_HAS_LEDS 1
#define PLATFORM_HAS_LEDS 1
/** @} */
/*---------------------------------------------------------------------------*/
/** \name USB configuration
*
* The USB pullup is driven by PC0 and is shared with LED1
*/
#define USB_PULLUP_PORT GPIO_C_NUM
#define USB_PULLUP_PIN 0
#define USB_PULLUP_PORT GPIO_C_NUM
#define USB_PULLUP_PIN 0
/** @} */
/*---------------------------------------------------------------------------*/
/** \name UART configuration
@ -115,17 +115,17 @@
* UART1_* below.
* @{
*/
#define UART0_RX_PORT GPIO_A_NUM
#define UART0_RX_PIN 0
#define UART0_RX_PORT GPIO_A_NUM
#define UART0_RX_PIN 0
#define UART0_TX_PORT GPIO_A_NUM
#define UART0_TX_PIN 1
#define UART0_TX_PORT GPIO_A_NUM
#define UART0_TX_PIN 1
#define UART1_CTS_PORT GPIO_B_NUM
#define UART1_CTS_PIN 0
#define UART1_CTS_PORT GPIO_B_NUM
#define UART1_CTS_PIN 0
#define UART1_RTS_PORT GPIO_D_NUM
#define UART1_RTS_PIN 3
#define UART1_RTS_PORT GPIO_D_NUM
#define UART1_RTS_PIN 3
/** @} */
/*---------------------------------------------------------------------------*/
/** \name SmartRF Button configuration
@ -139,32 +139,32 @@
* @{
*/
/** BUTTON_SELECT -> PA3 */
#define BUTTON_SELECT_PORT GPIO_A_NUM
#define BUTTON_SELECT_PIN 3
#define BUTTON_SELECT_VECTOR NVIC_INT_GPIO_PORT_A
#define BUTTON_SELECT_PORT GPIO_A_NUM
#define BUTTON_SELECT_PIN 3
#define BUTTON_SELECT_VECTOR NVIC_INT_GPIO_PORT_A
/** BUTTON_LEFT -> PC4 */
#define BUTTON_LEFT_PORT GPIO_C_NUM
#define BUTTON_LEFT_PIN 4
#define BUTTON_LEFT_VECTOR NVIC_INT_GPIO_PORT_C
#define BUTTON_LEFT_PORT GPIO_C_NUM
#define BUTTON_LEFT_PIN 4
#define BUTTON_LEFT_VECTOR NVIC_INT_GPIO_PORT_C
/** BUTTON_RIGHT -> PC5 */
#define BUTTON_RIGHT_PORT GPIO_C_NUM
#define BUTTON_RIGHT_PIN 5
#define BUTTON_RIGHT_VECTOR NVIC_INT_GPIO_PORT_C
#define BUTTON_RIGHT_PORT GPIO_C_NUM
#define BUTTON_RIGHT_PIN 5
#define BUTTON_RIGHT_VECTOR NVIC_INT_GPIO_PORT_C
/** BUTTON_UP -> PC6 */
#define BUTTON_UP_PORT GPIO_C_NUM
#define BUTTON_UP_PIN 6
#define BUTTON_UP_VECTOR NVIC_INT_GPIO_PORT_C
#define BUTTON_UP_PORT GPIO_C_NUM
#define BUTTON_UP_PIN 6
#define BUTTON_UP_VECTOR NVIC_INT_GPIO_PORT_C
/** BUTTON_DOWN -> PC7 */
#define BUTTON_DOWN_PORT GPIO_C_NUM
#define BUTTON_DOWN_PIN 7
#define BUTTON_DOWN_VECTOR NVIC_INT_GPIO_PORT_C
#define BUTTON_DOWN_PORT GPIO_C_NUM
#define BUTTON_DOWN_PIN 7
#define BUTTON_DOWN_VECTOR NVIC_INT_GPIO_PORT_C
/* Notify various examples that we have Buttons */
#define PLATFORM_HAS_BUTTON 1
#define PLATFORM_HAS_BUTTON 1
/** @} */
/*---------------------------------------------------------------------------*/
/**
@ -176,23 +176,49 @@
* ADC inputs can only be on port A.
* @{
*/
#define ADC_ALS_PWR_PORT GPIO_A_NUM /**< ALS power GPIO control port */
#define ADC_ALS_PWR_PIN 7 /**< ALS power GPIO control pin */
#define ADC_ALS_OUT_PIN 6 /**< ALS output ADC input pin on port A */
#define ADC_ALS_PWR_PORT GPIO_A_NUM /**< ALS power GPIO control port */
#define ADC_ALS_PWR_PIN 7 /**< ALS power GPIO control pin */
#define ADC_ALS_OUT_PIN 6 /**< ALS output ADC input pin on port A */
/** @} */
/*---------------------------------------------------------------------------*/
/**
* \name SPI configuration
*
* These values configure which CC2538 pins to use for the SPI lines.
* These values configure which CC2538 pins to use for the SPI lines. Both
* SPI instances can be used independently by providing the corresponding
* port / pin macros.
* @{
*/
#define SPI_CLK_PORT GPIO_A_NUM /**< Clock port */
#define SPI_CLK_PIN 2 /**< Clock pin */
#define SPI_MOSI_PORT GPIO_A_NUM /**< MOSI port */
#define SPI_MOSI_PIN 4 /**< MOSI pin */
#define SPI_MISO_PORT GPIO_A_NUM /**< MISO port */
#define SPI_MISO_PIN 5 /**< MISO pin */
#define SPI0_IN_USE 0
#define SPI1_IN_USE 0
#if SPI0_IN_USE
/** Clock port SPI0 */
#define SPI0_CLK_PORT GPIO_A_NUM
/** Clock pin SPI0 */
#define SPI0_CLK_PIN 2
/** TX port SPI0 (master mode: MOSI) */
#define SPI0_TX_PORT GPIO_A_NUM
/** TX pin SPI0 */
#define SPI0_TX_PIN 4
/** RX port SPI0 (master mode: MISO */
#define SPI0_RX_PORT GPIO_A_NUM
/** RX pin SPI0 */
#define SPI0_RX_PIN 5
#endif /* #if SPI0_IN_USE */
#if SPI1_IN_USE
/** Clock port SPI1 */
#define SPI1_CLK_PORT GPIO_A_NUM
/** Clock pin SPI1 */
#define SPI1_CLK_PIN 2
/** TX port SPI1 (master mode: MOSI) */
#define SPI1_TX_PORT GPIO_A_NUM
/** TX pin SPI1 */
#define SPI1_TX_PIN 4
/** RX port SPI1 (master mode: MISO) */
#define SPI1_RX_PORT GPIO_A_NUM
/** RX pin SPI1 */
#define SPI1_RX_PIN 5
#endif /* #if SPI1_IN_USE */
/** @} */
/*---------------------------------------------------------------------------*/
/**

View file

@ -40,6 +40,7 @@
#include <string.h>
#include "contiki.h"
#include "sys/cc.h"
#include "sys/clock.h"
#include "sys/etimer.h"
@ -136,8 +137,6 @@ long referenceVar;
static struct cooja_mt_thread rtimer_thread;
static struct cooja_mt_thread process_run_thread;
#define MIN(a, b) ( (a)<(b) ? (a) : (b) )
/*---------------------------------------------------------------------------*/
#if NETSTACK_CONF_WITH_IPV4
static void

View file

@ -37,18 +37,6 @@
#ifndef HAL_LCD_H
#define HAL_LCD_H
#ifndef MIN
# define MIN(n, m) (((n) < (m)) ? (n) : (m))
#endif
#ifndef MAX
# define MAX(n, m) (((n) < (m)) ? (m) : (n))
#endif
#ifndef ABS
# define ABS(n) (((n) < 0) ? -(n) : (n))
#endif
#define LCD_BACKLT_OUT P8OUT
#define LCD_BACKLT_DIR P8DIR
#define LCD_BACKLT_SEL P8SEL

View file

@ -46,6 +46,7 @@
#include "lpm.h"
#include "gpio-interrupt.h"
#include "dev/watchdog.h"
#include "dev/oscillators.h"
#include "ieee-addr.h"
#include "vims.h"
#include "cc26xx-model.h"
@ -119,23 +120,6 @@ set_rf_params(void)
#endif
}
/*---------------------------------------------------------------------------*/
static void
select_lf_xosc(void)
{
ti_lib_osc_interface_enable();
/* Make sure the SMPH clock within AUX is enabled */
ti_lib_aux_wuc_clock_enable(AUX_WUC_SMPH_CLOCK);
while(ti_lib_aux_wuc_clock_status(AUX_WUC_SMPH_CLOCK) != AUX_WUC_CLOCK_READY);
/* Switch LF clock source to the LF RCOSC if required */
if(ti_lib_osc_clock_source_get(OSC_SRC_CLK_LF) != OSC_XOSC_LF) {
ti_lib_osc_clock_source_set(OSC_SRC_CLK_LF, OSC_XOSC_LF);
}
ti_lib_osc_interface_disable();
}
/*---------------------------------------------------------------------------*/
/**
* \brief Main function for CC26xx-based platforms
*
@ -144,41 +128,39 @@ select_lf_xosc(void)
int
main(void)
{
/* Enable flash cache and prefetch. */
ti_lib_vims_mode_set(VIMS_BASE, VIMS_MODE_ENABLED);
ti_lib_vims_configure(VIMS_BASE, true, true);
ti_lib_int_master_disable();
/* Set the LF XOSC as the LF system clock source */
select_lf_xosc();
/*
* Make sure to open the latches - this will be important when returning
* from shutdown
*/
ti_lib_pwr_ctrl_io_freeze_disable();
/* Use DCDC instead of LDO to save current */
ti_lib_pwr_ctrl_source_set(PWRCTRL_PWRSRC_DCDC);
oscillators_select_lf_xosc();
lpm_init();
board_init();
/* Enable flash cache and prefetch. */
ti_lib_vims_mode_set(VIMS_BASE, VIMS_MODE_ENABLED);
ti_lib_vims_configure(VIMS_BASE, true, true);
gpio_interrupt_init();
/* Clock must always be enabled for the semaphore module */
HWREG(AUX_WUC_BASE + AUX_WUC_O_MODCLKEN1) = AUX_WUC_MODCLKEN1_SMPH;
leds_init();
/*
* Disable I/O pad sleep mode and open I/O latches in the AON IOC interface
* This is only relevant when returning from shutdown (which is what froze
* latches in the first place. Before doing these things though, we should
* allow software to first regain control of pins
*/
ti_lib_pwr_ctrl_io_freeze_disable();
fade(LEDS_RED);
ti_lib_int_master_enable();
cc26xx_rtc_init();
clock_init();
rtimer_init();
board_init();
watchdog_init();
process_init();
@ -187,7 +169,6 @@ main(void)
/* Character I/O Initialisation */
#if CC26XX_UART_CONF_ENABLE
cc26xx_uart_init();
cc26xx_uart_set_input(serial_line_input_byte);
#endif
serial_line_init();

View file

@ -136,7 +136,7 @@ static int enabled = SENSOR_STATUS_DISABLED;
static uint8_t sensor_value[SENSOR_DATA_BUF_SIZE];
/*---------------------------------------------------------------------------*/
/* Wait SENSOR_STARTUP_DELAY clock ticks for the sensor to be ready - ~80ms */
#define SENSOR_STARTUP_DELAY 11
#define SENSOR_STARTUP_DELAY 3
static struct ctimer startup_timer;
/*---------------------------------------------------------------------------*/
@ -187,7 +187,7 @@ enable_sensor(bool enable)
if(enable) {
/* Enable forced mode */
val = PM_NORMAL | OSRSP(1) | OSRST(1);
val = PM_FORCED | OSRSP(1) | OSRST(1);
} else {
val = PM_OFF;
}
@ -345,6 +345,7 @@ configure(int type, int enable)
case SENSORS_HW_INIT:
enabled = SENSOR_STATUS_INITIALISED;
init();
enable_sensor(0);
break;
case SENSORS_ACTIVE:
/* Must be initialised first */

View file

@ -42,12 +42,10 @@
*
* Once the sensor is stable, the driver will generate a sensors_changed event.
*
* Once a reading has been taken, the caller has two options:
* - Turn the sensor off by calling SENSORS_DEACTIVATE, but in order to take
* subsequent readings SENSORS_ACTIVATE must be called again
* - Leave the sensor on. In this scenario, the caller can simply keep calling
* value() for subsequent readings, but having the sensor on will consume
* energy
* We take readings in "Forced" mode. In this mode, the BMP will take a single
* measurement and it will then automatically go to sleep.
*
* SENSORS_ACTIVATE must be called again to trigger a new reading cycle
* @{
*
* \file

View file

@ -39,9 +39,55 @@
#include "contiki-conf.h"
#include "ti-lib.h"
#include "board-i2c.h"
#include "lpm.h"
#include <string.h>
#include <stdbool.h>
/*---------------------------------------------------------------------------*/
#define NO_INTERFACE 0xFF
/*---------------------------------------------------------------------------*/
static uint8_t slave_addr = 0x00;
static uint8_t interface = 0xFF;
static uint8_t interface = NO_INTERFACE;
/*---------------------------------------------------------------------------*/
static bool
accessible(void)
{
/* First, check the PD */
if(ti_lib_prcm_power_domain_status(PRCM_DOMAIN_SERIAL)
!= PRCM_DOMAIN_POWER_ON) {
return false;
}
/* Then check the 'run mode' clock gate */
if(!(HWREG(PRCM_BASE + PRCM_O_I2CCLKGR) & PRCM_I2CCLKGR_CLK_EN)) {
return false;
}
return true;
}
/*---------------------------------------------------------------------------*/
void
board_i2c_wakeup()
{
/* First, make sure the SERIAL PD is on */
ti_lib_prcm_power_domain_on(PRCM_DOMAIN_SERIAL);
while((ti_lib_prcm_power_domain_status(PRCM_DOMAIN_SERIAL)
!= PRCM_DOMAIN_POWER_ON));
/* Enable the clock to I2C */
ti_lib_prcm_peripheral_run_enable(PRCM_PERIPH_I2C0);
ti_lib_prcm_load_set();
while(!ti_lib_prcm_load_get());
/* Reset the I2C controller */
HWREG(PRCM_BASE + PRCM_O_RESETI2C) = PRCM_RESETI2C_I2C;
/* Enable and initialize the I2C master module */
ti_lib_i2c_master_init_exp_clk(I2C0_BASE,
ti_lib_sys_ctrl_peripheral_clock_get(
PRCM_PERIPH_I2C0, SYSCTRL_SYSBUS_ON),
true);
}
/*---------------------------------------------------------------------------*/
static bool
i2c_status()
@ -57,21 +103,34 @@ i2c_status()
}
/*---------------------------------------------------------------------------*/
void
board_i2c_init()
board_i2c_shutdown()
{
/* The I2C peripheral must be enabled */
ti_lib_prcm_peripheral_run_enable(PRCM_PERIPH_I2C0);
interface = NO_INTERFACE;
if(accessible()) {
ti_lib_i2c_master_disable(I2C0_BASE);
}
ti_lib_prcm_peripheral_run_disable(PRCM_PERIPH_I2C0);
ti_lib_prcm_load_set();
while(!ti_lib_prcm_load_get());
/* Reset the I2C controller */
HWREG(PRCM_BASE + PRCM_O_RESETI2C) = PRCM_RESETI2C_I2C;
/*
* Set all pins to GPIO Input and disable the output driver. Set internal
* pull to match external pull
*
* SDA and SCL: external PU resistor
* SDA HP and SCL HP: MPU PWR low
*/
ti_lib_ioc_pin_type_gpio_input(BOARD_IOID_SDA_HP);
ti_lib_ioc_io_port_pull_set(BOARD_IOID_SDA_HP, IOC_IOPULL_DOWN);
ti_lib_ioc_pin_type_gpio_input(BOARD_IOID_SCL_HP);
ti_lib_ioc_io_port_pull_set(BOARD_IOID_SCL_HP, IOC_IOPULL_DOWN);
/* Enable and initialize the I2C master module */
ti_lib_i2c_master_init_exp_clk(I2C0_BASE,
ti_lib_sys_ctrl_peripheral_clock_get(
PRCM_PERIPH_I2C0, SYSCTRL_SYSBUS_ON),
true);
ti_lib_ioc_pin_type_gpio_input(BOARD_IOID_SDA);
ti_lib_ioc_io_port_pull_set(BOARD_IOID_SDA, IOC_IOPULL_UP);
ti_lib_ioc_pin_type_gpio_input(BOARD_IOID_SCL);
ti_lib_ioc_io_port_pull_set(BOARD_IOID_SCL, IOC_IOPULL_UP);
}
/*---------------------------------------------------------------------------*/
bool
@ -248,8 +307,15 @@ board_i2c_select(uint8_t new_interface, uint8_t address)
{
slave_addr = address;
if(accessible() == false) {
board_i2c_wakeup();
}
if(new_interface != interface) {
interface = new_interface;
ti_lib_i2c_master_disable(I2C0_BASE);
if(interface == BOARD_I2C_INTERFACE_0) {
ti_lib_ioc_io_port_pull_set(BOARD_IOID_SDA, IOC_NO_IOPULL);
ti_lib_ioc_io_port_pull_set(BOARD_IOID_SCL, IOC_NO_IOPULL);
@ -263,6 +329,12 @@ board_i2c_select(uint8_t new_interface, uint8_t address)
ti_lib_ioc_pin_type_gpio_input(BOARD_IOID_SDA);
ti_lib_ioc_pin_type_gpio_input(BOARD_IOID_SCL);
}
/* Enable and initialize the I2C master module */
ti_lib_i2c_master_init_exp_clk(I2C0_BASE,
ti_lib_sys_ctrl_peripheral_clock_get(
PRCM_PERIPH_I2C0, SYSCTRL_SYSBUS_ON),
true);
}
}
/*---------------------------------------------------------------------------*/

View file

@ -48,13 +48,15 @@
#define BOARD_I2C_INTERFACE_0 0
#define BOARD_I2C_INTERFACE_1 1
/*---------------------------------------------------------------------------*/
#define board_i2c_deselect(...)
/*---------------------------------------------------------------------------*/
/**
* \brief Initialise the I2C controller with defaults for the sensortag
* \brief Put the I2C controller in a known state
*
* In this state, pins SDA and SCL will be under i2c control and pins SDA HP
* and SCL HP will be configured as gpio inputs. This is equal to selecting
* BOARD_I2C_INTERFACE_0, but without selecting a slave device address
*/
void board_i2c_init(void);
#define board_i2c_deselect() board_i2c_select(BOARD_I2C_INTERFACE_0, 0)
/*---------------------------------------------------------------------------*/
/**
* \brief Select an I2C slave
* \param interface The I2C interface to be used (BOARD_I2C_INTERFACE_0 or _1)
@ -99,6 +101,27 @@ bool board_i2c_write_single(uint8_t data);
*/
bool board_i2c_write_read(uint8_t *wdata, uint8_t wlen, uint8_t *rdata,
uint8_t rlen);
/**
* \brief Enables the I2C peripheral with defaults
*
* This function is called to wakeup and initialise the I2C.
*
* This function can be called explicitly, but it will also be called
* automatically by board_i2c_select() when required. One of those two
* functions MUST be called before any other I2C operation after a chip
* sleep / wakeup cycle or after a call to board_i2c_shutdown(). Failing to do
* so will lead to a bus fault.
*/
void board_i2c_wakeup(void);
/**
* \brief Stops the I2C peripheral and restores pins to s/w control
*
* This function is called automatically by the board's LPM logic, but it
* can also be called explicitly.
*/
void board_i2c_shutdown(void);
/*---------------------------------------------------------------------------*/
#endif /* BOARD_I2C_H_ */
/*---------------------------------------------------------------------------*/

View file

@ -40,12 +40,35 @@
#include "ti-lib.h"
#include "board-spi.h"
#include "board.h"
#include <stdbool.h>
/*---------------------------------------------------------------------------*/
#define CPU_FREQ 48000000ul
/*---------------------------------------------------------------------------*/
static bool
accessible(void)
{
/* First, check the PD */
if(ti_lib_prcm_power_domain_status(PRCM_DOMAIN_SERIAL)
!= PRCM_DOMAIN_POWER_ON) {
return false;
}
/* Then check the 'run mode' clock gate */
if(!(HWREG(PRCM_BASE + PRCM_O_SSICLKGR) & PRCM_SSICLKGR_CLK_EN_SSI0)) {
return false;
}
return true;
}
/*---------------------------------------------------------------------------*/
int
board_spi_write(const uint8_t *buf, size_t len)
{
if(accessible() == false) {
return 0;
}
while(len > 0) {
uint32_t ul;
@ -61,6 +84,10 @@ board_spi_write(const uint8_t *buf, size_t len)
int
board_spi_read(uint8_t *buf, size_t len)
{
if(accessible() == false) {
return 0;
}
while(len > 0) {
uint32_t ul;
@ -79,6 +106,10 @@ board_spi_read(uint8_t *buf, size_t len)
void
board_spi_flush()
{
if(accessible() == false) {
return;
}
uint32_t ul;
while(ti_lib_rom_ssi_data_get_non_blocking(SSI0_BASE, &ul));
}
@ -88,7 +119,12 @@ board_spi_open(uint32_t bit_rate, uint32_t clk_pin)
{
uint32_t buf;
/* SPI power */
/* First, make sure the SERIAL PD is on */
ti_lib_prcm_power_domain_on(PRCM_DOMAIN_SERIAL);
while((ti_lib_prcm_power_domain_status(PRCM_DOMAIN_SERIAL)
!= PRCM_DOMAIN_POWER_ON));
/* Enable clock in active mode */
ti_lib_rom_prcm_peripheral_run_enable(PRCM_PERIPH_SSI0);
ti_lib_prcm_load_set();
while(!ti_lib_prcm_load_get());
@ -113,6 +149,16 @@ board_spi_close()
ti_lib_rom_prcm_peripheral_run_disable(PRCM_PERIPH_SSI0);
ti_lib_prcm_load_set();
while(!ti_lib_prcm_load_get());
/* Restore pins to a low-consumption state */
ti_lib_ioc_pin_type_gpio_input(BOARD_IOID_SPI_MISO);
ti_lib_ioc_io_port_pull_set(BOARD_IOID_SPI_MISO, IOC_IOPULL_DOWN);
ti_lib_ioc_pin_type_gpio_input(BOARD_IOID_SPI_MOSI);
ti_lib_ioc_io_port_pull_set(BOARD_IOID_SPI_MOSI, IOC_IOPULL_DOWN);
ti_lib_ioc_pin_type_gpio_input(BOARD_IOID_SPI_CLK_FLASH);
ti_lib_ioc_io_port_pull_set(BOARD_IOID_SPI_CLK_FLASH, IOC_IOPULL_DOWN);
}
/*---------------------------------------------------------------------------*/
/** @} */

View file

@ -46,17 +46,16 @@
#include <stdint.h>
#include <string.h>
/*---------------------------------------------------------------------------*/
#define PRCM_DOMAINS (PRCM_DOMAIN_SERIAL | PRCM_DOMAIN_PERIPH)
#include <stdbool.h>
/*---------------------------------------------------------------------------*/
static void
power_domains_on(void)
{
/* Turn on relevant power domains */
ti_lib_prcm_power_domain_on(PRCM_DOMAINS);
/* Turn on the PERIPH PD */
ti_lib_prcm_power_domain_on(PRCM_DOMAIN_PERIPH);
/* Wait for domains to power on */
while((ti_lib_prcm_power_domain_status(PRCM_DOMAINS)
while((ti_lib_prcm_power_domain_status(PRCM_DOMAIN_PERIPH)
!= PRCM_DOMAIN_POWER_ON));
}
/*---------------------------------------------------------------------------*/
@ -64,8 +63,6 @@ static void
lpm_wakeup_handler(void)
{
power_domains_on();
board_i2c_init();
}
/*---------------------------------------------------------------------------*/
static void
@ -77,8 +74,12 @@ shutdown_handler(uint8_t mode)
SENSORS_DEACTIVATE(opt_3001_sensor);
SENSORS_DEACTIVATE(tmp_007_sensor);
SENSORS_DEACTIVATE(hdc_1000_sensor);
mpu_9250_sensor.configure(MPU_9250_SENSOR_SHUTDOWN, 0);
SENSORS_DEACTIVATE(mpu_9250_sensor);
ti_lib_gpio_pin_clear(BOARD_MPU_POWER);
}
/* In all cases, stop the I2C */
board_i2c_shutdown();
}
/*---------------------------------------------------------------------------*/
/*
@ -88,13 +89,47 @@ shutdown_handler(uint8_t mode)
* wake up so we can turn power domains back on for I2C and SSI, and to make
* sure everything on the board is off before CM3 shutdown.
*/
LPM_MODULE(sensortag_module, NULL, shutdown_handler, lpm_wakeup_handler);
LPM_MODULE(sensortag_module, NULL, shutdown_handler, lpm_wakeup_handler,
LPM_DOMAIN_NONE);
/*---------------------------------------------------------------------------*/
static void
configure_unused_pins(void)
{
/* DP[0..3] */
ti_lib_ioc_pin_type_gpio_input(BOARD_IOID_DP0);
ti_lib_ioc_io_port_pull_set(BOARD_IOID_DP0, IOC_IOPULL_DOWN);
ti_lib_ioc_pin_type_gpio_input(BOARD_IOID_DP1);
ti_lib_ioc_io_port_pull_set(BOARD_IOID_DP1, IOC_IOPULL_DOWN);
ti_lib_ioc_pin_type_gpio_input(BOARD_IOID_DP2);
ti_lib_ioc_io_port_pull_set(BOARD_IOID_DP2, IOC_IOPULL_DOWN);
ti_lib_ioc_pin_type_gpio_input(BOARD_IOID_DP3);
ti_lib_ioc_io_port_pull_set(BOARD_IOID_DP3, IOC_IOPULL_DOWN);
/* Devpack ID */
ti_lib_ioc_pin_type_gpio_input(BOARD_IOID_DEVPK_ID);
ti_lib_ioc_io_port_pull_set(BOARD_IOID_DEVPK_ID, IOC_IOPULL_UP);
/* Digital Microphone */
ti_lib_ioc_pin_type_gpio_output(BOARD_IOID_MIC_POWER);
ti_lib_gpio_pin_clear((1 << BOARD_IOID_MIC_POWER));
ti_lib_ioc_io_drv_strength_set(BOARD_IOID_MIC_POWER, IOC_CURRENT_2MA,
IOC_STRENGTH_MIN);
ti_lib_ioc_pin_type_gpio_input(BOARD_IOID_AUDIO_DI);
ti_lib_ioc_io_port_pull_set(BOARD_IOID_AUDIO_DI, IOC_IOPULL_DOWN);
ti_lib_ioc_pin_type_gpio_input(BOARD_IOID_AUDIO_CLK);
ti_lib_ioc_io_port_pull_set(BOARD_IOID_AUDIO_CLK, IOC_IOPULL_DOWN);
/* UART over Devpack - TX only (ToDo: Map all UART pins to Debugger) */
ti_lib_ioc_pin_type_gpio_input(BOARD_IOID_DP5_UARTTX);
ti_lib_ioc_io_port_pull_set(BOARD_IOID_DP5_UARTTX, IOC_IOPULL_DOWN);
}
/*---------------------------------------------------------------------------*/
void
board_init()
{
/* Disable global interrupts */
uint8_t int_disabled = ti_lib_int_master_disable();
bool int_disabled = ti_lib_int_master_disable();
power_domains_on();
@ -112,37 +147,19 @@ board_init()
ti_lib_prcm_load_set();
while(!ti_lib_prcm_load_get());
/* Enable GPT0 module - Wait for the clock to be enabled */
ti_lib_prcm_peripheral_run_enable(PRCM_PERIPH_TIMER0);
ti_lib_prcm_load_set();
while(!ti_lib_prcm_load_get());
/* Keys (input pullup) */
ti_lib_rom_ioc_pin_type_gpio_input(BOARD_IOID_KEY_LEFT);
ti_lib_rom_ioc_pin_type_gpio_input(BOARD_IOID_KEY_RIGHT);
ti_lib_ioc_io_port_pull_set(BOARD_IOID_KEY_LEFT, IOC_IOPULL_UP);
ti_lib_ioc_io_port_pull_set(BOARD_IOID_KEY_RIGHT, IOC_IOPULL_UP);
/* I2C controller */
board_i2c_init();
/* Sensor interface */
ti_lib_rom_ioc_pin_type_gpio_input(BOARD_IOID_MPU_INT);
ti_lib_ioc_io_port_pull_set(BOARD_IOID_MPU_INT, IOC_IOPULL_DOWN);
ti_lib_rom_ioc_pin_type_gpio_input(BOARD_IOID_REED_RELAY);
ti_lib_ioc_io_port_pull_set(BOARD_IOID_REED_RELAY, IOC_IOPULL_DOWN);
ti_lib_rom_ioc_pin_type_gpio_output(BOARD_IOID_MPU_POWER);
/* Flash interface */
ti_lib_rom_ioc_pin_type_gpio_output(BOARD_IOID_FLASH_CS);
ti_lib_gpio_pin_write(BOARD_FLASH_CS, 1);
board_i2c_wakeup();
buzzer_init();
/* Make sure the external flash is in the lower power mode */
ext_flash_init();
lpm_register_module(&sensortag_module);
/* For unsupported peripherals, select a default pin configuration */
configure_unused_pins();
/* Re-enable interrupt if initially enabled. */
if(!int_disabled) {
ti_lib_int_master_enable();

View file

@ -100,12 +100,16 @@
* Those values are not meant to be modified by the user
* @{
*/
#define BOARD_IOID_UART_RX IOID_17
#define BOARD_IOID_DP4_UARTRX IOID_28
#define BOARD_IOID_DP5_UARTTX IOID_29
#define BOARD_IOID_UART_RX BOARD_IOID_DP4_UARTRX
#define BOARD_IOID_UART_TX IOID_16
#define BOARD_IOID_UART_CTS IOID_UNUSED
#define BOARD_IOID_UART_RTS IOID_UNUSED
#define BOARD_UART_RXD (1 << BOARD_IOID_UART_RXD)
#define BOARD_UART_TXD (1 << BOARD_IOID_UART_TXD)
#define BOARD_UART_RX (1 << BOARD_IOID_UART_RX)
#define BOARD_UART_TX (1 << BOARD_IOID_UART_TX)
#define BOARD_UART_CTS (1 << BOARD_IOID_UART_CTS)
#define BOARD_UART_RTS (1 << BOARD_IOID_UART_RTS)
/** @} */
@ -156,7 +160,7 @@
*/
#define BOARD_IOID_FLASH_CS IOID_14
#define BOARD_FLASH_CS (1 << BOARD_IOID_FLASH_CS)
#define BOARD_SPI_CLK_FLASH IOID_11
#define BOARD_IOID_SPI_CLK_FLASH IOID_17
/** @} */
/*---------------------------------------------------------------------------*/
/**
@ -183,6 +187,44 @@
#define BOARD_MPU_POWER (1 << BOARD_IOID_MPU_POWER)
/** @} */
/*---------------------------------------------------------------------------*/
/**
* \brief Board devpack IOID mappings (LCD etc.)
*
* Those values are not meant to be modified by the user
* @{
*/
#define BOARD_IOID_AUDIOFS_TDO IOID_16
#define BOARD_IOID_DEVPACK_CS IOID_20
#define BOARD_IOID_DEVPK_LCD_EXTCOMIN IOID_22
#define BOARD_IOID_AUDIODO IOID_22
#define BOARD_IOID_DP2 IOID_23
#define BOARD_IOID_DP1 IOID_24
#define BOARD_IOID_DP0 IOID_25
#define BOARD_IOID_DP3 IOID_27
#define BOARD_IOID_DEVPK_ID IOID_30
#define BOARD_DEVPACK_CS (1 << BOARD_IOID_DEVPACK_CS)
/** @} */
/*---------------------------------------------------------------------------*/
/**
* \brief TMP Sensor
*
* Those values are not meant to be modified by the user
* @{
*/
#define BOARD_IOID_TMP_RDY IOID_1
/** @} */
/*---------------------------------------------------------------------------*/
/**
* \brief Digital Microphone
*
* Those values are not meant to be modified by the user
* @{
*/
#define BOARD_IOID_MIC_POWER IOID_13
#define BOARD_IOID_AUDIO_DI IOID_2
#define BOARD_IOID_AUDIO_CLK IOID_11
/** @} */
/*---------------------------------------------------------------------------*/
/**
* \name Device string used on startup
* @{

View file

@ -55,7 +55,7 @@
/*---------------------------------------------------------------------------*/
#define BUTTON_GPIO_CFG (IOC_CURRENT_2MA | IOC_STRENGTH_AUTO | \
IOC_IOPULL_UP | IOC_SLEW_DISABLE | \
IOC_HYST_DISABLE | IOC_BOTH_EDGES | \
IOC_HYST_ENABLE | IOC_BOTH_EDGES | \
IOC_INT_ENABLE | IOC_IOMODE_NORMAL | \
IOC_NO_WAKE_UP | IOC_INPUT_ENABLE | \
IOC_JTAG_DISABLE)
@ -116,7 +116,7 @@ button_press_handler(uint8_t ioid)
sensors_changed(&button_right_sensor);
}
} else {
lpm_shutdown(BOARD_IOID_KEY_RIGHT);
lpm_shutdown(BOARD_IOID_KEY_RIGHT, IOC_IOPULL_UP, IOC_WAKE_ON_LOW);
}
}
}

View file

@ -46,19 +46,12 @@
#include <stdio.h>
/*---------------------------------------------------------------------------*/
static uint8_t buzzer_on;
static lpm_power_domain_lock_t lock;
LPM_MODULE(buzzer_module, NULL, NULL, NULL, LPM_DOMAIN_PERIPH);
/*---------------------------------------------------------------------------*/
void
buzzer_init()
{
buzzer_on = 0;
/* Drive the I/O ID with GPT0 / Timer A */
ti_lib_ioc_port_configure_set(BOARD_IOID_BUZZER, IOC_PORT_MCU_PORT_EVENT0,
IOC_STD_OUTPUT);
/* GPT0 / Timer A: PWM, Interrupt Enable */
HWREG(GPT0_BASE + GPT_O_TAMR) = (TIMER_CFG_A_PWM & 0xFF) | GPT_TAMR_TAPWMIE;
}
/*---------------------------------------------------------------------------*/
uint8_t
@ -72,9 +65,28 @@ buzzer_start(int freq)
{
uint32_t load;
/* Enable GPT0 clocks under active, sleep, deep sleep */
ti_lib_prcm_peripheral_run_enable(PRCM_PERIPH_TIMER0);
ti_lib_prcm_peripheral_sleep_enable(PRCM_PERIPH_TIMER0);
ti_lib_prcm_peripheral_deep_sleep_enable(PRCM_PERIPH_TIMER0);
ti_lib_prcm_load_set();
while(!ti_lib_prcm_load_get());
/* Drive the I/O ID with GPT0 / Timer A */
ti_lib_ioc_port_configure_set(BOARD_IOID_BUZZER, IOC_PORT_MCU_PORT_EVENT0,
IOC_STD_OUTPUT);
/* GPT0 / Timer A: PWM, Interrupt Enable */
HWREG(GPT0_BASE + GPT_O_TAMR) = (TIMER_CFG_A_PWM & 0xFF) | GPT_TAMR_TAPWMIE;
buzzer_on = 1;
lpm_pd_lock_obtain(&lock, PRCM_DOMAIN_PERIPH);
/*
* Register ourself with LPM. This will keep the PERIPH PD powered on
* during deep sleep, allowing the buzzer to keep working while the chip is
* being power-cycled
*/
lpm_register_module(&buzzer_module);
/* Stop the timer */
ti_lib_timer_disable(GPT0_BASE, TIMER_A);
@ -88,12 +100,6 @@ buzzer_start(int freq)
/* Start */
ti_lib_timer_enable(GPT0_BASE, TIMER_A);
}
/* Run in sleep mode */
ti_lib_prcm_peripheral_sleep_enable(PRCM_PERIPH_TIMER0);
ti_lib_prcm_peripheral_deep_sleep_enable(PRCM_PERIPH_TIMER0);
ti_lib_prcm_load_set();
while(!ti_lib_prcm_load_get());
}
/*---------------------------------------------------------------------------*/
void
@ -101,24 +107,37 @@ buzzer_stop()
{
buzzer_on = 0;
lpm_pd_lock_release(&lock);
/*
* Unregister the buzzer module from LPM. This will effectively release our
* lock for the PERIPH PD allowing it to be powered down (unless some other
* module keeps it on)
*/
lpm_unregister_module(&buzzer_module);
/* Stop the timer */
ti_lib_timer_disable(GPT0_BASE, TIMER_A);
/*
* Stop running in sleep mode.
* ToDo: Currently GPT0 is in use by clock_delay_usec (GPT0/TB) and by this
* module here (GPT0/TA). clock_delay_usec will never need GPT0/TB in sleep
* mode and we control TA here. Thus, with the current setup, it's OK to
* control whether GPT0 runs in sleep mode in this module here. However, if
* some other module at some point starts using GPT0, we should change this
* to happen through an umbrella module
* Stop the module clock:
*
* Currently GPT0 is in use by clock_delay_usec (GPT0/TB) and by this
* module here (GPT0/TA).
*
* clock_delay_usec
* - is definitely not running when we enter here and
* - handles the module clock internally
*
* Thus, we can safely change the state of module clocks here.
*/
ti_lib_prcm_peripheral_run_disable(PRCM_PERIPH_TIMER0);
ti_lib_prcm_peripheral_sleep_disable(PRCM_PERIPH_TIMER0);
ti_lib_prcm_peripheral_deep_sleep_disable(PRCM_PERIPH_TIMER0);
ti_lib_prcm_load_set();
while(!ti_lib_prcm_load_get());
/* Un-configure the pin */
ti_lib_ioc_pin_type_gpio_input(BOARD_IOID_BUZZER);
ti_lib_ioc_io_input_set(BOARD_IOID_BUZZER, IOC_INPUT_DISABLE);
}
/*---------------------------------------------------------------------------*/
/** @} */

View file

@ -72,7 +72,7 @@
/* Part specific constants */
#define BLS_MANUFACTURER_ID 0xEF
#define BLS_DEVICE_ID 0x11
#define BLS_DEVICE_ID 0x12
#define BLS_PROGRAM_PAGE_SIZE 256
#define BLS_ERASE_SECTOR_SIZE 4096
@ -140,50 +140,8 @@ wait_ready(void)
}
/*---------------------------------------------------------------------------*/
/**
* \brief Put the device in power save mode. No access to data; only
* the status register is accessible.
* \return True when SPI transactions succeed
*/
static bool
power_down(void)
{
uint8_t cmd;
bool success;
cmd = BLS_CODE_DP;
select();
success = board_spi_write(&cmd, sizeof(cmd));
deselect();
return success;
}
/*---------------------------------------------------------------------------*/
/**
* \brief Take device out of power save mode and prepare it for normal operation
* \return True if the command was written successfully
*/
static bool
power_standby(void)
{
uint8_t cmd;
bool success;
cmd = BLS_CODE_RDP;
select();
success = board_spi_write(&cmd, sizeof(cmd));
if(success) {
success = wait_ready() == 0;
}
deselect();
return success;
}
/*---------------------------------------------------------------------------*/
/**
* Verify the flash part.
* @return True when successful.
* \brief Verify the flash part.
* \return True when successful.
*/
static bool
verify_part(void)
@ -210,6 +168,57 @@ verify_part(void)
return true;
}
/*---------------------------------------------------------------------------*/
/**
* \brief Put the device in power save mode. No access to data; only
* the status register is accessible.
*/
static void
power_down(void)
{
uint8_t cmd;
uint8_t i;
cmd = BLS_CODE_DP;
select();
board_spi_write(&cmd, sizeof(cmd));
deselect();
i = 0;
while(i < 10) {
if(!verify_part()) {
/* Verify Part failed: Device is powered down */
return;
}
i++;
}
/* Should not be required */
deselect();
}
/*---------------------------------------------------------------------------*/
/**
* \brief Take device out of power save mode and prepare it for normal operation
* \return True if the command was written successfully
*/
static bool
power_standby(void)
{
uint8_t cmd;
bool success;
cmd = BLS_CODE_RDP;
select();
success = board_spi_write(&cmd, sizeof(cmd));
if(success) {
success = wait_ready() == 0;
}
deselect();
return success;
}
/*---------------------------------------------------------------------------*/
/**
* \brief Enable write.
* \return Zero when successful.
@ -232,7 +241,7 @@ write_enable(void)
bool
ext_flash_open()
{
board_spi_open(4000000, BOARD_SPI_CLK_FLASH);
board_spi_open(4000000, BOARD_IOID_SPI_CLK_FLASH);
/* GPIO pin configuration */
ti_lib_ioc_pin_type_gpio_output(BOARD_IOID_FLASH_CS);
@ -406,4 +415,11 @@ ext_flash_test(void)
return ret;
}
/*---------------------------------------------------------------------------*/
void
ext_flash_init()
{
ext_flash_open();
ext_flash_close();
}
/*---------------------------------------------------------------------------*/
/** @} */

View file

@ -54,6 +54,8 @@ bool ext_flash_open(void);
/**
* \brief Close the storage driver
*
* This call will put the device in its lower power mode (power down).
*/
void ext_flash_close(void);
@ -94,6 +96,17 @@ bool ext_flash_write(size_t offset, size_t length, const uint8_t *buf);
* \return True when successful.
*/
bool ext_flash_test(void);
/**
* \brief Initialise the external flash
*
* This function will explicitly put the part in its lowest power mode
* (power-down).
*
* In order to perform any operation, the caller must first wake the device
* up by calling ext_flash_open()
*/
void ext_flash_init(void);
/*---------------------------------------------------------------------------*/
#endif /* EXT_FLASH_H_ */
/*---------------------------------------------------------------------------*/

View file

@ -212,12 +212,12 @@ static uint8_t acc_range_reg;
static uint8_t val;
static uint8_t interrupt_status;
/*---------------------------------------------------------------------------*/
#define SENSOR_STATUS_DISABLED 0
#define SENSOR_STATUS_BOOTING 1
#define SENSOR_STATUS_ENABLED 2
#define SENSOR_STATE_DISABLED 0
#define SENSOR_STATE_BOOTING 1
#define SENSOR_STATE_ENABLED 2
static int enabled = SENSOR_STATUS_DISABLED;
static int elements;
static int state = SENSOR_STATE_DISABLED;
static int elements = MPU_9250_SENSOR_TYPE_NONE;
/*---------------------------------------------------------------------------*/
/* 3 16-byte words for all sensor readings */
#define SENSOR_DATA_BUF_SIZE 3
@ -289,7 +289,9 @@ static void
select_axes(void)
{
val = ~mpu_config;
SENSOR_SELECT();
sensor_common_write_reg(PWR_MGMT_2, &val, 1);
SENSOR_DESELECT();
}
/*---------------------------------------------------------------------------*/
static void
@ -334,37 +336,6 @@ acc_set_range(uint8_t new_range)
return success;
}
/*---------------------------------------------------------------------------*/
/**
* \brief Initialise the MPU
* \return True if success
*/
static bool
init_sensor(void)
{
bool ret;
interrupt_status = false;
acc_range = ACC_RANGE_INVALID;
mpu_config = 0; /* All axes off */
/* Device reset */
val = 0x80;
SENSOR_SELECT();
ret = sensor_common_write_reg(PWR_MGMT_1, &val, 1);
SENSOR_DESELECT();
if(ret) {
delay_ms(200);
/* Initial configuration */
acc_set_range(ACC_RANGE_8G);
/* Power save */
sensor_sleep();
}
return ret;
}
/*---------------------------------------------------------------------------*/
/**
* \brief Check whether a data or wake on motion interrupt has occurred
* \return Return the interrupt status
@ -450,13 +421,13 @@ gyro_read(uint16_t *data)
/* Burst read of all gyroscope values */
success = sensor_common_read_reg(GYRO_XOUT_H, (uint8_t *)data, DATA_SIZE);
SENSOR_DESELECT();
if(success) {
convert_to_le((uint8_t *)data, DATA_SIZE);
} else {
sensor_common_set_error_data((uint8_t *)data, DATA_SIZE);
}
SENSOR_DESELECT();
} else {
success = false;
}
@ -514,15 +485,13 @@ gyro_convert(int16_t raw_data)
static void
notify_ready(void *not_used)
{
enabled = SENSOR_STATUS_ENABLED;
state = SENSOR_STATE_ENABLED;
sensors_changed(&mpu_9250_sensor);
}
/*---------------------------------------------------------------------------*/
static void
initialise(void *not_used)
{
init_sensor();
/* Configure the accelerometer range */
if((elements & MPU_9250_SENSOR_TYPE_ACC) != 0) {
acc_set_range(MPU_9250_SENSOR_ACC_RANGE);
@ -537,7 +506,7 @@ static void
power_up(void)
{
ti_lib_gpio_pin_write(BOARD_MPU_POWER, 1);
enabled = SENSOR_STATUS_BOOTING;
state = SENSOR_STATE_BOOTING;
ctimer_set(&startup_timer, SENSOR_BOOT_DELAY, initialise, NULL);
}
@ -553,7 +522,7 @@ value(int type)
int rv;
float converted_val = 0;
if(enabled == SENSOR_STATUS_DISABLED) {
if(state == SENSOR_STATE_DISABLED) {
PRINTF("MPU: Sensor Disabled\n");
return CC26XX_SENSOR_READING_ERROR;
}
@ -632,33 +601,42 @@ configure(int type, int enable)
{
switch(type) {
case SENSORS_HW_INIT:
ti_lib_rom_ioc_pin_type_gpio_input(BOARD_IOID_MPU_INT);
ti_lib_ioc_io_port_pull_set(BOARD_IOID_MPU_INT, IOC_IOPULL_DOWN);
ti_lib_ioc_io_hyst_set(BOARD_IOID_MPU_INT, IOC_HYST_ENABLE);
ti_lib_rom_ioc_pin_type_gpio_output(BOARD_IOID_MPU_POWER);
ti_lib_ioc_io_drv_strength_set(BOARD_IOID_MPU_POWER, IOC_CURRENT_4MA,
IOC_STRENGTH_MAX);
ti_lib_gpio_pin_clear(BOARD_MPU_POWER);
elements = MPU_9250_SENSOR_TYPE_NONE;
break;
case SENSORS_ACTIVE:
if((enable & MPU_9250_SENSOR_TYPE_ACC) != 0 ||
(enable & MPU_9250_SENSOR_TYPE_GYRO) != 0) {
if(((enable & MPU_9250_SENSOR_TYPE_ACC) != 0) ||
((enable & MPU_9250_SENSOR_TYPE_GYRO) != 0)) {
PRINTF("MPU: Enabling\n");
elements = enable & MPU_9250_SENSOR_TYPE_ALL;
power_up();
enabled = SENSOR_STATUS_BOOTING;
state = SENSOR_STATE_BOOTING;
} else {
PRINTF("MPU: Disabling\n");
ctimer_stop(&startup_timer);
elements = MPU_9250_SENSOR_TYPE_NONE;
enable_sensor(0);
while(ti_lib_i2c_master_busy(I2C0_BASE));
enabled = SENSOR_STATUS_DISABLED;
if(HWREG(GPIO_BASE + GPIO_O_DOUT31_0) & BOARD_MPU_POWER) {
/* Then check our state */
elements = MPU_9250_SENSOR_TYPE_NONE;
ctimer_stop(&startup_timer);
sensor_sleep();
while(ti_lib_i2c_master_busy(I2C0_BASE));
state = SENSOR_STATE_DISABLED;
ti_lib_gpio_pin_clear(BOARD_MPU_POWER);
}
}
break;
case MPU_9250_SENSOR_SHUTDOWN:
ti_lib_gpio_pin_write(BOARD_MPU_POWER, 0);
break;
default:
break;
}
return enabled;
return state;
}
/*---------------------------------------------------------------------------*/
/**
@ -672,12 +650,12 @@ status(int type)
switch(type) {
case SENSORS_ACTIVE:
case SENSORS_READY:
return enabled;
return state;
break;
default:
break;
}
return SENSOR_STATUS_DISABLED;
return SENSOR_STATE_DISABLED;
}
/*---------------------------------------------------------------------------*/
SENSORS_SENSOR(mpu_9250_sensor, "MPU9250", value, configure, status);

View file

@ -86,8 +86,6 @@
#define MPU_9250_SENSOR_TYPE_NONE 0
#define MPU_9250_SENSOR_TYPE_ALL (MPU_9250_SENSOR_TYPE_ACC | \
MPU_9250_SENSOR_TYPE_GYRO)
#define MPU_9250_SENSOR_SHUTDOWN 0xFF
/*---------------------------------------------------------------------------*/
/* Accelerometer range */
#define MPU_9250_SENSOR_ACC_RANGE_2G 0

View file

@ -69,16 +69,42 @@
#define REG_MANUFACTURER_ID 0x7E
#define REG_DEVICE_ID 0x7F
/*---------------------------------------------------------------------------*/
/* Register values */
#define MANUFACTURER_ID 0x5449 /* TI */
#define DEVICE_ID 0x3001 /* Opt 3001 */
#define CONFIG_RESET 0xC810
#define CONFIG_TEST 0xCC10
#define CONFIG_ENABLE 0x10CC /* 0xCC10 */
#define CONFIG_DISABLE 0x108C /* 0xC810 */
/*---------------------------------------------------------------------------*/
/* Bit values */
#define DATA_RDY_BIT 0x0080 /* Data ready */
/*
* Configuration Register Bits and Masks.
* We use uint16_t to read from / write to registers, meaning that the
* register's MSB is the variable's LSB.
*/
#define CONFIG_RN 0x00F0 /* [15..12] Range Number */
#define CONFIG_CT 0x0008 /* [11] Conversion Time */
#define CONFIG_M 0x0006 /* [10..9] Mode of Conversion */
#define CONFIG_OVF 0x0001 /* [8] Overflow */
#define CONFIG_CRF 0x8000 /* [7] Conversion Ready Field */
#define CONFIG_FH 0x4000 /* [6] Flag High */
#define CONFIG_FL 0x2000 /* [5] Flag Low */
#define CONFIG_L 0x1000 /* [4] Latch */
#define CONFIG_POL 0x0800 /* [3] Polarity */
#define CONFIG_ME 0x0400 /* [2] Mask Exponent */
#define CONFIG_FC 0x0300 /* [1..0] Fault Count */
/* Possible Values for CT */
#define CONFIG_CT_100 0x0000
#define CONFIG_CT_800 CONFIG_CT
/* Possible Values for M */
#define CONFIG_M_CONTI 0x0004
#define CONFIG_M_SINGLE 0x0002
#define CONFIG_M_SHUTDOWN 0x0000
/* Reset Value for the register 0xC810. All zeros except: */
#define CONFIG_RN_RESET 0x00C0
#define CONFIG_CT_RESET CONFIG_CT_800
#define CONFIG_L_RESET 0x1000
#define CONFIG_DEFAULTS (CONFIG_RN_RESET | CONFIG_CT_100 | CONFIG_L_RESET)
/* Enable / Disable */
#define CONFIG_ENABLE_CONTINUOUS (CONFIG_M_CONTI | CONFIG_DEFAULTS)
#define CONFIG_ENABLE_SINGLE_SHOT (CONFIG_M_SINGLE | CONFIG_DEFAULTS)
#define CONFIG_DISABLE CONFIG_DEFAULTS
/*---------------------------------------------------------------------------*/
/* Register length */
#define REGISTER_LENGTH 2
@ -86,24 +112,22 @@
/* Sensor data size */
#define DATA_LENGTH 2
/*---------------------------------------------------------------------------*/
#define SENSOR_STATUS_DISABLED 0
#define SENSOR_STATUS_NOT_READY 1
#define SENSOR_STATUS_ENABLED 2
/*
* SENSOR_STATE_SLEEPING and SENSOR_STATE_ACTIVE are mutually exclusive.
* SENSOR_STATE_DATA_READY can be ORd with both of the above. For example the
* sensor may be sleeping but with a conversion ready to read out.
*/
#define SENSOR_STATE_SLEEPING 0
#define SENSOR_STATE_ACTIVE 1
#define SENSOR_STATE_DATA_READY 2
static int enabled = SENSOR_STATUS_DISABLED;
static int state = SENSOR_STATE_SLEEPING;
/*---------------------------------------------------------------------------*/
/* Wait SENSOR_STARTUP_DELAY for the sensor to be ready - 125ms */
#define SENSOR_STARTUP_DELAY (CLOCK_SECOND >> 3)
static struct ctimer startup_timer;
/*---------------------------------------------------------------------------*/
static void
notify_ready(void *not_used)
{
enabled = SENSOR_STATUS_ENABLED;
sensors_changed(&opt_3001_sensor);
}
/*---------------------------------------------------------------------------*/
/**
* \brief Select the sensor on the I2C bus
*/
@ -114,6 +138,28 @@ select(void)
board_i2c_select(BOARD_I2C_INTERFACE_0, OPT3001_I2C_ADDRESS);
}
/*---------------------------------------------------------------------------*/
static void
notify_ready(void *not_used)
{
/*
* Depending on the CONFIGURATION.CONVERSION_TIME bits, a conversion will
* take either 100 or 800 ms. Here we inspect the CONVERSION_READY bit and
* if the reading is ready we notify, otherwise we just reschedule ourselves
*/
uint16_t val;
select();
sensor_common_read_reg(REG_CONFIGURATION, (uint8_t *)&val, REGISTER_LENGTH);
if(val & CONFIG_CRF) {
sensors_changed(&opt_3001_sensor);
state = SENSOR_STATE_DATA_READY;
} else {
ctimer_set(&startup_timer, SENSOR_STARTUP_DELAY, notify_ready, NULL);
}
}
/*---------------------------------------------------------------------------*/
/**
* \brief Turn the sensor on/off
* \param enable TRUE: on, FALSE: off
@ -122,13 +168,20 @@ static void
enable_sensor(bool enable)
{
uint16_t val;
uint16_t had_data_ready = state & SENSOR_STATE_DATA_READY;
select();
if(enable) {
val = CONFIG_ENABLE;
val = CONFIG_ENABLE_SINGLE_SHOT;
/* Writing CONFIG_ENABLE_SINGLE_SHOT to M bits will clear CRF bits */
state = SENSOR_STATE_ACTIVE;
} else {
val = CONFIG_DISABLE;
/* Writing CONFIG_DISABLE to M bits will not clear CRF bits */
state = SENSOR_STATE_SLEEPING | had_data_ready;
}
sensor_common_write_reg(REG_CONFIGURATION, (uint8_t *)&val, REGISTER_LENGTH);
@ -145,15 +198,15 @@ read_data(uint16_t *raw_data)
bool success;
uint16_t val;
if((state & SENSOR_STATE_DATA_READY) != SENSOR_STATE_DATA_READY) {
return false;
}
select();
success = sensor_common_read_reg(REG_CONFIGURATION, (uint8_t *)&val,
REGISTER_LENGTH);
if(success) {
success = (val & DATA_RDY_BIT) == DATA_RDY_BIT;
}
if(success) {
success = sensor_common_read_reg(REG_RESULT, (uint8_t *)&val, DATA_LENGTH);
}
@ -196,14 +249,9 @@ value(int type)
uint16_t raw_val;
float converted_val;
if(enabled != SENSOR_STATUS_ENABLED) {
PRINTF("Sensor disabled or starting up (%d)\n", enabled);
return CC26XX_SENSOR_READING_ERROR;
}
rv = read_data(&raw_val);
if(rv == 0) {
if(rv == false) {
return CC26XX_SENSOR_READING_ERROR;
}
@ -229,30 +277,38 @@ value(int type)
static int
configure(int type, int enable)
{
int rv = 0;
switch(type) {
case SENSORS_HW_INIT:
/*
* Device reset won't reset the sensor, so we put it to sleep here
* explicitly
*/
enable_sensor(0);
rv = 0;
break;
case SENSORS_ACTIVE:
if(enable) {
enable_sensor(1);
ctimer_set(&startup_timer, SENSOR_STARTUP_DELAY, notify_ready, NULL);
enabled = SENSOR_STATUS_NOT_READY;
rv = 1;
} else {
ctimer_stop(&startup_timer);
enable_sensor(0);
enabled = SENSOR_STATUS_DISABLED;
rv = 0;
}
break;
default:
break;
}
return enabled;
return rv;
}
/*---------------------------------------------------------------------------*/
/**
* \brief Returns the status of the sensor
* \param type SENSORS_ACTIVE or SENSORS_READY
* \return 1 if the sensor is enabled
* \param type ignored
* \return The state of the sensor SENSOR_STATE_xyz
*/
static int
status(int type)
@ -260,12 +316,10 @@ status(int type)
switch(type) {
case SENSORS_ACTIVE:
case SENSORS_READY:
return enabled;
break;
default:
break;
}
return SENSOR_STATUS_DISABLED;
return state;
}
/*---------------------------------------------------------------------------*/
SENSORS_SENSOR(opt_3001_sensor, "OPT3001", value, configure, status);

View file

@ -40,14 +40,16 @@
* sequence, but the call will not wait for it to complete so that the CPU can
* perform other tasks or drop to a low power mode.
*
* Once the sensor is stable, the driver will generate a sensors_changed event.
* Once the reading and conversion are complete, the driver will generate a
* sensors_changed event.
*
* Once a reading has been taken, the caller has two options:
* - Turn the sensor off by calling SENSORS_DEACTIVATE, but in order to take
* subsequent readings SENSORS_ACTIVATE must be called again
* - Leave the sensor on. In this scenario, the caller can simply keep calling
* value() for subsequent readings, but having the sensor on will consume
* energy
* We use single-shot readings. In this mode, the hardware automatically goes
* back to its shutdown mode after the conversion is finished. However, it will
* still respond to I2C operations, so the last conversion can still be read
* out.
*
* In order to take a new reading, the caller has to use SENSORS_ACTIVATE
* again.
* @{
*
* \file

View file

@ -88,7 +88,7 @@
#define SWAP(v) ((LO_UINT16(v) << 8) | HI_UINT16(v))
/*---------------------------------------------------------------------------*/
#define SELECT() board_i2c_select(BOARD_I2C_INTERFACE_0, SENSOR_I2C_ADDRESS);
#define SELECT() board_i2c_select(BOARD_I2C_INTERFACE_0, SENSOR_I2C_ADDRESS)
/*---------------------------------------------------------------------------*/
static uint8_t buf[DATA_SIZE];
static uint16_t val;
@ -124,7 +124,7 @@ enable_sensor(bool enable)
{
bool success;
SELECT()
SELECT();
if(enable) {
val = TMP007_VAL_CONFIG_ON;
@ -267,6 +267,10 @@ configure(int type, int enable)
{
switch(type) {
case SENSORS_HW_INIT:
ti_lib_ioc_pin_type_gpio_input(BOARD_IOID_TMP_RDY);
ti_lib_ioc_io_port_pull_set(BOARD_IOID_TMP_RDY, IOC_IOPULL_UP);
ti_lib_ioc_io_hyst_set(BOARD_IOID_TMP_RDY, IOC_HYST_ENABLE);
enable_sensor(false);
enabled = SENSOR_STATUS_INITIALISED;
break;

View file

@ -45,95 +45,65 @@
#include <stdint.h>
#include <string.h>
/*---------------------------------------------------------------------------*/
#define PRCM_DOMAINS (PRCM_DOMAIN_RFCORE | PRCM_DOMAIN_SERIAL | \
PRCM_DOMAIN_PERIPH | PRCM_DOMAIN_CPU | \
PRCM_DOMAIN_SYSBUS | PRCM_DOMAIN_VIMS)
/*---------------------------------------------------------------------------*/
#define LPM_DOMAINS (PRCM_DOMAIN_SERIAL | PRCM_DOMAIN_PERIPH)
/*---------------------------------------------------------------------------*/
static void
power_domains_on(void)
wakeup_handler(void)
{
/* Turn on relevant power domains */
ti_lib_prcm_power_domain_on(LPM_DOMAINS);
/* Wait for domains to power on */
while((ti_lib_prcm_power_domain_status(LPM_DOMAINS)
/* Turn on the PERIPH PD */
ti_lib_prcm_power_domain_on(PRCM_DOMAIN_PERIPH);
while((ti_lib_prcm_power_domain_status(PRCM_DOMAIN_PERIPH)
!= PRCM_DOMAIN_POWER_ON));
}
/*---------------------------------------------------------------------------*/
static void
lpm_wakeup_handler(void)
{
power_domains_on();
}
/*---------------------------------------------------------------------------*/
/*
* Declare a data structure to register with LPM.
* We don't care about what power mode we'll drop to, we don't care about
* getting notified before deep sleep. All we need is to be notified when we
* wake up so we can turn power domains back on
*/
LPM_MODULE(srf_module, NULL, NULL, lpm_wakeup_handler);
LPM_MODULE(srf_module, NULL, NULL, wakeup_handler, LPM_DOMAIN_NONE);
/*---------------------------------------------------------------------------*/
void
board_init()
static void
configure_unused_pins(void)
{
uint8_t int_disabled = ti_lib_int_master_disable();
/* Turn on all power domains */
ti_lib_prcm_power_domain_on(PRCM_DOMAINS);
/* Wait for power on domains */
while((ti_lib_prcm_power_domain_status(PRCM_DOMAINS)
!= PRCM_DOMAIN_POWER_ON));
/* Configure all clock domains to run at full speed */
ti_lib_prcm_clock_configure_set(PRCM_DOMAIN_SYSBUS | PRCM_DOMAIN_CPU |
PRCM_DOMAIN_CPU | PRCM_DOMAIN_TIMER |
PRCM_DOMAIN_SERIAL | PRCM_DOMAIN_PERIPH,
PRCM_CLOCK_DIV_1);
/* Enable GPIO peripheral */
ti_lib_prcm_peripheral_run_enable(PRCM_PERIPH_GPIO);
/* Apply settings and wait for them to take effect */
ti_lib_prcm_load_set();
while(!ti_lib_prcm_load_get()) ;
/* Keys (input pullup) */
ti_lib_ioc_pin_type_gpio_input(BOARD_IOID_KEY_UP);
ti_lib_ioc_pin_type_gpio_input(BOARD_IOID_KEY_DOWN);
ti_lib_ioc_pin_type_gpio_input(BOARD_IOID_KEY_LEFT);
ti_lib_ioc_pin_type_gpio_input(BOARD_IOID_KEY_RIGHT);
ti_lib_ioc_pin_type_gpio_input(BOARD_IOID_KEY_SELECT);
/* Turn off 3.3V domain (Powers the LCD and SD card reader): Output, low */
/* Turn off 3.3-V domain (lcd/sdcard power, output low) */
ti_lib_ioc_pin_type_gpio_output(BOARD_IOID_3V3_EN);
ti_lib_gpio_pin_write(BOARD_3V3_EN, 0);
/* LCD CSn (output high) */
ti_lib_ioc_pin_type_gpio_output(BOARD_IOID_LCD_CS);
ti_lib_gpio_pin_write(BOARD_LCD_CS, 1);
/* SD Card reader CSn (output high) */
ti_lib_ioc_pin_type_gpio_output(BOARD_IOID_SDCARD_CS);
ti_lib_gpio_pin_write(BOARD_SDCARD_CS, 1);
/* Accelerometer (PWR output low, CSn output high) */
/* Accelerometer (PWR output low, CSn output, high) */
ti_lib_ioc_pin_type_gpio_output(BOARD_IOID_ACC_PWR);
ti_lib_gpio_pin_write(BOARD_ACC_PWR, 0);
ti_lib_ioc_pin_type_gpio_output(BOARD_IOID_ACC_CS);
ti_lib_gpio_pin_write(BOARD_IOID_ACC_CS, 1);
/* Ambient light sensor (off, output low) */
ti_lib_ioc_pin_type_gpio_output(BOARD_IOID_ALS_PWR);
ti_lib_gpio_pin_write(BOARD_ALS_PWR, 0);
ti_lib_ioc_pin_type_gpio_input(BOARD_IOID_ALS_OUT);
ti_lib_ioc_io_port_pull_set(BOARD_IOID_ALS_OUT, IOC_NO_IOPULL);
}
/*---------------------------------------------------------------------------*/
void
board_init()
{
uint8_t int_disabled = ti_lib_int_master_disable();
/* Turn on relevant PDs */
wakeup_handler();
/* Configure all clock domains to run at full speed */
ti_lib_prcm_clock_configure_set(PRCM_DOMAIN_SYSBUS | PRCM_DOMAIN_CPU |
PRCM_DOMAIN_TIMER | PRCM_DOMAIN_SERIAL |
PRCM_DOMAIN_PERIPH, PRCM_CLOCK_DIV_1);
/* Enable GPIO peripheral */
ti_lib_prcm_peripheral_run_enable(PRCM_PERIPH_GPIO);
/* Apply settings and wait for them to take effect */
ti_lib_prcm_load_set();
while(!ti_lib_prcm_load_get());
lpm_register_module(&srf_module);
configure_unused_pins();
/* Re-enable interrupt if initially enabled. */
if(!int_disabled) {
ti_lib_int_master_enable();

View file

@ -107,8 +107,8 @@
*/
#define BOARD_IOID_UART_RX IOID_2
#define BOARD_IOID_UART_TX IOID_3
#define BOARD_IOID_UART_CTS IOID_0
#define BOARD_IOID_UART_RTS IOID_21
#define BOARD_IOID_UART_CTS IOID_UNUSED
#define BOARD_IOID_UART_RTS IOID_UNUSED
#define BOARD_UART_RX (1 << BOARD_IOID_UART_RX)
#define BOARD_UART_TX (1 << BOARD_IOID_UART_TX)
#define BOARD_UART_CTS (1 << BOARD_IOID_UART_CTS)

View file

@ -55,7 +55,7 @@
/*---------------------------------------------------------------------------*/
#define BUTTON_GPIO_CFG (IOC_CURRENT_2MA | IOC_STRENGTH_AUTO | \
IOC_IOPULL_UP | IOC_SLEW_DISABLE | \
IOC_HYST_DISABLE | IOC_BOTH_EDGES | \
IOC_HYST_ENABLE | IOC_BOTH_EDGES | \
IOC_INT_ENABLE | IOC_IOMODE_NORMAL | \
IOC_NO_WAKE_UP | IOC_INPUT_ENABLE | \
IOC_JTAG_DISABLE)
@ -137,7 +137,7 @@ button_press_handler(uint8_t ioid)
sensors_changed(&button_right_sensor);
}
} else {
lpm_shutdown(BOARD_IOID_KEY_RIGHT);
lpm_shutdown(BOARD_IOID_KEY_RIGHT, IOC_IOPULL_UP, IOC_WAKE_ON_LOW);
}
}

View file

@ -0,0 +1,72 @@
# Copyright (c) 2014, Friedrich-Alexander University Erlangen-Nuremberg
# 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 UNIVERSITY 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.
TOOLS=sky tools stm32w z80=hex2bin sensinode=nano_programmer
FAILTOOLS=stm32w=uip6_bridge sky=uip6-bridge sensinode=nano_usb_programmer
TOOLSDIR=../../tools
LOGS=$(patsubst %,%.log, $(TOOLS))
all: summary
FRC:
sky.log: RMFILES=serialdump-linux
stm32w.log: RMFILES=serialdump-linux
tools.log:
@$(MAKE) -C $(TOOLSDIR) > $@ 2>&1 && $(RM) $@.failed || touch $@.failed
%.log: FRC
@( cd $(TOOLSDIR)/$(subst =,/,$*) && $(RM) $(RMFILES) )
@touch $@
@$(MAKE) -C $(TOOLSDIR)/$(subst =,/,$*) > $@ 2>&1 && $(RM) $@.failed || touch $@.failed
summary: $(LOGS)
@(\
for T in $(TOOLS) ; do \
if [ -f $$T.log.failed ] ; then \
echo tools/$$T: FAIL ಠ_ಠ >> $@;\
cat $$T.log >> $@;\
else \
echo tools/$$T: OK >> $@;\
fi\
done \
)
@echo "Info: The following tools need fixing and are not tested:" $(subst =,/,$(FAILTOOLS)) >> $@
@echo $@
clean:
@make -C $(DOCDIR) clean
.PHONY: %.log

View file

@ -1,4 +1,4 @@
all: codeprop tunslip
all: tunslip
gitclean:
@git clean -d -x -n ..
@ -20,4 +20,4 @@ cleantargets:
@rm -f -v ${addprefix ../examples/*/*., ${shell ls ../platform/}}
@rm -f -v ${addprefix ../examples/*/*/*., ${shell ls ../platform/}}
cleandone:
@echo ${info All done!}
@echo ${info All done!}

View file

@ -169,6 +169,7 @@ public class MRM extends AbstractRadioMedium {
if (sender.getChannel() >= 0 &&
recv.getChannel() >= 0 &&
sender.getChannel() != recv.getChannel()) {
newConnection.addInterfered(recv);
continue;
}
final Radio recvFinal = recv;
@ -313,15 +314,15 @@ public class MRM extends AbstractRadioMedium {
/* Interfering/colliding radio connections */
for (RadioConnection conn : conns) {
for (Radio intfRadio : ((MRMRadioConnection) conn).getInterfered()) {
double signalStrength = ((MRMRadioConnection) conn).getInterferenceSignalStrength(intfRadio);
if (intfRadio.getCurrentSignalStrength() < signalStrength) {
intfRadio.setCurrentSignalStrength(signalStrength);
}
if (conn.getSource().getChannel() >= 0 &&
intfRadio.getChannel() >= 0 &&
conn.getSource().getChannel() != intfRadio.getChannel()) {
continue;
}
double signalStrength = ((MRMRadioConnection) conn).getInterferenceSignalStrength(intfRadio);
if (intfRadio.getCurrentSignalStrength() < signalStrength) {
intfRadio.setCurrentSignalStrength(signalStrength);
}
if (!intfRadio.isInterfered()) {
/*logger.warn("Radio was not interfered: " + intfRadio);*/

View file

@ -236,8 +236,9 @@ public abstract class AbstractRadioMedium extends RadioMedium {
case RECEPTION_STARTED:
case RECEPTION_INTERFERED:
case RECEPTION_FINISHED:
break;
case UNKNOWN:
return;
case HW_ON: {
/* Update signal strengths */
updateSignalStrengths();
@ -292,7 +293,7 @@ public abstract class AbstractRadioMedium extends RadioMedium {
break;
case TRANSMISSION_FINISHED: {
/* Remove radio connection */
/* Connection */
RadioConnection connection = getActiveConnectionFrom(radio);
if (connection == null) {
@ -322,7 +323,10 @@ public abstract class AbstractRadioMedium extends RadioMedium {
COUNTER_RX += connection.getDestinations().length;
COUNTER_INTERFERED += connection.getInterfered().length;
for (Radio intRadio : connection.getInterferedNonDestinations()) {
intRadio.signalReceptionEnd();
if (intRadio.isInterfered()) {
intRadio.signalReceptionEnd();
}
}
/* Update signal strengths */

View file

@ -42,6 +42,7 @@ public class DGRMDestinationRadio extends DestinationRadio {
public double signal = AbstractRadioMedium.SS_STRONG; /* RSSI */
public long delay = 0; /* EXPERIMENTAL: Propagation delay (us). */
public int lqi = 105;
public int channel = -1; /* not set by default */
public DGRMDestinationRadio() {
super();
@ -50,12 +51,17 @@ public class DGRMDestinationRadio extends DestinationRadio {
super(dest);
}
public int getChannel() {
return channel;
}
protected Object clone() {
DGRMDestinationRadio clone = new DGRMDestinationRadio(this.radio);
clone.ratio = this.ratio;
clone.delay = this.delay;
clone.signal = this.signal;
clone.lqi = this.lqi;
clone.channel = this.channel;
return clone;
}
@ -75,10 +81,13 @@ public class DGRMDestinationRadio extends DestinationRadio {
element.setText("" + lqi);
config.add(element);
element = new Element("delay");
element.setText("" + delay);
config.add(element);
element = new Element("channel");
element.setText("" + channel);
config.add(element);
return config;
}
@ -96,6 +105,8 @@ public class DGRMDestinationRadio extends DestinationRadio {
lqi = Integer.parseInt(element.getText());
} else if (element.getName().equals("delay")) {
delay = Long.parseLong(element.getText());
} else if (element.getName().equals("channel")) {
channel = Integer.parseInt(element.getText());
}
}
return true;

View file

@ -166,6 +166,19 @@ public class DirectedGraphMedium extends AbstractRadioMedium {
DGRMDestinationRadio dstRadios[] = getPotentialDestinations(conn.getSource());
if (dstRadios == null) continue;
for (DGRMDestinationRadio dstRadio : dstRadios) {
int activeSourceChannel = conn.getSource().getChannel();
int edgeChannel = dstRadio.channel;
int activeDstChannel = dstRadio.radio.getChannel();
if (activeSourceChannel != -1) {
if (edgeChannel != -1 && activeSourceChannel != edgeChannel) {
continue;
}
if (activeDstChannel != -1 && activeSourceChannel != activeDstChannel) {
continue;
}
}
if (dstRadio.radio.getCurrentSignalStrength() < dstRadio.signal) {
dstRadio.radio.setCurrentSignalStrength(dstRadio.signal);
}
@ -247,13 +260,27 @@ public class DirectedGraphMedium extends AbstractRadioMedium {
/*logger.info(source + ": " + destinations.length + " potential destinations");*/
for (DGRMDestinationRadio dest: destinations) {
if (dest.radio == source) {
/* Fail: cannot receive our own transmission */
/*logger.info(source + ": Fail, receiver is sender");*/
continue;
}
int srcc = source.getChannel();
int dstc = dest.radio.getChannel();
int edgeChannel = dest.getChannel();
if (edgeChannel >= 0 && dstc >= 0 && edgeChannel != dstc) {
/* Fail: the edge is configured for a different radio channel */
continue;
}
if (srcc >= 0 && dstc >= 0 && srcc != dstc) {
/* Fail: radios are on different (but configured) channels */
newConn.addInterfered(dest.radio);
continue;
}
if (!dest.radio.isRadioOn()) {
/* Fail: radio is off */
@ -268,14 +295,7 @@ public class DirectedGraphMedium extends AbstractRadioMedium {
newConn.addInterfered(dest.radio);
continue;
}
int srcc = source.getChannel();
int dstc = dest.radio.getChannel();
if ( srcc >= 0 && dstc >= 0 && srcc != dstc) {
/* Fail: radios are on different (but configured) channels */
continue;
}
if (dest.radio.isReceiving()) {
/* Fail: radio is already actively receiving */
/*logger.info(source + ": Fail, receiving");*/

View file

@ -192,6 +192,13 @@ public class UDGM extends AbstractRadioMedium {
if (sender.getChannel() >= 0 &&
recv.getChannel() >= 0 &&
sender.getChannel() != recv.getChannel()) {
/* Add the connection in a dormant state;
it will be activated later when the radio will be
turned on and switched to the right channel. This behavior
is consistent with the case when receiver is turned off. */
newConnection.addInterfered(recv);
continue;
}
Position recvPos = recv.getPosition();

25
tools/stm32w/Makefile Normal file
View file

@ -0,0 +1,25 @@
ifndef HOST_OS
ifeq ($(OS),Windows_NT)
HOST_OS := Windows
else
HOST_OS := $(shell uname)
endif
endif
ifeq ($(HOST_OS),Windows)
SERIALDUMP = serialdump-windows
endif
ifeq ($(HOST_OS),Darwin)
SERIALDUMP = serialdump-macos
endif
ifndef SERIALDUMP
# Assume Linux
SERIALDUMP = serialdump-linux
endif
all: $(SERIALDUMP)
$(SERIALDUMP): serialdump.c
$(CC) -O2 -o $@ $<