diff --git a/msba2-common/Makefile.dep b/msba2-common/Makefile.dep index 5182f34f4b814a5a08cef27f8c8844b4570ef4cb..bffa6c72d75820e3bfdbcf81a7a3bdca18712759 100644 --- a/msba2-common/Makefile.dep +++ b/msba2-common/Makefile.dep @@ -1,3 +1,9 @@ +ifneq (,$(findstring cc110x,$(USEMODULE))) + ifeq (,$(findstring gpioint,$(USEMODULE))) + USEMODULE += gpioint + endif +endif + ifneq (,$(findstring cc110x_ng,$(USEMODULE))) ifeq (,$(findstring cc110x_spi,$(USEMODULE))) USEMODULE += cc110x_spi diff --git a/redbee-econotag/Makefile.include b/redbee-econotag/Makefile.include index 7275c2daf660ca33ccf982d315533ab59f025791..26738a93fc0615dcceb3ee3874b702091de913d3 100644 --- a/redbee-econotag/Makefile.include +++ b/redbee-econotag/Makefile.include @@ -5,11 +5,14 @@ export CPU = mc1322x export PREFIX = @arm-none-eabi- export CC = @$(PREFIX)gcc export AR = @$(PREFIX)ar -export CFLAGS += -std=gnu99 -march=armv4t -mtune=arm7tdmi-s -mlong-calls \ +export CFLAGS = -std=gnu99 -march=armv4t -mtune=arm7tdmi-s -mlong-calls \ + +export CFLAGS_BASIC = -std=gnu99 -march=armv4t -mtune=arm7tdmi-s -mlong-calls \ -msoft-float -mthumb-interwork -fno-strict-aliasing -fno-common \ -ffixed-r8 -ffunction-sections -ffreestanding -fno-builtin \ -nodefaultlibs -Wcast-align -Wall -Wstrict-prototypes -Wextra \ -Os -pipe +export CFLAGS += $(CFLAGS_BASIC) -mthumb $(warning TODO add -mthumb) export AFLAGS = -Wa,-gstabs $(CFLAGS) export AS = $(PREFIX)as diff --git a/redbee-econotag/drivers/Makefile b/redbee-econotag/drivers/Makefile index 8b8b6094b917440d87cc9cad42d4f3be1fd7e3b8..0a40ae1d50689cdbe03fe776d30a2368a9f1fbfb 100644 --- a/redbee-econotag/drivers/Makefile +++ b/redbee-econotag/drivers/Makefile @@ -3,7 +3,7 @@ BINDIR = $(RIOTBOARD)/$(BOARD)/bin/ OBJ = $(SRC:%.c=$(BINDIR)%.o) DEP = $(SRC:%.c=$(BINDIR)%.d) -INCLUDES += -I$(RIOTBASE)/sys/include/ -I$(RIOTBASE)/drivers/cc110x_ng/include/ +INCLUDES += -I$(RIOTBASE)/sys/include/ .PHONY: redbee-econotag_drivers.a diff --git a/redbee-econotag/drivers/include/maca.h b/redbee-econotag/drivers/include/maca.h new file mode 100644 index 0000000000000000000000000000000000000000..7c2bc8e0717d3920b238c17f0bb8e1b4a9abe8a1 --- /dev/null +++ b/redbee-econotag/drivers/include/maca.h @@ -0,0 +1,531 @@ +/* + * maca.h - The MACA driver for the Redbee EconoTag + * Copyright (C) 2013 Thomas Eichinger <thomas.eichinger@fu-berlin.de> + * + * This source code is licensed under the GNU General Public License, + * Version 3. See the file LICENSE for more details. + * + * This file is part of RIOT. + */ + +#ifndef MACA_H_ +#define MACA_H_ + +#include "maca_packet.h" +#include <stdint.h> + +/*********************************************************/ +/* function definitions */ +/*********************************************************/ + +/* functions for the initialization and turning on and off of the MACA */ +void maca_init ( void ); +void maca_on ( void ); +void maca_off ( void ); + +/* function to check if MACA is running right */ +void maca_check ( void ); + +/* functions to configure MACA */ +void maca_set_power ( uint8_t power ); +void maca_set_channel ( uint8_t channel ); +uint16_t maca_set_address ( uint16_t addr ); +uint16_t maca_get_address ( void ); + +/* get Link Quality Indicator */ +extern uint8_t (*get_lqi) ( void ); + + +/* interface to configure demodulator */ +#define MACA_DEMOD_DCD 1 /* -96dBm, 22.2mA */ +#define MACA_DEMOD_NCD 0 /* -100dBm, 24.2mA */ +void set_demodulator_type ( uint8_t type ); + +/* macro for setting checksum filtering */ +extern volatile uint8_t fcs_mode; +#define MACA_SET_FCS_MODE(x) fcs_mode = (x) + +/* MACA_SET_PRM_MODE(PROMISC) to disable address filtering */ +/* MACA_SET_PRM_MODE(AUTOACK) to enable address filtering AND autoack */ +extern volatile uint8_t prm_mode; +#define MACA_SET_PRM_MODE(x) prm_mode = (x) + +/* functions working on maca_packet_t */ +void maca_set_tx_packet ( volatile maca_packet_t *packet ); +volatile maca_packet_t* maca_get_rx_packet ( void ); +volatile maca_packet_t* maca_get_free_packet ( void ); +void maca_free_packet ( volatile maca_packet_t *packet ); +void maca_free_all_packets ( void ); + +extern volatile maca_packet_t *maca_rx_head, *maca_tx_head; +extern volatile uint32_t maca_entry; + +extern void maca_rx_callback ( volatile maca_packet_t *packet ) __attribute__((weak)); +extern void maca_tx_callback ( volatile maca_packet_t *packet ) __attribute__((weak)); + +/* internal lowlevel MACA functions */ +void _maca_reset ( void ); +void _maca_init_phy ( void ); +void _maca_flyback_init ( void ); +void _maca_resume_maca_sync ( void ); +void _maca_radio_init ( void ); +uint32_t _maca_init_from_flash ( uint32_t address ); + +#define MACA_MAX_PACKET_SIZE (MACA_MAX_PAYLOAD_SIZE + 2) /* +2 for checksum */ + +/*********************************************************/ +/* register definitions */ +/*********************************************************/ + +#define MACA_BASE_ADDRESS (0x80004000) + +struct MACA_struct { + union { + // Reset the MACA Module + uint32_t RESET; + struct MACA_RESET { + uint32_t RST:1; // MACA Reset + uint32_t CLK_ON:1; // MACA Clk on/off + uint32_t :30; + } RESETbits; + }; + union { + // Write: random generator seed + // Read: get random data + uint32_t RANDOM; + struct MACA_RANDOM { + uint32_t :32; + } RANDOMbits; + }; + union { + // Control register of the MACA + uint32_t CONTROL; + struct MACA_CONTROL { + uint32_t SEQUENCE :3; // set new mode of operation (see MACA_CONTROL_SEQUENCE_*) + uint32_t MODE :2; // transmission access mode (see MACA_CONTROL_MODE_*) + uint32_t TM :1; // test mode (see MACA_CONTROL_TM_*) + uint32_t :1; // LFSR reserved + uint32_t AUTO :1; // restart Rx automatically (see MACA_CONTROL_AUTO_*) + uint32_t BCN :1; // filter beacon only (see MACA_CONTROL_BCN_*) + uint32_t ASAP :1; // start action sequence ASAP (see MACA_CONTROL_ASAP_*) + uint32_t REL :1; // clk selector (see MACA_CONTROL_REL_*) + uint32_t PRM :1; // promiscuous mode (see MACA_CONTROL_PRM_*) + uint32_t NOFC :1; // no frame check (see MACA_CONTROL_NOFC_*) + uint32_t ROLE :1; // current role + uint32_t :1; // reserved + uint32_t RSTO :1; // reset slot offset (see MACA_CONTROL_RSTO_*) + uint32_t PRE_COUNT :4; // preamble repeat counter (btween 0-15) + uint32_t ISM :1; // ISM reserved + uint32_t :11; + } CONTROLbits; + }; + union { + uint32_t STATUS; + struct + { + uint32_t COMPLETE_CODE :4; // complete code (see MACA_STATUS_COMPLETECODE_*) + uint32_t :8; // reserved + uint32_t OVR :1; // Rx buffer overrun (see MACA_STATUS_OVR_*) + uint32_t BUSY :1; // channel busy detection (see MACA_STATUS_BUSY_*) + uint32_t CRC :1; // checksum failed (see MACA_STATUS_CRC_*) + uint32_t TO :1; // time-out (see MACA_STATUS_TO_*) + uint32_t :16; // reserved + } STATUSbits; + }; + union { + uint32_t FRMPND; + struct + { + uint32_t PND :1; // Ack Frame Pending Status (see MACA_FRMPND_PND_*) + uint32_t :31; // reserved + }FRMPNbits; + }; + union { + uint32_t MC1322x_ID; + struct + { + uint32_t MC1322x_ID :8; // the 9bit MC1322x ID (see MACA_MC1322x_ID_*) + uint32_t :24; // reserved + }MC1322x_IDbits; + }; + union { + uint32_t TMREN; + struct + { + uint32_t STRT :1; // enable start clk circuit (see MACA_TMREN_STRT_*) + uint32_t CPL :1; // enable complete clk circuit (see MACA_TMREN_CPL_*) + uint32_t SFT :1; // enable soft complete clk circ (see MACA_TMREN_SFT_*) + uint32_t :29; // reserved + }TMRENbits; + }; + union { + uint32_t TMRDIS; + struct + { + uint32_t STRT :1; // disable start clk circuit (see MACA_TMRDIS_STRT_*) + uint32_t CPL :1; // disable complete clk circuit (see MACA_TMRDIS_CPL_*) + uint32_t SFT :1; // disable soft complete clk circ (see MACA_TMRDIS_SFT_*) + uint32_t STRT_OFF :1; // abort start clk (see MACA_TMRDIS_STRTOFF_*) + uint32_t CPL_OFF :1; // abort complete clk (see MACA_TMRDIS_CPLOFF_*) + uint32_t SFT_OFF :1; // abort soft complete clk (see MACA_TMRDIS_SFT_OFF_*) + uint32_t :26; // reserved + }TMRDISbits; + }; + uint32_t CLK; // sets a new absolute clock value + // Ensure that the timers are not active + uint32_t STARTCLK; // see (9.7.10) + uint32_t CPLCLK; // see (9.7.11) + uint32_t SFTCLK; // see (9.7.12) + uint32_t CLKOFFSET; // see (9.7.13) + uint32_t RELCLK; // see (9.7.14) + uint32_t CPLTIM; // see (9.7.15) + union { + uint32_t SLOTOFFSET; // see (9.7.16) + struct + { + uint32_t TX_SLOT_OFFSET :12; + uint32_t :4; + uint32_t RX_SLOT_OFFSEt :12; + uint32_t :4; + }SLOTOFFSETbits; + }; + uint32_t TIMESTAMP; // see (9.7.17) + uint32_t DMARX; // see (9.7.18) + uint32_t DMATX; // see (9.7.19) + uint32_t DMAPOLL; // see (9.7.20) + union { + uint32_t TXLEN; // see (9.7.21) + struct + { + uint32_t TX_LEN :15; // Tx payload length + uint32_t :17; // reserved + }TXLENbits; + }; + union { + uint32_t TXSEQNR; // see (9.7.22) + struct + { + uint32_t TXSEQN :8; // Tx sequ. number + uint32_t :24; // reserved + }TXSEQNRbits; + }; + union { + uint32_t SETRXLVL; // see (9.7.23) + struct + { + uint32_t FIFO_LVL :16; // FIFO level + uint32_t :16; // reserved + }SETRXLVLbits; + }; + union { + uint32_t GETRXLVL; // see (9.7.24) + struct + { + uint32_t RECVBYTES :16; // received bytes + uint32_t :16; // reserved + }GETRXLVLbits; + }; + union { + uint32_t IRQ; // read only see (9.7.25) + struct + { + uint32_t ACPL :1; // Action Complete Interrupt + uint32_t POLL :1; // Poll Indication Interrupt + uint32_t DI :1; // Data Indication Interrupt + uint32_t :6; // reserved + uint32_t LVL :1; // FIFO Level Interrupt + uint32_t SFT :1; // Soft Complete Clk Interrupt + uint32_t FLT :1; // Filter Failed Interrupt + uint32_t CRC :1; // Checksum Failed Interrupt + uint32_t CM :1; // Complete Clock Interrupt + uint32_t SYNC :1; // Sync Detected Interrupt + uint32_t STRT :1; // Action Started Interrupt + uint32_t :16; // reserved + }IRQbits; + }; + union { + uint32_t CLRIRQ; // write only see (9.7.26) + // write 1 to clear + struct + { + uint32_t ACPL :1; // Clear Action Complete Interrupt + uint32_t POLL :1; // Clear Poll Indication Interrupt + uint32_t DI :1; // Clear Data Indication Interrupt + uint32_t :6; // reserved + uint32_t LVL :1; // Clear FIFO Level Interrupt + uint32_t SFT :1; // Clear Soft Complete Clk Interrupt + uint32_t FLT :1; // Clear Filter Failed Interrupt + uint32_t CRC :1; // Clear Checksum Failed Interrupt + uint32_t CM :1; // Clear Complete Clock Interrupt + uint32_t SYNC :1; // Clear Sync Detected Interrupt + uint32_t STRT :1; // Clear Action Started Interrupt + uint32_t :16; // reserved + }CLRIRQbits; + }; + union { + uint32_t SETIRQ; // write only see (9.7.27) + // write 1 to set IRQ + struct + { + uint32_t ACPL :1; // Trigger Action Complete Interrupt + uint32_t POLL :1; // Trigger Poll Indication Interrupt + uint32_t DI :1; // Trigger Data Indication Interrupt + uint32_t :6; // reserved + uint32_t LVL :1; // Trigger FIFO Level Interrupt + uint32_t SFT :1; // Trigger Soft Complete Clk Interrupt + uint32_t FLT :1; // Trigger Filter Failed Interrupt + uint32_t CRC :1; // Trigger Checksum Failed Interrupt + uint32_t CM :1; // Trigger Complete Clock Interrupt + uint32_t SYNC :1; // Trigger Sync Detected Interrupt + uint32_t STRT :1; // Trigger Action Started Interrupt + uint32_t :16; // reserved + }SETIRQbits; + }; + union { + uint32_t MASKIRQ; // write only see (9.7.28) + // write 1 to enable IRQ + struct + { + uint32_t ACPL :1; // Enable Action Complete Interrupt + uint32_t POLL :1; // Enable Poll Indication Interrupt + uint32_t DI :1; // Enable Data Indication Interrupt + uint32_t WU :1; // reserved but needed?? + uint32_t RST :1; // reserved but needed?? + uint32_t :4; // reserved + uint32_t LVL :1; // Enable FIFO Level Interrupt + uint32_t SFT :1; // Enable Soft Complete Clk Interrupt + uint32_t FLT :1; // Enable Filter Failed Interrupt + uint32_t CRC :1; // Enable Checksum Failed Interrupt + uint32_t CM :1; // Enable Complete Clock Interrupt + uint32_t SYNC :1; // Enable Sync Detected Interrupt + uint32_t STRT :1; // Enable Action Started Interrupt + uint32_t :16; // reserved + }MASKIRQbits; + }; + union { + uint32_t MACPANID; // see (9.7.29) + struct + { + uint32_t PANID :16; // MAC PAN ID for the 802.15.4 std network + } MACPANIDbits; + }; + union { + uint32_t MAC16ADDR; // see (9.7.30) + struct + { + uint32_t ADDR :16; // reflects the MAC short address + } MAC16ADDRbits; + }; + uint32_t MAC64HI; // see (9.7.31) + uint32_t MAC64LO; // see (9.7.32) + union { + uint32_t FLTREJ; // see (9.7.33) + struct + { + uint32_t BCN :1; // Reject Beacon packets + uint32_t DATA :1; // Reject Data packets + uint32_t ACK :1; // Reject ACK packets + uint32_t CMD :1; // Reject MAC CMD packets + uint32_t :4; // reserved + uint32_t POLL :1; // Accept POLL packets + uint32_t :7; // reserved + uint32_t FC_MASK :16; // Frame Control Mask + }FLTREJbits; + }; + union { + uint32_t CLKDIV; // see (9.7.34) + struct + { + uint32_t Divider :16; // prescale value for the MACA transmit clk + uint32_t :16; // reserved + }CLKDIVbits; + }; + union { + uint32_t WARMUP; // see (9.7.35) + struct + { + uint32_t Rx_WARMUP :12; // receiver warmup time + uint32_t :4; // reserved + uint32_t Tx_WARMUP :12; // transmitter warmuptime + uint32_t :4; // reserved + }WARMUPbits; + }; + uint32_t PREAMBLE; // see (9.7.36) + uint32_t FRAMESYNC0; // see (9.7.37) + uint32_t FRAMESYNC1; // see (9.7.38) + union { + uint32_t TXACKDELAY; // see (9.7.39) + struct + { + uint32_t TXACKDELAY :12; // Tx Acknowledgement Delay + uint32_t :4; // reserved + uint32_t TXPOLLDELAY :12; // Tx Poll Delay + uint32_t :4; // reserved + }TXACKDELAYbits; + }; + union { + uint32_t RXACKDELAY; // see (9.7.40) + struct + { + uint32_t RXACKDELAY :12; // Rx Acknowledgement Delay + uint32_t :4; // reserved + uint32_t RXAUTODELAY :12; // time to disable receiver before restarting + uint32_t :4; // reserved + }RXACKDELAYbits; + }; + union { + uint32_t EOFDELAY; // see (9.7.41) + struct + { + uint32_t EOFDELAY :12; // End Of Frame Delay + uint32_t :20; // reserved + }EOFDELAYbits; + }; + union { + uint32_t CCADELAY; // see (9.7.42) + struct + { + uint32_t CCADELAY :12; // CCA Delay + uint32_t :4; // reserved + uint32_t CCALENGTH :12; // Length of time to perform CCA + uint32_t :4; // reserved + }CCADELAYbits; + }; + union { + uint32_t RXEND; // see (9.7.43) + struct + { + uint32_t RXACK_END :12; // Rx Acknowledgement Window End in Normal Mode + uint32_t :4; // reserved + uint32_t RXSLOTTED_END :12; // Rx Acknowledgement Window End in slotted CSMA-CA mode + uint32_t :4; // reserved + }RXENDbits; + }; + union { + uint32_t TXCCADELAY; // see (9.7.44) + struct + { + uint32_t TXCCADELAY :12; // Delay from end of CCA to Tx start + uint32_t :20; // reserved + }RXENDbits; + }; + uint32_t KEY3; // see (9.7.45) + uint32_t KEY2; // see (9.7.45) + uint32_t KEY1; // see (9.7.45) + uint32_t KEY0; // see (9.7.45) + union { + uint32_t OPTIONS; // see (9.7.46) + struct + { + uint32_t POLL :1; // enables writing to DMAPOLL + uint32_t PLL_TX :1; // responde to PLL unlock only while transmition + uint32_t PLL_IGNORE :1; // ignore PLL unlock signal + uint32_t SEED_KEY :1; // generation can be seeded + uint32_t :28; // reserved + }OPTIONSbits; + }; + +}; + +static volatile struct MACA_struct * const MACA = (void *) (MACA_BASE_ADDRESS + 0x04); // +4 because base + 0x00 is reserved + +#define MACA_CONTROL_SEQUENCE_NOP 0 +#define MACA_CONTROL_SEQUENCE_ABORT 1 +#define MACA_CONTROL_SEQUENCE_WAIT 2 +#define MACA_CONTROL_SEQUENCE_TX 3 +#define MACA_CONTROL_SEQUENCE_RX 4 +#define MACA_CONTROL_SEQUENCE_TXPOLL 5 +#define MACA_CONTROL_SEQUENCE_CCA 6 +#define MACA_CONTROL_SEQUENCE_ED 7 + +#define MACA_CONTROL_MODE_NOCCA 0 +#define MACA_CONTROL_MODE_NONSLOTTED_CSMACA 1 +#define MACA_CONTROL_MODE_SLOTTED_CSMACA 2 +#define MACA_CONTROL_MODE_RESERVED 3 + +#define MACA_CONTROL_TM_NORMAL 0 +#define MACA_CONTROL_TM_TM 1 + +#define MACA_CONTROL_AUTO_OFF 0 +#define MACA_CONTROL_AUTO_ON 1 + +#define MACA_CONTROL_BCN_OFF 0 +#define MACA_CONTROL_BCN_ON 1 + +#define MACA_CONTROL_ASAP_OFF 0 +#define MACA_CONTROL_ASAP_ON 1 + +#define MACA_CONTROL_REL_ABSOLUTE 0 +#define MACA_CONTROL_REL_RELATIVE 1 + +#define MACA_CONTROL_PRM_OFF 0 +#define MACA_CONTROL_PRM_ON 1 + +#define MACA_CONTROL_NOFC_OFF 0 +#define MACA_CONTROL_USE_FCS 0 +#define MACA_CONTROL_NOFC_ON 1 +#define MACA_CONTROL_NO_FCS 1 + +#define MACA_CONTROL_ROLE_NOPAN 0 +#define MACA_CONTROL_ROLE_PAN 1 + +#define MACA_CONTROL_RSTO_DONOT_RST 0 +#define MACA_CONTROL_RSTO_DO_RST 1 + +#define MACA_STATUS_COMPLETECODE_SUCCESS 0 +#define MACA_STATUS_COMPLETECODE_TIMEOUT 1 +#define MACA_STATUS_COMPLETECODE_CHANBUSY 2 +#define MACA_STATUS_COMPLETECODE_CRC_FAIL 3 +#define MACA_STATUS_COMPLETECODE_ABORTED 4 +#define MACA_STATUS_COMPLETECODE_NOACK 5 +#define MACA_STATUS_COMPLETECODE_NODATA 6 +#define MACA_STATUS_COMPLETECODE_LATESTART 7 +#define MACA_STATUS_COMPLETECODE_EXTTIMEOUT 8 +#define MACA_STATUS_COMPLETECODE_EXTPNDTIMEOUT 9 +#define MACA_STATUS_COMPLETECODE_PLLUNLOCK 12 +#define MACA_STATUS_COMPLETECODE_EXTABORT 13 +#define MACA_STATUS_COMPLETECODE_NOTCOMPLETE 14 +#define MACA_STATUS_COMPLETECODE_DMABUSERROR 15 + +#define MACA_STATUS_OVR_FALSE 0 +#define MACA_STATUS_OVR_TRUE 1 + +#define MACA_STATUS_BUSY_FALSE 0 +#define MACA_STATUS_BUSY_TRUE 1 + +#define MACA_STATUS_CRC_OK 0 +#define MACA_STATUS_CRC_ERROR 1 + +#define MACA_STATUS_TO_FALSE 0 +#define MACA_STATUS_TO_TRUE 1 + +#define MACA_FRMPND_PND_NODATA 0 +#define MACA_FRMPND_PND_DATAAVAIL 1 + +#define MACA_MC1322x_ID_ENGINEERING 0 +#define MACA_MC1322x_ID_MC13224_1 1 +#define MACA_MC1322x_ID_MC13224_2 9 +#define MACA_MC1322x_ID_MC13226 17 + + +#define MACA_TMREN_STRT_ENABLE 1 + +#define MACA_TMREN_CPL_ENABLE 1 + +#define MACA_TMREN_SFT_ENABLE 1 + +#define MACA_TMRDIS_STRT_DISABLE 1 + +#define MACA_TMRDIS_CPL_DISABLE 1 + +#define MACA_TMRDIS_SFT_DISABLE 1 + +#define MACA_TMRDIS_STRTOFF_ABORT 1 + +#define MACA_TMRDIS_CPLOFF_ABORT 1 + +#define MACA_TMRDIS_SFTOFF_ABORT 1 + + + +#endif // MACA_H_ \ No newline at end of file diff --git a/redbee-econotag/drivers/include/maca_packet.h b/redbee-econotag/drivers/include/maca_packet.h new file mode 100644 index 0000000000000000000000000000000000000000..11c4c1b0f7d18bcef21ab330c86287c196c953fe --- /dev/null +++ b/redbee-econotag/drivers/include/maca_packet.h @@ -0,0 +1,44 @@ +/* + * maca_packet.h - defines a rxtx packet for the MACA driver + * Copyright (C) 2013 Thomas Eichinger <thomas.eichinger@fu-berlin.de> + * + * This source code is licensed under the GNU General Public License, + * Version 3. See the file LICENSE for more details. + * + * This file is part of RIOT. + */ + +#ifndef PACKET_H +#define PACKET_H + +#include <stdint.h> + +/* does not include 2 byte FCS checksum */ +#ifndef MACA_MAX_PAYLOAD_SIZE +#define MACA_MAX_PAYLOAD_SIZE 125 +#endif + +#define PACKET_STATS 0 + +struct packet { + uint8_t length; /*< does not include FCS checksum */ + volatile struct packet * left; + volatile struct packet * right; + /* offset into data for first byte of the packet payload */ + /* On TX this should be 0 */ + /* On RX this should be 1 since the maca puts the length as the first byte*/ + uint8_t offset; + uint8_t lqi; + uint8_t status; + uint32_t rx_time; + #if PACKET_STATS + uint8_t seen; + uint8_t post_tx; + uint8_t get_free; + uint8_t rxd; + #endif + uint8_t data[MACA_MAX_PAYLOAD_SIZE+2+1]; /* +2 for FCS; + 1 since maca returns the length as the first byte */ +}; +typedef struct packet maca_packet_t; + +#endif \ No newline at end of file diff --git a/redbee-econotag/drivers/include/nvm.h b/redbee-econotag/drivers/include/nvm.h new file mode 100644 index 0000000000000000000000000000000000000000..2a8c72bfebeff2fdb57bfab57f8e9d7905e8ffa3 --- /dev/null +++ b/redbee-econotag/drivers/include/nvm.h @@ -0,0 +1,58 @@ +/* + * nvm.h - non-volatile memory specific definitions + * Copyright (C) 2013 Thomas Eichinger <thomas.eichinger@fu-berlin.de> + * + * This source code is licensed under the GNU General Public License, + * Version 3. See the file LICENSE for more details. + * + * This file is part of RIOT. + */ + +#ifndef NVM_H +#define NVM_H + +#include <stdint.h> + +typedef enum +{ + g_nvm_type_no_nvm_c = 0, + g_nvm_type_SST_c, + g_nvm_type_ST_c, + g_nvm_type_ATM_c, + g_nvm_type_Max_c +} nvm_type_t; + + +typedef enum +{ + g_nvm_err_no_error_c = 0, + g_nvm_err_invalid_interface_c, + g_nvm_err_onvalid_nvm_type_c, + g_nvm_err_invalid_pointer_c, + g_nvm_err_write_protect_c, + g_nvm_err_verify_error_c, + g_nvm_err_address_space_overflow_c, + g_nvm_err_blank_check_error_c, + g_nvm_err_restricted_area_c, + g_nvm_err_max_error_c +} nvm_err_t; + +typedef enum +{ + g_nvm_internal_interface_c = 0, + g_nvm_external_interface_c, + g_nvm_interface_max_c +} nvm_interface_t; + +/* ROM code seems to be THUMB */ +/* need to be in a THUMB block before calling them */ +extern nvm_err_t (*nvm_detect)(nvm_interface_t nvm_interface,nvm_type_t* p_nvm_type); +extern nvm_err_t (*nvm_read)(nvm_interface_t nvm_interface , nvm_type_t nvm_type , void *p_dest, uint32_t address, uint32_t num_bytes); +extern nvm_err_t (*nvm_write)(nvm_interface_t nvm_interface, nvm_type_t nvm_type ,void *p_src, uint32_t address, uint32_t num_bytes); +/* sector bit field selects which sector to erase */ +/* SST flash has 32 sectors 4096 bytes each */ +/* bit 0 is the first sector, bit 31 is the last */ +extern nvm_err_t (*nvm_erase)(nvm_interface_t nvm_interface, nvm_type_t nvm_type ,uint32_t sector_bitfield); +extern void(*nvm_setsvar)(uint32_t zero_for_awesome); + +#endif //NVM_H diff --git a/redbee-econotag/drivers/include/uart.h b/redbee-econotag/drivers/include/uart.h index 760fc45d044e5b374be3934e90d47cd864921f04..b95e6abcd1f0f632da9e25773a9e024dfac627e6 100644 --- a/redbee-econotag/drivers/include/uart.h +++ b/redbee-econotag/drivers/include/uart.h @@ -97,6 +97,8 @@ void uart_set_baudrate(volatile struct UART_struct *uart, uint32_t baud); void uart_flow_ctl(volatile struct UART_struct *uart, uint8_t on); +#define UART0_BUFSIZE (32) + /* The mc1322x has a 32 byte hardware FIFO for transmitted characters. * Currently it is always filled from a larger RAM buffer. It would be * possible to eliminate that overhead by filling directly from a chain diff --git a/redbee-econotag/drivers/maca.c b/redbee-econotag/drivers/maca.c new file mode 100644 index 0000000000000000000000000000000000000000..befbc3c7fae77c974638ccdce1ce2d6f2364f84f --- /dev/null +++ b/redbee-econotag/drivers/maca.c @@ -0,0 +1,1064 @@ +/* + * maca.c - The MACA driver for the Redbee EconoTag + * Copyright (C) 2013 Thomas Eichinger <thomas.eichinger@fu-berlin.de> + * + * This source code is licensed under the GNU General Public License, + * Version 3. See the file LICENSE for more details. + * + * This file is part of RIOT. + */ + +#include "maca.h" +#include "maca_packet.h" +#include "nvm.h" +#include "mc1322x.h" +#include <stdio.h> + +// number of packets in the maca_packet_pool +#ifndef MACA_NUM_PACKETS +#define MACA_NUM_PACKETS 32 +#endif + +/* for 250kHz clock */ +#define MACA_CLOCK_DIV 95 +/* (32 chips/sym) * (sym/4bits) * (8bits/byte) = (64 chips/byte) */ +/* (8 chips/clk) * (byte/64 chips) = byte/8clks */ +#define CLK_PER_BYTE 8 + +#ifndef RECV_SOFTIMEOUT +#define RECV_SOFTIMEOUT (1024*128*CLK_PER_BYTE) +#endif + +#ifndef CPL_TIMEOUT +#define CPL_TIMEOUT (2*128*CLK_PER_BYTE) +#endif + + + +static volatile maca_packet_t maca_packet_pool[MACA_NUM_PACKETS]; + +static volatile maca_packet_t *maca_free_head; +static volatile maca_packet_t *maca_rx_end; +static volatile maca_packet_t *maca_tx_end; +static volatile maca_packet_t *maca_dma_tx; +static volatile maca_packet_t *maca_dma_rx; + +volatile maca_packet_t *maca_rx_head; +volatile maca_packet_t *maca_tx_head; + +static volatile maca_packet_t maca_dummy_ack; + +uint8_t (*get_lqi)(void) = (void *) 0x0000e04d; + +#define MACA_NO_POST 0 +#define MACA_TX_POST 1 +#define MACA_RX_POST 2 +#define MACA_MAX_POST 3 +static volatile uint8_t maca_last_post = MACA_NO_POST; + +void maca_init ( void ) { + _maca_reset(); + _maca_radio_init(); + _maca_flyback_init(); + _maca_init_phy(); + maca_set_channel ( 0 ); + maca_set_power ( 0 ); + + maca_free_head = 0; + maca_tx_head = 0; + maca_rx_head = 0; + maca_rx_end = 0; + maca_tx_end = 0; + maca_dma_rx = 0; + maca_dma_tx = 0; + + maca_free_all_packets(); + + // promiscuous, no CCA + MACA->CONTROLbits.PRM = MACA_CONTROL_PRM_ON; + MACA->CONTROLbits.MODE = MACA_CONTROL_MODE_NOCCA; + + enable_irq ( INT_NUM_MACA ); + ITC->INTFRCbits.MACA = 1; +} + +void _maca_reset ( void ) { + volatile uint32_t c; + + MACA->RESETbits.RST = 1; + + for ( c = 0; c < 100; c++ ) { + continue; + } + + MACA->RESETbits.CLK_ON = 1; + MACA->CONTROLbits.SEQUENCE = MACA_CONTROL_SEQUENCE_NOP; + + for ( c = 0; c < 400000; c++ ) { + continue; + } + + // clear all interrupts + MACA->CLRIRQ = 0xffff; +} + +void maca_on ( void ) { + + // turn on the radio regulators + CRM->VREG_CNTLbits.BUCK_EN = 0x0; + CRM->VREG_CNTLbits.BUCK_SYNC_REC_EN = 0x0; + CRM->VREG_CNTLbits.BUCK_BYPASS_EN = 0x0; + CRM->VREG_CNTLbits.VREG_1P5V_EN = 0x3; + CRM->VREG_CNTLbits.VREG_1P5V_SEL = 0x3; + CRM->VREG_CNTLbits.VREG_1P8V_EN = 0x0; + CRM->VREG_CNTLbits.BUCK_CLKDIV = 0xf; + + // reinitialize phy + _maca_reset(); + _maca_init_phy(); + + enable_irq ( INT_NUM_MACA ); + ITC->INTFRCbits.MACA = 0x1; +} + +void maca_off ( void ) { + disable_irq ( INT_NUM_MACA ); + + // turn off radio regulators + CRM->VREG_CNTL = 0x00000f00; + + MACA->RESETbits.RST = 0x1; +} + +void maca_free_all_packets ( void ) { + volatile uint32_t i; + safe_irq_disable ( INT_NUM_MACA ); + + maca_free_head = 0; + + for ( i = 0; i < MACA_NUM_PACKETS; i++ ) { + maca_free_packet ( ( volatile maca_packet_t * ) & ( maca_packet_pool[i] ) ); + } + + maca_rx_head = 0; + maca_rx_end = 0; + maca_tx_head = 0; + maca_tx_end = 0; + + irq_restore(); + + // force MACA interrupt if there are pending irqs + if ( ITC->NIPENDbits.MACA ) { + ITC->INTFRCbits.MACA = 0x1; + } +} + +void _maca_bound_check ( volatile maca_packet_t *packet ) { + volatile uint32_t i; + + if ( !packet || packet == &maca_dummy_ack ) { + return; + } + + for ( i = 0; i < MACA_NUM_PACKETS; i++ ) { + if ( packet == &maca_packet_pool[i] ) { + return; + } + } + + // bad packet bounds! next, nirvana... + printf ( "bad packet bounds! Halting... \n" ); + + while ( 1 ) { + continue; + } +} + +void maca_free_packet ( volatile maca_packet_t *packet ) { + safe_irq_disable ( INT_NUM_MACA ); + + // _maca_bound_check( packet ); + + if ( !packet || packet == &maca_dummy_ack ) { + return; + } + + // _maca_bound_check( maca_free_head ); + + packet->length = 0; + packet->offset = 0; + packet->left = maca_free_head; + packet->right = 0; + + maca_free_head = packet; + + // _maca_bound_check( maca_free_head ); + + irq_restore(); + + if ( ITC->NIPENDbits.MACA ) { + ITC->INTFRCbits.MACA = 0x1; + } +} + +volatile maca_packet_t *maca_get_free_packet ( void ) { + volatile maca_packet_t *packet; + + safe_irq_disable ( INT_NUM_MACA ); + // _maca_bound_check( maca_free_head ); + + packet = maca_free_head; + + if ( packet ) { + maca_free_head = packet->left; + maca_free_head->right = 0; + } + + // _maca_bound_check( maca_free_head ); + + irq_restore(); + + if ( ITC->NIPENDbits.MACA ) { + ITC->INTFRCbits.MACA = 0x1; + } + + return packet; +} + +volatile maca_packet_t *maca_get_rx_packet ( void ) { + volatile maca_packet_t *packet; + safe_irq_disable ( INT_NUM_MACA ); + + // maca_bound_check ( maca_rx_head ); + + packet = maca_rx_head; + + if ( packet ) { + maca_rx_head = packet->left; + maca_rx_head->right = 0; + } + + irq_restore (); + + if ( ITC->NIPENDbits.MACA ) { + ITC->INTFRCbits.MACA = 0x1; + } + + return packet; +} + +void maca_set_tx_packet ( volatile maca_packet_t *packet ) { + safe_irq_disable ( INT_NUM_MACA ); + + // maca_bound_check ( packet ); + + if ( !packet ) { + return; + } + + if ( !maca_tx_head ) { + // start a new queue + maca_tx_end = packet; + maca_tx_end->left = 0; + maca_tx_end->right = 0; + maca_tx_head = maca_tx_end; + } + else { + // add packet to the end of the queue + maca_tx_end->left = packet; + packet->right = maca_tx_end; + // move the queue + maca_tx_end = packet; + maca_tx_end->left = 0; + } + + irq_restore (); + + if ( ITC->NIPENDbits.MACA || maca_last_post == MACA_NO_POST ) { + ITC->INTFRCbits.MACA = 0x1; + } + + if ( maca_last_post == MACA_RX_POST ) { + MACA->SFTCLK = MACA->CLK + CLK_PER_BYTE; + } + + return; +} + +void _maca_post_receive ( void ) { + maca_last_post = MACA_RX_POST; + + // from the libmc1322x implementation: + // "this sets the rxlen field + // this is undocumented but very important + // you will not receive anything without setting it" + MACA->TXLEN = ( MACA_MAX_PACKET_SIZE<<16 ); + + if ( !maca_dma_rx ) { + maca_dma_rx = maca_get_free_packet (); + + if ( !maca_dma_rx ) { + MACA->SFTCLK = MACA->CLK + RECV_SOFTIMEOUT; + MACA->TMRENbits.SFT = 0x1; + + // no free buffers, so don't start reception + enable_irq ( INT_NUM_MACA ); + return; + } + } + + // maca_bound_check ( maca_dma_rx ); + // maca_bound_check ( maca_dma_tx ); + + // load starting addess + MACA->DMARX = ( uint32_t ) & ( maca_dma_rx->data[0] ); + // wind up a timer for timeout + MACA->SFTCLK = MACA->CLK + RECV_SOFTIMEOUT; + // enable the soft complete clk circuit + MACA->TMRENbits.SFT = 0x1; + // start the receive sequence + MACA->CONTROLbits.ASAP = MACA_CONTROL_ASAP_ON; + MACA->CONTROLbits.PRE_COUNT = 0x4; + MACA->CONTROLbits.NOFC = MACA_CONTROL_NOFC_OFF; // aka use FCS + MACA->CONTROLbits.PRM = MACA_CONTROL_PRM_ON; + MACA->CONTROLbits.AUTO = MACA_CONTROL_AUTO_ON; + MACA->CONTROLbits.SEQUENCE = MACA_CONTROL_SEQUENCE_RX; +} + +void _maca_post_transmit ( void ) { + safe_irq_disable ( INT_NUM_MACA ); + + maca_last_post = MACA_TX_POST; + maca_dma_tx = maca_tx_head; + + MACA->TXSEQNRbits.TXSEQN = maca_dma_tx->data[2]; + MACA->TXLENbits.TX_LEN = ( uint16_t ) ( ( maca_dma_tx->length ) + 2 ); + // set rx length to ACK length + MACA->TXLEN = ( uint32_t ) ( 3<<16 ); + // load data starting address + MACA->DMATX = ( uint32_t ) & ( maca_dma_tx->data[0 + maca_dma_tx->offset] ); + + if ( !maca_dma_rx ) { + maca_dma_rx = maca_get_free_packet(); + + if ( !maca_dma_rx ) { + printf ( "tried to fill MACA->DMARX in maca_post_tx but there are no packet buffers left" ); + maca_dma_rx = &maca_dummy_ack; + } + } + + // maca_bound_check ( maca_dma_rx ); + // maca_bound_check ( maca_dma_tx ); + + MACA->DMARX = ( uint32_t ) & ( maca_dma_rx->data[0] ); + + // disable soft timeout clk and start clk + MACA->TMRDISbits.SFT = MACA_TMRDIS_SFT_DISABLE; + MACA->TMRDISbits.CPL = MACA_TMRDIS_CPL_DISABLE; + + // set cpl clk to a long range and enable it + // for the case MACA locks + MACA->CPLCLK = MACA->CLK + CPL_TIMEOUT; + MACA->TMRENbits.CPL = 0x1; + + irq_restore (); + + MACA->CONTROLbits.ASAP = MACA_CONTROL_ASAP_ON; + MACA->CONTROLbits.PRE_COUNT = 0x4; + MACA->CONTROLbits.PRM = MACA_CONTROL_PRM_ON; + MACA->CONTROLbits.MODE = MACA_CONTROL_MODE_NOCCA; + MACA->CONTROLbits.SEQUENCE = MACA_CONTROL_SEQUENCE_TX; + +} + +void _maca_free_tx_head ( void ) { + volatile maca_packet_t *packet; + safe_irq_disable ( INT_NUM_MACA ); + + packet = maca_tx_head; + maca_tx_head = maca_tx_head->left; + + if ( maca_tx_head == 0 ) { + maca_tx_end = 0; + } + + maca_free_packet ( packet ); + + irq_restore (); + + if ( ITC->NIPENDbits.MACA ) { + ITC->INTFRCbits.MACA = 1; + } + + return; +} + +void _maca_add_to_rx ( volatile maca_packet_t *packet ) { + safe_irq_disable ( INT_NUM_MACA ); + + if ( !packet ) { + printf ( "packet null passed to _maca_add_to_rx\n" ); + return; + } + + packet->offset = 1; // first byte is the length + + if ( maca_rx_head == 0 ) { + // start a new queue + maca_rx_end = packet; + maca_rx_end->left = 0; + maca_rx_end->right = 0; + maca_rx_head = maca_rx_end; + } + else { + // enqueue packet + maca_rx_end->left = packet; + packet->right = maca_rx_end; + maca_rx_end = packet; + maca_rx_end->left = 0; + } + + irq_restore(); + + if ( ITC->NIPENDbits.MACA ) { + ITC->INTFRCbits.MACA = 1; + } + + return; +} + +void _maca_decode_status ( void ) { + volatile uint32_t code; + + code = MACA->STATUSbits.COMPLETE_CODE; + + switch ( code ) { + case MACA_STATUS_COMPLETECODE_ABORTED: { + printf ( "maca: aborted\n" ); + _maca_resume_maca_sync (); + break; + } + + case MACA_STATUS_COMPLETECODE_NOTCOMPLETE: { + printf ( "maca: not completed\n" ); + _maca_resume_maca_sync (); + break; + } + + case MACA_STATUS_COMPLETECODE_TIMEOUT: { + printf ( "maca: timeout\n" ); + _maca_resume_maca_sync (); + break; + } + + case MACA_STATUS_COMPLETECODE_NOACK: { + printf ( "maca: no ack\n" ); + _maca_resume_maca_sync (); + break; + } + + case MACA_STATUS_COMPLETECODE_EXTTIMEOUT: { + printf ( "maca: ext timeout\n" ); + _maca_resume_maca_sync (); + break; + } + + case MACA_STATUS_COMPLETECODE_EXTPNDTIMEOUT: { + printf ( "maca: ext pnd timeout\n" ); + _maca_resume_maca_sync (); + break; + } + case MACA_STATUS_COMPLETECODE_SUCCESS: { + printf ( "maca: success\n" ); + _maca_resume_maca_sync (); + break; + } + + default: { + printf ( "maca status: %x", MACA->STATUSbits.COMPLETE_CODE ); + _maca_resume_maca_sync (); + } + } +} + +void maca_isr ( void ) { + //maca_entry++; + + if ( MACA->STATUSbits.OVR ) { + printf ( "maca overrun\n" ); + } + + if ( MACA->STATUSbits.BUSY ) { + printf ( "maca busy\n" ); + } + + if ( MACA->STATUSbits.CRC ) { + printf ( "maca crc error\n" ); + } + + if ( MACA->STATUSbits.TO ) { + printf ( "maca timeout\n" ); + } + + if ( MACA->IRQbits.DI ) { + MACA->CLRIRQbits.DI = 0x1; + maca_dma_rx->length = MACA->GETRXLVLbits.RECVBYTES - 2; // packet length doesn't include length + maca_dma_rx->lqi = get_lqi(); + maca_dma_rx->rx_time = MACA->TIMESTAMP; + + // does the packet need an ACK? + if ( MACA->CONTROLbits.PRM == MACA_CONTROL_PRM_OFF && + ( maca_dma_rx->data[1] & 0x20 ) ) { + volatile uint32_t wait_clk; + wait_clk = MACA->CLK + 200; + + while ( MACA->CLK < wait_clk ) { + continue; + } + } + + if ( maca_rx_callback != 0 ) { + maca_rx_callback ( maca_dma_rx ); + } + + _maca_add_to_rx ( maca_dma_rx ); + maca_dma_rx = 0; + } + + // filter faild + if ( MACA->IRQbits.FLT ) { + printf ( "maca filter faild\n" ); + _maca_resume_maca_sync (); + MACA->CLRIRQbits.FLT = 0x1; + } + + // CRC checksum faild + if ( MACA->IRQbits.CRC ) { + printf ( "maca crc checksum faild\n" ); + _maca_resume_maca_sync (); + MACA->CLRIRQbits.CRC = 0x1; + } + + // softclock interrupt + if ( MACA->IRQbits.SFT ) { + MACA->CLRIRQbits.SFT = 0x1; + } + + // poll interrupt + if ( MACA->IRQbits.POLL ) { + MACA->CLRIRQbits.POLL = 0x1; + } + + // action complete interrupt + if ( MACA->IRQbits.ACPL ) { + if ( maca_last_post == MACA_TX_POST ) { + maca_tx_head->status = MACA->STATUSbits.COMPLETE_CODE; + + if ( maca_tx_callback != 0 ) { + maca_tx_callback ( maca_tx_head ); + } + + maca_dma_tx = 0x0; + _maca_free_tx_head (); + maca_last_post = MACA_NO_POST; + } + + _maca_resume_maca_sync (); + MACA->CLRIRQbits.ACPL = 0x1; + } + + _maca_decode_status (); + + // this should never happen ... + if ( MACA->IRQ != 0 ) { + printf ( "MACA->IRQ is %x", (unsigned int) MACA->IRQ ); + } + + if ( maca_tx_head != 0 ) { + _maca_post_transmit (); + } + else { + _maca_post_receive (); + } +} + +void _maca_init_phy ( void ) { + MACA->CLKDIV = MACA_CLOCK_DIV; + MACA->WARMUP = 0x00180012; + MACA->EOFDELAY = 0x00000004; + MACA->CCADELAY = 0x001a0022; + MACA->TXCCADELAY = 0x00000025; + MACA->FRAMESYNC0 = 0x000000a7; + MACA->CLK = 0x00000008; + MACA->RXACKDELAY = 0x0000001e; + MACA->RXEND = 0x000000b4; + MACA->TXACKDELAY = 0x00000044; + MACA->MASKIRQbits.ACPL = 0x1; + MACA->MASKIRQbits.CM = 0x1; + MACA->MASKIRQbits.FLT = 0x1; + MACA->MASKIRQbits.CRC = 0x1; + MACA->MASKIRQbits.DI = 0x1; + MACA->MASKIRQbits.SFT = 0x1; + MACA->MASKIRQbits.RST = 0x1; + MACA->SLOTOFFSET = 0x00350000; +} + +#define MTOC_BASE 0x80009a00 //Modem Tracking Oscillator Controller +void _maca_flyback_init ( void ) { + uint32_t val8, tmp; + + val8 = * ( volatile uint32_t * ) ( MTOC_BASE+8 ); + tmp = val8 | 0x0000f7df; + * ( volatile uint32_t * ) ( MTOC_BASE+8 ) = tmp; + * ( volatile uint32_t * ) ( MTOC_BASE+12 ) = 0x00ffffff; + * ( volatile uint32_t * ) ( MTOC_BASE+16 ) = ( ( ( uint32_t ) 0x00ffffff ) >>12 ); + * ( volatile uint32_t * ) ( MTOC_BASE ) = 16; +} + +#define MACA_MAX_SEQ_1 2 +const uint32_t maca_addr_seq_1[MACA_MAX_SEQ_1] = { + 0x80003048, + 0x8000304c, +}; + +const uint32_t maca_data_seq_1[MACA_MAX_SEQ_1] = { + 0x00000f78, + 0x00607707, +}; + + +#define MACA_MAX_SEQ_2 2 +const uint32_t maca_addr_seq_2[MACA_MAX_SEQ_2] = { + 0x8000a050, + 0x8000a054, +}; + +const uint32_t maca_data_seq_2[MACA_MAX_SEQ_2] = { + 0x0000047b, + 0x0000007b, +}; + +#define MACA_MAX_CAL3_SEQ_1 3 +const uint32_t maca_addr_cal3_seq_1[MACA_MAX_CAL3_SEQ_1] = { 0x80009400,0x80009a04,0x80009a00, }; +const uint32_t maca_data_cal3_seq_1[MACA_MAX_CAL3_SEQ_1] = {0x00020017,0x8185a0a4,0x8c900025, }; + +#define MACA_MAX_CAL3_SEQ_2 2 +const uint32_t maca_addr_cal3_seq_2[MACA_MAX_CAL3_SEQ_2] = { 0x80009a00,0x80009a00,}; +const uint32_t maca_data_cal3_seq_2[MACA_MAX_CAL3_SEQ_2] = { 0x8c900021,0x8c900027,}; + +#define MACA_MAX_CAL3_SEQ_3 1 +const uint32_t maca_addr_cal3_seq_3[MACA_MAX_CAL3_SEQ_3] = { 0x80009a00 }; +const uint32_t maca_data_cal3_seq_3[MACA_MAX_CAL3_SEQ_3] = { 0x8c900000 }; + +#define MACA_MAX_CAL5 4 +const uint32_t maca_addr_cal5[MACA_MAX_CAL5] = { + 0x80009400, + 0x8000a050, + 0x8000a054, + 0x80003048, +}; +const uint32_t maca_data_cal5[MACA_MAX_CAL5] = { + 0x00000017, + 0x00000000, + 0x00000000, + 0x00000f00, +}; + +#define MACA_MAX_DATA 43 +const uint32_t maca_addr_reg_rep[MACA_MAX_DATA] = { + 0x80004118,0x80009204,0x80009208,0x8000920c, + 0x80009210,0x80009300,0x80009304,0x80009308, + 0x8000930c,0x80009310,0x80009314,0x80009318, + 0x80009380,0x80009384,0x80009388,0x8000938c, + 0x80009390,0x80009394,0x8000a008,0x8000a018, + 0x8000a01c,0x80009424,0x80009434,0x80009438, + 0x8000943c,0x80009440,0x80009444,0x80009448, + 0x8000944c,0x80009450,0x80009460,0x80009464, + 0x8000947c,0x800094e0,0x800094e4,0x800094e8, + 0x800094ec,0x800094f0,0x800094f4,0x800094f8, + 0x80009470,0x8000981c,0x80009828 +}; + +const uint32_t maca_data_reg_rep[MACA_MAX_DATA] = { + 0x00180012,0x00000605,0x00000504,0x00001111, + 0x0fc40000,0x20046000,0x4005580c,0x40075801, + 0x4005d801,0x5a45d800,0x4a45d800,0x40044000, + 0x00106000,0x00083806,0x00093807,0x0009b804, + 0x000db800,0x00093802,0x00000015,0x00000002, + 0x0000000f,0x0000aaa0,0x01002020,0x016800fe, + 0x8e578248,0x000000dd,0x00000946,0x0000035a, + 0x00100010,0x00000515,0x00397feb,0x00180358, + 0x00000455,0x00000001,0x00020003,0x00040014, + 0x00240034,0x00440144,0x02440344,0x04440544, + 0x0ee7fc00,0x00000082,0x0000002a +}; + +uint8_t ctov[16] = { + 0x0b,0x0b,0x0b,0x0a, + 0x0d,0x0d,0x0c,0x0c, + 0x0f,0x0e,0x0e,0x0e, + 0x11,0x10,0x10,0x0f +}; + +#define _INIT_CTOV_WORD_1 0x00dfbe77 +#define _INIT_CTOV_WORD_2 0x023126e9 +uint8_t get_ctov ( uint32_t r0, uint32_t r1 ) { + r0 = r0 * _INIT_CTOV_WORD_1; + r0 += ( r1 << 22 ); + r0 += _INIT_CTOV_WORD_2; + + r0 = ( uint32_t ) ( ( ( int32_t ) r0 ) >>25 ); + return ( uint8_t ) r0; +} + +static uint8_t _ram_values[4]; + +void _maca_radio_init ( void ) { + volatile uint32_t c; + + // sequence 1 + for ( c = 0; c < MACA_MAX_SEQ_1; c++ ) { + if ( ( uint32_t ) maca_addr_seq_1[c] != CRM->VREG_CNTL ) { + * ( ( volatile uint32_t * ) ( maca_addr_seq_1[c] ) ) = maca_data_seq_1[c]; + } + } + + // sequence 1 delay + for ( c = 0; c < 0x161a8; c++ ) { + continue; + } + + // sequence 2 + for ( c = 0; c < MACA_MAX_SEQ_2; c++ ) { + * ( ( volatile uint32_t * ) ( maca_addr_seq_2[c] ) ) = maca_data_seq_2[c]; + } + + // modem value + * ( ( volatile uint32_t * ) 0x80009000 ) = 0x80050100; + + // cal 3 seq 1 + for ( c = 0; c < MACA_MAX_CAL3_SEQ_1; c++ ) { + * ( ( volatile uint32_t * ) ( maca_addr_cal3_seq_1[c] ) ) = maca_data_cal3_seq_1[c]; + } + + // cal 3 delay + for ( c = 0; c < 0x11194; c++ ) { + continue; + } + + // cal 3 seq 2 + for ( c = 0; c < MACA_MAX_CAL3_SEQ_2; c++ ) { + * ( ( volatile uint32_t * ) ( maca_addr_cal3_seq_2[c] ) ) = maca_data_cal3_seq_2[c]; + } + + // cal 3 delay + for ( c = 0; c < 0x11194; c++ ) { + continue; + } + + // cal 3 seq 3 + for ( c = 0; c < MACA_MAX_CAL3_SEQ_3; c++ ) { + * ( ( volatile uint32_t * ) ( maca_addr_cal3_seq_3[c] ) ) = maca_data_cal3_seq_3[c]; + } + + // cal 5 + for ( c = 0; c < MACA_MAX_CAL5; c++ ) { + if ( ( uint32_t ) maca_addr_cal5[c] != CRM->VREG_CNTL ) { + * ( ( volatile uint32_t * ) ( maca_addr_cal5[c] ) ) = maca_data_cal5[c]; + } + } + + /*reg replacment */ + for ( c = 0; c < MACA_MAX_DATA; c++ ) { + * ( ( volatile uint32_t * ) ( maca_addr_reg_rep[c] ) ) = maca_data_reg_rep[c]; + } + + _maca_init_from_flash ( 0x1f000 ); + + for ( c=0; c<4; c++ ) { + printf ( " 0x%02x\n\r", _ram_values[c] ); + } + + for ( c=0; c<16; c++ ) { + ctov[c] = get_ctov ( c, _ram_values[3] ); + } +} + +const uint32_t PSMVAL[19] = { + 0x0000080f, 0x0000080f, 0x0000080f, + 0x0000080f, 0x0000081f, 0x0000081f, + 0x0000081f, 0x0000080f, 0x0000080f, + 0x0000080f, 0x0000001f, 0x0000000f, + 0x0000000f, 0x00000816, 0x0000001b, + 0x0000000b, 0x00000802, 0x00000817, + 0x00000003, +}; + +const uint32_t PAVAL[19] = { + 0x000022c0, 0x000022c0, 0x000022c0, + 0x00002280, 0x00002303, 0x000023c0, + 0x00002880, 0x000029f0, 0x000029f0, + 0x000029f0, 0x000029c0, 0x00002bf0, + 0x000029f0, 0x000028a0, 0x00002800, + 0x00002ac0, 0x00002880, 0x00002a00, + 0x00002b00, +}; + +const uint32_t AIMVAL[19] = { + 0x000123a0, 0x000163a0, 0x0001a3a0, + 0x0001e3a0, 0x000223a0, 0x000263a0, + 0x0002a3a0, 0x0002e3a0, 0x000323a0, + 0x000363a0, 0x0003a3a0, 0x0003a3a0, + 0x0003e3a0, 0x000423a0, 0x000523a0, + 0x000423a0, 0x0004e3a0, 0x0004e3a0, + 0x0004e3a0, +}; + +// #define MRRF_BASE 0x80009400 // Modem Radio Receiver Functions +// void _set_demodulator_type ( uint8_t demod ) { +// uint32_t val = *(uint32_t*)(MRRF_BASE); +// if ( demod == MACA_DEMOD_NCD ) { +// val = (val & ~1); +// } else { +// val = (val | 1); +// } +// *(uint32_t*)(MRRF_BASE) = val; +// } + +#define ADDR_POW1 0x8000a014 +#define ADDR_POW2 (ADDR_POW1 + 12) +#define ADDR_POW3 (ADDR_POW1 + 64) + +void maca_set_power ( uint8_t power ) { + safe_irq_disable ( INT_NUM_MACA ); + + * ( ( uint32_t * ) ( ADDR_POW1 ) ) = PSMVAL[power]; + +#ifdef USE_PA + * ( ( uint32_t * ) ( ADDR_POW2 ) ) = 0xffffdfff & PAVAL[power]; /* single port */ +#else + * ( ( uint32_t * ) ( ADDR_POW2 ) ) = 0x00002000 | PAVAL[power]; /* dual port */ +#endif + + * ( ( uint32_t * ) ( ADDR_POW3 ) ) = AIMVAL[power]; + irq_restore(); + + if ( ITC->NIPENDbits.MACA ) { + ITC->INTFRCbits.MACA = 1; + } +} + +const uint8_t VCODivI[16] = { + 0x2f, 0x2f, 0x2f, 0x2f, + 0x2f, 0x2f, 0x2f, 0x2f, + 0x2f, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, +}; + +const uint32_t VCODivF[16] = { + 0x00355555, 0x006aaaaa, 0x00a00000, 0x00d55555, + 0x010aaaaa, 0x01400000, 0x01755555, 0x01aaaaaa, + 0x01e00000, 0x00155555, 0x004aaaaa, 0x00800000, + 0x00b55555, 0x00eaaaaa, 0x01200000, 0x01555555, +}; + +#define ADDR_CHAN1 0x80009800 +#define ADDR_CHAN2 (ADDR_CHAN1+12) +#define ADDR_CHAN3 (ADDR_CHAN1+16) +#define ADDR_CHAN4 (ADDR_CHAN1+48) + +void maca_set_channel ( uint8_t chan ) { + volatile uint32_t tmp; + safe_irq_disable ( INT_NUM_MACA ); + + tmp = * ( uint32_t * ) ( ADDR_CHAN1 ); + tmp = tmp & 0xbfffffff; + * ( ( uint32_t * ) ( ADDR_CHAN1 ) ) = tmp; + + * ( ( uint32_t * ) ( ADDR_CHAN2 ) ) = VCODivI[chan]; + * ( ( uint32_t * ) ( ADDR_CHAN3 ) ) = VCODivF[chan]; + + tmp = * ( ( uint32_t * ) ( ADDR_CHAN4 ) ); + tmp = tmp | 2; + * ( ( uint32_t * ) ( ADDR_CHAN4 ) ) = tmp; + + tmp = * ( ( uint32_t * ) ( ADDR_CHAN4 ) ); + tmp = tmp | 4; + * ( ( uint32_t * ) ( ADDR_CHAN4 ) ) = tmp; + + tmp = tmp & 0xffffe0ff; + tmp = tmp | ( ( ( ctov[chan] ) <<8 ) &0x1f00 ); + * ( ( uint32_t * ) ( ADDR_CHAN4 ) ) = tmp; + + irq_restore(); + + if ( ITC->NIPENDbits.MACA ) { + ITC->INTFRCbits.MACA = 1; + } +} + +uint16_t maca_set_address ( uint16_t addr ) { + safe_irq_disable ( INT_NUM_MACA ); + + MACA->MAC16ADDR = addr; + + irq_restore(); + + if ( ITC->NIPENDbits.MACA ) { + ITC->INTFRCbits.MACA = 1; + } + return MACA->MAC16ADDR; +} + +uint16_t maca_get_address ( void ) { + return MACA->MAC16ADDR; +} + +#define MACA_ROM_END 0x0013ffff +#define MACA_ENTRY_EOF 0x00000e0f +uint32_t _exec_init_entry ( volatile uint32_t *entries, uint8_t *value_buffer ) { + volatile uint32_t i; + + if ( entries[0] <= MACA_ROM_END ) { + if ( entries[0] == 0 ) { + /* do delay */ + printf ( "init_entry: delay 0x%08x\n", (unsigned int) entries[1] ); + + for ( i=0; i < entries[1]; i++ ) { + continue; + } + + return 2; + } + else if ( entries[0] == 1 ) { + /* do bit set/clear */ + printf ( "init_entry: bit set/clear 0x%08x 0x%08x 0x%08x\n", (unsigned int) entries[1], + (unsigned int) entries[2], + (unsigned int) entries[3] ); + * ( uint32_t * ) ( entries[2] ) = ( * ( uint32_t * ) ( entries[2] ) & entries[1] ) | ( entries[3] & entries[1] ); + return 4; + } + else if ( entries[0] >= 16 && entries[0] < 0xfff1 ) { + /* store bytes in value_buffer */ + printf ( "init_entry: store in value_buffer 0x%02x position %d\n", (unsigned int) entries[1], + (unsigned int) ( entries[0]>>4 ) - 1 ); + value_buffer[ ( entries[0]>>4 )-1] = entries[1]; + return 2; + } + else if ( entries[0] == MACA_ENTRY_EOF ) { + printf ( "init_entry: EOF \n" ); + return 0; + } + else { + /* invalid */ + printf ( "init_entry: invalid code 0x%08x\n", (unsigned int) entries[0] ); + return 0; + } + } + else { + /* address not in ROM */ + /* store value in address command */ + printf ( "init_entry: address value pair - *0x%08x = 0x%08x\n", (unsigned int) entries[0], + (unsigned int) entries[1] ); + + if ( entries[0] != CRM->VREG_CNTL ) { + * ( uint32_t * ) ( entries[0] ) = entries[1]; + } + else { + printf ( "skipping CRM->VREG_CNTL\n" ); + } + + return 2; + } +} + +#define MACA_FLASH_INIT_MAGIC 0x00000abc +uint32_t _maca_init_from_flash ( uint32_t addr ) { + nvm_type_t type = 0; + nvm_err_t err; + + volatile uint32_t buffer[8]; + volatile uint32_t length; + volatile uint32_t i = 0; + volatile uint32_t j = 0; + + err = nvm_detect ( g_nvm_internal_interface_c, &type ); + printf ( "nvm_detect returned type 0x%08x err 0x%02x\n", type, err ); + + nvm_setsvar ( 0 ); + err = nvm_read ( g_nvm_internal_interface_c, type, ( uint8_t * ) buffer, addr, 8 ); + i += 8; + printf ( "nvm_read returned: 0x%02x\n", err ); + + for ( j = 0; j < 4; j++ ) { + printf ( "0x%08x\n", (unsigned int) buffer[j] ); + } + + if ( buffer[0] == MACA_FLASH_INIT_MAGIC ) { + length = buffer[1] & 0x0000ffff; + + while ( i < ( length-4 ) ) { + err = nvm_read ( g_nvm_internal_interface_c, type, ( uint8_t * ) buffer, addr+i, 32 ); + i += 4 * _exec_init_entry ( buffer, _ram_values ); + } + } + else { + i = 0; + } + + nvm_setsvar ( 1 ); + return i; +} + +void _maca_resume_maca_sync ( void ) { + volatile uint32_t clk; + volatile uint32_t tsm_rx_steps; + volatile uint32_t last_warmup_step; + volatile uint32_t last_warmup_data; + volatile uint32_t last_warmdown_step; + volatile uint32_t last_warmdown_data; + volatile uint32_t i; + + safe_irq_disable ( INT_NUM_MACA ); + + /* manual TSM modem shutdown */ + /* read TSM_RX_STEPS */ + tsm_rx_steps = * ( volatile uint32_t * ) ( 0x80009204 ); + /* isolate the RX_WU_STEPS */ + /* shift left to align with 32-bit addressing */ + last_warmup_step = ( tsm_rx_steps & 0x1f ) << 2; + /* Read "current" TSM step and save this value for later */ + last_warmup_data = ( * ( ( volatile uint32_t * ) ( 0x80009300 + last_warmup_step ) ) ); + + /* isolate the RX_WD_STEPS */ + /* right-shift bits down to bit 0 position */ + /* left-shift to align with 32-bit addressing */ + last_warmdown_step = ( ( tsm_rx_steps & 0x1f00 ) >> 8 ) << 2; + /* write "last warmdown data" to current TSM step to shutdown rx */ + last_warmdown_data = ( * ( ( volatile uint32_t * ) ( 0x80009300 + last_warmdown_step ) ) ); + ( * ( ( volatile uint32_t * ) ( 0x80009300 + last_warmup_step ) ) ) = last_warmdown_data; + + /* Abort */ + MACA->CONTROLbits.SEQUENCE = MACA_CONTROL_SEQUENCE_ABORT; + + /* Wait ~8us */ + for ( clk = MACA->CLK, i = 0; MACA->CLK - clk < 3 && i < 300; i++ ) { + continue; + } + + /* NOP */ + MACA->CONTROLbits.SEQUENCE = MACA_CONTROL_SEQUENCE_NOP; + + /* Wait ~8us */ + for ( clk = MACA->CLK, i = 0; MACA->CLK - clk < 3 && i < 300; i++ ) { + continue; + } + + /* restore original "last warmup step" data to TSM (VERY IMPORTANT!!!) */ + ( * ( ( volatile uint32_t * ) ( 0x80009300 + last_warmup_step ) ) ) = last_warmup_data; + + /* Clear all MACA interrupts - we should have gotten the ABORT IRQ */ + MACA->CLRIRQ = 0xffff; + + irq_restore(); +} diff --git a/redbee-econotag/drivers/nvm.c b/redbee-econotag/drivers/nvm.c new file mode 100644 index 0000000000000000000000000000000000000000..5d4538ef264e75c3d14940699369d780b885fdb7 --- /dev/null +++ b/redbee-econotag/drivers/nvm.c @@ -0,0 +1,22 @@ +/* + * nvm.c - non-volatile memory implementations + * Copyright (C) 2013 Thomas Eichinger <thomas.eichinger@fu-berlin.de> + * + * This source code is licensed under the GNU General Public License, + * Version 3. See the file LICENSE for more details. + * + * This file is part of RIOT. + */ + +#include "nvm.h" + +nvm_err_t (*nvm_detect) (nvm_interface_t nvm_interface, nvm_type_t* p_nvm_type) + = (void*) 0x00006cb9; +nvm_err_t (*nvm_read) (nvm_interface_t nvm_interface, nvm_type_t nvm_type, void *p_dest, uint32_t address, uint32_t num_bytes) + = (void*) 0x00006d69; +nvm_err_t (*nvm_write) (nvm_interface_t nvm_interface, nvm_type_t nvm_type, void *p_src, uint32_t address, uint32_t numb_bytes) + = (void*) 0x00006ec5; +nvm_err_t (*nvm_erase) (nvm_interface_t nvm_interface, nvm_type_t nvm_type, uint32_t sector_bitfield) + = (void*) 0x00006e05; +void (*nvm_sets_var) (uint32_t zero_is_for_winners) + = (void*) 0x00007085; \ No newline at end of file