📄 cc2420.c
字号:
#endif break; } } return IRQ_HANDLED;}irqreturn_t CC2420_irq_handler(int irq, void *dev, struct pt_regs *regs){ int gpio_pin = IRQ_TO_GPIO(irq);//printk(KERN_INFO "IRQ %d happened \n",CC2420_state); switch (gpio_pin) { case SG2_GPIO16_CC_SFD: switch (CC2420_state) { case TX_STATE:// printk(KERN_INFO "IRQ type is SFD!\n"); // if SFD already fell, then disable interrupt if(!TEST_SFD_PIN()){ set_irq_type(CC2420_SFD_IRQ, IRQT_NOEDGE);// printk(KERN_INFO "SFD already fallen\n"); } else{#ifdef PSI set_irq_type(CC2420_SFD_IRQ, IRQT_FALLING);#endif CC2420_state = TX_WAIT;// printk("in irq 1, CC2420_state changed to: %d\n", CC2420_state);// printk(KERN_INFO "CC2420 state is in TX_WAIT\n"); } tx_buf_ptr->time = 0;// printk(KERN_INFO "SFD:FSMSTATE is %d\n", CC2420_read_reg(CC2420_FSMSTATE)); if(CC2420_state == TX_WAIT){// printk(KERN_INFO "cc2420_state: Tx_Wait\n"); CC2420_set_transmit_timer(CC2420_TMIT_DELAY); break; } case TX_WAIT: CC2420_state = POST_TX_STATE;// printk("in irq 2, CC2420_state changed to: %d\n", CC2420_state);// printk(KERN_INFO "SFD: TX_WAIT\n"); //disable SFD interrupt set_irq_type(CC2420_SFD_IRQ, IRQT_NOEDGE); //enable SFD interrupt as rising edge interrupt#ifdef PSI set_irq_type(CC2420_SFD_IRQ, IRQT_FALLING);#else set_irq_type(CC2420_SFD_IRQ, IRQT_BOTHEDGE);#endif //if acks are enabled and it is a unicast packet, wait for ack if((is_ack_enable) && (tx_buf_ptr->addr != TOS_BCAST_ADDR)) { CC2420_set_ack_timer(CC2420_ACK_DELAY); } else{ CC2420_packet_sent(); } break; default: rx_buf_ptr->time = 0; } break; case SG2_GPIO114_CC_FIFO: break; case SG2_GPIO0_CC_FIFOP:// printk(KERN_INFO "IRQ type is FIFOP\n"); // if(CC2420_state != IDLE_STATE || non_blocking_mode) {//comment out by YC, cc2420 should always read when data available // if we're trying to send a message and a FIFOP interrupt occurs // and acks are enabled, we need to backoff longer so that we don't // interfere with the ACK if (is_ack_enable && (CC2420_state == PRE_TX_STATE)) { if (timer_is_running()) { timer_stop(); timer_start((Mac_congestion_backoff( ) * CC2420_SYMBOL_UNIT) + CC2420_ACK_DELAY); } } /** Check for RXFIFO overflow **/ if(!TEST_FIFO_PIN()){ CC2420_flush_RXFIFO(); // printk(KERN_INFO "RXFIFO overflow\n"); CC2420_recv_failed(); return SUCCESS; } //bottom half tasklet_schedule(&read_packet_tasklet); set_irq_type(CC2420_FIFOP_IRQ, IRQT_NOEDGE);// } else// CC2420_flush_RXFIFO(); break;// case SG2_GPIO116_CC_CCA:// break; default: printk(KERN_INFO "Unknown GPIO %d interrupt happened\n", gpio_pin); break; } return IRQ_HANDLED;}unsigned int CC2420_poll(struct file *filp, struct poll_table_struct *wait){ unsigned int mask = 0; poll_wait(filp, &inq, wait); if(ok_to_read) { mask |= POLLIN | POLLRDNORM;// printk(KERN_INFO "poll: data ready\n"); }// else// printk(KERN_INFO "poll: data not ready\n"); return mask;}/* * -Set CC2420 Channel * Valid channel values are 11 through 26 * Freq = 2045 + 5(k-11) Mhz for k = 11, 12, ..., 26 * chnl: requested 802.15.4 channel * return Status of the tune operation */uint8_t CC2420_tune_preset(uint8_t chnl){ int fsctrl; uint8_t status; fsctrl = 357 + 5*(chnl-11); g_current_parameters[CP_FSCTRL] = (g_current_parameters[CP_FSCTRL] & 0xfc00)\ | (fsctrl << CC2420_FSCTRL_FREQ); status = CC2420_write_reg(CC2420_FSCTRL, g_current_parameters[CP_FSCTRL]); // if the oscillator is started, recalibrate for the new frequency // if the oscillator is NOT on, we should not transition to RX mode if (status & (1 << CC2420_XOSC16M_STABLE)) CC2420_cmd_strobe(CC2420_SRXON); return SUCCESS;} /* * TuneManual * Tune the radio to a given frequency. Frequencies may be set in * 1 MHz steps between 2400 MHz and 2483 MHz * * Desiredfreq: The desired frequency, in MHz. * Return Status of the tune operation */uint8_t CC2420_tune_manual(uint16_t DesiredFreq) { int fsctrl; uint8_t status; fsctrl = DesiredFreq - 2048; g_current_parameters[CP_FSCTRL] = (g_current_parameters[CP_FSCTRL] & 0xfc00) \ | (fsctrl << CC2420_FSCTRL_FREQ); status = CC2420_write_reg(CC2420_FSCTRL, g_current_parameters[CP_FSCTRL]); // if the oscillator is started, recalibrate for the new frequency // if the oscillator is NOT on, we should not transition to RX mode if (status & (1 << CC2420_XOSC16M_STABLE)) CC2420_cmd_strobe(CC2420_SRXON); return SUCCESS;}/* * Get the current frequency of the radio */uint16_t CC2420_get_frequency( ) { return ((g_current_parameters[CP_FSCTRL] & (0x1FF << CC2420_FSCTRL_FREQ))+2048);} /* * Get the current channel of the radio */uint8_t CC2420_get_preset( ) { uint16_t _freq = (g_current_parameters[CP_FSCTRL] & (0x1FF << CC2420_FSCTRL_FREQ)); _freq = (_freq - 357)/5; _freq = _freq + 11; return _freq;}/************************************************************************** TxMode* Shift the CC2420 Radio into transmit mode.* return SUCCESS if the radio was successfully switched to TX mode.*************************************************************************/uint8_t CC2420_tx_mode( ) { CC2420_cmd_strobe(CC2420_STXON); return SUCCESS;}/************************************************************************** TxModeOnCCA* Shift the CC2420 Radio into transmit mode when the next clear channel* is detected.** return SUCCESS if the transmit request has been accepted*************************************************************************/uint8_t CC2420_tx_onCCA( ) { CC2420_cmd_strobe(CC2420_STXONCCA); return SUCCESS;}/************************************************************************* * RxMode * Shift the CC2420 Radio into receive mode*************************************************************************/uint8_t CC2420_rx_mode( ) { CC2420_cmd_strobe(CC2420_SRXON); return SUCCESS;}/************************************************************************** SetRFPower* power = 31 => full power (0dbm)* 3 => lowest power (-25dbm)* return SUCCESS if the radio power was successfully set*************************************************************************/uint8_t CC2420_set_rf_power(uint8_t power) { g_current_parameters[CP_TXCTRL] = (g_current_parameters[CP_TXCTRL] & (~CC2420_TXCTRL_PAPWR_MASK)) | (power << CC2420_TXCTRL_PAPWR); CC2420_write_reg(CC2420_TXCTRL, g_current_parameters[CP_TXCTRL]); return SUCCESS;} /************************************************************************* * GetRFPower * return power seeting*************************************************************************/uint8_t CC2420_get_rf_power( ) { return (g_current_parameters[CP_TXCTRL] & CC2420_TXCTRL_PAPWR_MASK); //rfpower;}uint8_t CC2420_enable_AutoAck( ) { g_current_parameters[CP_MDMCTRL0] |= (1 << CC2420_MDMCTRL0_AUTOACK); return CC2420_write_reg(CC2420_MDMCTRL0,g_current_parameters[CP_MDMCTRL0]);}uint8_t CC2420_disable_AutoAck( ) { g_current_parameters[CP_MDMCTRL0] &= ~(1 << CC2420_MDMCTRL0_AUTOACK); return CC2420_write_reg(CC2420_MDMCTRL0, g_current_parameters[CP_MDMCTRL0]);}uint8_t CC2420_enable_AddrDecode( ) { g_current_parameters[CP_MDMCTRL0] |= (1 << CC2420_MDMCTRL0_ADRDECODE); return CC2420_write_reg(CC2420_MDMCTRL0, g_current_parameters[CP_MDMCTRL0]);}uint8_t CC2420_disable_AddrDecode( ) { g_current_parameters[CP_MDMCTRL0] &= ~(1 << CC2420_MDMCTRL0_ADRDECODE); return CC2420_write_reg(CC2420_MDMCTRL0, g_current_parameters[CP_MDMCTRL0]);}/** Enable link layer hardware acknowledgements **/ void CC2420_enable_ack() { is_ack_enable = TRUE; CC2420_enable_AddrDecode(); CC2420_enable_AutoAck();}/** Disable link layer hardware acknowledgements **/void CC2420_disable_ack() { is_ack_enable = FALSE; CC2420_disable_AddrDecode(); CC2420_disable_AutoAck();}uint8_t CC2420_set_short_addr(uint16_t addr) { addr = toLSB16(addr); return CC2420_write_RAM(CC2420_RAM_SHORTADR, 2, (uint8_t*)&addr);}/* * CC2420_init( ) is called when driver is installed. * It will turn CC2420 oscillator on, setup SPI port. */uint8_t CC2420_init(struct tosmac_device *dev){ int ret; down(&CC2420_sem); CC2420_state = DISABLED_STATE;// printk("in init 1, CC2420_state changed to: %d\n", CC2420_state); TOS_LOCAL_ADDRESS = local_addr; HPLCC2420_init(); CC2420_set_parameters(); CC2420_state = WARMUP_STATE;// printk("in init 2, CC2420_state changed to: %d\n", CC2420_state); HPLCC2420_start(); if (CC2420_oscillator_on() != SUCCESS) goto fail;// printk(KERN_INFO "CC2420 Oscillator is on.\n"); CC2420_set_regs(); CC2420_set_short_addr(TOS_LOCAL_ADDRESS); CC2420_tune_manual(((g_current_parameters[CP_FSCTRL] << CC2420_FSCTRL_FREQ) & 0x1FF) + 2048); CC2420_rx_mode(); CC2420_state = IDLE_STATE;// printk("in init 3, CC2420_state changed to: %d\n", CC2420_state); non_blocking_mode = FALSE; current_DSN = 0; is_ack_enable = FALSE; is_packet_receiving = FALSE; rx_buf_ptr = &rx_buf;//$$ rx_buf_ptr->length = 0; count_retry = 0; count_send_restart = 0; rx_buf_ptr->length = 0;#ifndef PSI// CC2420_enable_ack();#endif// printk(KERN_INFO "IOCFG0 is %x\n", CC2420_read_reg(CC2420_IOCFG0));// printk(KERN_INFO "cc2420_start_finished\n"); //enable interrupts ret = request_irq(CC2420_FIFOP_IRQ, CC2420_irq_handler, SA_INTERRUPT, "cc2420", dev); if(ret) {// printk(KERN_INFO "Failed to request FIFOP interrupt.\n"); goto fail; } set_irq_type(CC2420_FIFOP_IRQ, IRQT_FALLING); ret = request_irq(CC2420_SFD_IRQ, CC2420_irq_handler, SA_INTERRUPT, "cc2420", dev); if(ret) {// printk(KERN_INFO "Failed to request SFD interrupt.\n"); goto fail; }#ifdef PSI set_irq_type(CC2420_SFD_IRQ, IRQT_FALLING);#else set_irq_type(CC2420_SFD_IRQ, IRQT_BOTHEDGE);#endif ret = request_irq(CC2420_OST_IRQ, CC2420_timer_irq_handler, SA_INTERRUPT, "cc2420", dev); if(ret) {// printk(KERN_INFO "Failed to request OS Timer interrupt.\n"); goto fail; } // init timer timer_init(); up(&CC2420_sem); return SUCCESS;fail: up(&CC2420_sem); return FAIL;}/* * CC2420_start( ) is called when CC2420 device is opened. * It will request all interrupts and do init related with CC2420 */uint8_t CC2420_start(uint8_t is_non_blocking) //(struct tosmac_device *dev){ if(is_non_blocking) { non_blocking_mode = TRUE; ok_to_read = FALSE; } else non_blocking_mode = FALSE; return SUCCESS;}void CC2420_stop(struct tosmac_device * dev){// printk(KERN_INFO "Close device\n");}uint8_t CC2420_exit(struct tosmac_device *dev){ free_irq(CC2420_FIFOP_IRQ, dev); free_irq(CC2420_SFD_IRQ, dev); free_irq(CC2420_OST_IRQ, dev); CC2420_state = DISABLED_STATE;// printk("in exit, CC2420_state changed to: %d\n", CC2420_state); CC2420_oscillator_off(); HPLCC2420_exit(); return SUCCESS;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -