📄 cc2420.c
字号:
/* * driver/tosmac/CC2420.c * * Author: Gefan Zhang * Trevor Pering * Last modified by Y.Cheng:11/April/2008 * */#ifdef PSI#include "CC2420_psi.h"#define NOT_KERNEL#endif#ifndef NOT_KERNEL#include <linux/config.h>#include <linux/module.h>#include <linux/fs.h>#include <linux/kernel.h>#include <linux/interrupt.h>#include <linux/time.h>#include <linux/timer.h>#include <linux/string.h>#include <linux/errno.h>#include <linux/init.h>#include <linux/ioctl.h>#include <linux/cdev.h>#include <linux/delay.h>#include <linux/random.h>#include <linux/poll.h>#include <linux/wait.h>#include <asm/uaccess.h>#include <asm/irq.h>#include <asm/mach/irq.h>#include <asm/mach-types.h>#include <asm/hardware.h>#include <asm/system.h>#include <asm/atomic.h>#include <asm/arch/pxa-regs.h>#include <asm/arch/stargate2.h>#include "../platx/pmic.h"#endif#ifndef NOT_KERNEL#include "SG2_CC2420.h"#include "TOSMac.h"#include "ostimer.h"#endif#include "byteorder.h"#include "CC2420.h"#include "CC2420Const.h"#include "AM.h"uint8_t CC2420_CHANNEL = CC2420_DEF_CHANNEL;uint8_t CC2420_RFPOWER = CC2420_DEF_RFPOWER;#define MAX_SEND_TRIES 8#define MAX_RESTART_TRIES 10static DECLARE_WAIT_QUEUE_HEAD(wq);static DECLARE_WAIT_QUEUE_HEAD(rq);static DECLARE_WAIT_QUEUE_HEAD(inq);// don't make these static so our HPL hacks can get to themstatic __u8 send_done = 0; static __u8 recv_done = 0; static DECLARE_MUTEX(CC2420_sem); //declare the singnal variableDECLARE_TASKLET(read_packet_tasklet, CC2420_read_packet, 0);enum { DISABLED_STATE = 0, DISABLED_STATE_STARTTASK, IDLE_STATE,//YC: ready to send TX_STATE,//YC: CCA passed , get data ready, send data TX_WAIT, //YC: wait for read message to receive ack message PRE_TX_STATE,//YC: check CCA in this state, after CCA available, to TX_STATE; if fail, backoff to retry CCA POST_TX_STATE,//YC: check ack message in this state POST_TX_ACK_STATE,//YC: this state indicate ack check has been done, either passed or failed from POST_TX_STATE RX_STATE, //YC: not used POWER_DOWN_STATE, WARMUP_STATE, TIMER_INITIAL = 0, TIMER_BACKOFF, TIMER_ACK, TIMER_RESTART, TIMER_TRANSMIT };uint8_t count_retry;uint8_t count_send_restart;uint8_t CC2420_state;uint8_t CC2420_timer_state;uint8_t non_blocking_mode;uint8_t ok_to_read;uint8_t state_timer;uint8_t current_DSN; // data sequence numberuint8_t is_ack_enable;uint8_t is_packet_receiving;TOS_MsgPtr tx_buf_ptr; // pointer to transmit bufferTOS_MsgPtr rx_buf_ptr; // pointer to receive bufferTOS_Msg rx_buf; // temp save received messagesTOS_Msg rx_packet; // save received packetuint8_t rx_packet_length; // length of recevied packetuint16_t g_current_parameters[14];//CC2420 Params settingvoid CC2420_set_parameters( ){ // Set default parameters from CC2420 chipset specs, p.62 g_current_parameters[CP_MAIN] = 0xf800; g_current_parameters[CP_MDMCTRL0] = ((0 << CC2420_MDMCTRL0_ADRDECODE) | (2 << CC2420_MDMCTRL0_CCAHIST) | (3 << CC2420_MDMCTRL0_CCAMODE) | (1 << CC2420_MDMCTRL0_AUTOCRC) | (2 << CC2420_MDMCTRL0_PREAMBL)); g_current_parameters[CP_MDMCTRL1] = 20 << CC2420_MDMCTRL1_CORRTHRESH; g_current_parameters[CP_RSSI] = 0xE080; g_current_parameters[CP_SYNCWORD] = 0xA70F; g_current_parameters[CP_TXCTRL] = ((1 << CC2420_TXCTRL_BUFCUR) | (1 << CC2420_TXCTRL_TURNARND) | (3 << CC2420_TXCTRL_PACUR) | (1 << CC2420_TXCTRL_PADIFF) | (CC2420_RFPOWER << CC2420_TXCTRL_PAPWR)); g_current_parameters[CP_RXCTRL0] = ((1 << CC2420_RXCTRL0_BUFCUR) | (2 << CC2420_RXCTRL0_MLNAG) | (3 << CC2420_RXCTRL0_LOLNAG) | (2 << CC2420_RXCTRL0_HICUR) | (1 << CC2420_RXCTRL0_MCUR) | (1 << CC2420_RXCTRL0_LOCUR)); g_current_parameters[CP_RXCTRL1] = ((1 << CC2420_RXCTRL1_LOLOGAIN) | (1 << CC2420_RXCTRL1_HIHGM) | (1 << CC2420_RXCTRL1_LNACAP) | (1 << CC2420_RXCTRL1_RMIXT) | (1 << CC2420_RXCTRL1_RMIXV) | (2 << CC2420_RXCTRL1_RMIXCUR)); g_current_parameters[CP_FSCTRL] = ((1 << CC2420_FSCTRL_LOCK) | ((357+5*(CC2420_CHANNEL-11)) << CC2420_FSCTRL_FREQ)); g_current_parameters[CP_SECCTRL0] = ((1 << CC2420_SECCTRL0_CBCHEAD) | (1 << CC2420_SECCTRL0_SAKEYSEL) | (1 << CC2420_SECCTRL0_TXKEYSEL) | (1 << CC2420_SECCTRL0_SECM)); g_current_parameters[CP_SECCTRL1] = 0; g_current_parameters[CP_BATTMON] = 0; // set fifop threshold to greater than size of tos msg, // fifop goes active at end of msg g_current_parameters[CP_IOCFG0] = (((127) << CC2420_IOCFG0_FIFOTHR) | (1 <<CC2420_IOCFG0_FIFOPPOL)); g_current_parameters[CP_IOCFG1] = 0;} /************************************************************************ * CC2420_set_regs * - Configure CC2420 registers with current values * - Readback 1st register written to make sure electrical connection OK *************************************************************************/uint8_t CC2420_set_regs( ){ uint16_t data; CC2420_write_reg(CC2420_MAIN,g_current_parameters[CP_MAIN]); CC2420_write_reg(CC2420_MDMCTRL0, g_current_parameters[CP_MDMCTRL0]); data = CC2420_read_reg(CC2420_MDMCTRL0);// printk(KERN_INFO "MDMCTRL0 is %x\n", data);// printk(KERN_INFO "gcurrent is is %x\n", g_current_parameters[CP_MDMCTRL0]); CC2420_write_reg(CC2420_MDMCTRL1, g_current_parameters[CP_MDMCTRL1]); CC2420_write_reg(CC2420_RSSI, g_current_parameters[CP_RSSI]); CC2420_write_reg(CC2420_SYNCWORD, g_current_parameters[CP_SYNCWORD]); CC2420_write_reg(CC2420_TXCTRL, g_current_parameters[CP_TXCTRL]); CC2420_write_reg(CC2420_RXCTRL0, g_current_parameters[CP_RXCTRL0]); CC2420_write_reg(CC2420_RXCTRL1, g_current_parameters[CP_RXCTRL1]); CC2420_write_reg(CC2420_FSCTRL, g_current_parameters[CP_FSCTRL]); CC2420_write_reg(CC2420_SECCTRL0, g_current_parameters[CP_SECCTRL0]); CC2420_write_reg(CC2420_SECCTRL1, g_current_parameters[CP_SECCTRL1]);// printk(KERN_INFO "before set:IOCFG0 is %x\n", CC2420_read_reg(CC2420_IOCFG0)); CC2420_write_reg(CC2420_IOCFG0, g_current_parameters[CP_IOCFG0]); CC2420_write_reg(CC2420_IOCFG1, g_current_parameters[CP_IOCFG1]);// printk(KERN_INFO "after set:IOCFG0 is %x\n", CC2420_read_reg(CC2420_IOCFG0)); CC2420_cmd_strobe(CC2420_SFLUSHTX); //flush Tx fifo CC2420_cmd_strobe(CC2420_SFLUSHRX); return TRUE; }uint8_t CC2420_oscillator_on( ){ uint8_t status; int timeout = 500; // 500us delay CC2420_cmd_strobe(CC2420_SXOSCON); do { status = CC2420_cmd_strobe(CC2420_SNOP); if (timeout-- <= 0) return FAIL; udelay(1); } while (!(status & (1 << CC2420_XOSC16M_STABLE)));// printk(KERN_INFO "After Oscillator on, status is %d\n", status); return SUCCESS;}uint8_t CC2420_oscillator_off( ){ uint8_t status; status = CC2420_cmd_strobe(CC2420_SNOP); status = CC2420_cmd_strobe(CC2420_SXOSCOFF); return SUCCESS;}void CC2420_send_failed() { CC2420_state = IDLE_STATE;// printk("in send failed, CC2420_state changed to: %d", CC2420_state);// tx_buf_ptr->length = tx_buf_ptr->length - MSG_HEADER_SIZE - MSG_FOOTER_SIZE; tx_buf_ptr->length = 255; send_done = 1; wake_up_interruptible(&wq);}void CC2420_recv_failed(void){ CC2420_state = IDLE_STATE; send_done=1;//added by YC wake_up_interruptible(&wq);//added by YC// printk("in recv failed, CC2420_state changed to: %d", CC2420_state); rx_packet.length = 255; // length=255 means rx_packet is not a valid packet rx_buf_ptr->length = 0; if(!non_blocking_mode) { recv_done = 1; wake_up_interruptible(&rq); }}void CC2420_flush_RXFIFO() { set_irq_type(CC2420_FIFOP_IRQ, IRQT_NOEDGE); CC2420_read_reg(CC2420_RXFIFO); CC2420_cmd_strobe(CC2420_SFLUSHRX); CC2420_cmd_strobe(CC2420_SFLUSHRX); // do it twice is_packet_receiving = FALSE; set_irq_type(CC2420_FIFOP_IRQ, IRQT_FALLING);}void CC2420_flush_TXFIFO() //added by YC, not used{ CC2420_cmd_strobe(CC2420_SFLUSHTX); CC2420_cmd_strobe(CC2420_SFLUSHTX); // do it twice}void CC2420_set_initial_timer(uint16_t jiffy) { CC2420_timer_state = TIMER_INITIAL; if (jiffy == 0) timer_start(2); else timer_start(jiffy);}void CC2420_set_transmit_timer(uint16_t jiffy) { CC2420_timer_state = TIMER_TRANSMIT; if (jiffy < 1) jiffy = 1; timer_start(jiffy);}void CC2420_set_backoff_timer(uint16_t jiffy){ CC2420_timer_state = TIMER_BACKOFF; if (jiffy == 0) timer_start(2); else timer_start(jiffy);} void CC2420_set_ack_timer(uint16_t jiffy) { CC2420_timer_state = TIMER_ACK; timer_start(jiffy);}void CC2420_set_restart_timer(uint16_t jiffy) { CC2420_timer_state = TIMER_RESTART; if (jiffy == 0) timer_start(2); else timer_start(jiffy);}int8_t Mac_initial_backoff(){ int8_t random_byte; get_random_bytes(&random_byte, 1); return ((random_byte & 0xF) + 1);}int8_t Mac_congestion_backoff(){ int8_t random_byte; get_random_bytes(&random_byte, 1); return ((random_byte & 0x3F) + 1);}void CC2420_packet_rcvd() { int i; // FIXME: This function is horribly inefficient and should be rewritten to use // macros and functions like memcpy and memset, and also to copy into // a buffer specificed by the upper layers instead of into an internal // holding buffer -- right now there is a lot of unncessary copying that // goes on./* rx_packet.length = rx_buf_ptr->length; rx_packet.fcfhi = rx_buf_ptr->fcfhi; rx_packet.fcflo = rx_buf_ptr->fcflo; rx_packet.dsn = rx_buf_ptr->dsn; rx_packet.destpan = rx_buf_ptr->destpan; rx_packet.addr = rx_buf_ptr->addr; rx_packet.type = rx_buf_ptr->type; rx_packet.group = rx_buf_ptr->group; for(i = 0; i < (rx_packet_length - MSG_HEADER_SIZE - 1 - MSG_FOOTER_SIZE); i++) { rx_packet.data[i] = rx_buf_ptr->data[i]; } for(; i < TOSH_DATA_LENGTH; i++) rx_packet.data[i] = '\0'; i = TOSH_DATA_LENGTH; rx_packet.data[i++] = rx_buf_ptr->strength; rx_packet.data[i++] = rx_buf_ptr->lqi; rx_packet.data[i++] = rx_buf_ptr->crc; rx_packet.data[i++] = rx_buf_ptr->ack; rx_packet.data[i++] = (rx_buf_ptr->time>>8) & 0xFF; rx_packet.data[i++] = rx_buf_ptr->time & 0xFF; rx_buf_ptr->length = 0; for (i = 0; i < TOSH_DATA_LENGTH; i++) rx_buf_ptr->data[i] = '\0'; */ //YC: below three statements replace the copying/set zero operations above memcpy(&rx_packet, rx_buf_ptr,rx_buf_ptr->length+MSG_HEADER_SIZE +1 + TOSMSG_FOOTER_SIZE); rx_buf_ptr->length = 0; memset(rx_buf_ptr->data,'\0',TOSH_DATA_LENGTH); is_packet_receiving = FALSE; // CC2420_state = IDLE_STATE; //commemted out by YC, this will break the CC2420 tx loop, and hang writing operation // wake_up_interruptible(&wq);//added by YC, if comment out the state change, no need for this // printk("in packet rcvd, CC2420_state changed to: %d\n", CC2420_state); // FIXME: not sure why there are two receive queues -- really only needs // to be one, and it's just used differently at the higher layer if(!non_blocking_mode){ recv_done = 1; wake_up_interruptible(&rq); } else { ok_to_read = TRUE; wake_up_interruptible(&inq); } return;}void CC2420_packet_sent()
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -