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 ## of environment variable defined below
- BUILD_TYPE='doxygen' BUILD_CATEGORY='doxygen' - BUILD_TYPE='doxygen' BUILD_CATEGORY='doxygen'
- BUILD_TYPE='compile-base' BUILD_CATEGORY='compile' - BUILD_TYPE='compile-base' BUILD_CATEGORY='compile'
- BUILD_TYPE='compile-tools' BUILD_CATEGORY='compile'
- BUILD_TYPE='collect' - BUILD_TYPE='collect'
- BUILD_TYPE='collect-lossy' - BUILD_TYPE='collect-lossy'
- BUILD_TYPE='rpl' - BUILD_TYPE='rpl'

View file

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

View file

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

View file

@ -39,6 +39,7 @@
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
#include "contiki.h" #include "contiki.h"
#include "sys/cc.h"
#include "contiki-net.h" #include "contiki-net.h"
#include "er-coap.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 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))) #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 */ /* parsed message struct */
typedef struct { typedef struct {
uint8_t *buffer; /* pointer to CoAP header / incoming packet buffer / memory to serialize packet */ 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/assert.h"
#include "lib/list.h" #include "lib/list.h"
#include "sys/cc.h"
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
#define MIN(a, b) ((a) < (b) ? (a) : (b))
/*---------------------------------------------------------------------------*/
#define DEBUG 0 #define DEBUG 0
#if DEBUG #if DEBUG
#define PRINTF(...) PRINTF(__VA_ARGS__) #define PRINTF(...) PRINTF(__VA_ARGS__)

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -42,20 +42,13 @@
* @{ * @{
*/ */
#include "sys/cc.h"
#include "net/rime/rime.h" #include "net/rime/rime.h"
#include "net/rime/ipolite.h" #include "net/rime/ipolite.h"
#include "lib/random.h" #include "lib/random.h"
#include <string.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 #define DEBUG 0
#if DEBUG #if DEBUG
#include <stdio.h> #include <stdio.h>

View file

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

View file

@ -42,21 +42,13 @@
* @{ * @{
*/ */
#include "sys/cc.h"
#include "net/rime/rime.h" #include "net/rime/rime.h"
#include "net/rime/polite.h" #include "net/rime/polite.h"
#include "lib/random.h" #include "lib/random.h"
#include <string.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 static void
recv(struct abc_conn *abc) recv(struct abc_conn *abc)

View file

@ -127,14 +127,33 @@
#define NULL 0 #define NULL 0
#endif /* NULL */ #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 #define CC_CONCAT2(s1, s2) s1##s2
/** /**
* A C preprocessing macro for concatenating to * A C preprocessing macro for concatenating two preprocessor tokens.
* strings.
* *
* We need use two macros (CC_CONCAT and CC_CONCAT2) in order to allow * We need use two macros (CC_CONCAT and CC_CONCAT2) in order to allow
* concatenation of two \#defined macros. * concatenation of two \#defined macros.
*/ */
#define CC_CONCAT(s1, s2) CC_CONCAT2(s1, s2) #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_ */ #endif /* CC_H_ */

View file

@ -280,9 +280,6 @@ typedef char r_uart_ptchar;
#define OUT_X(addrx,value) (*addrx = value) #define OUT_X(addrx,value) (*addrx = value)
#define IN_X(addrx) (*addrx) #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 // Align on the upper value <val> on a <n> boundary
// i.e. Upper(0, 4)= 4 // i.e. Upper(0, 4)= 4
// Upper(1, 4)= 4 // Upper(1, 4)= 4

View file

@ -1,5 +1,9 @@
/* /*
* Copyright (c) 2013, University of Michigan. * Copyright (c) 2013, University of Michigan.
*
* Copyright (c) 2015, Weptech elektronik GmbH
* Author: Ulf Knoblich, ulf.knoblich@weptech.de
*
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -41,102 +45,281 @@
#include "dev/spi.h" #include "dev/spi.h"
#include "dev/ssi.h" #include "dev/ssi.h"
#include "dev/gpio.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) #ifndef SPI0_TX_PORT
#define SPI_CLK_PIN_MASK GPIO_PIN_MASK(SPI_CLK_PIN) #define SPI0_TX_PORT (-1)
#define SPI_MOSI_PORT_BASE GPIO_PORT_TO_BASE(SPI_MOSI_PORT) #endif
#define SPI_MOSI_PIN_MASK GPIO_PIN_MASK(SPI_MOSI_PIN) #ifndef SPI0_TX_PIN
#define SPI_MISO_PORT_BASE GPIO_PORT_TO_BASE(SPI_MISO_PORT) #define SPI0_TX_PIN (-1)
#define SPI_MISO_PIN_MASK GPIO_PIN_MASK(SPI_MISO_PIN) #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
/** #ifndef SPI0_RX_PORT
* \brief Initialize the SPI bus. #define SPI0_RX_PORT (-1)
* #endif
* This SPI init() function uses the following defines to set the pins: #ifndef SPI0_RX_PIN
* SPI_CLK_PORT SPI_CLK_PIN #define SPI0_RX_PIN (-1)
* SPI_MOSI_PORT SPI_MOSI_PIN #endif
* SPI_MISO_PORT SPI_MISO_PIN #if SPI0_RX_PORT >= 0 && SPI0_RX_PIN < 0 || \
* SPI0_RX_PORT < 0 && SPI0_RX_PIN >= 0
* This sets the mode to Motorola SPI with the following format options: #error Both SPI0_RX_PORT and SPI0_RX_PIN must be valid or invalid
* Clock phase: 1; data captured on second (rising) edge #endif
* Clock polarity: 1; clock is high when idle
* Data size: 8 bits /* 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 void
spi_init(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 */ /* 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 */ /* 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 */ /* 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(regs->clk.port,
ioc_set_sel(SPI_MOSI_PORT, SPI_MOSI_PIN, IOC_PXX_SEL_SSI0_TXD); regs->clk.pin,
REG(IOC_SSIRXD_SSI0) = (SPI_MISO_PORT * 8) + SPI_MISO_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 */ /* Put all the SSI gpios into peripheral mode */
GPIO_PERIPHERAL_CONTROL(SPI_CLK_PORT_BASE, SPI_CLK_PIN_MASK); GPIO_PERIPHERAL_CONTROL(GPIO_PORT_TO_BASE(regs->clk.port),
GPIO_PERIPHERAL_CONTROL(SPI_MOSI_PORT_BASE, SPI_MOSI_PIN_MASK); GPIO_PIN_MASK(regs->clk.pin));
GPIO_PERIPHERAL_CONTROL(SPI_MISO_PORT_BASE, SPI_MISO_PIN_MASK); 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 */ /* Disable any pull ups or the like */
ioc_set_over(SPI_CLK_PORT, SPI_CLK_PIN, IOC_OVERRIDE_DIS); ioc_set_over(regs->clk.port, regs->clk.pin, IOC_OVERRIDE_DIS);
ioc_set_over(SPI_MOSI_PORT, SPI_MOSI_PIN, IOC_OVERRIDE_DIS); ioc_set_over(regs->tx.port, regs->tx.pin, IOC_OVERRIDE_DIS);
ioc_set_over(SPI_MISO_PORT, SPI_MISO_PIN, IOC_OVERRIDE_DIS); ioc_set_over(regs->rx.port, regs->rx.pin, IOC_OVERRIDE_DIS);
/* Configure the clock */ /* 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 * mode: Motorola frame format
* clock: High when idle * clock: High when idle
* data: Valid on rising edges of the clock * data: Valid on rising edges of the clock
* bits: 8 byte data * 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 */ /* Enable the SSI */
REG(SSI0_BASE + SSI_CR1) |= SSI_CR1_SSE; REG(regs->base + SSI_CR1) |= SSI_CR1_SSE;
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
void 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); ioc_set_over(port, pin, IOC_OVERRIDE_DIS);
GPIO_SET_OUTPUT(GPIO_PORT_TO_BASE(port), GPIO_PIN_MASK(pin)); GPIO_SET_OUTPUT(GPIO_PORT_TO_BASE(port), GPIO_PIN_MASK(pin));
GPIO_SET_PIN(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_ #ifndef SSI_H_
#define SSI_H_ #define SSI_H_
/*---------------------------------------------------------------------------*/
/** \name Number of SSI instances supported by this CPU.
* @{
*/
#define SSI_INSTANCE_COUNT 2
/** @} */
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/** \name Base register memory locations. /** \name Base register memory locations.
* @{ * @{

View file

@ -1,5 +1,9 @@
/* /*
* Copyright (c) 2013, University of Michigan. * Copyright (c) 2013, University of Michigan.
*
* Copyright (c) 2015, Weptech elektronik GmbH
* Author: Ulf Knoblich, ulf.knoblich@weptech.de
*
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * 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 * Header file for the cc2538 SPI driver, including macros for the
* implementation of the low-level SPI primitives such as waiting for the TX * implementation of the low-level SPI primitives such as waiting for the TX
* FIFO to be ready, inserting into the TX FIFO, etc. * 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_ #ifndef SPI_ARCH_H_
#define SPI_ARCH_H_ #define SPI_ARCH_H_
#include "contiki.h"
#include "dev/ssi.h" #include "dev/ssi.h"
/*---------------------------------------------------------------------------*/
#define SPI_WAITFORTxREADY() do { \ /* The SPI instance to use when using the deprecated SPI API. */
while(!(REG(SSI0_BASE + SSI_SR) & SSI_SR_TNF)); \ #ifdef SPI_CONF_DEFAULT_INSTANCE
} while(0) #if SPI_CONF_DEFAULT_INSTANCE > (SSI_INSTANCE_COUNT - 1)
#error Invalid SPI_CONF_DEFAULT_INSTANCE: valid values are 0 and 1
#define SPI_TXBUF REG(SSI0_BASE + SSI_DR) #else
#define SPI_DEFAULT_INSTANCE SPI_CONF_DEFAULT_INSTANCE
#define SPI_RXBUF REG(SSI0_BASE + SSI_DR) #endif
#endif
#define SPI_WAITFOREOTx() do { \ /*---------------------------------------------------------------------------*/
while(REG(SSI0_BASE + SSI_SR) & SSI_SR_BSY); \ /* Default values for the clock rate divider */
} while(0) #ifdef SPI0_CONF_CPRS_CPSDVSR
#define SPI0_CPRS_CPSDVSR SPI0_CONF_CPRS_CPSDVSR
#define SPI_WAITFOREORx() do { \ #else
while(!(REG(SSI0_BASE + SSI_SR) & SSI_SR_RNE)); \ #define SPI0_CPRS_CPSDVSR 2
} while(0)
#ifdef SPI_FLUSH
#error "You must include spi-arch.h before spi.h for the CC2538."
#endif #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 { \ #ifdef SPI1_CONF_CPRS_CPSDVSR
GPIO_CLR_PIN(GPIO_PORT_TO_BASE(port), GPIO_PIN_MASK(pin)); \ #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) } while(0)
#define SPIX_BUF(spi) REG(CC_CONCAT3(SSI, spi, _BASE) + SSI_DR)
#define SPI_CS_SET(port, pin) do { \ #define SPIX_WAITFOREOTx(spi) do { \
GPIO_SET_PIN(GPIO_PORT_TO_BASE(port), GPIO_PIN_MASK(pin)); \ while(REG(CC_CONCAT3(SSI, spi, _BASE) + SSI_SR) & SSI_SR_BSY) ; \
} while(0) } 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 /** \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); void spix_init(uint8_t spi);
/** \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);
/** /**
* \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 * This function configures the SSI peripheral to use a particular SPI
* configuration that a slave device requires. It should always be called * 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. * 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, * \param frame_format Set the SSI frame format. Use SSI_CR0_FRF_MOTOROLA,
* SSI_CR0_FRF_TI, or SSI_CR0_FRF_MICROWIRE. * SSI_CR0_FRF_TI, or SSI_CR0_FRF_MICROWIRE.
* \param clock_polarity In Motorola mode, set whether the clock is high or low * \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 * \param data_size The number of bits in each "byte" of data. Must be
* between 4 and 16, inclusive. * between 4 and 16, inclusive.
*/ */
void spi_set_mode(uint32_t frame_format, uint32_t clock_polarity, void spix_set_mode(uint8_t spi, uint32_t frame_format,
uint32_t clock_phase, uint32_t data_size); 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 += cc26xx-rf.c contiki-watchdog.c
CONTIKI_CPU_SOURCEFILES += putchar.c ieee-addr.c batmon-sensor.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 += 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 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 * Here, we configure GPT0 Timer A, which we subsequently use in
* clock_delay_usec * 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_peripheral_run_enable(PRCM_PERIPH_TIMER0);
ti_lib_prcm_load_set(); ti_lib_prcm_load_set();
while(!ti_lib_prcm_load_get()); while(!ti_lib_prcm_load_get());
@ -155,11 +161,19 @@ clock_wait(clock_time_t i)
void void
clock_delay_usec(uint16_t len) clock_delay_usec(uint16_t len)
{ {
uint32_t clock_status;
if(ti_lib_prcm_power_domain_status(PRCM_DOMAIN_PERIPH) != if(ti_lib_prcm_power_domain_status(PRCM_DOMAIN_PERIPH) !=
PRCM_DOMAIN_POWER_ON) { PRCM_DOMAIN_POWER_ON) {
power_domain_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_load_set(GPT0_BASE, TIMER_B, len);
ti_lib_timer_enable(GPT0_BASE, TIMER_B); 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 * function, hence the direct register access here
*/ */
while(HWREG(GPT0_BASE + GPT_O_CTL) & GPT_CTL_TBEN); 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 "contiki.h"
#include "dev/radio.h" #include "dev/radio.h"
#include "dev/cc26xx-rf.h" #include "dev/cc26xx-rf.h"
#include "dev/oscillators.h"
#include "net/packetbuf.h" #include "net/packetbuf.h"
#include "net/rime/rimestats.h" #include "net/rime/rimestats.h"
#include "net/linkaddr.h" #include "net/linkaddr.h"
@ -46,6 +47,7 @@
#include "sys/energest.h" #include "sys/energest.h"
#include "sys/clock.h" #include "sys/clock.h"
#include "sys/rtimer.h" #include "sys/rtimer.h"
#include "sys/cc.h"
#include "lpm.h" #include "lpm.h"
#include "ti-lib.h" #include "ti-lib.h"
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
@ -68,6 +70,7 @@
#include <stdint.h> #include <stdint.h>
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
#include <stdbool.h>
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
#define BUSYWAIT_UNTIL(cond, max_time) \ #define BUSYWAIT_UNTIL(cond, max_time) \
do { \ do { \
@ -76,10 +79,6 @@
while(!(cond) && RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + (max_time))); \ while(!(cond) && RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + (max_time))); \
} while(0) } while(0)
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
#ifndef MIN
#define MIN(n, m) (((n) < (m)) ? (n) : (m))
#endif
/*---------------------------------------------------------------------------*/
#ifdef __GNUC__ #ifdef __GNUC__
#define CC_ALIGN_ATTR(n) __attribute__ ((aligned(n))) #define CC_ALIGN_ATTR(n) __attribute__ ((aligned(n)))
#else #else
@ -393,74 +392,6 @@ static int on(void);
static int off(void); static int off(void);
static void setup_interrupts(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 static uint8_t
rf_is_accessible(void) rf_is_accessible(void)
{ {
@ -498,16 +429,19 @@ static uint_fast8_t
rf_send_cmd(uint32_t cmd, uint32_t *status) rf_send_cmd(uint32_t cmd, uint32_t *status)
{ {
uint32_t timeout_count = 0; uint32_t timeout_count = 0;
bool interrupts_disabled;
/* /*
* Make sure ContikiMAC doesn't turn us off from within an interrupt while * Make sure ContikiMAC doesn't turn us off from within an interrupt while
* we are accessing RF Core registers * we are accessing RF Core registers
*/ */
ti_lib_int_master_disable(); interrupts_disabled = ti_lib_int_master_disable();
if(!rf_is_accessible()) { if(!rf_is_accessible()) {
PRINTF("rf_send_cmd: RF was off\n"); 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; 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); *status = HWREG(RFC_DBELL_BASE + RFC_DBELL_O_CMDSTA);
if(++timeout_count > 50000) { if(++timeout_count > 50000) {
PRINTF("rf_send_cmd: Timeout\n"); PRINTF("rf_send_cmd: Timeout\n");
ti_lib_int_master_enable(); if(!interrupts_disabled) {
ti_lib_int_master_enable();
}
return RF_CMD_ERROR; return RF_CMD_ERROR;
} }
} while(*status == RF_CMD_STATUS_PENDING); } 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 * If we reach here the command is no longer pending. It is either completed
@ -978,8 +916,8 @@ static int
power_up(void) power_up(void)
{ {
uint32_t cmd_status; 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_CPE0);
ti_lib_int_pend_clear(INT_RF_CPE1); ti_lib_int_pend_clear(INT_RF_CPE1);
ti_lib_int_disable(INT_RF_CPE0); ti_lib_int_disable(INT_RF_CPE0);
@ -1002,7 +940,10 @@ power_up(void)
HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIEN) = 0x0; HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIEN) = 0x0;
ti_lib_int_enable(INT_RF_CPE0); ti_lib_int_enable(INT_RF_CPE0);
ti_lib_int_enable(INT_RF_CPE1); ti_lib_int_enable(INT_RF_CPE1);
ti_lib_int_master_enable();
if(!interrupts_disabled) {
ti_lib_int_master_enable();
}
/* Let CPE boot */ /* Let CPE boot */
HWREG(RFC_PWR_NONBUF_BASE + RFC_PWR_O_PWMCLKEN) = RF_CORE_CLOCKS_MASK; HWREG(RFC_PWR_NONBUF_BASE + RFC_PWR_O_PWMCLKEN) = RF_CORE_CLOCKS_MASK;
@ -1022,7 +963,7 @@ power_up(void)
static void static void
power_down(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_CPE0);
ti_lib_int_disable(INT_RF_CPE1); 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_pend_clear(INT_RF_CPE1);
ti_lib_int_enable(INT_RF_CPE0); ti_lib_int_enable(INT_RF_CPE0);
ti_lib_int_enable(INT_RF_CPE1); ti_lib_int_enable(INT_RF_CPE1);
ti_lib_int_master_enable(); if(!interrupts_disabled) {
ti_lib_int_master_enable();
}
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
static int static int
@ -1160,6 +1103,8 @@ cc26xx_rf_cpe0_isr(void)
static void static void
setup_interrupts(void) setup_interrupts(void)
{ {
bool interrupts_disabled;
/* We are already turned on by the caller, so this should not happen */ /* We are already turned on by the caller, so this should not happen */
if(!rf_is_accessible()) { if(!rf_is_accessible()) {
PRINTF("setup_interrupts: No access\n"); PRINTF("setup_interrupts: No access\n");
@ -1167,7 +1112,7 @@ setup_interrupts(void)
} }
/* Disable interrupts */ /* Disable interrupts */
ti_lib_int_master_disable(); interrupts_disabled = ti_lib_int_master_disable();
/* Set all interrupt channels to CPE0 channel, error to CPE1 */ /* Set all interrupt channels to CPE0 channel, error to CPE1 */
HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEISL) = ERROR_IRQ; 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_pend_clear(INT_RF_CPE1);
ti_lib_int_enable(INT_RF_CPE0); ti_lib_int_enable(INT_RF_CPE0);
ti_lib_int_enable(INT_RF_CPE1); ti_lib_int_enable(INT_RF_CPE1);
ti_lib_int_master_enable();
if(!interrupts_disabled) {
ti_lib_int_master_enable();
}
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
static uint8_t static uint8_t
@ -1199,7 +1147,7 @@ request(void)
return LPM_MODE_MAX_SUPPORTED; 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 static int
init(void) init(void)
@ -1530,7 +1478,7 @@ on(void)
* Request the HF XOSC as the source for the HF clock. Needed before we can * 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. * 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 * 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 * 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/ * 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) { if(rf_radio_setup(RF_MODE_IEEE) != RF_CMD_OK) {
PRINTF("on: radio_setup() failed\n"); PRINTF("on: radio_setup() failed\n");
@ -1597,7 +1545,7 @@ off(void)
power_down(); power_down();
/* Switch HF clock source to the RCOSC to preserve power */ /* 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 */ /* We pulled the plug, so we need to restore the status manually */
GET_FIELD(cmd_ieee_rx_buf, radioOp, status) = IDLE; 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; uint8_t was_on;
int j; int j;
uint32_t cmd_status; uint32_t cmd_status;
bool interrupts_disabled;
PROCESS_BEGIN(); 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 * Under ContikiMAC, some IEEE-related operations will be called from an
* interrupt context. We need those to see that we are in BLE mode. * 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; 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 * 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 { } else {
/* Request the HF XOSC to source the HF clock. */ /* Request the HF XOSC to source the HF clock. */
request_hf_xosc(); oscillators_request_hf_xosc();
/* We were off: Boot the CPE */ /* We were off: Boot the CPE */
if(power_up() != RF_CMD_OK) { 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 */ /* 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 */ /* Enter BLE mode */
@ -2118,13 +2069,17 @@ PROCESS_THREAD(cc26xx_rf_ble_beacon_process, ev, data)
power_down(); power_down();
/* Switch HF clock source to the RCOSC to preserve power */ /* 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); 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; ble_mode_on = 0;
ti_lib_int_master_enable();
if(!interrupts_disabled) {
ti_lib_int_master_enable();
}
/* Wait unless this is the last burst */ /* Wait unless this is the last burst */
if(i < BLE_ADV_MESSAGES - 1) { 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; ble_mode_on = 0;
ti_lib_int_master_enable();
if(!interrupts_disabled) {
ti_lib_int_master_enable();
}
} }
PROCESS_END(); PROCESS_END();
} }

View file

@ -44,6 +44,7 @@
#include "ti-lib.h" #include "ti-lib.h"
#include <stdint.h> #include <stdint.h>
#include <stdbool.h>
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
#define cc26xx_rtc_isr(...) AONRTCIntHandler(__VA_ARGS__) #define cc26xx_rtc_isr(...) AONRTCIntHandler(__VA_ARGS__)
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
@ -54,9 +55,11 @@ void
cc26xx_rtc_init(void) cc26xx_rtc_init(void)
{ {
uint32_t compare_value; uint32_t compare_value;
bool interrupts_disabled;
/* Disable and clear interrupts */ /* 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_disable();
ti_lib_aon_rtc_event_clear(AON_RTC_CH0); ti_lib_aon_rtc_event_clear(AON_RTC_CH0);
@ -65,22 +68,25 @@ cc26xx_rtc_init(void)
/* Setup the wakeup event */ /* 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_WU0, AON_EVENT_RTC0);
ti_lib_aon_event_mcu_wake_up_set(AON_EVENT_MCU_WU1, AON_EVENT_RTC2); 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 */ /* 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) + compare_value = (RTIMER_SECOND / CLOCK_SECOND) +
ti_lib_aon_rtc_current_compare_value_get(); ti_lib_aon_rtc_current_compare_value_get();
ti_lib_aon_rtc_compare_value_set(AON_RTC_CH2, compare_value); 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 */ /* Enable channel 2 and the RTC */
ti_lib_aon_rtc_combined_event_config(AON_RTC_CH0 | AON_RTC_CH2);
ti_lib_aon_rtc_channel_enable(AON_RTC_CH2); ti_lib_aon_rtc_channel_enable(AON_RTC_CH2);
ti_lib_aon_rtc_enable(); ti_lib_aon_rtc_enable();
ti_lib_int_enable(INT_AON_RTC); 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 rtimer_clock_t

View file

@ -40,6 +40,7 @@
#include "sys/energest.h" #include "sys/energest.h"
#include <stdint.h> #include <stdint.h>
#include <stdbool.h>
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/* Which events to trigger a UART interrupt */ /* Which events to trigger a UART interrupt */
#define CC26XX_UART_RX_INTERRUPT_TRIGGERS (UART_INT_RX | UART_INT_RT) #define CC26XX_UART_RX_INTERRUPT_TRIGGERS (UART_INT_RX | UART_INT_RT)
@ -53,35 +54,98 @@
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
static int (*input_handler)(unsigned char c); static int (*input_handler)(unsigned char c);
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
static void static bool
power_domain_on(void) 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); ti_lib_prcm_power_domain_on(PRCM_DOMAIN_SERIAL);
while(ti_lib_prcm_power_domain_status(PRCM_DOMAIN_SERIAL) while(ti_lib_prcm_power_domain_status(PRCM_DOMAIN_SERIAL)
!= PRCM_DOMAIN_POWER_ON); != 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 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. * Make sure the TX pin is output / high before assigning it to UART control
* This function uses SysCtrlClockGet() to get the system clock * to avoid falling edge glitches
* frequency. This could be also be a variable or hard coded value
* instead of a function call.
*/ */
ti_lib_uart_config_set_exp_clk(UART0_BASE, ti_lib_ioc_pin_type_gpio_output(BOARD_IOID_UART_TX);
ti_lib_sys_ctrl_peripheral_clock_get( ti_lib_gpio_pin_write(BOARD_UART_TX, 1);
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)
{
/* /*
* Map UART signals to the correct GPIO pins and configure them as * Map UART signals to the correct GPIO pins and configure them as
* hardware controlled. * 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, ti_lib_ioc_pin_type_uart(UART0_BASE, BOARD_IOID_UART_RX, BOARD_IOID_UART_TX,
BOARD_IOID_UART_CTS, BOARD_IOID_UART_RTS); 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. * 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); 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 */ /* Enable FIFOs */
ti_lib_uart_int_enable(UART0_BASE, CC26XX_UART_RX_INTERRUPT_TRIGGERS); HWREG(UART0_BASE + UART_O_LCRH) |= UART_LCRH_FEN;
}
/*---------------------------------------------------------------------------*/
static void
uart_on(void)
{
power_domain_on();
/* Configure baud rate and enable */ if(input_handler) {
if((HWREG(UART0_BASE + UART_O_CTL) & UART_CTL_UARTEN) == 0) { ctl_val += UART_CTL_RXE;
configure_registers();
/* Enable UART */
ti_lib_uart_enable(UART0_BASE);
} }
}
/*---------------------------------------------------------------------------*/ /* Enable TX, RX (conditionally), and the UART. */
static uint8_t HWREG(UART0_BASE + UART_O_CTL) = ctl_val;
lpm_permit_max_pm_handler(void)
{
return LPM_MODE_MAX_SUPPORTED;
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
static void static void
lpm_drop_handler(uint8_t mode) lpm_drop_handler(uint8_t mode)
{ {
/* Do nothing if the PD is off */ /*
if(ti_lib_prcm_power_domain_status(PRCM_DOMAIN_SERIAL) * First, wait for any outstanding TX to complete. If we have an input
!= PRCM_DOMAIN_POWER_ON) { * handler, the SERIAL PD will be kept on and the UART module clock will
return; * 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 * If we have a registered input_handler then we need to retain RX
* it's on, this means that some other code module wants UART functionality * capability. Thus, if this is not a shutdown notification and we have an
* during deep sleep, so we stay enabled * input handler, we do nothing
*/ */
if((HWREG(PRCM_BASE + PRCM_O_UARTCLKGDS) & 1) == 0) { if((mode != LPM_MODE_SHUTDOWN) && (input_handler != NULL)) {
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) {
return; 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 */ /* Disable all UART interrupts and clear all flags */
ti_lib_prcm_peripheral_run_enable(PRCM_PERIPH_UART0); 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(); ti_lib_prcm_load_set();
while(!ti_lib_prcm_load_get()); while(!ti_lib_prcm_load_get());
/* Disable Interrupts */ /* Set pins to low leakage configuration in preparation for deep sleep */
ti_lib_int_master_disable(); 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 */ /* Make sure the peripheral is disabled */
ti_lib_uart_disable(UART0_BASE); ti_lib_uart_disable(UART0_BASE);
/* Disable all UART module interrupts */ /* Disable all UART interrupts and clear all flags */
ti_lib_uart_int_disable(UART0_BASE, CC26XX_UART_INTERRUPT_ALL); disable_interrupts();
configure_registers(); /* Setup pins, Baud rate and FIFO levels */
configure();
/* Acknowledge UART interrupts */ /* Enable UART interrupts */
ti_lib_int_enable(INT_UART0); enable_interrupts();
}
/*---------------------------------------------------------------------------*/
void
cc26xx_uart_init()
{
bool interrupts_disabled;
/* Re-enable processor interrupts */ /* Return early if disabled by user conf or if ports are misconfigured */
ti_lib_int_master_enable(); if(usable() == false) {
return;
}
/* Enable UART */ /* Disable Interrupts */
ti_lib_uart_enable(UART0_BASE); interrupts_disabled = ti_lib_int_master_disable();
/* Register ourselves with the LPM module */ /* Register ourselves with the LPM module */
lpm_register_module(&uart_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 void
cc26xx_uart_write_byte(uint8_t c) cc26xx_uart_write_byte(uint8_t c)
{ {
if(ti_lib_prcm_power_domain_status(PRCM_DOMAIN_SERIAL) /* Return early if disabled by user conf or if ports are misconfigured */
!= PRCM_DOMAIN_POWER_ON) { if(usable() == false) {
return; return;
} }
if(accessible() == false) {
enable();
}
ti_lib_uart_char_put(UART0_BASE, c); ti_lib_uart_char_put(UART0_BASE, c);
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
@ -214,9 +307,52 @@ void
cc26xx_uart_set_input(int (*input)(unsigned char c)) cc26xx_uart_set_input(int (*input)(unsigned char c))
{ {
input_handler = input; 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; 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 void
cc26xx_uart_isr(void) cc26xx_uart_isr(void)
{ {
@ -225,6 +361,8 @@ cc26xx_uart_isr(void)
ENERGEST_ON(ENERGEST_TYPE_IRQ); ENERGEST_ON(ENERGEST_TYPE_IRQ);
power_and_clock();
/* Read out the masked interrupt status */ /* Read out the masked interrupt status */
flags = ti_lib_uart_int_status(UART0_BASE, true); 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 * \brief Assigns a callback to be called when the UART receives a byte
* \param input A pointer to the function * \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)); 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_ */ #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/leds.h"
#include "dev/watchdog.h" #include "dev/watchdog.h"
#include "dev/cc26xx-rtc.h" #include "dev/cc26xx-rtc.h"
#include "dev/oscillators.h"
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
#if ENERGEST_CONF_ON #if ENERGEST_CONF_ON
static unsigned long irq_energest = 0; static unsigned long irq_energest = 0;
@ -64,9 +65,6 @@ static unsigned long irq_energest = 0;
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
LIST(modules_list); 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 */ /* PDs that may stay on in deep sleep */
#define LOCKABLE_DOMAINS ((uint32_t)(PRCM_DOMAIN_SERIAL | PRCM_DOMAIN_PERIPH)) #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) #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 void
lpm_pd_lock_obtain(lpm_power_domain_lock_t *lock, uint32_t domains) lpm_shutdown(uint32_t wakeup_pin, uint32_t io_pull, uint32_t wake_on)
{
/* 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_registered_module_t *module; lpm_registered_module_t *module;
int i; int i, j;
rtimer_clock_t t0; uint32_t io_cfg = (IOC_STD_INPUT & ~IOC_IOPULL_M) | io_pull |
uint32_t io_cfg = (IOC_STD_INPUT & ~IOC_IOPULL_M) | IOC_IOPULL_UP | wake_on;
IOC_WAKE_ON_LOW;
/* 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; for(module = list_head(modules_list); module != NULL;
module = module->next) { module = module->next) {
if(module->shutdown) { 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++) { /* Freeze I/O latches in AON */
t0 = RTIMER_NOW(); ti_lib_aon_ioc_freeze_enable();
leds_toggle(LEDS_ALL);
while(RTIMER_CLOCK_LT(RTIMER_NOW(), (t0 + (RTIMER_SECOND >> 3))));
}
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); oscillators_switch_to_hf_rc();
ti_lib_ioc_port_configure_set(pin, IOC_PORT_GPIO, io_cfg); 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: * Notify all modules that we're back on and rely on them to restore clocks
* - 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
* and power domains as required. * and power domains as required.
*/ */
void static void
lpm_wake_up() wake_up(void)
{ {
lpm_registered_module_t *module; lpm_registered_module_t *module;
@ -182,8 +221,8 @@ lpm_wake_up()
ti_lib_aon_ioc_freeze_disable(); ti_lib_aon_ioc_freeze_disable();
ti_lib_sys_ctrl_aon_sync(); ti_lib_sys_ctrl_aon_sync();
/* Power up AUX and allow it to go to sleep */ /* Check operating conditions, optimally choose DCDC versus GLDO */
ti_lib_aon_wuc_aux_wakeup_event(AONWUC_AUX_ALLOW_SLEEP); ti_lib_sys_ctrl_dcdc_voltage_conditional_control();
/* Notify all registered modules that we've just woken up */ /* Notify all registered modules that we've just woken up */
for(module = list_head(modules_list); module != NULL; for(module = list_head(modules_list); module != NULL;
@ -198,16 +237,11 @@ void
lpm_drop() lpm_drop()
{ {
lpm_registered_module_t *module; lpm_registered_module_t *module;
lpm_power_domain_lock_t *lock;
uint8_t max_pm = LPM_MODE_MAX_SUPPORTED; uint8_t max_pm = LPM_MODE_MAX_SUPPORTED;
uint8_t module_pm; uint8_t module_pm;
uint32_t domains = LOCKABLE_DOMAINS; uint32_t domains = LOCKABLE_DOMAINS;
if(shutdown_requested) {
shutdown_now();
}
if(RTIMER_CLOCK_LT(cc26xx_rtc_get_next_trigger(), if(RTIMER_CLOCK_LT(cc26xx_rtc_get_next_trigger(),
RTIMER_NOW() + STANDBY_MIN_DURATION)) { RTIMER_NOW() + STANDBY_MIN_DURATION)) {
lpm_sleep(); lpm_sleep();
@ -244,26 +278,21 @@ lpm_drop()
* This is a chance for modules to delay us a little bit until an ongoing * 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 * operation has finished (e.g. uart TX) or to configure themselves for
* deep sleep. * 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; for(module = list_head(modules_list); module != NULL;
module = module->next) { module = module->next) {
if(module->shutdown) { if(module->shutdown) {
module->shutdown(max_pm); 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 */ /* 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 */ /* 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); 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 */ /* Configure clock sources for MCU and AUX: No clock */
ti_lib_aon_wuc_mcu_power_down_config(AONWUC_NO_CLOCK); ti_lib_aon_wuc_mcu_power_down_config(AONWUC_NO_CLOCK);
ti_lib_aon_wuc_aux_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); ti_lib_aon_wuc_aux_sram_config(false);
/* Disable retention in the RFCORE RAM */ /* Disable retention in the RFCORE RAM */
HWREG(PRCM_BASE + PRCM_O_RAMRETEN) &= ~PRCM_RAMRETEN_RFC; ti_lib_prcm_retention_disable(PRCM_DOMAIN_RFCORE);
/* 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;
/* /*
* Always turn off RFCORE, CPU, SYSBUS and VIMS. RFCORE should be off * 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); 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. * source while in deep sleep.
*/ */
if(domains == LOCKABLE_DOMAINS) { if(domains == LOCKABLE_DOMAINS) {
@ -362,7 +401,7 @@ lpm_drop()
* the chip properly, and then we will enable the global interrupt without * the chip properly, and then we will enable the global interrupt without
* unpending events so the handlers can fire * unpending events so the handlers can fire
*/ */
lpm_wake_up(); wake_up();
ti_lib_int_master_enable(); ti_lib_int_master_enable();
} }
@ -396,10 +435,26 @@ lpm_register_module(lpm_registered_module_t *module)
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
void void
lpm_unregister_module(lpm_registered_module_t *module)
{
list_remove(modules_list, module);
}
/*---------------------------------------------------------------------------*/
void
lpm_init() lpm_init()
{ {
list_init(modules_list); 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> #include <stdint.h>
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
#define LPM_MODE_SLEEP PWRCTRL_ACTIVE #define LPM_MODE_SLEEP 1
#define LPM_MODE_DEEP_SLEEP PWRCTRL_POWER_DOWN #define LPM_MODE_DEEP_SLEEP 2
#define LPM_MODE_SHUTDOWN PWRCTRL_SHUTDOWN #define LPM_MODE_SHUTDOWN 3
#define LPM_MODE_MAX_SUPPORTED LPM_MODE_DEEP_SLEEP #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 { typedef struct lpm_registered_module {
struct lpm_registered_module *next; struct lpm_registered_module *next;
uint8_t (*request_max_pm)(void); uint8_t (*request_max_pm)(void);
void (*shutdown)(uint8_t mode); void (*shutdown)(uint8_t mode);
void (*wakeup)(void); void (*wakeup)(void);
uint32_t domain_lock;
} lpm_registered_module_t; } 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 * 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 is in charge of turning power domains back on. This
* function will normally be called within an interrupt context. * 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 = \ #define LPM_MODULE(n, m, s, w, l) static lpm_registered_module_t n = \
{ NULL, m, s, w } { 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 * \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 * \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 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); void lpm_shutdown(uint32_t wakeup_pin, uint32_t io_pull, uint32_t wake_on);
/**
* \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);
/** /**
* \brief Register a module for LPM notifications. * \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); 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 * \brief Initialise the low-power mode management module
*/ */
void lpm_init(void); 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_ */ #endif /* LPM_H_ */
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/

View file

@ -29,6 +29,7 @@
*/ */
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
#include "cc26xx-uart.h" #include "cc26xx-uart.h"
#include "ti-lib.h"
#include <string.h> #include <string.h>
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
@ -47,9 +48,16 @@ puts(const char *str)
return 0; return 0;
} }
for(i = 0; i < strlen(str); i++) { 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; return i;
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
@ -62,9 +70,16 @@ dbg_send_bytes(const unsigned char *s, unsigned int len)
if(i >= len) { if(i >= len) {
break; break;
} }
putchar(*s++); cc26xx_uart_write_byte(*s++);
i++; 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; return i;
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/

View file

@ -58,6 +58,10 @@ slip_arch_writeb(unsigned char c)
void void
slip_arch_init(unsigned long ubr) 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); cc26xx_uart_set_input(slip_input_byte);
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/

View file

@ -148,7 +148,7 @@
#include "driverlib/aux_wuc.h" #include "driverlib/aux_wuc.h"
#define ti_lib_aux_wuc_clock_enable(...) AUXWUCClockEnable(__VA_ARGS__) #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_status(...) AUXWUCClockStatus(__VA_ARGS__)
#define ti_lib_aux_wuc_clock_freq_req(...) AUXWUCClockFreqReq(__VA_ARGS__) #define ti_lib_aux_wuc_clock_freq_req(...) AUXWUCClockFreqReq(__VA_ARGS__)
#define ti_lib_aux_wuc_power_ctrl(...) AUXWUCPowerCtrl(__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_aon_update(...) SysCtrlAonUpdate(__VA_ARGS__)
#define ti_lib_sys_ctrl_set_recharge_before_power_down(...) SysCtrlSetRechargeBeforePowerDown(__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_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 */ /* ssi.h */
#include "driverlib/ssi.h" #include "driverlib/ssi.h"

View file

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

View file

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

View file

@ -6,8 +6,6 @@ boards. More specifically, the example demonstrates:
* How to take sensor readings * How to take sensor readings
* How to use buttons and the reed relay (triggered by holding a magnet near S3 * How to use buttons and the reed relay (triggered by holding a magnet near S3
on the SensorTag). 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 * 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 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 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 * - The example also shows how to retrieve the duration of a
* button press (in ticks). The driver will generate a * button press (in ticks). The driver will generate a
* sensors_changed event upon button release * 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 * - Reed Relay : Will toggle the sensortag buzzer on/off
* *
* @{ * @{
@ -100,7 +94,6 @@
#include "button-sensor.h" #include "button-sensor.h"
#include "batmon-sensor.h" #include "batmon-sensor.h"
#include "board-peripherals.h" #include "board-peripherals.h"
#include "lpm.h"
#include "cc26xx-rf.h" #include "cc26xx-rf.h"
#include "ti-lib.h" #include "ti-lib.h"
@ -251,8 +244,7 @@ get_light_reading()
printf("OPT: Light Read Error\n"); 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); ctimer_set(&opt_timer, next, init_opt_reading, NULL);
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
@ -369,26 +361,6 @@ init_sensor_readings(void)
#endif #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) PROCESS_THREAD(cc26xx_demo_process, ev, data)
{ {
@ -406,8 +378,6 @@ PROCESS_THREAD(cc26xx_demo_process, ev, data)
get_sync_sensor_readings(); get_sync_sensor_readings();
init_sensor_readings(); init_sensor_readings();
keep_uart_on();
while(1) { while(1) {
PROCESS_YIELD(); PROCESS_YIELD();
@ -462,8 +432,6 @@ PROCESS_THREAD(cc26xx_demo_process, ev, data)
button_select_sensor.value(BUTTON_SENSOR_VALUE_DURATION)); button_select_sensor.value(BUTTON_SENSOR_VALUE_DURATION));
#endif #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); value = opt_3001_sensor.value(0);
SENSORS_DEACTIVATE(opt_3001_sensor);
if(value != CC26XX_SENSOR_READING_ERROR) { if(value != CC26XX_SENSOR_READING_ERROR) {
opt_reading.raw = value; opt_reading.raw = value;
@ -587,6 +585,7 @@ get_light_reading()
value % 100); 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); ctimer_set(&opt_timer, next, init_light_reading, NULL);
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/

View file

@ -59,12 +59,13 @@
#include "contiki-conf.h" #include "contiki-conf.h"
#include "sys/process.h" #include "sys/process.h"
#include "dev/serial-line.h" #include "dev/serial-line.h"
#include "dev/cc26xx-uart.h"
#include "net/ip/uip.h" #include "net/ip/uip.h"
#include "net/ip/uip-udp-packet.h" #include "net/ip/uip-udp-packet.h"
#include "net/ip/uiplib.h" #include "net/ip/uiplib.h"
#include "lpm.h"
#include "net-uart.h" #include "net-uart.h"
#include "httpd-simple.h" #include "httpd-simple.h"
#include "sys/cc.h"
#include "ti-lib.h" #include "ti-lib.h"
@ -86,10 +87,6 @@
#define ADDRESS_CONVERSION_OK 1 #define ADDRESS_CONVERSION_OK 1
#define ADDRESS_CONVERSION_ERROR 0 #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 struct uip_udp_conn *udp_conn = NULL;
static uint8_t buffer[MAX_MSG_SIZE]; static uint8_t buffer[MAX_MSG_SIZE];
@ -148,37 +145,16 @@ net_input(void)
return; 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 static void
release_uart(void) release_uart(void)
{ {
/* Release serial PD lock */ cc26xx_uart_set_input(NULL);
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());
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
static void static void
keep_uart_on(void) keep_uart_on(void)
{ {
/* Keep the serial PD on */ cc26xx_uart_set_input(serial_line_input_byte);
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());
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
static int static int

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -78,28 +78,28 @@
#undef LEDS_RED #undef LEDS_RED
#undef LEDS_CONF_ALL #undef LEDS_CONF_ALL
#define LEDS_YELLOW 2 /**< LED2 (Yellow) -> PC1 */ #define LEDS_YELLOW 2 /**< LED2 (Yellow) -> PC1 */
#define LEDS_GREEN 4 /**< LED3 (Green) -> PC2 */ #define LEDS_GREEN 4 /**< LED3 (Green) -> PC2 */
#define LEDS_ORANGE 8 /**< LED4 (Orange) -> PC3 */ #define LEDS_ORANGE 8 /**< LED4 (Orange) -> PC3 */
#if USB_SERIAL_CONF_ENABLE #if USB_SERIAL_CONF_ENABLE
#define LEDS_CONF_ALL 14 #define LEDS_CONF_ALL 14
#define LEDS_RED LEDS_ORANGE #define LEDS_RED LEDS_ORANGE
#else #else
#define LEDS_CONF_ALL 15 #define LEDS_CONF_ALL 15
#define LEDS_RED 1 /**< LED1 (Red) -> PC0 */ #define LEDS_RED 1 /**< LED1 (Red) -> PC0 */
#endif #endif
/* Notify various examples that we have LEDs */ /* Notify various examples that we have LEDs */
#define PLATFORM_HAS_LEDS 1 #define PLATFORM_HAS_LEDS 1
/** @} */ /** @} */
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/** \name USB configuration /** \name USB configuration
* *
* The USB pullup is driven by PC0 and is shared with LED1 * The USB pullup is driven by PC0 and is shared with LED1
*/ */
#define USB_PULLUP_PORT GPIO_C_NUM #define USB_PULLUP_PORT GPIO_C_NUM
#define USB_PULLUP_PIN 0 #define USB_PULLUP_PIN 0
/** @} */ /** @} */
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/** \name UART configuration /** \name UART configuration
@ -115,17 +115,17 @@
* UART1_* below. * UART1_* below.
* @{ * @{
*/ */
#define UART0_RX_PORT GPIO_A_NUM #define UART0_RX_PORT GPIO_A_NUM
#define UART0_RX_PIN 0 #define UART0_RX_PIN 0
#define UART0_TX_PORT GPIO_A_NUM #define UART0_TX_PORT GPIO_A_NUM
#define UART0_TX_PIN 1 #define UART0_TX_PIN 1
#define UART1_CTS_PORT GPIO_B_NUM #define UART1_CTS_PORT GPIO_B_NUM
#define UART1_CTS_PIN 0 #define UART1_CTS_PIN 0
#define UART1_RTS_PORT GPIO_D_NUM #define UART1_RTS_PORT GPIO_D_NUM
#define UART1_RTS_PIN 3 #define UART1_RTS_PIN 3
/** @} */ /** @} */
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/** \name SmartRF Button configuration /** \name SmartRF Button configuration
@ -139,32 +139,32 @@
* @{ * @{
*/ */
/** BUTTON_SELECT -> PA3 */ /** BUTTON_SELECT -> PA3 */
#define BUTTON_SELECT_PORT GPIO_A_NUM #define BUTTON_SELECT_PORT GPIO_A_NUM
#define BUTTON_SELECT_PIN 3 #define BUTTON_SELECT_PIN 3
#define BUTTON_SELECT_VECTOR NVIC_INT_GPIO_PORT_A #define BUTTON_SELECT_VECTOR NVIC_INT_GPIO_PORT_A
/** BUTTON_LEFT -> PC4 */ /** BUTTON_LEFT -> PC4 */
#define BUTTON_LEFT_PORT GPIO_C_NUM #define BUTTON_LEFT_PORT GPIO_C_NUM
#define BUTTON_LEFT_PIN 4 #define BUTTON_LEFT_PIN 4
#define BUTTON_LEFT_VECTOR NVIC_INT_GPIO_PORT_C #define BUTTON_LEFT_VECTOR NVIC_INT_GPIO_PORT_C
/** BUTTON_RIGHT -> PC5 */ /** BUTTON_RIGHT -> PC5 */
#define BUTTON_RIGHT_PORT GPIO_C_NUM #define BUTTON_RIGHT_PORT GPIO_C_NUM
#define BUTTON_RIGHT_PIN 5 #define BUTTON_RIGHT_PIN 5
#define BUTTON_RIGHT_VECTOR NVIC_INT_GPIO_PORT_C #define BUTTON_RIGHT_VECTOR NVIC_INT_GPIO_PORT_C
/** BUTTON_UP -> PC6 */ /** BUTTON_UP -> PC6 */
#define BUTTON_UP_PORT GPIO_C_NUM #define BUTTON_UP_PORT GPIO_C_NUM
#define BUTTON_UP_PIN 6 #define BUTTON_UP_PIN 6
#define BUTTON_UP_VECTOR NVIC_INT_GPIO_PORT_C #define BUTTON_UP_VECTOR NVIC_INT_GPIO_PORT_C
/** BUTTON_DOWN -> PC7 */ /** BUTTON_DOWN -> PC7 */
#define BUTTON_DOWN_PORT GPIO_C_NUM #define BUTTON_DOWN_PORT GPIO_C_NUM
#define BUTTON_DOWN_PIN 7 #define BUTTON_DOWN_PIN 7
#define BUTTON_DOWN_VECTOR NVIC_INT_GPIO_PORT_C #define BUTTON_DOWN_VECTOR NVIC_INT_GPIO_PORT_C
/* Notify various examples that we have Buttons */ /* 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. * 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_PORT GPIO_A_NUM /**< ALS power GPIO control port */
#define ADC_ALS_PWR_PIN 7 /**< ALS power GPIO control pin */ #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_OUT_PIN 6 /**< ALS output ADC input pin on port A */
/** @} */ /** @} */
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/** /**
* \name SPI configuration * \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 SPI0_IN_USE 0
#define SPI_CLK_PIN 2 /**< Clock pin */ #define SPI1_IN_USE 0
#define SPI_MOSI_PORT GPIO_A_NUM /**< MOSI port */ #if SPI0_IN_USE
#define SPI_MOSI_PIN 4 /**< MOSI pin */ /** Clock port SPI0 */
#define SPI_MISO_PORT GPIO_A_NUM /**< MISO port */ #define SPI0_CLK_PORT GPIO_A_NUM
#define SPI_MISO_PIN 5 /**< MISO pin */ /** 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 <string.h>
#include "contiki.h" #include "contiki.h"
#include "sys/cc.h"
#include "sys/clock.h" #include "sys/clock.h"
#include "sys/etimer.h" #include "sys/etimer.h"
@ -136,8 +137,6 @@ long referenceVar;
static struct cooja_mt_thread rtimer_thread; static struct cooja_mt_thread rtimer_thread;
static struct cooja_mt_thread process_run_thread; static struct cooja_mt_thread process_run_thread;
#define MIN(a, b) ( (a)<(b) ? (a) : (b) )
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
#if NETSTACK_CONF_WITH_IPV4 #if NETSTACK_CONF_WITH_IPV4
static void static void

View file

@ -37,18 +37,6 @@
#ifndef HAL_LCD_H #ifndef HAL_LCD_H
#define 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_OUT P8OUT
#define LCD_BACKLT_DIR P8DIR #define LCD_BACKLT_DIR P8DIR
#define LCD_BACKLT_SEL P8SEL #define LCD_BACKLT_SEL P8SEL

View file

@ -46,6 +46,7 @@
#include "lpm.h" #include "lpm.h"
#include "gpio-interrupt.h" #include "gpio-interrupt.h"
#include "dev/watchdog.h" #include "dev/watchdog.h"
#include "dev/oscillators.h"
#include "ieee-addr.h" #include "ieee-addr.h"
#include "vims.h" #include "vims.h"
#include "cc26xx-model.h" #include "cc26xx-model.h"
@ -119,23 +120,6 @@ set_rf_params(void)
#endif #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 * \brief Main function for CC26xx-based platforms
* *
@ -144,41 +128,39 @@ select_lf_xosc(void)
int int
main(void) 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 */ /* Set the LF XOSC as the LF system clock source */
select_lf_xosc(); oscillators_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);
lpm_init(); lpm_init();
board_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(); 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(); 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); fade(LEDS_RED);
ti_lib_int_master_enable();
cc26xx_rtc_init(); cc26xx_rtc_init();
clock_init(); clock_init();
rtimer_init(); rtimer_init();
board_init();
watchdog_init(); watchdog_init();
process_init(); process_init();
@ -187,7 +169,6 @@ main(void)
/* Character I/O Initialisation */ /* Character I/O Initialisation */
#if CC26XX_UART_CONF_ENABLE #if CC26XX_UART_CONF_ENABLE
cc26xx_uart_init(); cc26xx_uart_init();
cc26xx_uart_set_input(serial_line_input_byte);
#endif #endif
serial_line_init(); serial_line_init();

View file

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

View file

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

View file

@ -39,9 +39,55 @@
#include "contiki-conf.h" #include "contiki-conf.h"
#include "ti-lib.h" #include "ti-lib.h"
#include "board-i2c.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 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 static bool
i2c_status() i2c_status()
@ -57,21 +103,34 @@ i2c_status()
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
void void
board_i2c_init() board_i2c_shutdown()
{ {
/* The I2C peripheral must be enabled */ interface = NO_INTERFACE;
ti_lib_prcm_peripheral_run_enable(PRCM_PERIPH_I2C0);
if(accessible()) {
ti_lib_i2c_master_disable(I2C0_BASE);
}
ti_lib_prcm_peripheral_run_disable(PRCM_PERIPH_I2C0);
ti_lib_prcm_load_set(); ti_lib_prcm_load_set();
while(!ti_lib_prcm_load_get()); 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_ioc_pin_type_gpio_input(BOARD_IOID_SDA);
ti_lib_i2c_master_init_exp_clk(I2C0_BASE, ti_lib_ioc_io_port_pull_set(BOARD_IOID_SDA, IOC_IOPULL_UP);
ti_lib_sys_ctrl_peripheral_clock_get( ti_lib_ioc_pin_type_gpio_input(BOARD_IOID_SCL);
PRCM_PERIPH_I2C0, SYSCTRL_SYSBUS_ON), ti_lib_ioc_io_port_pull_set(BOARD_IOID_SCL, IOC_IOPULL_UP);
true);
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
bool bool
@ -248,8 +307,15 @@ board_i2c_select(uint8_t new_interface, uint8_t address)
{ {
slave_addr = address; slave_addr = address;
if(accessible() == false) {
board_i2c_wakeup();
}
if(new_interface != interface) { if(new_interface != interface) {
interface = new_interface; interface = new_interface;
ti_lib_i2c_master_disable(I2C0_BASE);
if(interface == BOARD_I2C_INTERFACE_0) { 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_SDA, IOC_NO_IOPULL);
ti_lib_ioc_io_port_pull_set(BOARD_IOID_SCL, 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_SDA);
ti_lib_ioc_pin_type_gpio_input(BOARD_IOID_SCL); 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_0 0
#define BOARD_I2C_INTERFACE_1 1 #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 * \brief Select an I2C slave
* \param interface The I2C interface to be used (BOARD_I2C_INTERFACE_0 or _1) * \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, bool board_i2c_write_read(uint8_t *wdata, uint8_t wlen, uint8_t *rdata,
uint8_t rlen); 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_ */ #endif /* BOARD_I2C_H_ */
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/

View file

@ -40,12 +40,35 @@
#include "ti-lib.h" #include "ti-lib.h"
#include "board-spi.h" #include "board-spi.h"
#include "board.h" #include "board.h"
#include <stdbool.h>
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
#define CPU_FREQ 48000000ul #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 int
board_spi_write(const uint8_t *buf, size_t len) board_spi_write(const uint8_t *buf, size_t len)
{ {
if(accessible() == false) {
return 0;
}
while(len > 0) { while(len > 0) {
uint32_t ul; uint32_t ul;
@ -61,6 +84,10 @@ board_spi_write(const uint8_t *buf, size_t len)
int int
board_spi_read(uint8_t *buf, size_t len) board_spi_read(uint8_t *buf, size_t len)
{ {
if(accessible() == false) {
return 0;
}
while(len > 0) { while(len > 0) {
uint32_t ul; uint32_t ul;
@ -79,6 +106,10 @@ board_spi_read(uint8_t *buf, size_t len)
void void
board_spi_flush() board_spi_flush()
{ {
if(accessible() == false) {
return;
}
uint32_t ul; uint32_t ul;
while(ti_lib_rom_ssi_data_get_non_blocking(SSI0_BASE, &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; 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_rom_prcm_peripheral_run_enable(PRCM_PERIPH_SSI0);
ti_lib_prcm_load_set(); ti_lib_prcm_load_set();
while(!ti_lib_prcm_load_get()); 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_rom_prcm_peripheral_run_disable(PRCM_PERIPH_SSI0);
ti_lib_prcm_load_set(); ti_lib_prcm_load_set();
while(!ti_lib_prcm_load_get()); 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 <stdint.h>
#include <string.h> #include <string.h>
/*---------------------------------------------------------------------------*/ #include <stdbool.h>
#define PRCM_DOMAINS (PRCM_DOMAIN_SERIAL | PRCM_DOMAIN_PERIPH)
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
static void static void
power_domains_on(void) power_domains_on(void)
{ {
/* Turn on relevant power domains */ /* Turn on the PERIPH PD */
ti_lib_prcm_power_domain_on(PRCM_DOMAINS); ti_lib_prcm_power_domain_on(PRCM_DOMAIN_PERIPH);
/* Wait for domains to power on */ /* 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)); != PRCM_DOMAIN_POWER_ON));
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
@ -64,8 +63,6 @@ static void
lpm_wakeup_handler(void) lpm_wakeup_handler(void)
{ {
power_domains_on(); power_domains_on();
board_i2c_init();
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
static void static void
@ -77,8 +74,12 @@ shutdown_handler(uint8_t mode)
SENSORS_DEACTIVATE(opt_3001_sensor); SENSORS_DEACTIVATE(opt_3001_sensor);
SENSORS_DEACTIVATE(tmp_007_sensor); SENSORS_DEACTIVATE(tmp_007_sensor);
SENSORS_DEACTIVATE(hdc_1000_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 * 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. * 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 void
board_init() board_init()
{ {
/* Disable global interrupts */ /* Disable global interrupts */
uint8_t int_disabled = ti_lib_int_master_disable(); bool int_disabled = ti_lib_int_master_disable();
power_domains_on(); power_domains_on();
@ -112,37 +147,19 @@ board_init()
ti_lib_prcm_load_set(); ti_lib_prcm_load_set();
while(!ti_lib_prcm_load_get()); 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 */ /* I2C controller */
board_i2c_init(); board_i2c_wakeup();
/* 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);
buzzer_init(); buzzer_init();
/* Make sure the external flash is in the lower power mode */
ext_flash_init();
lpm_register_module(&sensortag_module); lpm_register_module(&sensortag_module);
/* For unsupported peripherals, select a default pin configuration */
configure_unused_pins();
/* Re-enable interrupt if initially enabled. */ /* Re-enable interrupt if initially enabled. */
if(!int_disabled) { if(!int_disabled) {
ti_lib_int_master_enable(); ti_lib_int_master_enable();

View file

@ -100,12 +100,16 @@
* Those values are not meant to be modified by the user * 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_TX IOID_16
#define BOARD_IOID_UART_CTS IOID_UNUSED #define BOARD_IOID_UART_CTS IOID_UNUSED
#define BOARD_IOID_UART_RTS IOID_UNUSED #define BOARD_IOID_UART_RTS IOID_UNUSED
#define BOARD_UART_RXD (1 << BOARD_IOID_UART_RXD) #define BOARD_UART_RX (1 << BOARD_IOID_UART_RX)
#define BOARD_UART_TXD (1 << BOARD_IOID_UART_TXD) #define BOARD_UART_TX (1 << BOARD_IOID_UART_TX)
#define BOARD_UART_CTS (1 << BOARD_IOID_UART_CTS) #define BOARD_UART_CTS (1 << BOARD_IOID_UART_CTS)
#define BOARD_UART_RTS (1 << BOARD_IOID_UART_RTS) #define BOARD_UART_RTS (1 << BOARD_IOID_UART_RTS)
/** @} */ /** @} */
@ -156,7 +160,7 @@
*/ */
#define BOARD_IOID_FLASH_CS IOID_14 #define BOARD_IOID_FLASH_CS IOID_14
#define BOARD_FLASH_CS (1 << BOARD_IOID_FLASH_CS) #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) #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 * \name Device string used on startup
* @{ * @{

View file

@ -55,7 +55,7 @@
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
#define BUTTON_GPIO_CFG (IOC_CURRENT_2MA | IOC_STRENGTH_AUTO | \ #define BUTTON_GPIO_CFG (IOC_CURRENT_2MA | IOC_STRENGTH_AUTO | \
IOC_IOPULL_UP | IOC_SLEW_DISABLE | \ 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_INT_ENABLE | IOC_IOMODE_NORMAL | \
IOC_NO_WAKE_UP | IOC_INPUT_ENABLE | \ IOC_NO_WAKE_UP | IOC_INPUT_ENABLE | \
IOC_JTAG_DISABLE) IOC_JTAG_DISABLE)
@ -116,7 +116,7 @@ button_press_handler(uint8_t ioid)
sensors_changed(&button_right_sensor); sensors_changed(&button_right_sensor);
} }
} else { } 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> #include <stdio.h>
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
static uint8_t buzzer_on; static uint8_t buzzer_on;
static lpm_power_domain_lock_t lock; LPM_MODULE(buzzer_module, NULL, NULL, NULL, LPM_DOMAIN_PERIPH);
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
void void
buzzer_init() buzzer_init()
{ {
buzzer_on = 0; 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 uint8_t
@ -72,9 +65,28 @@ buzzer_start(int freq)
{ {
uint32_t load; 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; 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 */ /* Stop the timer */
ti_lib_timer_disable(GPT0_BASE, TIMER_A); ti_lib_timer_disable(GPT0_BASE, TIMER_A);
@ -88,12 +100,6 @@ buzzer_start(int freq)
/* Start */ /* Start */
ti_lib_timer_enable(GPT0_BASE, TIMER_A); 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 void
@ -101,24 +107,37 @@ buzzer_stop()
{ {
buzzer_on = 0; 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 */ /* Stop the timer */
ti_lib_timer_disable(GPT0_BASE, TIMER_A); ti_lib_timer_disable(GPT0_BASE, TIMER_A);
/* /*
* Stop running in sleep mode. * Stop the module clock:
* 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 * Currently GPT0 is in use by clock_delay_usec (GPT0/TB) and by this
* mode and we control TA here. Thus, with the current setup, it's OK to * module here (GPT0/TA).
* 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 * clock_delay_usec
* to happen through an umbrella module * - 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_sleep_disable(PRCM_PERIPH_TIMER0);
ti_lib_prcm_peripheral_deep_sleep_disable(PRCM_PERIPH_TIMER0); ti_lib_prcm_peripheral_deep_sleep_disable(PRCM_PERIPH_TIMER0);
ti_lib_prcm_load_set(); ti_lib_prcm_load_set();
while(!ti_lib_prcm_load_get()); 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 */ /* Part specific constants */
#define BLS_MANUFACTURER_ID 0xEF #define BLS_MANUFACTURER_ID 0xEF
#define BLS_DEVICE_ID 0x11 #define BLS_DEVICE_ID 0x12
#define BLS_PROGRAM_PAGE_SIZE 256 #define BLS_PROGRAM_PAGE_SIZE 256
#define BLS_ERASE_SECTOR_SIZE 4096 #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 * \brief Verify the flash part.
* the status register is accessible. * \return True when successful.
* \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.
*/ */
static bool static bool
verify_part(void) verify_part(void)
@ -210,6 +168,57 @@ verify_part(void)
return true; 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. * \brief Enable write.
* \return Zero when successful. * \return Zero when successful.
@ -232,7 +241,7 @@ write_enable(void)
bool bool
ext_flash_open() ext_flash_open()
{ {
board_spi_open(4000000, BOARD_SPI_CLK_FLASH); board_spi_open(4000000, BOARD_IOID_SPI_CLK_FLASH);
/* GPIO pin configuration */ /* GPIO pin configuration */
ti_lib_ioc_pin_type_gpio_output(BOARD_IOID_FLASH_CS); ti_lib_ioc_pin_type_gpio_output(BOARD_IOID_FLASH_CS);
@ -406,4 +415,11 @@ ext_flash_test(void)
return ret; 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 * \brief Close the storage driver
*
* This call will put the device in its lower power mode (power down).
*/ */
void ext_flash_close(void); 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. * \return True when successful.
*/ */
bool ext_flash_test(void); 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_ */ #endif /* EXT_FLASH_H_ */
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/

View file

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

View file

@ -69,16 +69,42 @@
#define REG_MANUFACTURER_ID 0x7E #define REG_MANUFACTURER_ID 0x7E
#define REG_DEVICE_ID 0x7F #define REG_DEVICE_ID 0x7F
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/* Register values */ /*
#define MANUFACTURER_ID 0x5449 /* TI */ * Configuration Register Bits and Masks.
#define DEVICE_ID 0x3001 /* Opt 3001 */ * We use uint16_t to read from / write to registers, meaning that the
#define CONFIG_RESET 0xC810 * register's MSB is the variable's LSB.
#define CONFIG_TEST 0xCC10 */
#define CONFIG_ENABLE 0x10CC /* 0xCC10 */ #define CONFIG_RN 0x00F0 /* [15..12] Range Number */
#define CONFIG_DISABLE 0x108C /* 0xC810 */ #define CONFIG_CT 0x0008 /* [11] Conversion Time */
/*---------------------------------------------------------------------------*/ #define CONFIG_M 0x0006 /* [10..9] Mode of Conversion */
/* Bit values */ #define CONFIG_OVF 0x0001 /* [8] Overflow */
#define DATA_RDY_BIT 0x0080 /* Data ready */ #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 */ /* Register length */
#define REGISTER_LENGTH 2 #define REGISTER_LENGTH 2
@ -86,24 +112,22 @@
/* Sensor data size */ /* Sensor data size */
#define DATA_LENGTH 2 #define DATA_LENGTH 2
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
#define SENSOR_STATUS_DISABLED 0 /*
#define SENSOR_STATUS_NOT_READY 1 * SENSOR_STATE_SLEEPING and SENSOR_STATE_ACTIVE are mutually exclusive.
#define SENSOR_STATUS_ENABLED 2 * 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 */ /* Wait SENSOR_STARTUP_DELAY for the sensor to be ready - 125ms */
#define SENSOR_STARTUP_DELAY (CLOCK_SECOND >> 3) #define SENSOR_STARTUP_DELAY (CLOCK_SECOND >> 3)
static struct ctimer startup_timer; 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 * \brief Select the sensor on the I2C bus
*/ */
@ -114,6 +138,28 @@ select(void)
board_i2c_select(BOARD_I2C_INTERFACE_0, OPT3001_I2C_ADDRESS); 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 * \brief Turn the sensor on/off
* \param enable TRUE: on, FALSE: off * \param enable TRUE: on, FALSE: off
@ -122,13 +168,20 @@ static void
enable_sensor(bool enable) enable_sensor(bool enable)
{ {
uint16_t val; uint16_t val;
uint16_t had_data_ready = state & SENSOR_STATE_DATA_READY;
select(); select();
if(enable) { 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 { } else {
val = CONFIG_DISABLE; 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); sensor_common_write_reg(REG_CONFIGURATION, (uint8_t *)&val, REGISTER_LENGTH);
@ -145,15 +198,15 @@ read_data(uint16_t *raw_data)
bool success; bool success;
uint16_t val; uint16_t val;
if((state & SENSOR_STATE_DATA_READY) != SENSOR_STATE_DATA_READY) {
return false;
}
select(); select();
success = sensor_common_read_reg(REG_CONFIGURATION, (uint8_t *)&val, success = sensor_common_read_reg(REG_CONFIGURATION, (uint8_t *)&val,
REGISTER_LENGTH); REGISTER_LENGTH);
if(success) {
success = (val & DATA_RDY_BIT) == DATA_RDY_BIT;
}
if(success) { if(success) {
success = sensor_common_read_reg(REG_RESULT, (uint8_t *)&val, DATA_LENGTH); success = sensor_common_read_reg(REG_RESULT, (uint8_t *)&val, DATA_LENGTH);
} }
@ -196,14 +249,9 @@ value(int type)
uint16_t raw_val; uint16_t raw_val;
float converted_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); rv = read_data(&raw_val);
if(rv == 0) { if(rv == false) {
return CC26XX_SENSOR_READING_ERROR; return CC26XX_SENSOR_READING_ERROR;
} }
@ -229,30 +277,38 @@ value(int type)
static int static int
configure(int type, int enable) configure(int type, int enable)
{ {
int rv = 0;
switch(type) { switch(type) {
case SENSORS_HW_INIT: 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; break;
case SENSORS_ACTIVE: case SENSORS_ACTIVE:
if(enable) { if(enable) {
enable_sensor(1); enable_sensor(1);
ctimer_set(&startup_timer, SENSOR_STARTUP_DELAY, notify_ready, NULL); ctimer_set(&startup_timer, SENSOR_STARTUP_DELAY, notify_ready, NULL);
enabled = SENSOR_STATUS_NOT_READY; rv = 1;
} else { } else {
ctimer_stop(&startup_timer); ctimer_stop(&startup_timer);
enable_sensor(0); enable_sensor(0);
enabled = SENSOR_STATUS_DISABLED; rv = 0;
} }
break; break;
default: default:
break; break;
} }
return enabled; return rv;
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/** /**
* \brief Returns the status of the sensor * \brief Returns the status of the sensor
* \param type SENSORS_ACTIVE or SENSORS_READY * \param type ignored
* \return 1 if the sensor is enabled * \return The state of the sensor SENSOR_STATE_xyz
*/ */
static int static int
status(int type) status(int type)
@ -260,12 +316,10 @@ status(int type)
switch(type) { switch(type) {
case SENSORS_ACTIVE: case SENSORS_ACTIVE:
case SENSORS_READY: case SENSORS_READY:
return enabled;
break;
default: default:
break; break;
} }
return SENSOR_STATUS_DISABLED; return state;
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
SENSORS_SENSOR(opt_3001_sensor, "OPT3001", value, configure, status); 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 * 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. * 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: * We use single-shot readings. In this mode, the hardware automatically goes
* - Turn the sensor off by calling SENSORS_DEACTIVATE, but in order to take * back to its shutdown mode after the conversion is finished. However, it will
* subsequent readings SENSORS_ACTIVATE must be called again * still respond to I2C operations, so the last conversion can still be read
* - Leave the sensor on. In this scenario, the caller can simply keep calling * out.
* value() for subsequent readings, but having the sensor on will consume *
* energy * In order to take a new reading, the caller has to use SENSORS_ACTIVATE
* again.
* @{ * @{
* *
* \file * \file

View file

@ -88,7 +88,7 @@
#define SWAP(v) ((LO_UINT16(v) << 8) | HI_UINT16(v)) #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 uint8_t buf[DATA_SIZE];
static uint16_t val; static uint16_t val;
@ -124,7 +124,7 @@ enable_sensor(bool enable)
{ {
bool success; bool success;
SELECT() SELECT();
if(enable) { if(enable) {
val = TMP007_VAL_CONFIG_ON; val = TMP007_VAL_CONFIG_ON;
@ -267,6 +267,10 @@ configure(int type, int enable)
{ {
switch(type) { switch(type) {
case SENSORS_HW_INIT: 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); enable_sensor(false);
enabled = SENSOR_STATUS_INITIALISED; enabled = SENSOR_STATUS_INITIALISED;
break; break;

View file

@ -45,95 +45,65 @@
#include <stdint.h> #include <stdint.h>
#include <string.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 static void
power_domains_on(void) wakeup_handler(void)
{ {
/* Turn on relevant power domains */ /* Turn on the PERIPH PD */
ti_lib_prcm_power_domain_on(LPM_DOMAINS); ti_lib_prcm_power_domain_on(PRCM_DOMAIN_PERIPH);
while((ti_lib_prcm_power_domain_status(PRCM_DOMAIN_PERIPH)
/* Wait for domains to power on */
while((ti_lib_prcm_power_domain_status(LPM_DOMAINS)
!= PRCM_DOMAIN_POWER_ON)); != PRCM_DOMAIN_POWER_ON));
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
static void
lpm_wakeup_handler(void)
{
power_domains_on();
}
/*---------------------------------------------------------------------------*/
/* /*
* Declare a data structure to register with LPM. * 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 * 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 * getting notified before deep sleep. All we need is to be notified when we
* wake up so we can turn power domains back on * 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 static void
board_init() configure_unused_pins(void)
{ {
uint8_t int_disabled = ti_lib_int_master_disable(); /* Turn off 3.3-V domain (lcd/sdcard power, output low) */
/* 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 */
ti_lib_ioc_pin_type_gpio_output(BOARD_IOID_3V3_EN); ti_lib_ioc_pin_type_gpio_output(BOARD_IOID_3V3_EN);
ti_lib_gpio_pin_write(BOARD_3V3_EN, 0); ti_lib_gpio_pin_write(BOARD_3V3_EN, 0);
/* LCD CSn (output high) */ /* Accelerometer (PWR output low, 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) */
ti_lib_ioc_pin_type_gpio_output(BOARD_IOID_ACC_PWR); ti_lib_ioc_pin_type_gpio_output(BOARD_IOID_ACC_PWR);
ti_lib_gpio_pin_write(BOARD_ACC_PWR, 0); 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) */ /* Ambient light sensor (off, output low) */
ti_lib_ioc_pin_type_gpio_output(BOARD_IOID_ALS_PWR); ti_lib_ioc_pin_type_gpio_output(BOARD_IOID_ALS_PWR);
ti_lib_gpio_pin_write(BOARD_ALS_PWR, 0); ti_lib_gpio_pin_write(BOARD_ALS_PWR, 0);
ti_lib_ioc_pin_type_gpio_input(BOARD_IOID_ALS_OUT); 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); 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); lpm_register_module(&srf_module);
configure_unused_pins();
/* Re-enable interrupt if initially enabled. */ /* Re-enable interrupt if initially enabled. */
if(!int_disabled) { if(!int_disabled) {
ti_lib_int_master_enable(); ti_lib_int_master_enable();

View file

@ -107,8 +107,8 @@
*/ */
#define BOARD_IOID_UART_RX IOID_2 #define BOARD_IOID_UART_RX IOID_2
#define BOARD_IOID_UART_TX IOID_3 #define BOARD_IOID_UART_TX IOID_3
#define BOARD_IOID_UART_CTS IOID_0 #define BOARD_IOID_UART_CTS IOID_UNUSED
#define BOARD_IOID_UART_RTS IOID_21 #define BOARD_IOID_UART_RTS IOID_UNUSED
#define BOARD_UART_RX (1 << BOARD_IOID_UART_RX) #define BOARD_UART_RX (1 << BOARD_IOID_UART_RX)
#define BOARD_UART_TX (1 << BOARD_IOID_UART_TX) #define BOARD_UART_TX (1 << BOARD_IOID_UART_TX)
#define BOARD_UART_CTS (1 << BOARD_IOID_UART_CTS) #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 | \ #define BUTTON_GPIO_CFG (IOC_CURRENT_2MA | IOC_STRENGTH_AUTO | \
IOC_IOPULL_UP | IOC_SLEW_DISABLE | \ 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_INT_ENABLE | IOC_IOMODE_NORMAL | \
IOC_NO_WAKE_UP | IOC_INPUT_ENABLE | \ IOC_NO_WAKE_UP | IOC_INPUT_ENABLE | \
IOC_JTAG_DISABLE) IOC_JTAG_DISABLE)
@ -137,7 +137,7 @@ button_press_handler(uint8_t ioid)
sensors_changed(&button_right_sensor); sensors_changed(&button_right_sensor);
} }
} else { } 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: gitclean:
@git clean -d -x -n .. @git clean -d -x -n ..

View file

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

View file

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

View file

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

View file

@ -166,6 +166,19 @@ public class DirectedGraphMedium extends AbstractRadioMedium {
DGRMDestinationRadio dstRadios[] = getPotentialDestinations(conn.getSource()); DGRMDestinationRadio dstRadios[] = getPotentialDestinations(conn.getSource());
if (dstRadios == null) continue; if (dstRadios == null) continue;
for (DGRMDestinationRadio dstRadio : dstRadios) { 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) { if (dstRadio.radio.getCurrentSignalStrength() < dstRadio.signal) {
dstRadio.radio.setCurrentSignalStrength(dstRadio.signal); dstRadio.radio.setCurrentSignalStrength(dstRadio.signal);
} }
@ -254,6 +267,20 @@ public class DirectedGraphMedium extends AbstractRadioMedium {
continue; 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()) { if (!dest.radio.isRadioOn()) {
/* Fail: radio is off */ /* Fail: radio is off */
@ -269,13 +296,6 @@ public class DirectedGraphMedium extends AbstractRadioMedium {
continue; 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()) { if (dest.radio.isReceiving()) {
/* Fail: radio is already actively receiving */ /* Fail: radio is already actively receiving */
/*logger.info(source + ": Fail, receiving");*/ /*logger.info(source + ": Fail, receiving");*/

View file

@ -192,6 +192,13 @@ public class UDGM extends AbstractRadioMedium {
if (sender.getChannel() >= 0 && if (sender.getChannel() >= 0 &&
recv.getChannel() >= 0 && recv.getChannel() >= 0 &&
sender.getChannel() != recv.getChannel()) { 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; continue;
} }
Position recvPos = recv.getPosition(); 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 $@ $<