📄 cc2420.c
字号:
// This file is part of MANTIS OS, Operating System// See http://mantis.cs.colorado.edu///// Copyright (C) 2003,2004,2005 University of Colorado, Boulder//// This program is free software; you can redistribute it and/or// modify it under the terms of the mos license (see file LICENSE)#include "com.h"#include "mos.h"#include "spi.h"#if defined(PLATFORM_MICAZ) || defined(PLATFORM_TELOSB)#include <stdarg.h>#include "sem.h"#include "msched.h"#include "node_id.h"#include "mutex.h"#include "clock.h"#include "cc2420.h"#include "led.h"#include "bitops.h"#include "plat_dep.h"#include "printf.h"#if defined(CC2420) || !defined(SCONS)#define DEFAULT_CHANNEL 26static uint16_t pan_id = 0x2420;static uint16_t id;static uint8_t cc2420_com_mode;static comBuf *cc2420_recv_buf; //receive buffer// NOT COMPLETE//#define CC2420_INTERRUPT_DRIVEN#ifdef CC2420_INTERRUPT_DRIVENstatic sem spi_sem;typedef void (*spi_state_f) (void);static Thread *spi_thread;static uint8_t current_state;static spi_state_f spi_state;void spi_state_init(void);void spi_state_idle(void);#define SPI_STATE_INIT 0#endifstatic inline void spi_rx_address(uint8_t addr){ SPI_TX_BUF = (addr) | 0x40; SPI_WAIT_EOTX();}static void spi_strobe(uint8_t byte){ UNSET_PORT_1(CC2420_CHIP_SELECT); spi_tx_byte(byte); SET_PORT_1(CC2420_CHIP_SELECT);}void spi_set_register(uint8_t reg, uint16_t val){ UNSET_PORT_1(CC2420_CHIP_SELECT); spi_tx_byte(reg); spi_tx_byte((uint8_t)(val >> 8)); spi_tx_byte((uint8_t)(val)); SET_PORT_1(CC2420_CHIP_SELECT);}uint16_t spi_get_register(uint8_t reg){ uint16_t ret; UNSET_PORT_1 (CC2420_CHIP_SELECT); spi_rx_address(reg); ret = spi_rx_word(); SET_PORT_1(CC2420_CHIP_SELECT); return ret;}static uint8_t spi_update_status(void){ uint8_t ret; UNSET_PORT_1(CC2420_CHIP_SELECT); spi_tx_byte (CC2420_SNOP); ret = SPI_RX_BUF; SET_PORT_1(CC2420_CHIP_SELECT); return ret;}static void spi_write_ram(void *addr, uint16_t radio_addr, uint8_t count){ uint8_t i; UNSET_PORT_1(CC2420_CHIP_SELECT); spi_tx_byte (0x80 | (radio_addr & 0x7F)); spi_tx_byte((radio_addr >> 1) & 0xC0); for(i = 0; i < count; i++) { spi_tx_byte(((uint8_t *)addr)[i]); } SET_PORT_1(CC2420_CHIP_SELECT);}static void spi_read_ram(void *addr, uint16_t radio_addr, uint8_t count){ uint8_t i; UNSET_PORT_1(CC2420_CHIP_SELECT); spi_tx_byte(0x80 | (radio_addr & 0x7F)); spi_tx_byte(((radio_addr >> 1) & 0xC0) | 0x20); for(i = 0; i < count; i++) { ((uint8_t *)addr)[i] = spi_rx(); } SET_PORT_1(CC2420_CHIP_SELECT);}static void spi_write_fifo(void *addr, uint8_t count){ uint8_t i; UNSET_PORT_1(CC2420_CHIP_SELECT); spi_tx_byte(CC2420_TXFIFO); for(i = 0; i < count; i++) { spi_tx_byte(((uint8_t *)addr)[i]); } SET_PORT_1(CC2420_CHIP_SELECT);}static void spi_read_fifo(void *addr, uint8_t count){ uint8_t i; UNSET_PORT_1(CC2420_CHIP_SELECT); spi_rx_address(CC2420_RXFIFO); for(i = 0; i < count; i++) { while(!(PORT_IN(CC2420_FIFO_PORT) & CC2420_FIFO_PIN)) ; ((uint8_t *)addr)[i] = spi_rx(); } SET_PORT_1(CC2420_CHIP_SELECT);}static void spi_read_fifo_garbage(uint8_t count){ uint8_t i; UNSET_PORT_1(CC2420_CHIP_SELECT); spi_rx_address(CC2420_RXFIFO); for(i = 0; i < count; i++) { spi_rx_garbage(); } SET_PORT_1(CC2420_CHIP_SELECT);}static void spi_read_fifo_no_wait(void *addr, uint8_t count){ uint8_t i; UNSET_PORT_1(CC2420_CHIP_SELECT); spi_rx_address(CC2420_RXFIFO); for(i = 0; i < count; i++) { ((uint8_t *)addr)[i] = spi_rx(); } SET_PORT_1(CC2420_CHIP_SELECT);}void cc2420_init(void){ handle_t int_handle; id = mos_node_id_get(); int_handle = mos_disable_ints();#ifdef CC2420_INTERRUPT_DRIVEN current_state = SPI_STATE_INIT; spi_state = spi_state_init; mos_sem_init(&spi_sem, 0);#endif SET_DIR_2(CC2420_RESET, CC2420_VREG); SET_PORT_1(CC2420_RESET); SET_DIR_2(CC2420_MOSI, CC2420_SPI_CLOCK); SET_DIR_1(CC2420_CHIP_SELECT); SET_PORT_2(CC2420_MOSI, CC2420_SPI_CLOCK); SET_PORT_1(CC2420_CHIP_SELECT); UNSET_DIR_1(CC2420_CCA); UNSET_DIR_1(CC2420_SFD); UNSET_PORT_1(CC2420_SFD); UNSET_DIR_1(CC2420_FIFO); UNSET_DIR_1(CC2420_MISO); PLAT_SPI_INIT(); // set the voltage regulator on, reset pin inactive SET_PORT_1(CC2420_VREG); mos_udelay(4000); UNSET_PORT_1(CC2420_RESET); mos_udelay(4); SET_PORT_1(CC2420_RESET); mos_udelay(20); PLAT_ENABLE_FIFOP_INT(); UNSET_DIR_1(CC2420_FIFOP); UNSET_PORT_1(CC2420_FIFOP);#ifndef CC2420_INTERRUPT_DRIVEN spi_strobe(CC2420_SXOSCON); // turn on automatic packet ack //spi_set_register (CC2420_MDMCTRL0, 0x0AF2); // no auto ack //printf("before set reg\n"); spi_set_register(CC2420_MDMCTRL0, 0x02E2);// printf("CC2420_INIT: MDMCTRL0 = %x\n", spi_get_register(CC2420_MDMCTRL0)); /* mos_enable_ints(int_handle); uint16_t val = spi_get_register(CC2420_MDMCTRL0); printf("CC2420_MDMCTRL0 = %x\n", val); int_handle = mos_disable_ints(); */ //spi_set_register (CC2420_MDMCTRL0, 0x12F2); // set correlation threshold = 20 spi_set_register(CC2420_MDMCTRL1, 0x0500); // set fifop threshold to max spi_set_register(CC2420_IOCFG0, 0x007F); // turn off security spi_set_register(CC2420_SECCTRL0, 0x01C4); // set the channel cc2420_set_channel(DEFAULT_CHANNEL); // wait for the oscillator //printf("before osc\n"); cc2420_wait_for_osc(); //printf("after osc\n"); spi_write_ram(&id, CC2420RAM_SHORTADDR, sizeof(id)); spi_write_ram(&pan_id, CC2420RAM_PANID, sizeof(pan_id)); #else spi_thread = mos_thread_current();#endif // start out with a free com buf com_swap_bufs(IFACE_RADIO, NULL, &cc2420_recv_buf); // set initial com mode cc2420_com_mode = IF_OFF; spi_strobe(CC2420_SFLUSHRX); spi_strobe(CC2420_SFLUSHTX); mos_enable_ints(int_handle); // if we are interrupt driven, wait for the #ifdef CC2420_INTERRUPT_DRIVEN mos_thread_suspend();#endif}//#endifvoid cc2420_wait_for_osc(void){ uint8_t status_byte; do { status_byte = spi_update_status(); } while(!(status_byte & (1 << CC2420_XOSC16M_STABLE)));}void cc2420_set_channel(uint8_t chan){ uint16_t c; c = (uint16_t)(chan - 11); c = c + (c << 2); c = c + 357; c = c + 0x4000; handle_t int_handle = mos_disable_ints(); spi_set_register(CC2420_FSCTRL, c); mos_enable_ints(int_handle);}void com_ioctl_IFACE_RADIO(uint8_t request, ...){ int arg; va_list ap; va_start(ap, request); arg = va_arg(ap, int); switch(request) { //case CC2420_USE_ACK: //break; default: break; } va_end(ap); return;}void com_mode_IFACE_RADIO(uint8_t md){ handle_t int_handle; switch(md) { case IF_OFF: int_handle = mos_disable_ints(); //disable FIFOP (receive) interrupt UNMASK_1(EIMSK, CC2420_FIFOP_PIN); //turn off radio spi_strobe(CC2420_SRFOFF); mos_enable_ints(int_handle); cc2420_com_mode = md; break; case IF_STANDBY: break; case IF_IDLE: break; case IF_LISTEN: int_handle = mos_disable_ints(); //enable FIFOP (receive) interrupt MASK_1(EIMSK, CC2420_FIFOP_PIN); //power up radio spi_strobe(CC2420_SRXON); spi_strobe(CC2420_SFLUSHRX); mos_enable_ints(int_handle); //cc2420_com_mode = md; cc2420_com_mode = CC2420_MODE_RX; break; } return;}uint8_t com_send_IFACE_RADIO (comBuf *buf){ handle_t int_handle; uint8_t status; // 11 bytes overhead for header int8_t len = buf->size + 11; // noack frame control field uint16_t fcf = 0x8841; // ack frame control field //uint16_t fcf = 0x8861; static uint8_t seq = 0; uint16_t dest_addr = 0x1234; while(PORT_IN(CC2420_SFD_PORT) & (1 << CC2420_SFD_PIN) || PORT_IN(CC2420_FIFOP_PORT) & (1 << CC2420_FIFOP_PIN)) ; int_handle = mos_disable_ints(); spi_strobe(CC2420_SFLUSHTX); // turn on receiver if necessary //if (cc2420_com_mode != CC2420_MODE_RX) { spi_strobe(CC2420_SRXON); //} // wait for RSSI do { status = spi_update_status(); //mos_udelay(0x1fff); } while(!(status & (1 << CC2420_RSSI_VALID))); // fill up the fifo with the frame format spi_write_fifo(&len, sizeof(len)); spi_write_fifo(&fcf, sizeof(fcf)); spi_write_fifo(&seq, sizeof(seq)); spi_write_fifo(&pan_id, sizeof(pan_id)); spi_write_fifo(&dest_addr, sizeof(dest_addr)); spi_write_fifo(&id, sizeof(id)); spi_write_fifo(buf->data, buf->size); // wait for transmission do { spi_strobe(CC2420_STXONCCA); status = spi_update_status(); mos_udelay(100); } while(!(status & (1 << CC2420_TX_ACTIVE))); /* uint8_t mem; uint16_t fcf2; spi_read_ram(&mem, 0x0, 1); spi_read_ram(&fcf2, 0x01, 2); */ while(!(PORT_IN(CC2420_SFD_PORT) & (1 << CC2420_SFD_PIN))) ; //printf("sfd set\n"); if(cc2420_com_mode != CC2420_MODE_RX) { int_handle = mos_disable_ints(); spi_strobe(CC2420_SRFOFF); printf("srfoff is set\n"); mos_enable_ints(int_handle); } seq++; //printf("returning from send\n"); return 0;}#ifdef CC2420_INTERRUPT_DRIVENstatic uint8_t spi_init[] ARCH_PROGMEM = { CC2420_SXOSCON, CC2420_MDMCTRL0, 0x02E2 >> 8, 0x02E2 & 0xff, CC2420_MDMCTRL1, 0x0500 >> 8, 0x0500 & 0xff, CC2420_IOCFG0, 0x007F >> 8, 0x007F & 0xff, CC2420_SECCTRL0, 0x01C4 >> 8, 0x01C4 & 0xff, 0};static uint8_t spi_i;static uint8_t spi_data;void spi_state_init(void){ switch(current_state) { case SPI_STATE_INIT: if((spi_data = pgm_read_byte(&spi_init[spi_i++])) != 0) { /*SPDR*/ SPI_TX_BUF = spi_data; } else { spi_state = spi_state_idle; mos_thread_resume(spi_thread); } break; }}void spi_state_idle(void){ }SIGNAL (SIG_SPI){ spi_state();}#endifCC2420_FIFOP_INTERRUPT(){#ifdef PLATFORM_TELOSB // clear interrupt flag P1IFG &= ~(1 << 0);#endif uint8_t len; uint16_t fcf; uint8_t seq; uint16_t addr; // exit on overflow, indicated by FIFOP == 1 and FIFO == 0 if((PORT_IN(CC2420_FIFOP_PORT) & (1 << CC2420_FIFOP_PIN)) && !(PORT_IN(CC2420_FIFO_PORT) & (1 << CC2420_FIFO_PIN))) { // not sure why there are two of these... (from example code) spi_strobe(CC2420_SFLUSHRX); spi_strobe(CC2420_SFLUSHRX); return; } spi_read_fifo(&len, sizeof(len)); // mask out msb len &= 0x7f; if(len < 5) { spi_read_fifo_garbage(len); return; } spi_read_fifo_no_wait(&fcf, sizeof(fcf)); spi_read_fifo(&seq, sizeof(seq)); if(len == 5) { // could be an ack packet spi_read_fifo_garbage(len); return; } else if(len < 11) { // packet is too short, discard spi_read_fifo_garbage(len); return; } else { // make sure we have a com buf if(!cc2420_recv_buf) { com_swap_bufs(IFACE_RADIO, NULL, &cc2420_recv_buf); if(!cc2420_recv_buf) { return; } } cc2420_recv_buf->size = len - 11; // skip the dest PAN addr (taken care of by hw addr recognition) spi_read_fifo_garbage(4); spi_read_fifo_no_wait(&addr, sizeof(addr)); spi_read_fifo_no_wait(cc2420_recv_buf->data, cc2420_recv_buf->size); // skip over RSSI for now spi_read_fifo_garbage(2); com_swap_bufs(IFACE_RADIO, cc2420_recv_buf, &cc2420_recv_buf); }}#endif#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -