mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
1527 lines
43 KiB
Diff
1527 lines
43 KiB
Diff
From b5ecce21b0f3467bf5ef35b84a921bb081417764 Mon Sep 17 00:00:00 2001
|
|
From: Thomas Eichinger <thomas.eichinger1@gmail.com>
|
|
Date: Tue, 25 Nov 2014 15:46:26 +0100
|
|
Subject: [PATCH 2/5] Add RIOT adaption
|
|
|
|
---
|
|
bsp/boards/board_ow.h | 40 +++
|
|
bsp/boards/riot-adaption/Makefile | 3 +
|
|
bsp/boards/riot-adaption/board_info.h | 90 ++++++
|
|
bsp/boards/riot-adaption/board_ow.c | 28 ++
|
|
bsp/boards/riot-adaption/debugpins.c | 27 ++
|
|
bsp/boards/riot-adaption/eui64.c | 25 ++
|
|
bsp/boards/riot-adaption/leds_ow.c | 137 ++++++++++
|
|
bsp/boards/riot-adaption/radio.c | 496 ++++++++++++++++++++++++++++++++++
|
|
bsp/boards/riot-adaption/radiotimer.c | 155 +++++++++++
|
|
bsp/boards/riot-adaption/spi_ow.c | 321 ++++++++++++++++++++++
|
|
bsp/boards/riot-adaption/uart_ow.c | 96 +++++++
|
|
11 files changed, 1418 insertions(+)
|
|
create mode 100644 bsp/boards/board_ow.h
|
|
create mode 100644 bsp/boards/riot-adaption/Makefile
|
|
create mode 100644 bsp/boards/riot-adaption/board_info.h
|
|
create mode 100644 bsp/boards/riot-adaption/board_ow.c
|
|
create mode 100644 bsp/boards/riot-adaption/debugpins.c
|
|
create mode 100644 bsp/boards/riot-adaption/eui64.c
|
|
create mode 100644 bsp/boards/riot-adaption/leds_ow.c
|
|
create mode 100644 bsp/boards/riot-adaption/radio.c
|
|
create mode 100644 bsp/boards/riot-adaption/radiotimer.c
|
|
create mode 100644 bsp/boards/riot-adaption/spi_ow.c
|
|
create mode 100644 bsp/boards/riot-adaption/uart_ow.c
|
|
|
|
diff --git a/bsp/boards/board_ow.h b/bsp/boards/board_ow.h
|
|
new file mode 100644
|
|
index 0000000..adc373c
|
|
--- /dev/null
|
|
+++ b/bsp/boards/board_ow.h
|
|
@@ -0,0 +1,40 @@
|
|
+#ifndef __BOARD_H
|
|
+#define __BOARD_H
|
|
+
|
|
+/**
|
|
+\addtogroup BSP
|
|
+\{
|
|
+\addtogroup board
|
|
+\{
|
|
+
|
|
+\brief Cross-platform declaration "board" bsp module.
|
|
+
|
|
+\author Thomas Watteyne <watteyne@eecs.berkeley.edu>, February 2012.
|
|
+*/
|
|
+
|
|
+#include "board_info.h"
|
|
+#include "toolchain_defs.h"
|
|
+
|
|
+//=========================== define ==========================================
|
|
+
|
|
+typedef enum {
|
|
+ DO_NOT_KICK_SCHEDULER,
|
|
+ KICK_SCHEDULER,
|
|
+} kick_scheduler_t;
|
|
+
|
|
+//=========================== typedef =========================================
|
|
+
|
|
+//=========================== variables =======================================
|
|
+
|
|
+//=========================== prototypes ======================================
|
|
+
|
|
+void board_init(void);
|
|
+void board_sleep(void);
|
|
+void board_reset(void);
|
|
+
|
|
+/**
|
|
+\}
|
|
+\}
|
|
+*/
|
|
+
|
|
+#endif
|
|
diff --git a/bsp/boards/riot-adaption/Makefile b/bsp/boards/riot-adaption/Makefile
|
|
new file mode 100644
|
|
index 0000000..fad1c2e
|
|
--- /dev/null
|
|
+++ b/bsp/boards/riot-adaption/Makefile
|
|
@@ -0,0 +1,3 @@
|
|
+MODULE = openwsn
|
|
+
|
|
+include $(RIOTBASE)/Makefile.base
|
|
\ No newline at end of file
|
|
diff --git a/bsp/boards/riot-adaption/board_info.h b/bsp/boards/riot-adaption/board_info.h
|
|
new file mode 100644
|
|
index 0000000..85f2eb1
|
|
--- /dev/null
|
|
+++ b/bsp/boards/riot-adaption/board_info.h
|
|
@@ -0,0 +1,90 @@
|
|
+/**
|
|
+\brief agilefox board information bsp module (based on openmoteSTM32 code).
|
|
+
|
|
+This module simply defines some strings describing the board, which CoAP uses
|
|
+to return the board's description.
|
|
+
|
|
+\author Thomas Watteyne <watteyne@eecs.berkeley.edu>, February 2012.
|
|
+\author Tengfei Chang <tengfei.chang@gmail.com>, July 2012.
|
|
+\author Alaeddine Weslati <alaeddine.weslati@inria.fr>, August 2013.
|
|
+*/
|
|
+
|
|
+#ifndef __BOARD_INFO_H
|
|
+#define __BOARD_INFO_H
|
|
+
|
|
+#include "stdint.h"
|
|
+#include "string.h"
|
|
+#include "cpu.h"
|
|
+
|
|
+//=========================== defines =========================================
|
|
+
|
|
+#define INTERRUPT_DECLARATION(); //no declaration
|
|
+
|
|
+#define DISABLE_INTERRUPTS() disableIRQ();
|
|
+#define ENABLE_INTERRUPTS() enableIRQ();
|
|
+
|
|
+//===== timer
|
|
+
|
|
+#define PORT_TIMER_WIDTH uint32_t
|
|
+#define PORT_RADIOTIMER_WIDTH uint32_t
|
|
+
|
|
+#define PORT_SIGNED_INT_WIDTH int32_t
|
|
+#define PORT_TICS_PER_MS 32
|
|
+#define SCHEDULER_WAKEUP() //EXTI->SWIER |= EXTI_Line1;
|
|
+#define SCHEDULER_ENABLE_INTERRUPT() //enable in board use EXTI_Line1
|
|
+
|
|
+//===== pinout
|
|
+
|
|
+// [P4.7] radio SLP_TR_CNTL
|
|
+#define PORT_PIN_RADIO_SLP_TR_CNTL_HIGH() //GPIOA->ODR |= (1<<0);
|
|
+#define PORT_PIN_RADIO_SLP_TR_CNTL_LOW() //GPIOA->ODR &= ~(1<<0);
|
|
+// radio reset line
|
|
+// radio /RST
|
|
+#define PORT_PIN_RADIO_RESET_HIGH() //GPIOC->ODR |= 0X0040;// nothing
|
|
+#define PORT_PIN_RADIO_RESET_LOW() //GPIOC->ODR &= ~0X0040;// nothing
|
|
+
|
|
+//===== IEEE802154E timing
|
|
+
|
|
+//// time-slot related
|
|
+//#define PORT_TsSlotDuration 491 // counter counts one extra count, see datasheet
|
|
+//// execution speed related
|
|
+//#define PORT_maxTxDataPrepare 66 // 2014us (measured 746us)
|
|
+//#define PORT_maxRxAckPrepare 10 // 305us (measured 83us)
|
|
+//#define PORT_maxRxDataPrepare 33 // 1007us (measured 84us)
|
|
+//#define PORT_maxTxAckPrepare 10 // 305us (measured 219us)
|
|
+//// radio speed related
|
|
+//#define PORT_delayTx 9 // 214us (measured 219us)
|
|
+//#define PORT_delayRx 0 // 0us (can not measure)
|
|
+//// radio watchdog
|
|
+
|
|
+// time-slot related
|
|
+#define PORT_TsSlotDuration 245 // counter counts one extra count, see datasheet
|
|
+// execution speed related (rcc configure need 235us)
|
|
+#define PORT_maxTxDataPrepare 33 // 2014us (measured 812us+235) stm32
|
|
+#define PORT_maxRxAckPrepare 10 // 900us (measured 171us+235) stm32
|
|
+#define PORT_maxRxDataPrepare 16 // 976us (measured 170us+235) stm32
|
|
+#define PORT_maxTxAckPrepare 10 // 900us (measured 323us+235) stm32
|
|
+// radio speed related
|
|
+#define PORT_delayTx 10 // 549us (measured 315us+235) .....
|
|
+#define PORT_delayRx 0 // 0us (can not measure)
|
|
+
|
|
+//===== adaptive_sync accuracy
|
|
+
|
|
+#define SYNC_ACCURACY 2 // ticks
|
|
+
|
|
+//=========================== typedef ========================================
|
|
+
|
|
+//=========================== variables =======================================
|
|
+
|
|
+static const uint8_t rreg_uriquery[] = "h=ucb";
|
|
+static const uint8_t infoBoardname[] = "riot-os";
|
|
+static const uint8_t infouCName[] = "various";
|
|
+static const uint8_t infoRadioName[] = "various";
|
|
+
|
|
+//=========================== prototypes ======================================
|
|
+
|
|
+//=========================== public ==========================================
|
|
+
|
|
+//=========================== private =========================================
|
|
+
|
|
+#endif
|
|
diff --git a/bsp/boards/riot-adaption/board_ow.c b/bsp/boards/riot-adaption/board_ow.c
|
|
new file mode 100644
|
|
index 0000000..95f29b1
|
|
--- /dev/null
|
|
+++ b/bsp/boards/riot-adaption/board_ow.c
|
|
@@ -0,0 +1,28 @@
|
|
+#include "board_ow.h"
|
|
+#include "radiotimer.h"
|
|
+#include "radio.h"
|
|
+#include "debugpins.h"
|
|
+#include "spi_ow.h"
|
|
+
|
|
+#define ENABLE_DEBUG (1)
|
|
+#include "debug.h"
|
|
+
|
|
+void board_init_ow(void)
|
|
+{
|
|
+ DEBUG("%s\n",__PRETTY_FUNCTION__);
|
|
+ spi_init_ow();
|
|
+ radio_init();
|
|
+ DEBUG("%s\n",__PRETTY_FUNCTION__);
|
|
+ radiotimer_init();
|
|
+ DEBUG("%s\n",__PRETTY_FUNCTION__);
|
|
+ debugpins_init();
|
|
+ DEBUG("%s\n",__PRETTY_FUNCTION__);
|
|
+}
|
|
+
|
|
+void board_sleep(void)
|
|
+{
|
|
+}
|
|
+
|
|
+void board_reset(void)
|
|
+{
|
|
+}
|
|
\ No newline at end of file
|
|
diff --git a/bsp/boards/riot-adaption/debugpins.c b/bsp/boards/riot-adaption/debugpins.c
|
|
new file mode 100644
|
|
index 0000000..06c7c2e
|
|
--- /dev/null
|
|
+++ b/bsp/boards/riot-adaption/debugpins.c
|
|
@@ -0,0 +1,27 @@
|
|
+#include "debugpins.h"
|
|
+
|
|
+void debugpins_init(void) {}
|
|
+
|
|
+void debugpins_frame_toggle(void) {}
|
|
+void debugpins_frame_clr(void) {}
|
|
+void debugpins_frame_set(void) {}
|
|
+
|
|
+void debugpins_slot_toggle(void) {}
|
|
+void debugpins_slot_clr(void) {}
|
|
+void debugpins_slot_set(void) {}
|
|
+
|
|
+void debugpins_fsm_toggle(void) {}
|
|
+void debugpins_fsm_clr(void) {}
|
|
+void debugpins_fsm_set(void) {}
|
|
+
|
|
+void debugpins_task_toggle(void) {}
|
|
+void debugpins_task_clr(void) {}
|
|
+void debugpins_task_set(void) {}
|
|
+
|
|
+void debugpins_isr_toggle(void) {}
|
|
+void debugpins_isr_clr(void) {}
|
|
+void debugpins_isr_set(void) {}
|
|
+
|
|
+void debugpins_radio_toggle(void) {}
|
|
+void debugpins_radio_clr(void) {}
|
|
+void debugpins_radio_set(void) {}
|
|
\ No newline at end of file
|
|
diff --git a/bsp/boards/riot-adaption/eui64.c b/bsp/boards/riot-adaption/eui64.c
|
|
new file mode 100644
|
|
index 0000000..da9da6d
|
|
--- /dev/null
|
|
+++ b/bsp/boards/riot-adaption/eui64.c
|
|
@@ -0,0 +1,25 @@
|
|
+#include "eui64.h"
|
|
+
|
|
+//=========================== defines =========================================
|
|
+// stm32f103rey, 96-bit unique ID address
|
|
+#define UNIQUE_ID_BASE_ADDRESS 0x1FFFF7E8
|
|
+
|
|
+//=========================== variables =======================================
|
|
+
|
|
+const uint8_t const *uid = (const uint8_t *const) UNIQUE_ID_BASE_ADDRESS;
|
|
+
|
|
+//=========================== prototypes ======================================
|
|
+
|
|
+//=========================== public ==========================================
|
|
+
|
|
+void eui64_get(uint8_t* addressToWrite)
|
|
+{
|
|
+ addressToWrite[0] = uid[0];
|
|
+ addressToWrite[1] = uid[1];
|
|
+ addressToWrite[2] = uid[2];
|
|
+ addressToWrite[3] = uid[3];
|
|
+ addressToWrite[4] = uid[4];
|
|
+ addressToWrite[5] = uid[5];
|
|
+ addressToWrite[6] = uid[6];
|
|
+ addressToWrite[7] = uid[7];
|
|
+}
|
|
\ No newline at end of file
|
|
diff --git a/bsp/boards/riot-adaption/leds_ow.c b/bsp/boards/riot-adaption/leds_ow.c
|
|
new file mode 100644
|
|
index 0000000..cd892e1
|
|
--- /dev/null
|
|
+++ b/bsp/boards/riot-adaption/leds_ow.c
|
|
@@ -0,0 +1,137 @@
|
|
+#include "board.h"
|
|
+#include "leds.h"
|
|
+
|
|
+void Delay(void);
|
|
+
|
|
+
|
|
+void leds_init_ow(void)
|
|
+{
|
|
+}
|
|
+
|
|
+/* red */
|
|
+void leds_error_on(void)
|
|
+{
|
|
+ LED_RED_ON;
|
|
+}
|
|
+
|
|
+void leds_error_off(void)
|
|
+{
|
|
+ LED_RED_OFF;
|
|
+}
|
|
+void leds_error_toggle(void)
|
|
+{
|
|
+ LED_RED_TOGGLE;
|
|
+}
|
|
+uint8_t leds_error_isOn(void)
|
|
+{
|
|
+ uint8_t bitstatus = 0x00;
|
|
+ if ((LED_RED_PORT->ODR & LED_RED_PIN) != (uint32_t)0)
|
|
+ {
|
|
+ bitstatus = 0x00;
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ bitstatus = 0x01;
|
|
+ }
|
|
+ return bitstatus;
|
|
+}
|
|
+void leds_error_blink(void) {}
|
|
+
|
|
+/* green */
|
|
+void leds_sync_on(void)
|
|
+{
|
|
+ LED_GREEN_ON;
|
|
+}
|
|
+void leds_sync_off(void)
|
|
+{
|
|
+ LED_GREEN_OFF;
|
|
+}
|
|
+void leds_sync_toggle(void)
|
|
+{
|
|
+ LED_GREEN_TOGGLE;
|
|
+}
|
|
+uint8_t leds_sync_isOn(void)
|
|
+{
|
|
+ uint8_t bitstatus = 0x00;
|
|
+ if ((LED_GREEN_PORT->ODR & LED_GREEN_PIN) != (uint32_t)0)
|
|
+ {
|
|
+ bitstatus = 0x00;
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ bitstatus = 0x01;
|
|
+ }
|
|
+ return bitstatus;
|
|
+}
|
|
+
|
|
+/* orange */
|
|
+void leds_radio_on(void)
|
|
+{
|
|
+ LED_ORANGE_ON;
|
|
+}
|
|
+void leds_radio_off(void)
|
|
+{
|
|
+ LED_ORANGE_OFF;
|
|
+}
|
|
+void leds_radio_toggle(void)
|
|
+{
|
|
+ LED_ORANGE_TOGGLE;
|
|
+}
|
|
+uint8_t leds_radio_isOn(void)
|
|
+{
|
|
+ uint8_t bitstatus = 0x00;
|
|
+ if ((LED_ORANGE_PORT->ODR & LED_ORANGE_PIN) != (uint32_t)0)
|
|
+ {
|
|
+ bitstatus = 0x00;
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ bitstatus = 0x01;
|
|
+ }
|
|
+ return bitstatus;
|
|
+}
|
|
+
|
|
+/* yellow */
|
|
+void leds_debug_on(void) {}
|
|
+void leds_debug_off(void) {}
|
|
+void leds_debug_toggle(void) {}
|
|
+uint8_t leds_debug_isOn(void) { return 0;}
|
|
+
|
|
+void leds_all_on(void)
|
|
+{
|
|
+ leds_error_on();
|
|
+ leds_sync_on();
|
|
+ leds_radio_on();
|
|
+}
|
|
+void leds_all_off(void)
|
|
+{
|
|
+ leds_error_off();
|
|
+ leds_sync_off();
|
|
+ leds_radio_off();
|
|
+}
|
|
+void leds_all_toggle(void)
|
|
+{
|
|
+ leds_error_toggle();
|
|
+ leds_sync_toggle();
|
|
+ leds_radio_toggle();
|
|
+}
|
|
+
|
|
+void leds_circular_shift(void)
|
|
+{
|
|
+ leds_error_toggle();
|
|
+ Delay();
|
|
+ leds_sync_toggle();
|
|
+ Delay();
|
|
+ leds_radio_toggle();
|
|
+ Delay();
|
|
+}
|
|
+
|
|
+void leds_increment(void) {}
|
|
+
|
|
+//=========================== private =========================================
|
|
+
|
|
+void Delay(void)
|
|
+{
|
|
+ uint32_t i;
|
|
+ for(i=0; i<0xfffff; i++);
|
|
+}
|
|
\ No newline at end of file
|
|
diff --git a/bsp/boards/riot-adaption/radio.c b/bsp/boards/riot-adaption/radio.c
|
|
new file mode 100644
|
|
index 0000000..203550c
|
|
--- /dev/null
|
|
+++ b/bsp/boards/riot-adaption/radio.c
|
|
@@ -0,0 +1,496 @@
|
|
+#include "board_ow.h"
|
|
+#include "radio.h"
|
|
+#include "at86rf231_ow.h"
|
|
+#include "spi_ow.h"
|
|
+#include "radiotimer.h"
|
|
+#include "debugpins.h"
|
|
+#include "leds.h"
|
|
+#include "board.h"
|
|
+#include "spi.h"
|
|
+#include "periph_conf.h"
|
|
+
|
|
+#define ENABLE_DEBUG (0)
|
|
+#include "debug.h"
|
|
+
|
|
+
|
|
+//=========================== defines =========================================
|
|
+
|
|
+//=========================== variables =======================================
|
|
+
|
|
+typedef struct {
|
|
+ radiotimer_capture_cbt startFrame_cb;
|
|
+ radiotimer_capture_cbt endFrame_cb;
|
|
+ radio_state_t state;
|
|
+} radio_vars_t;
|
|
+
|
|
+radio_vars_t radio_vars;
|
|
+
|
|
+//=========================== prototypes ======================================
|
|
+
|
|
+void radio_spiWriteReg(uint8_t reg_addr, uint8_t reg_setting);
|
|
+uint8_t radio_spiReadReg(uint8_t reg_addr);
|
|
+void radio_spiWriteTxFifo(uint8_t* bufToWrite, uint8_t lenToWrite);
|
|
+void radio_spiReadRxFifo(uint8_t* pBufRead,
|
|
+ uint8_t* pLenRead,
|
|
+ uint8_t maxBufLen,
|
|
+ uint8_t* pLqi);
|
|
+uint8_t radio_spiReadRadioInfo(void);
|
|
+
|
|
+//=========================== public ==========================================
|
|
+
|
|
+//===== admin
|
|
+
|
|
+void radio_init(void) {
|
|
+
|
|
+ // clear variables
|
|
+ memset(&radio_vars,0,sizeof(radio_vars_t));
|
|
+
|
|
+ // change state
|
|
+ radio_vars.state = RADIOSTATE_STOPPED;
|
|
+ DEBUG("%s\n",__PRETTY_FUNCTION__);
|
|
+ // configure the radio
|
|
+ radio_spiWriteReg(RG_TRX_STATE, CMD_FORCE_TRX_OFF); // turn radio off
|
|
+
|
|
+ radio_spiWriteReg(RG_IRQ_MASK,
|
|
+ (AT_IRQ_RX_START| AT_IRQ_TRX_END)); // tell radio to fire interrupt on TRX_END and RX_START
|
|
+ radio_spiReadReg(RG_IRQ_STATUS); // deassert the interrupt pin in case is high
|
|
+ radio_spiWriteReg(RG_ANT_DIV, RADIO_CHIP_ANTENNA); // use chip antenna
|
|
+#define RG_TRX_CTRL_1 0x04
|
|
+ radio_spiWriteReg(RG_TRX_CTRL_1, 0x20); // have the radio calculate CRC
|
|
+ //busy wait until radio status is TRX_OFF
|
|
+ uint16_t c = 0;
|
|
+ while((radio_spiReadReg(RG_TRX_STATUS) & 0x1F) != TRX_OFF)
|
|
+ if (c++ == 10000) {
|
|
+ DEBUG("radio_spiReadReg timeout\n");
|
|
+ break;
|
|
+ }
|
|
+ DEBUG("%s\n",__PRETTY_FUNCTION__);
|
|
+ // change state
|
|
+ radio_vars.state = RADIOSTATE_RFOFF;
|
|
+}
|
|
+
|
|
+void radio_setOverflowCb(radiotimer_compare_cbt cb) {
|
|
+ radiotimer_setOverflowCb(cb);
|
|
+}
|
|
+
|
|
+void radio_setCompareCb(radiotimer_compare_cbt cb) {
|
|
+ radiotimer_setCompareCb(cb);
|
|
+}
|
|
+
|
|
+void radio_setStartFrameCb(radiotimer_capture_cbt cb) {
|
|
+ radio_vars.startFrame_cb = cb;
|
|
+}
|
|
+
|
|
+void radio_setEndFrameCb(radiotimer_capture_cbt cb) {
|
|
+ radio_vars.endFrame_cb = cb;
|
|
+}
|
|
+
|
|
+//===== reset
|
|
+
|
|
+void radio_reset(void) {
|
|
+ PORT_PIN_RADIO_RESET_LOW();
|
|
+}
|
|
+
|
|
+//===== timer
|
|
+
|
|
+void radio_startTimer(PORT_TIMER_WIDTH period) {
|
|
+ radiotimer_start(period);
|
|
+}
|
|
+
|
|
+PORT_TIMER_WIDTH radio_getTimerValue(void) {
|
|
+ return radiotimer_getValue();
|
|
+}
|
|
+
|
|
+void radio_setTimerPeriod(PORT_TIMER_WIDTH period) {
|
|
+ radiotimer_setPeriod(period);
|
|
+}
|
|
+
|
|
+PORT_TIMER_WIDTH radio_getTimerPeriod(void) {
|
|
+ return radiotimer_getPeriod();
|
|
+}
|
|
+
|
|
+//===== RF admin
|
|
+
|
|
+void radio_setFrequency(uint8_t frequency) {
|
|
+ // change state
|
|
+ radio_vars.state = RADIOSTATE_SETTING_FREQUENCY;
|
|
+
|
|
+ // configure the radio to the right frequecy
|
|
+ radio_spiWriteReg(RG_PHY_CC_CCA,0x20+frequency);
|
|
+
|
|
+ // change state
|
|
+ radio_vars.state = RADIOSTATE_FREQUENCY_SET;
|
|
+}
|
|
+
|
|
+void radio_rfOn(void) {
|
|
+ PORT_PIN_RADIO_RESET_LOW();
|
|
+}
|
|
+
|
|
+void radio_rfOff(void) {
|
|
+ DEBUG("%s\n",__PRETTY_FUNCTION__);
|
|
+ // change state
|
|
+ radio_vars.state = RADIOSTATE_TURNING_OFF;
|
|
+ radio_spiReadReg(RG_TRX_STATUS);
|
|
+ DEBUG("step 1\n");
|
|
+ // turn radio off
|
|
+ radio_spiWriteReg(RG_TRX_STATE, CMD_FORCE_TRX_OFF);
|
|
+ DEBUG("step 2\n");
|
|
+ radio_spiWriteReg(RG_TRX_STATE, CMD_TRX_OFF);
|
|
+
|
|
+ // busy wait until done
|
|
+ uint16_t c = 0;
|
|
+ while((radio_spiReadReg(RG_TRX_STATUS) & 0x1F) != TRX_OFF)
|
|
+ ;// if (c++ == 100000) {
|
|
+// DEBUG("%s: radio_spiReadReg timeout\n", __PRETTY_FUNCTION__);
|
|
+// break;
|
|
+// }
|
|
+
|
|
+ DEBUG("step 3\n");
|
|
+ // wiggle debug pin
|
|
+ debugpins_radio_clr();
|
|
+ leds_radio_off();
|
|
+ DEBUG("step 4\n");
|
|
+ // change state
|
|
+ radio_vars.state = RADIOSTATE_RFOFF;
|
|
+ DEBUG("step 5\n");
|
|
+}
|
|
+
|
|
+//===== TX
|
|
+
|
|
+void radio_loadPacket(uint8_t* packet, uint8_t len) {
|
|
+ // change state
|
|
+ radio_vars.state = RADIOSTATE_LOADING_PACKET;
|
|
+
|
|
+ // load packet in TXFIFO
|
|
+ radio_spiWriteTxFifo(packet,len);
|
|
+
|
|
+ // change state
|
|
+ radio_vars.state = RADIOSTATE_PACKET_LOADED;
|
|
+}
|
|
+
|
|
+void radio_txEnable(void) {
|
|
+ // change state
|
|
+ radio_vars.state = RADIOSTATE_ENABLING_TX;
|
|
+
|
|
+ // wiggle debug pin
|
|
+ debugpins_radio_set();
|
|
+ leds_radio_on();
|
|
+
|
|
+ // turn on radio's PLL
|
|
+ radio_spiWriteReg(RG_TRX_STATE, CMD_PLL_ON);
|
|
+ uint16_t c = 0;
|
|
+ while((radio_spiReadReg(RG_TRX_STATUS) & 0x1F) != PLL_ON) // busy wait until done
|
|
+ ;// if (c++ == 100000) {
|
|
+// DEBUG("%s: radio_spiReadReg timeout\n", __PRETTY_FUNCTION__);
|
|
+// break;
|
|
+// }
|
|
+
|
|
+ // change state
|
|
+ radio_vars.state = RADIOSTATE_TX_ENABLED;
|
|
+}
|
|
+
|
|
+void radio_txNow(void) {
|
|
+ PORT_TIMER_WIDTH val;
|
|
+ // change state
|
|
+ radio_vars.state = RADIOSTATE_TRANSMITTING;
|
|
+ leds_radio_toggle();
|
|
+ // send packet by pulsing the SLP_TR_CNTL pin
|
|
+ PORT_PIN_RADIO_SLP_TR_CNTL_HIGH();
|
|
+ PORT_PIN_RADIO_SLP_TR_CNTL_LOW();
|
|
+ leds_radio_toggle();
|
|
+ // The AT86RF231 does not generate an interrupt when the radio transmits the
|
|
+ // SFD, which messes up the MAC state machine. The danger is that, if we leave
|
|
+ // this funtion like this, any radio watchdog timer will expire.
|
|
+ // Instead, we cheat an mimick a start of frame event by calling
|
|
+ // ieee154e_startOfFrame from here. This also means that software can never catch
|
|
+ // a radio glitch by which #radio_txEnable would not be followed by a packet being
|
|
+ // transmitted (I've never seen that).
|
|
+ if (radio_vars.startFrame_cb!=NULL) {
|
|
+ // call the callback
|
|
+ val=radiotimer_getCapturedTime();
|
|
+ radio_vars.startFrame_cb(val);
|
|
+ }
|
|
+ DEBUG("SENT");
|
|
+}
|
|
+
|
|
+//===== RX
|
|
+
|
|
+void radio_rxEnable(void) {
|
|
+ // change state
|
|
+ radio_vars.state = RADIOSTATE_ENABLING_RX;
|
|
+
|
|
+ // put radio in reception mode
|
|
+ radio_spiWriteReg(RG_TRX_STATE, CMD_RX_ON);
|
|
+
|
|
+ // wiggle debug pin
|
|
+ debugpins_radio_set();
|
|
+ leds_radio_on();
|
|
+
|
|
+ // busy wait until radio really listening
|
|
+ uint16_t c = 0;
|
|
+ while((radio_spiReadReg(RG_TRX_STATUS) & 0x1F) != RX_ON)
|
|
+ ;// if (c++ == 100000) {
|
|
+// DEBUG("%s: radio_spiReadReg timeout\n",__PRETTY_FUNCTION__);
|
|
+// break;
|
|
+// }
|
|
+
|
|
+ // change state
|
|
+ radio_vars.state = RADIOSTATE_LISTENING;
|
|
+}
|
|
+
|
|
+void radio_rxNow(void) {
|
|
+ // nothing to do
|
|
+
|
|
+}
|
|
+
|
|
+void radio_getReceivedFrame(uint8_t* pBufRead,
|
|
+ uint8_t* pLenRead,
|
|
+ uint8_t maxBufLen,
|
|
+ int8_t* pRssi,
|
|
+ uint8_t* pLqi,
|
|
+ uint8_t* pCrc) {
|
|
+ uint8_t temp_reg_value;
|
|
+
|
|
+ //===== crc
|
|
+ temp_reg_value = radio_spiReadReg(RG_PHY_RSSI);
|
|
+ *pCrc = (temp_reg_value & 0x80)>>7; // msb is whether packet passed CRC
|
|
+
|
|
+ //===== rssi
|
|
+ // as per section 8.4.3 of the AT86RF231, the RSSI is calculate as:
|
|
+ // -91 + ED [dBm]
|
|
+ temp_reg_value = radio_spiReadReg(RG_PHY_ED_LEVEL);
|
|
+ *pRssi = -91 + temp_reg_value;
|
|
+
|
|
+ //===== packet
|
|
+ radio_spiReadRxFifo(pBufRead,
|
|
+ pLenRead,
|
|
+ maxBufLen,
|
|
+ pLqi);
|
|
+}
|
|
+
|
|
+//=========================== private =========================================
|
|
+
|
|
+static inline void CSn_SET(void)
|
|
+{
|
|
+ SPI_0_CS_PORT->BSRR = (1 << SPI_0_CS_PIN);
|
|
+}
|
|
+static inline void CSn_CLR(void)
|
|
+{
|
|
+ SPI_0_CS_PORT->BRR = (1 << SPI_0_CS_PIN);
|
|
+}
|
|
+
|
|
+uint8_t radio_spiReadRadioInfo(void){
|
|
+ uint8_t spi_tx_buffer[3];
|
|
+ uint8_t spi_rx_buffer[3];
|
|
+ DEBUG("%s\n",__PRETTY_FUNCTION__);
|
|
+ // prepare buffer to send over SPI
|
|
+ spi_tx_buffer[0] = (0x80 | 0x1E); // [b7] Read/Write: 1 (read)
|
|
+ // [b6] RAM/Register : 1 (register)
|
|
+ // [b5-0] address: 0x1E (Manufacturer ID, Lower 16 Bit)
|
|
+ spi_tx_buffer[1] = 0x00; // send a SNOP strobe just to get the reg value
|
|
+ spi_tx_buffer[2] = 0x00; // send a SNOP strobe just to get the reg value
|
|
+
|
|
+ // retrieve radio manufacturer ID over SPI
|
|
+ // spi_txrx(spi_tx_buffer,
|
|
+ // sizeof(spi_tx_buffer),
|
|
+ // SPI_BUFFER,
|
|
+ // spi_rx_buffer,
|
|
+ // sizeof(spi_rx_buffer),
|
|
+ // SPI_FIRST,
|
|
+ // SPI_LAST);
|
|
+ CSn_CLR();
|
|
+ spi_transfer_bytes(SPI_0, spi_tx_buffer, spi_rx_buffer, 3);
|
|
+ CSn_SET();
|
|
+ return spi_rx_buffer[2];
|
|
+}
|
|
+
|
|
+void radio_spiWriteReg(uint8_t reg_addr, uint8_t reg_setting) {
|
|
+ uint8_t spi_tx_buffer[2];
|
|
+ uint8_t spi_rx_buffer[2];
|
|
+ spi_tx_buffer[0] = (0xC0 | reg_addr); // turn addess in a 'reg write' address
|
|
+ spi_tx_buffer[1] = reg_setting;
|
|
+
|
|
+ // spi_txrx(spi_tx_buffer,
|
|
+ // sizeof(spi_tx_buffer),
|
|
+ // SPI_BUFFER,
|
|
+ // (uint8_t*)spi_rx_buffer,
|
|
+ // sizeof(spi_rx_buffer),
|
|
+ // SPI_FIRST,
|
|
+ // SPI_LAST);
|
|
+ CSn_CLR();
|
|
+ spi_transfer_byte(SPI_0, spi_tx_buffer[0], NULL);
|
|
+ spi_transfer_byte(SPI_0, spi_tx_buffer[1], NULL);
|
|
+ CSn_SET();
|
|
+}
|
|
+
|
|
+uint8_t radio_spiReadReg(uint8_t reg_addr) {
|
|
+ uint8_t spi_tx_buffer[2];
|
|
+ uint8_t spi_rx_buffer[2];
|
|
+ spi_tx_buffer[0] = (0x80 | reg_addr); // turn addess in a 'reg read' address
|
|
+ spi_tx_buffer[1] = 0x00; // send a no_operation command just to get the reg value
|
|
+
|
|
+ // spi_txrx(spi_tx_buffer,
|
|
+ // sizeof(spi_tx_buffer),
|
|
+ // SPI_BUFFER,
|
|
+ // (uint8_t*)spi_rx_buffer,
|
|
+ // sizeof(spi_rx_buffer),
|
|
+ // SPI_FIRST,
|
|
+ // SPI_LAST);
|
|
+ CSn_CLR();
|
|
+ spi_transfer_byte(SPI_0, spi_tx_buffer[0], NULL);
|
|
+ spi_transfer_byte(SPI_0, 0, spi_rx_buffer);
|
|
+ CSn_SET();
|
|
+
|
|
+ return spi_rx_buffer[0];
|
|
+}
|
|
+
|
|
+/** for testing purposes, remove if not needed anymore**/
|
|
+
|
|
+void radio_spiWriteTxFifo(uint8_t* bufToWrite, uint8_t lenToWrite) {
|
|
+ uint8_t spi_tx_buffer[2];
|
|
+ uint8_t spi_rx_buffer[1+1+127]; // 1B SPI address, 1B length, max. 127B data
|
|
+ DEBUG("%s\n",__PRETTY_FUNCTION__);
|
|
+ spi_tx_buffer[0] = 0x60; // SPI destination address for TXFIFO
|
|
+ spi_tx_buffer[1] = lenToWrite; // length byte
|
|
+
|
|
+ CSn_CLR();
|
|
+ spi_transfer_byte(SPI_0, spi_tx_buffer[0], NULL);
|
|
+ spi_transfer_byte(SPI_0, spi_tx_buffer[1], NULL);
|
|
+ spi_transfer_bytes(SPI_0, bufToWrite, NULL, lenToWrite);
|
|
+ CSn_SET();
|
|
+
|
|
+ // spi_txrx(spi_tx_buffer,
|
|
+ // sizeof(spi_tx_buffer),
|
|
+ // SPI_BUFFER,
|
|
+ // spi_rx_buffer,
|
|
+ // sizeof(spi_rx_buffer),
|
|
+ // SPI_FIRST,
|
|
+ // SPI_NOTLAST);
|
|
+
|
|
+ // spi_txrx(bufToWrite,
|
|
+ // lenToWrite,
|
|
+ // SPI_BUFFER,
|
|
+ // spi_rx_buffer,
|
|
+ // sizeof(spi_rx_buffer),
|
|
+ // SPI_NOTFIRST,
|
|
+ // SPI_LAST);
|
|
+}
|
|
+
|
|
+
|
|
+
|
|
+void radio_spiReadRxFifo(uint8_t* pBufRead,
|
|
+ uint8_t* pLenRead,
|
|
+ uint8_t maxBufLen,
|
|
+ uint8_t* pLqi) {
|
|
+ // when reading the packet over SPI from the RX buffer, you get the following:
|
|
+ // - *[1B] dummy byte because of SPI
|
|
+ // - *[1B] length byte
|
|
+ // - [0-125B] packet (excluding CRC)
|
|
+ // - *[2B] CRC
|
|
+ // - *[1B] LQI
|
|
+ uint8_t spi_tx_buffer[125];
|
|
+ uint8_t spi_rx_buffer[3];
|
|
+ DEBUG("%s\n",__PRETTY_FUNCTION__);
|
|
+ spi_tx_buffer[0] = 0x20;
|
|
+
|
|
+ CSn_CLR();
|
|
+ spi_transfer_byte(SPI_0, spi_tx_buffer[0], NULL);
|
|
+ spi_transfer_byte(SPI_0, 0, spi_rx_buffer);
|
|
+ // 2 first bytes
|
|
+ // spi_txrx(spi_tx_buffer,
|
|
+ // 2,
|
|
+ // SPI_BUFFER,
|
|
+ // spi_rx_buffer,
|
|
+ // sizeof(spi_rx_buffer),
|
|
+ // SPI_FIRST,
|
|
+ // SPI_NOTLAST);
|
|
+
|
|
+ *pLenRead = spi_rx_buffer[0];
|
|
+
|
|
+ if (*pLenRead>2 && *pLenRead<=127) {
|
|
+ // valid length
|
|
+ spi_transfer_byte(SPI_0, spi_tx_buffer[0], NULL);
|
|
+ spi_transfer_bytes(SPI_0, NULL, pBufRead, *pLenRead);
|
|
+
|
|
+ // //read packet
|
|
+ // spi_txrx(spi_tx_buffer,
|
|
+ // *pLenRead,
|
|
+ // SPI_BUFFER,
|
|
+ // pBufRead,
|
|
+ // 125,
|
|
+ // SPI_NOTFIRST,
|
|
+ // SPI_NOTLAST);
|
|
+ spi_transfer_byte(SPI_0, 0, 0);
|
|
+ spi_transfer_byte(SPI_0, 0, 0);
|
|
+ spi_transfer_byte(SPI_0, 0, pLqi);
|
|
+ // CRC (2B) and LQI (1B)
|
|
+ // spi_txrx(spi_tx_buffer,
|
|
+ // 2+1,
|
|
+ // SPI_BUFFER,
|
|
+ // spi_rx_buffer,
|
|
+ // 3,
|
|
+ // SPI_NOTFIRST,
|
|
+ // SPI_LAST);
|
|
+
|
|
+ // *pLqi = spi_rx_buffer[2];
|
|
+
|
|
+ } else {
|
|
+ // invalid length
|
|
+ spi_transfer_byte(SPI_0, 0, 0);
|
|
+ // read a just byte to close spi
|
|
+ // spi_txrx(spi_tx_buffer,
|
|
+ // 1,
|
|
+ // SPI_BUFFER,
|
|
+ // spi_rx_buffer,
|
|
+ // sizeof(spi_rx_buffer),
|
|
+ // SPI_NOTFIRST,
|
|
+ // SPI_LAST);
|
|
+ }
|
|
+ CSn_SET();
|
|
+}
|
|
+
|
|
+//=========================== callbacks =======================================
|
|
+
|
|
+//=========================== interrupt handlers ==============================
|
|
+
|
|
+kick_scheduler_t radio_isr(void) {
|
|
+ PORT_TIMER_WIDTH capturedTime;
|
|
+ uint8_t irq_status;
|
|
+
|
|
+ // capture the time
|
|
+ capturedTime = radiotimer_getCapturedTime();
|
|
+
|
|
+ // reading IRQ_STATUS causes radio's IRQ pin to go low
|
|
+ irq_status = radio_spiReadReg(RG_IRQ_STATUS);
|
|
+
|
|
+ // start of frame event
|
|
+ if (irq_status & AT_IRQ_RX_START) {
|
|
+ DEBUG("Start of frame.\n");
|
|
+ // change state
|
|
+ radio_vars.state = RADIOSTATE_RECEIVING;
|
|
+ if (radio_vars.startFrame_cb!=NULL) {
|
|
+ // call the callback
|
|
+ radio_vars.startFrame_cb(capturedTime);
|
|
+ // kick the OS
|
|
+ return KICK_SCHEDULER;
|
|
+ } else {
|
|
+ while(1);
|
|
+ }
|
|
+ }
|
|
+ // end of frame event
|
|
+ if (irq_status & AT_IRQ_TRX_END) {
|
|
+ DEBUG("End of Frame.\n");
|
|
+ // change state
|
|
+ radio_vars.state = RADIOSTATE_TXRX_DONE;
|
|
+ if (radio_vars.endFrame_cb!=NULL) {
|
|
+ // call the callback
|
|
+ radio_vars.endFrame_cb(capturedTime);
|
|
+ // kick the OS
|
|
+ return KICK_SCHEDULER;
|
|
+ } else {
|
|
+ while(1);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return DO_NOT_KICK_SCHEDULER;
|
|
+}
|
|
\ No newline at end of file
|
|
diff --git a/bsp/boards/riot-adaption/radiotimer.c b/bsp/boards/riot-adaption/radiotimer.c
|
|
new file mode 100644
|
|
index 0000000..e9c0b54
|
|
--- /dev/null
|
|
+++ b/bsp/boards/riot-adaption/radiotimer.c
|
|
@@ -0,0 +1,155 @@
|
|
+/**
|
|
+\brief openmoteSTM32 definition of the "radiotimer" bsp module.
|
|
+On openmoteSTM32, we use RTC for the radiotimer module.
|
|
+\author Thomas Watteyne <watteyne@eecs.berkeley.edu>, February 2012.
|
|
+\author Chang Tengfei <tengfei.chang@gmail.com>, July 2012.
|
|
+*/
|
|
+
|
|
+#include "stdint.h"
|
|
+
|
|
+#include "periph/timer.h"
|
|
+
|
|
+#include "leds.h"
|
|
+#include "radiotimer.h"
|
|
+#include "board_info.h"
|
|
+
|
|
+#define ENABLE_DEBUG (0)
|
|
+#include "debug.h"
|
|
+
|
|
+
|
|
+//=========================== variables =======================================
|
|
+
|
|
+enum radiotimer_irqstatus_enum{
|
|
+ RADIOTIMER_NONE = 0x00, //alarm interrupt default status
|
|
+ RADIOTIMER_OVERFLOW = 0x01, //alarm interrupt caused by overflow
|
|
+ RADIOTIMER_COMPARE = 0x02, //alarm interrupt caused by compare
|
|
+};
|
|
+
|
|
+typedef struct {
|
|
+ radiotimer_compare_cbt overflow_cb;
|
|
+ radiotimer_compare_cbt compare_cb;
|
|
+ uint8_t overflowORcompare;//indicate RTC alarm interrupt status
|
|
+ uint16_t currentSlotPeriod;
|
|
+} radiotimer_vars_t;
|
|
+
|
|
+volatile radiotimer_vars_t radiotimer_vars;
|
|
+uint16_t current_period;
|
|
+
|
|
+//=========================== prototypes ======================================
|
|
+
|
|
+//=========================== public ==========================================
|
|
+
|
|
+//===== admin
|
|
+
|
|
+void radiotimer_init(void) {
|
|
+ // clear local variables
|
|
+ memset(&radiotimer_vars,0,sizeof(radiotimer_vars_t));
|
|
+ current_period = 0;
|
|
+}
|
|
+
|
|
+void radiotimer_setOverflowCb(radiotimer_compare_cbt cb) {
|
|
+ radiotimer_vars.overflow_cb = cb;
|
|
+}
|
|
+
|
|
+void radiotimer_setCompareCb(radiotimer_compare_cbt cb) {
|
|
+ radiotimer_vars.compare_cb = cb;
|
|
+}
|
|
+
|
|
+void radiotimer_setStartFrameCb(radiotimer_capture_cbt cb) {
|
|
+ while(1);
|
|
+}
|
|
+
|
|
+void radiotimer_setEndFrameCb(radiotimer_capture_cbt cb) {
|
|
+ while(1);
|
|
+}
|
|
+
|
|
+void radiotimer_start(uint16_t period) {
|
|
+ DEBUG("%s\n", __PRETTY_FUNCTION__);
|
|
+ timer_init(TIMER_1, 1, &radiotimer_isr);
|
|
+ timer_set(TIMER_1, 1, (0xffff)&((unsigned int)period));
|
|
+ current_period = period;
|
|
+ radiotimer_vars.currentSlotPeriod = period;
|
|
+ radiotimer_vars.overflowORcompare = RADIOTIMER_OVERFLOW;
|
|
+}
|
|
+
|
|
+//===== direct access
|
|
+
|
|
+uint16_t radiotimer_getValue(void) {
|
|
+ return (uint16_t)((0xffff)&timer_read(TIMER_1));
|
|
+}
|
|
+
|
|
+void radiotimer_setPeriod(uint16_t period) {
|
|
+ timer_set(TIMER_1, 1, (0xffff)&((unsigned int)period));
|
|
+ current_period = period;
|
|
+ radiotimer_vars.currentSlotPeriod = period;
|
|
+
|
|
+ //set radiotimer irpstatus
|
|
+ radiotimer_vars.overflowORcompare = RADIOTIMER_OVERFLOW;
|
|
+}
|
|
+
|
|
+uint16_t radiotimer_getPeriod(void) {
|
|
+ return current_period;
|
|
+}
|
|
+
|
|
+//===== compare
|
|
+
|
|
+void radiotimer_schedule(uint16_t offset) {
|
|
+ timer_irq_disable(TIMER_1);
|
|
+ timer_set(TIMER_1, 1, offset);
|
|
+ current_period = offset;
|
|
+ timer_irq_enable(TIMER_1);
|
|
+ //set radiotimer irpstatus
|
|
+ radiotimer_vars.overflowORcompare = RADIOTIMER_COMPARE;
|
|
+}
|
|
+
|
|
+void radiotimer_cancel(void) {
|
|
+ timer_irq_disable(TIMER_1);
|
|
+ timer_clear(TIMER_1, 1);
|
|
+ current_period = 0;
|
|
+ timer_irq_enable(TIMER_1);
|
|
+
|
|
+ //set radiotimer irpstatus
|
|
+ radiotimer_vars.overflowORcompare = RADIOTIMER_OVERFLOW;
|
|
+}
|
|
+
|
|
+//===== capture
|
|
+
|
|
+inline uint16_t radiotimer_getCapturedTime(void) {
|
|
+ return (uint16_t)((0xffff)&timer_read(TIMER_1));
|
|
+}
|
|
+
|
|
+//=========================== private =========================================
|
|
+
|
|
+//=========================== interrupt handlers ==============================
|
|
+
|
|
+kick_scheduler_t radiotimer_isr(void) {
|
|
+ uint8_t taiv_temp = radiotimer_vars.overflowORcompare;
|
|
+ switch (taiv_temp) {
|
|
+ case RADIOTIMER_COMPARE:
|
|
+ DEBUG("%s cmp\n", __PRETTY_FUNCTION__);
|
|
+ if (radiotimer_vars.compare_cb!=NULL) {
|
|
+ radiotimer_vars.compare_cb();
|
|
+ // kick the OS
|
|
+ return KICK_SCHEDULER;
|
|
+ }
|
|
+ break;
|
|
+ case RADIOTIMER_OVERFLOW: // timer overflows
|
|
+ DEBUG("%s of\n", __PRETTY_FUNCTION__);
|
|
+ if (radiotimer_vars.overflow_cb!=NULL) {
|
|
+ //Wait until last write operation on RTC registers has finished
|
|
+ timer_reset(TIMER_1);
|
|
+ // call the callback
|
|
+ radiotimer_vars.overflow_cb();
|
|
+ DEBUG("returned...\n");
|
|
+ // kick the OS
|
|
+ return KICK_SCHEDULER;
|
|
+ }
|
|
+ break;
|
|
+ case RADIOTIMER_NONE: // this should not happen
|
|
+ DEBUG("%s none\n", __PRETTY_FUNCTION__);
|
|
+ default:
|
|
+ DEBUG("%s default\n", __PRETTY_FUNCTION__);
|
|
+ // while(1); // this should not happen
|
|
+ }
|
|
+ return DO_NOT_KICK_SCHEDULER;
|
|
+}
|
|
\ No newline at end of file
|
|
diff --git a/bsp/boards/riot-adaption/spi_ow.c b/bsp/boards/riot-adaption/spi_ow.c
|
|
new file mode 100644
|
|
index 0000000..56193f6
|
|
--- /dev/null
|
|
+++ b/bsp/boards/riot-adaption/spi_ow.c
|
|
@@ -0,0 +1,321 @@
|
|
+#include "stdio.h"
|
|
+#include "stdint.h"
|
|
+#include "string.h"
|
|
+#include "spi_ow.h"
|
|
+#include "spi.h"
|
|
+#include "leds.h"
|
|
+#include "board.h"
|
|
+#include "radio.h"
|
|
+#include "periph/gpio.h"
|
|
+#include "periph_conf.h"
|
|
+#include "at86rf231.h"
|
|
+
|
|
+#define ENABLE_DEBUG (0)
|
|
+#include "debug.h"
|
|
+
|
|
+//=========================== defines =========================================
|
|
+
|
|
+//=========================== variables =======================================
|
|
+
|
|
+typedef struct {
|
|
+ // information about the current transaction
|
|
+ uint8_t* pNextTxByte;
|
|
+ uint8_t numTxedBytes;
|
|
+ uint8_t txBytesLeft;
|
|
+ spi_return_t returnType;
|
|
+ uint8_t* pNextRxByte;
|
|
+ uint8_t maxRxBytes;
|
|
+ spi_first_t isFirst;
|
|
+ spi_last_t isLast;
|
|
+ // state of the module
|
|
+ uint8_t busy;
|
|
+#ifdef SPI_IN_INTERRUPT_MODE
|
|
+ // callback when module done
|
|
+ spi_cbt callback;
|
|
+#endif
|
|
+} spi_vars_t;
|
|
+
|
|
+volatile spi_vars_t spi_vars;
|
|
+
|
|
+//=========================== prototypes ======================================
|
|
+// inline static void RESET_CLR(void) { GPIOC->BRR = 1<<1; }
|
|
+// inline static void RESET_SET(void) { GPIOC->BSRR = 1<<1; }
|
|
+// inline static void CSn_SET(void) { GPIOA->BSRR = 1<<4; }
|
|
+// inline static void CSn_CLR(void) { GPIOA->BRR = 1<<4; }
|
|
+// inline static void SLEEP_CLR(void) { GPIOA->BRR = 1<<2; }
|
|
+static inline void RESET_CLR(void)
|
|
+{
|
|
+ SPI_0_RESET_PORT->BRR = (1 << SPI_0_RESET_PIN);
|
|
+}
|
|
+static inline void RESET_SET(void)
|
|
+{
|
|
+ SPI_0_RESET_PORT->BSRR = (1 << SPI_0_RESET_PIN);
|
|
+}
|
|
+static inline void CSn_SET(void)
|
|
+{
|
|
+ SPI_0_CS_PORT->BSRR = (1 << SPI_0_CS_PIN);
|
|
+}
|
|
+static inline void CSn_CLR(void)
|
|
+{
|
|
+ SPI_0_CS_PORT->BRR = (1 << SPI_0_CS_PIN);
|
|
+}
|
|
+static inline void SLEEP_CLR(void)
|
|
+{
|
|
+ SPI_0_SLEEP_PORT->BRR = (1 << SPI_0_SLEEP_PIN);
|
|
+}
|
|
+
|
|
+//=========================== public ==========================================
|
|
+
|
|
+void spi_init_ow(void) {
|
|
+ // clear variables
|
|
+ memset(&spi_vars,0,sizeof(spi_vars_t));
|
|
+
|
|
+ /* set up GPIO pins */
|
|
+ /* SCLK and MOSI*/
|
|
+ GPIOA->CRL &= ~(0xf << (5 * 4));
|
|
+ GPIOA->CRL |= (0xb << (5 * 4));
|
|
+ GPIOA->CRL &= ~(0xf << (7 * 4));
|
|
+ GPIOA->CRL |= (0xb << (7 * 4));
|
|
+ /* MISO */
|
|
+ gpio_init_in(SPI_0_MISO_GPIO, GPIO_NOPULL);
|
|
+
|
|
+ /* SPI init */
|
|
+ spi_init_master(SPI_0, SPI_CONF_FIRST_RISING, 4500000);
|
|
+
|
|
+ spi_poweron(SPI_0);
|
|
+
|
|
+ /* IRQ0 */
|
|
+ gpio_init_in(SPI_0_IRQ0_GPIO, GPIO_NOPULL);
|
|
+ gpio_init_int(SPI_0_IRQ0_GPIO, GPIO_NOPULL, GPIO_RISING, radio_isr);
|
|
+
|
|
+ /* Connect EXTI4 Line to PC4 pin */
|
|
+ gpio_irq_enable(SPI_0_IRQ0_GPIO);
|
|
+
|
|
+ /* CS */
|
|
+ gpio_init_out(SPI_0_CS_GPIO, GPIO_NOPULL);
|
|
+ /* SLEEP */
|
|
+ gpio_init_out(SPI_0_SLEEP_GPIO, GPIO_NOPULL);
|
|
+ /* RESET */
|
|
+ gpio_init_out(SPI_0_RESET_GPIO, GPIO_NOPULL);
|
|
+
|
|
+ // force reset
|
|
+ RESET_CLR();
|
|
+ CSn_SET();
|
|
+ SLEEP_CLR();
|
|
+
|
|
+ for (uint16_t j=0;j<0xFFFF;j++); //small wait
|
|
+
|
|
+ RESET_SET();
|
|
+ // /* set up GPIO pins */
|
|
+ // /* SCLK and MOSI*/
|
|
+ // GPIOA->CRL &= ~(0xf << (5 * 4));
|
|
+ // GPIOA->CRL |= (0xb << (5 * 4));
|
|
+ // GPIOA->CRL &= ~(0xf << (7 * 4));
|
|
+ // GPIOA->CRL |= (0xb << (7 * 4));
|
|
+ // /* MISO */
|
|
+ // gpio_init_in(SPI_0_MISO_GPIO, GPIO_NOPULL);
|
|
+
|
|
+ // /* SPI init */
|
|
+ // spi_init_master(SPI_0, SPI_CONF_FIRST_RISING, 4500000);
|
|
+
|
|
+ // spi_poweron(SPI_0);
|
|
+
|
|
+ // /* IRQ0 */
|
|
+ // gpio_init_in(SPI_0_IRQ0_GPIO, GPIO_NOPULL);
|
|
+ // gpio_init_int(SPI_0_IRQ0_GPIO, GPIO_NOPULL, GPIO_RISING, radio_isr);
|
|
+
|
|
+ // /* Connect EXTI4 Line to PC4 pin */
|
|
+ // gpio_irq_enable(SPI_0_IRQ0_GPIO);
|
|
+
|
|
+ // /* CS */
|
|
+ // gpio_init_out(SPI_0_CS_GPIO, GPIO_NOPULL);
|
|
+ // /* SLEEP */
|
|
+ // gpio_init_out(SPI_0_SLEEP_GPIO, GPIO_NOPULL);
|
|
+ // /* RESET */
|
|
+ // gpio_init_out(SPI_0_RESET_GPIO, GPIO_NOPULL);
|
|
+
|
|
+ // /* force reset */
|
|
+ // RESET_CLR();
|
|
+ // CSn_SET();
|
|
+ // SLEEP_CLR();
|
|
+
|
|
+ // vtimer_usleep(AT86RF231_TIMING__RESET);
|
|
+
|
|
+ // RESET_SET();
|
|
+
|
|
+ // /* Wait until TRX_OFF is entered */
|
|
+ // vtimer_usleep(AT86RF231_TIMING__RESET_TO_TRX_OFF);
|
|
+
|
|
+ // /* Send a FORCE TRX OFF command */
|
|
+ // at86rf231_reg_write(AT86RF231_REG__TRX_STATE, AT86RF231_TRX_STATE__FORCE_TRX_OFF);
|
|
+
|
|
+ // /* Wait until TRX_OFF state is entered from P_ON */
|
|
+ // vtimer_usleep(AT86RF231_TIMING__SLEEP_TO_TRX_OFF);
|
|
+
|
|
+ // /* busy wait for TRX_OFF state */
|
|
+ // uint8_t status;
|
|
+ // uint8_t max_wait = 100; // TODO : move elsewhere, this is in 10us
|
|
+
|
|
+ // do {
|
|
+ // status = at86rf231_get_status();
|
|
+
|
|
+ // vtimer_usleep(10);
|
|
+
|
|
+ // if (!--max_wait) {
|
|
+ // printf("at86rf231 : ERROR : could not enter TRX_OFF mode\n");
|
|
+ // break;
|
|
+ // }
|
|
+ // } while ((status & AT86RF231_TRX_STATUS_MASK__TRX_STATUS)
|
|
+ // != AT86RF231_TRX_STATUS__TRX_OFF);
|
|
+
|
|
+}
|
|
+
|
|
+#ifdef SPI_IN_INTERRUPT_MODE
|
|
+void spi_setCallback(spi_cbt cb) {
|
|
+ spi_vars.callback = cb;
|
|
+}
|
|
+#endif
|
|
+
|
|
+void spi_txrx(uint8_t* bufTx,
|
|
+ uint8_t lenbufTx,
|
|
+ spi_return_t returnType,
|
|
+ uint8_t* bufRx,
|
|
+ uint8_t maxLenBufRx,
|
|
+ spi_first_t isFirst,
|
|
+ spi_last_t isLast) {
|
|
+
|
|
+#ifdef SPI_IN_INTERRUPT_MODE
|
|
+ // disable interrupts
|
|
+ NVIC_RESETPRIMASK();
|
|
+#endif
|
|
+
|
|
+ // register spi frame to send
|
|
+ spi_vars.pNextTxByte = bufTx;
|
|
+ spi_vars.numTxedBytes = 0;
|
|
+ spi_vars.txBytesLeft = lenbufTx;
|
|
+ spi_vars.returnType = returnType;
|
|
+ spi_vars.pNextRxByte = bufRx;
|
|
+ spi_vars.maxRxBytes = maxLenBufRx;
|
|
+ spi_vars.isFirst = isFirst;
|
|
+ spi_vars.isLast = isLast;
|
|
+
|
|
+ // SPI is now busy
|
|
+ spi_vars.busy = 1;
|
|
+
|
|
+
|
|
+ // lower CS signal to have slave listening
|
|
+ if (spi_vars.isFirst==SPI_FIRST) {
|
|
+ CSn_CLR();
|
|
+ }
|
|
+
|
|
+#ifdef SPI_IN_INTERRUPT_MODE
|
|
+ // implementation 1. use a callback function when transaction finishes
|
|
+
|
|
+ // write first byte to TX buffer
|
|
+ SPI_I2S_SendData(SPI1,*spi_vars.pNextTxByte);
|
|
+
|
|
+ // re-enable interrupts
|
|
+ NVIC_SETPRIMASK();
|
|
+#else
|
|
+ // implementation 2. busy wait for each byte to be sent
|
|
+ // send all bytes
|
|
+ while (spi_vars.txBytesLeft>0) {
|
|
+ // write next byte to TX buffer
|
|
+ // SPI_I2S_SendData(SPI1,*spi_vars.pNextTxByte);
|
|
+ spi_transfer_byte(SPI_0, *((char*)spi_vars.pNextTxByte), NULL);
|
|
+
|
|
+ // busy wait on the interrupt flag
|
|
+// uint16_t c = 0;
|
|
+// while (SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_RXNE) == RESET)
|
|
+// ;// if (c++ == 10000) {
|
|
+// // //DEBUG("spi_txrx timeout\n");
|
|
+// // break;
|
|
+// // }
|
|
+
|
|
+// // clear the interrupt flag
|
|
+// SPI_I2S_ClearFlag(SPI1, SPI_I2S_FLAG_RXNE);
|
|
+ // save the byte just received in the RX buffer
|
|
+ switch (spi_vars.returnType) {
|
|
+ case SPI_FIRSTBYTE:
|
|
+ if (spi_vars.numTxedBytes==0) {
|
|
+ spi_transfer_byte(SPI_0, 0, (char*)spi_vars.pNextRxByte);
|
|
+ // *spi_vars.pNextRxByte = SPI_I2S_ReceiveData(SPI1);
|
|
+ }
|
|
+ break;
|
|
+ case SPI_BUFFER:
|
|
+ spi_transfer_byte(SPI_0, 0, (char*)spi_vars.pNextRxByte);
|
|
+ // *spi_vars.pNextRxByte = SPI_I2S_ReceiveData(SPI1);
|
|
+ spi_vars.pNextRxByte++;
|
|
+ break;
|
|
+ case SPI_LASTBYTE:
|
|
+ spi_transfer_byte(SPI_0, 0, (char*)spi_vars.pNextRxByte);
|
|
+ // *spi_vars.pNextRxByte = SPI_I2S_ReceiveData(SPI1);
|
|
+ break;
|
|
+ }
|
|
+ // one byte less to go
|
|
+ spi_vars.pNextTxByte++;
|
|
+ spi_vars.numTxedBytes++;
|
|
+ spi_vars.txBytesLeft--;
|
|
+ }
|
|
+
|
|
+ // put CS signal high to signal end of transmission to slave
|
|
+ if (spi_vars.isLast==SPI_LAST) {
|
|
+ CSn_SET();
|
|
+ }
|
|
+
|
|
+ // SPI is not busy anymore
|
|
+ spi_vars.busy = 0;
|
|
+#endif
|
|
+}
|
|
+
|
|
+//=========================== private =========================================
|
|
+
|
|
+//=========================== interrupt handlers ==============================
|
|
+
|
|
+kick_scheduler_t spi_isr(void) {
|
|
+#ifdef SPI_IN_INTERRUPT_MODE
|
|
+ // save the byte just received in the RX buffer
|
|
+ switch (spi_vars.returnType) {
|
|
+ case SPI_FIRSTBYTE:
|
|
+ if (spi_vars.numTxedBytes==0) {
|
|
+ *spi_vars.pNextRxByte = SPI_I2S_ReceiveData(SPI1);
|
|
+ }
|
|
+ break;
|
|
+ case SPI_BUFFER:
|
|
+ *spi_vars.pNextRxByte = SPI_I2S_ReceiveData(SPI1);
|
|
+ spi_vars.pNextRxByte++;
|
|
+ break;
|
|
+ case SPI_LASTBYTE:
|
|
+ *spi_vars.pNextRxByte = SPI_I2S_ReceiveData(SPI1);
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ // one byte less to go
|
|
+ spi_vars.pNextTxByte++;
|
|
+ spi_vars.numTxedBytes++;
|
|
+ spi_vars.txBytesLeft--;
|
|
+
|
|
+ if (spi_vars.txBytesLeft>0) {
|
|
+ // write next byte to TX buffer
|
|
+ SPI_SendData(SPI1,*spi_vars.pNextTxByte);
|
|
+ } else {
|
|
+ // put CS signal high to signal end of transmission to slave
|
|
+ if (spi_vars.isLast==SPI_LAST) {
|
|
+ GPIO_SetBits(GPIOA, GPIO_Pin_4);
|
|
+ }
|
|
+ // SPI is not busy anymore
|
|
+ spi_vars.busy = 0;
|
|
+
|
|
+ // SPI is done!
|
|
+ if (spi_vars.callback!=NULL) {
|
|
+ // call the callback
|
|
+ spi_vars.callback();
|
|
+ // kick the OS
|
|
+ return 1;
|
|
+ }
|
|
+ }
|
|
+#else
|
|
+ while(1);// this should never happen
|
|
+ return 1;
|
|
+#endif
|
|
+}
|
|
\ No newline at end of file
|
|
diff --git a/bsp/boards/riot-adaption/uart_ow.c b/bsp/boards/riot-adaption/uart_ow.c
|
|
new file mode 100644
|
|
index 0000000..c2bcb4f
|
|
--- /dev/null
|
|
+++ b/bsp/boards/riot-adaption/uart_ow.c
|
|
@@ -0,0 +1,96 @@
|
|
+#include "uart_ow.h"
|
|
+#include "leds.h"
|
|
+#include "periph/uart.h"
|
|
+
|
|
+//=========================== defines =========================================
|
|
+
|
|
+//=========================== variables =======================================
|
|
+
|
|
+typedef struct {
|
|
+ uart_tx_cbt txCb;
|
|
+ uart_rx_cbt rxCb;
|
|
+ uint8_t startOrend;
|
|
+ uint8_t flagByte;
|
|
+} uart_vars_t;
|
|
+
|
|
+volatile uart_vars_t uart_vars;
|
|
+
|
|
+//=========================== prototypes ======================================
|
|
+
|
|
+//=========================== public ==========================================
|
|
+
|
|
+void uart_init_ow(void)
|
|
+{
|
|
+ // reset local variables
|
|
+ memset(&uart_vars,0,sizeof(uart_vars_t));
|
|
+
|
|
+ //when this value is 0, we are send the first data
|
|
+ uart_vars.startOrend = 0;
|
|
+ //flag byte for start byte and end byte
|
|
+ uart_vars.flagByte = 0x7E;
|
|
+}
|
|
+
|
|
+void uart_setCallbacks(uart_tx_cbt txCb, uart_rx_cbt rxCb)
|
|
+{
|
|
+ uart_vars.txCb = txCb;
|
|
+ uart_vars.rxCb = rxCb;
|
|
+}
|
|
+
|
|
+void uart_enableInterrupts(void)
|
|
+{
|
|
+ // USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
|
|
+}
|
|
+
|
|
+void uart_disableInterrupts(void)
|
|
+{
|
|
+ // USART_ITConfig(USART1, USART_IT_TXE, DISABLE);
|
|
+ // USART_ITConfig(USART1, USART_IT_RXNE, DISABLE);
|
|
+}
|
|
+
|
|
+void uart_clearRxInterrupts(void)
|
|
+{
|
|
+ // USART_ClearFlag(USART1, USART_FLAG_RXNE);
|
|
+}
|
|
+
|
|
+void uart_clearTxInterrupts(void)
|
|
+{
|
|
+ // USART_ClearFlag(USART1, USART_FLAG_TXE);
|
|
+}
|
|
+
|
|
+void uart_writeByte(uint8_t byteToWrite)
|
|
+{
|
|
+ // USART_SendData(USART1, byteToWrite);
|
|
+ // while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
|
|
+
|
|
+ // //start or end byte?
|
|
+ // if(byteToWrite == uart_vars.flagByte) {
|
|
+ // uart_vars.startOrend = (uart_vars.startOrend == 0)?1:0;
|
|
+ // //start byte
|
|
+ // if(uart_vars.startOrend == 1) {
|
|
+ // USART_ITConfig(USART1, USART_IT_TXE, ENABLE);
|
|
+ // } else {
|
|
+ // USART_ITConfig(USART1, USART_IT_TXE, DISABLE);
|
|
+ // }
|
|
+ // }
|
|
+}
|
|
+
|
|
+uint8_t uart_readByte(void)
|
|
+{
|
|
+ // uint16_t temp;
|
|
+ // temp = USART_ReceiveData(USART1);
|
|
+ // return (uint8_t)temp;
|
|
+}
|
|
+
|
|
+//=========================== interrupt handlers ==============================
|
|
+
|
|
+kick_scheduler_t uart_tx_isr(void)
|
|
+{
|
|
+ uart_vars.txCb();
|
|
+ return DO_NOT_KICK_SCHEDULER;
|
|
+}
|
|
+
|
|
+kick_scheduler_t uart_rx_isr(void)
|
|
+{
|
|
+ uart_vars.rxCb();
|
|
+ return DO_NOT_KICK_SCHEDULER;
|
|
+}
|
|
\ No newline at end of file
|
|
--
|
|
2.2.0
|
|
|