嵌入式linux下CC1101的驱动 arm9 tq2440开发板

时间:2022-01-06 20:06:04

连接方式如下,本文代码皆基于此种连接方式编写:(经TQ2440开发板验证正确驱动)

嵌入式linux下CC1101的驱动 arm9 tq2440开发板

采用的是GPIO口模拟SPI通信的方式,内核版本为linux-2.6.30,其实主要从51单片机驱动CC1101的代码中移植而来;

代码如下:

cc1101.h:

#ifndef _CC1101_H
#define _CC1101_H

#define INT8U unsigned char
#define INT16U unsigned int

#define WRITE_BURST 0x40 //连续写入
#define READ_SINGLE 0x80 //读
#define READ_BURST 0xC0 //连续读
#define BYTES_IN_RXFIFO 0x7F //接收缓冲区的有效字节数
#define CRC_OK 0x80 //CRC校验通过位标志
#define CCxxx0_IOCFG2 0x00 // GDO2 output pin configuration
#define CCxxx0_IOCFG1 0x01 // GDO1 output pin configuration
#define CCxxx0_IOCFG0 0x02 // GDO0 output pin configuration
#define CCxxx0_FIFOTHR 0x03 // RX FIFO and TX FIFO thresholds
#define CCxxx0_SYNC1 0x04 // Sync word, high INT8U
#define CCxxx0_SYNC0 0x05 // Sync word, low INT8U
#define CCxxx0_PKTLEN 0x06 // Packet length
#define CCxxx0_PKTCTRL1 0x07 // Packet automation control
#define CCxxx0_PKTCTRL0 0x08 // Packet automation control
#define CCxxx0_ADDR 0x09 // Device address
#define CCxxx0_CHANNR 0x0A // Channel number
#define CCxxx0_FSCTRL1 0x0B // Frequency synthesizer control
#define CCxxx0_FSCTRL0 0x0C // Frequency synthesizer control
#define CCxxx0_FREQ2 0x0D // Frequency control word, high INT8U
#define CCxxx0_FREQ1 0x0E // Frequency control word, middle INT8U
#define CCxxx0_FREQ0 0x0F // Frequency control word, low INT8U
#define CCxxx0_MDMCFG4 0x10 // Modem configuration
#define CCxxx0_MDMCFG3 0x11 // Modem configuration
#define CCxxx0_MDMCFG2 0x12 // Modem configuration
#define CCxxx0_MDMCFG1 0x13 // Modem configuration
#define CCxxx0_MDMCFG0 0x14 // Modem configuration
#define CCxxx0_DEVIATN 0x15 // Modem deviation setting
#define CCxxx0_MCSM2 0x16 // Main Radio Control State Machine configuration
#define CCxxx0_MCSM1 0x17 // Main Radio Control State Machine configuration
#define CCxxx0_MCSM0 0x18 // Main Radio Control State Machine configuration
#define CCxxx0_FOCCFG 0x19 // Frequency Offset Compensation configuration
#define CCxxx0_BSCFG 0x1A // Bit Synchronization configuration
#define CCxxx0_AGCCTRL2 0x1B // AGC control
#define CCxxx0_AGCCTRL1 0x1C // AGC control
#define CCxxx0_AGCCTRL0 0x1D // AGC control
#define CCxxx0_WOREVT1 0x1E // High INT8U Event 0 timeout
#define CCxxx0_WOREVT0 0x1F // Low INT8U Event 0 timeout
#define CCxxx0_WORCTRL 0x20 // Wake On Radio control
#define CCxxx0_FREND1 0x21 // Front end RX configuration
#define CCxxx0_FREND0 0x22 // Front end TX configuration
#define CCxxx0_FSCAL3 0x23 // Frequency synthesizer calibration
#define CCxxx0_FSCAL2 0x24 // Frequency synthesizer calibration
#define CCxxx0_FSCAL1 0x25 // Frequency synthesizer calibration
#define CCxxx0_FSCAL0 0x26 // Frequency synthesizer calibration
#define CCxxx0_RCCTRL1 0x27 // RC oscillator configuration
#define CCxxx0_RCCTRL0 0x28 // RC oscillator configuration
#define CCxxx0_FSTEST 0x29 // Frequency synthesizer calibration control
#define CCxxx0_PTEST 0x2A // Production test
#define CCxxx0_AGCTEST 0x2B // AGC test
#define CCxxx0_TEST2 0x2C // Various test settings
#define CCxxx0_TEST1 0x2D // Various test settings
#define CCxxx0_TEST0 0x2E // Various test settings

// Strobe commands
#define CCxxx0_SRES 0x30 // Reset chip.
#define CCxxx0_SFSTXON 0x31 // Enable and calibrate frequency synthesizer (if MCSM0.FS_AUTOCAL=1).
// If in RX/TX: Go to a wait state where only the synthesizer is
// running (for quick RX / TX turnaround).
#define CCxxx0_SXOFF 0x32 // Turn off crystal oscillator.
#define CCxxx0_SCAL 0x33 // Calibrate frequency synthesizer and turn it off
// (enables quick start).
#define CCxxx0_SRX 0x34 // Enable RX. Perform calibration first if coming from IDLE and
// MCSM0.FS_AUTOCAL=1.
#define CCxxx0_STX 0x35 // In IDLE state: Enable TX. Perform calibration first if
// MCSM0.FS_AUTOCAL=1. If in RX state and CCA is enabled:
// Only go to TX if channel is clear.
#define CCxxx0_SIDLE 0x36 // Exit RX / TX, turn off frequency synthesizer and exit
// Wake-On-Radio mode if applicable.
#define CCxxx0_SAFC 0x37 // Perform AFC adjustment of the frequency synthesizer
#define CCxxx0_SWOR 0x38 // Start automatic RX polling sequence (Wake-on-Radio)
#define CCxxx0_SPWD 0x39 // Enter power down mode when CSn goes high.
#define CCxxx0_SFRX 0x3A // Flush the RX FIFO buffer.
#define CCxxx0_SFTX 0x3B // Flush the TX FIFO buffer.
#define CCxxx0_SWORRST 0x3C // Reset real time clock.
#define CCxxx0_SNOP 0x3D // No operation. May be used to pad strobe commands to two
// INT8Us for simpler software.

#define CCxxx0_PARTNUM 0x30
#define CCxxx0_VERSION 0x31
#define CCxxx0_FREQEST 0x32
#define CCxxx0_LQI 0x33
#define CCxxx0_RSSI 0x34
#define CCxxx0_MARCSTATE 0x35
#define CCxxx0_WORTIME1 0x36
#define CCxxx0_WORTIME0 0x37
#define CCxxx0_PKTSTATUS 0x38
#define CCxxx0_VCO_VC_DAC 0x39
#define CCxxx0_TXBYTES 0x3A
#define CCxxx0_RXBYTES 0x3B

#define CCxxx0_PATABLE 0x3E

#define CCxxx0_TXFIFO 0x3F
#define CCxxx0_RXFIFO 0x3F


// RF_SETTINGS is a data structure which contains all relevant CCxxx0 registers
typedef struct {
INT8U iocfg0; // GDO0 Output Pin Configuration
INT8U fifothr; // RX FIFO and TX FIFO Thresholds
INT8U pktctrl0; // Packet Automation Control
INT8U fsctrl1; // Frequency Synthesizer Control
INT8U freq2; // Frequency Control Word, High Byte
INT8U freq1; // Frequency Control Word, Middle Byte
INT8U freq0; // Frequency Control Word, Low Byte
INT8U mdmcfg4; // Modem Configuration
INT8U mdmcfg3; // Modem Configuration
INT8U mdmcfg2; // Modem Configuration
INT8U deviatn; // Modem Deviation Setting
INT8U mcsm0; // Main Radio Control State Machine Configuration
INT8U foccfg; // Frequency Offset Compensation Configuration
INT8U worctrl; // Wake On Radio Control
INT8U fscal3; // Frequency Synthesizer Calibration
INT8U fscal2; // Frequency Synthesizer Calibration
INT8U fscal1; // Frequency Synthesizer Calibration
INT8U fscal0; // Frequency Synthesizer Calibration
INT8U test2; // Various Test Settings
INT8U test1; // Various Test Settings
INT8U test0; // Various Test Settings
} RF_SETTINGS;

#endif


cc1101.c

#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/sched.h>

#include <linux/kernel.h> /* printk() */
#include <linux/slab.h> /* kmalloc() */
#include <linux/fs.h> /* everything... */
#include <linux/errno.h> /* error codes */
#include <linux/types.h> /* size_t */
#include <linux/proc_fs.h>
#include <linux/fcntl.h> /* O_ACCMODE */
#include <linux/seq_file.h>
#include <linux/cdev.h>
#include <linux/poll.h>

#include <linux/irq.h>
#include <asm/irq.h>
#include <linux/interrupt.h>
#include <asm/uaccess.h>
#include <mach/regs-gpio.h>
#include <mach/hardware.h>
#include <linux/platform_device.h>

#include <asm/system.h> /* cli(), *_flags */
#include <asm/uaccess.h> /* copy_*_user */

#include "cc1101.h"

int nop_tmp;

typedef struct cc1101_spi_pin_t
{
unsigned long spi_SCK; /* GPF4 = SCK 输出 */
unsigned long spi_MOSI; /* GPF3 = MOSI 输出 */
unsigned long spi_GDO2; /* GPG6 = GD02 输出 */
unsigned long spi_MISO; /* GPG5 = MISO 输入 */
unsigned long spi_CSN; /* GPG11 = CSN 输出 */
unsigned long spi_GDO0; /* GPG7 = GD01 输入类型 */
}cc1101_spi_pin;

typedef struct cc1101_spi_pintype_t
{
unsigned long spi_SCK; /* GPF4 = SCK 输出 */
unsigned long spi_MOSI; /* GPF3 = MOSI 输出 */
unsigned long spi_GDO2; /* GPG6 = GD02 输出 */
unsigned long spi_MISO; /* GPG5 = MISO 输入 */
unsigned long spi_CSN; /* GPG11 = CSN 输出 */
unsigned long spi_GDO0; /* GPG7 = GD01 下降沿中断类型 */
}cc1101_spi_pintype;

static cc1101_spi_pin cc1101_pin = {
S3C2410_GPF4,
S3C2410_GPF3,
S3C2410_GPG6,
S3C2410_GPG5,
S3C2410_GPG11,
S3C2410_GPG7,
};

static cc1101_spi_pintype cc1101_pintype = {
S3C2410_GPF4_OUTP,
S3C2410_GPF3_OUTP,
S3C2410_GPG6_OUTP,
S3C2410_GPG5_INP,
S3C2410_GPG11_OUTP,
S3C2410_GPG7_EINT15,
};

#define MISO s3c2410_gpio_getpin(cc1101_pin.spi_MISO)
#define GDO0 s3c2410_gpio_getpin(cc1101_pin.spi_GDO0)

#define MOSI_H s3c2410_gpio_setpin(cc1101_pin.spi_MOSI, 1)
#define MOSI_L s3c2410_gpio_setpin(cc1101_pin.spi_MOSI, 0)

#define CSN_H s3c2410_gpio_setpin(cc1101_pin.spi_CSN, 1)
#define CSN_L s3c2410_gpio_setpin(cc1101_pin.spi_CSN, 0)

#define SCK_H s3c2410_gpio_setpin(cc1101_pin.spi_SCK, 1)
#define SCK_L s3c2410_gpio_setpin(cc1101_pin.spi_SCK, 0)

#define GDO2_H s3c2410_gpio_setpin(cc1101_pin.spi_GDO2, 1)
#define GDO2_L s3c2410_gpio_setpin(cc1101_pin.spi_GDO2, 0)

void soc_init(void)
{
s3c2410_gpio_cfgpin(cc1101_pin.spi_SCK, cc1101_pintype.spi_SCK);
s3c2410_gpio_cfgpin(cc1101_pin.spi_MOSI, cc1101_pintype.spi_MOSI);
s3c2410_gpio_cfgpin(cc1101_pin.spi_GDO2, cc1101_pintype.spi_GDO2);
s3c2410_gpio_cfgpin(cc1101_pin.spi_MISO, cc1101_pintype.spi_MISO);
s3c2410_gpio_cfgpin(cc1101_pin.spi_CSN, cc1101_pintype.spi_CSN);
s3c2410_gpio_cfgpin(cc1101_pin.spi_GDO0, cc1101_pintype.spi_GDO0);

printk("cc1101 set pin ok!");
}

static void cc1101_delay(unsigned int s)
{
unsigned int i;
for(i = 0; i < s; i++);
for(i = 0; i < s; i++);
}

void halWait(INT16U timeout)
{
int i;
do
{
for(i = 0; i < 150; i++)
nop_tmp++;
}
while (--timeout);
}


void SpiInit(void)
{
CSN_L;
SCK_L;
CSN_H;
}

/*****************************************************************************************/
//鍑芥暟鍚嶏細CpuInit()
//杈撳叆锛氭棤
//杈撳嚭锛氭棤
//鍔熻兘鎻忚堪锛歋PI鍒濆鍖栫▼搴?
/*****************************************************************************************/
void CpuInit(void)
{
soc_init();
SpiInit();
cc1101_delay(1500000);
}


//*****************************************************************************************
//鍑芥暟鍚嶏細SpisendByte(INT8U dat)
//杈撳叆锛氬彂閫佺殑鏁版嵁
//杈撳嚭锛氭棤
//鍔熻兘鎻忚堪锛歋PI鍙戦€佷竴涓瓧鑺?
//*****************************************************************************************
INT8U SpiTxRxByte(INT8U dat)
{
INT8U i,temp;
temp = 0;

SCK_L;
for(i=0; i<8; i++)
{
if(dat & 0x80)
{
MOSI_H;
}
else MOSI_L;
dat <<= 1;

SCK_H;
nop_tmp++;
nop_tmp++;
nop_tmp++;
nop_tmp++;
nop_tmp++;
nop_tmp++;

temp <<= 1;
if(MISO)temp++;
SCK_L;
nop_tmp++;
nop_tmp++;
nop_tmp++;
nop_tmp++;
nop_tmp++;
nop_tmp++;
}
return temp;
}

//*****************************************************************************************
//鍑芥暟鍚嶏細void RESET_CC1100(void)
//杈撳叆锛氭棤
//杈撳嚭锛氭棤
//鍔熻兘鎻忚堪锛氬浣岰C1100
//*****************************************************************************************
void RESET_CC1100(void)
{
CSN_L;
while (MISO);

SpiTxRxByte(CCxxx0_SRES); //鍐欏叆澶嶄綅鍛戒护

while (MISO);

CSN_H;
}

//*****************************************************************************************
//鍑芥暟鍚嶏細void POWER_UP_RESET_CC1100(void)
//杈撳叆锛氭棤
//杈撳嚭锛氭棤
//鍔熻兘鎻忚堪锛氫笂鐢靛浣岰C1100
//*****************************************************************************************
void POWER_UP_RESET_CC1100(void)
{
CSN_H;
halWait(10);
CSN_L;
halWait(10);
CSN_H;
halWait(410);
RESET_CC1100(); //澶嶄綅CC1100
}

//*****************************************************************************************
//鍑芥暟鍚嶏細void halSpiWriteReg(INT8U addr, INT8U value)
//杈撳叆锛氬湴鍧€鍜岄厤缃瓧
//杈撳嚭锛氭棤
//鍔熻兘鎻忚堪锛歋PI鍐欏瘎瀛樺櫒
//*****************************************************************************************
void halSpiWriteReg(INT8U addr, INT8U value)
{
CSN_L;
while (MISO);
SpiTxRxByte(addr); //鍐欏湴鍧€
SpiTxRxByte(value); //鍐欏叆閰嶇疆
CSN_H;
}

//*****************************************************************************************
//鍑芥暟鍚嶏細void halSpiWriteBurstReg(INT8U addr, INT8U *buffer, INT8U count)
//杈撳叆锛氬湴鍧€锛屽啓鍏ョ紦鍐插尯锛屽啓鍏ヤ釜鏁?
//杈撳嚭锛氭棤
//鍔熻兘鎻忚堪锛歋PI杩炵画鍐欓厤缃瘎瀛樺櫒
//*****************************************************************************************
void halSpiWriteBurstReg(INT8U addr, INT8U *buffer, INT8U count)
{
INT8U i, temp;
temp = addr | WRITE_BURST;
CSN_L;
while (MISO);
SpiTxRxByte(temp);
for (i = 0; i < count; i++)
{
SpiTxRxByte(buffer[i]);
}
CSN_H;
}

//*****************************************************************************************
//鍑芥暟鍚嶏細void halSpiStrobe(INT8U strobe)
//杈撳叆锛氬懡浠?
//杈撳嚭锛氭棤
//鍔熻兘鎻忚堪锛歋PI鍐欏懡浠?
//*****************************************************************************************
void halSpiStrobe(INT8U strobe)
{
CSN_L;
while (MISO);
SpiTxRxByte(strobe); //鍐欏叆鍛戒护
CSN_H;
}

//*****************************************************************************************
//鍑芥暟鍚嶏細INT8U halSpiReadReg(INT8U addr)
//杈撳叆锛氬湴鍧€
//杈撳嚭锛氳瀵勫瓨鍣ㄧ殑閰嶇疆瀛?
//鍔熻兘鎻忚堪锛歋PI璇诲瘎瀛樺櫒
//*****************************************************************************************
INT8U halSpiReadReg(INT8U addr)
{
INT8U temp, value;
temp = addr|READ_SINGLE;//璇诲瘎瀛樺櫒鍛戒护
CSN_L;
while (MISO);
SpiTxRxByte(temp);
value = SpiTxRxByte(0);
CSN_H;
return value;
}


//*****************************************************************************************
//鍑芥暟鍚嶏細void halSpiReadBurstReg(INT8U addr, INT8U *buffer, INT8U count)
//杈撳叆锛氬湴鍧€锛岃鍑烘暟鎹悗鏆傚瓨鐨勭紦鍐插尯锛岃鍑洪厤缃釜鏁?
//杈撳嚭锛氭棤
//鍔熻兘鎻忚堪锛歋PI杩炵画鍐欓厤缃瘎瀛樺櫒
//*****************************************************************************************
void halSpiReadBurstReg(INT8U addr, INT8U *buffer, INT8U count)
{
INT8U i,temp;
temp = addr | READ_BURST; //鍐欏叆瑕佽鐨勯厤缃瘎瀛樺櫒鍦板潃鍜岃鍛戒护
CSN_L;
while (MISO);
SpiTxRxByte(temp);
for (i = 0; i < count; i++)
{
buffer[i] = SpiTxRxByte(0);
}
CSN_H;
}


//*****************************************************************************************
//鍑芥暟鍚嶏細INT8U halSpiReadReg(INT8U addr)
//杈撳叆锛氬湴鍧€
//杈撳嚭锛氳鐘舵€佸瘎瀛樺櫒褰撳墠鍊?
//鍔熻兘鎻忚堪锛歋PI璇荤姸鎬佸瘎瀛樺櫒
//*****************************************************************************************
INT8U halSpiReadStatus(INT8U addr)
{
INT8U value,temp;
temp = addr | READ_BURST; //鍐欏叆瑕佽鐨勭姸鎬佸瘎瀛樺櫒鐨勫湴鍧€鍚屾椂鍐欏叆璇诲懡浠?
CSN_L;
while (MISO);
SpiTxRxByte(temp);
value = SpiTxRxByte(0);
CSN_H;
return value;
}
//*****************************************************************************************
//鍑芥暟鍚嶏細void halRfWriteRfSettings(RF_SETTINGS *pRfSettings)
//杈撳叆锛氭棤
//杈撳嚭锛氭棤
//鍔熻兘鎻忚堪锛氶厤缃瓹C1100鐨勫瘎瀛樺櫒
//*****************************************************************************************
void halRfWriteRfSettings(void)
{
//*******************************此rfSettings配置来自Smart RF***********************************//
//*******************************Low data rate----2.4kbaud**************************************//
//*******************************Carrier frequency-----433.99MHz********************************//
RF_SETTINGS rfSettings = {
0x06, // IOCFG0 GDO0 Output Pin Configuration
0x47, // FIFOTHR RX FIFO and TX FIFO Thresholds
0x05, // PKTCTRL0 Packet Automation Control
0x06, // FSCTRL1 Frequency Synthesizer Control
0x10, // FREQ2 Frequency Control Word, High Byte
0xB1, // FREQ1 Frequency Control Word, Middle Byte
0x3B, // FREQ0 Frequency Control Word, Low Byte
0xF6, // MDMCFG4 Modem Configuration
0x83, // MDMCFG3 Modem Configuration
0x13, // MDMCFG2 Modem Configuration
0x15, // DEVIATN Modem Deviation Setting
0x18, // MCSM0 Main Radio Control State Machine Configuration
0x16, // FOCCFG Frequency Offset Compensation Configuration
0xFB, // WORCTRL Wake On Radio Control
0xE9, // FSCAL3 Frequency Synthesizer Calibration
0x2A, // FSCAL2 Frequency Synthesizer Calibration
0x00, // FSCAL1 Frequency Synthesizer Calibration
0x1F, // FSCAL0 Frequency Synthesizer Calibration
0x81, // TEST2 Various Test Settings
0x35, // TEST1 Various Test Settings
0x09, // TEST0 Various Test Settings
};

halSpiWriteReg(CCxxx0_IOCFG0, rfSettings.iocfg0);
halSpiWriteReg(CCxxx0_FIFOTHR, rfSettings.fifothr);
halSpiWriteReg(CCxxx0_PKTCTRL0, rfSettings.pktctrl0);
halSpiWriteReg(CCxxx0_FSCTRL1, rfSettings.fsctrl1);
halSpiWriteReg(CCxxx0_FREQ2, rfSettings.freq2);
halSpiWriteReg(CCxxx0_FREQ1, rfSettings.freq1);
halSpiWriteReg(CCxxx0_FREQ0, rfSettings.freq0);
halSpiWriteReg(CCxxx0_MDMCFG4, rfSettings.mdmcfg4);
halSpiWriteReg(CCxxx0_MDMCFG3, rfSettings.mdmcfg3);
halSpiWriteReg(CCxxx0_MDMCFG2, rfSettings.mdmcfg2);
halSpiWriteReg(CCxxx0_DEVIATN, rfSettings.deviatn);
halSpiWriteReg(CCxxx0_MCSM0, rfSettings.mcsm0);
halSpiWriteReg(CCxxx0_FOCCFG, rfSettings.foccfg);
halSpiWriteReg(CCxxx0_WORCTRL, rfSettings.worctrl);
halSpiWriteReg(CCxxx0_FSCAL3, rfSettings.fscal3);
halSpiWriteReg(CCxxx0_FSCAL2, rfSettings.fscal2);
halSpiWriteReg(CCxxx0_FSCAL1, rfSettings.fscal1);
halSpiWriteReg(CCxxx0_FSCAL0, rfSettings.fscal0);
halSpiWriteReg(CCxxx0_TEST2, rfSettings.test2);
halSpiWriteReg(CCxxx0_TEST1, rfSettings.test1);
halSpiWriteReg(CCxxx0_TEST0, rfSettings.test0);
}
//*****************************************************************************************
//鍑芥暟鍚嶏細void halRfSendPacket(INT8U *txBuffer, INT8U size)
//杈撳叆锛氬彂閫佺殑缂撳啿鍖猴紝鍙戦€佹暟鎹釜鏁?
//杈撳嚭锛氭棤
//鍔熻兘鎻忚堪锛欳C1100鍙戦€佷竴缁勬暟鎹?
//*****************************************************************************************

void halRfSendPacket(INT8U *txBuffer, INT8U size)
{
halSpiStrobe(CCxxx0_SIDLE);
halSpiStrobe(CCxxx0_STX); //杩涘叆鍙戦€佹ā寮忓彂閫佹暟鎹?
halSpiWriteReg(CCxxx0_TXFIFO, size);
halSpiWriteBurstReg(CCxxx0_TXFIFO, txBuffer, size); //鍐欏叆瑕佸彂閫佺殑鏁版嵁

// Wait for GDO0 to be set -> sync transmitted
while (!GDO0);
// Wait for GDO0 to be cleared -> end of packet
while (GDO0);
halSpiStrobe(CCxxx0_SFTX);
halSpiStrobe(CCxxx0_SIDLE);
halSpiStrobe(CCxxx0_SRX);
}

//************************************************************************************************//
//********************************* 鏃犱腑鏂帴鏀跺嚱鏁? ************************************//
//***********************************************************************************************//
INT8U halRfReceivePacket(INT8U *rxBuffer, INT8U *length)
{
INT8U status[2];
INT8U packetLength;
INT8U i=(*length)*4; // 鍏蜂綋澶氬皯瑕佹牴鎹甦atarate鍜宭ength鏉ュ喅瀹?

halSpiStrobe(CCxxx0_SIDLE);
halSpiStrobe(CCxxx0_SRX); //杩涘叆鎺ユ敹鐘舵€?
cc1101_delay(20);
while (GDO0)
{
cc1101_delay(20);
--i;
if(i<1)
return 0;
}
if ((halSpiReadStatus(CCxxx0_RXBYTES) & BYTES_IN_RXFIFO)) //濡傛灉鎺ョ殑瀛楄妭鏁颁笉涓?
{
packetLength = halSpiReadReg(CCxxx0_RXFIFO);//璇诲嚭绗竴涓瓧鑺傦紝姝ゅ瓧鑺備负璇ュ抚鏁版嵁闀垮害
if (packetLength <= *length) //濡傛灉鎵€瑕佺殑鏈夋晥鏁版嵁闀垮害灏忎簬绛変簬鎺ユ敹鍒扮殑鏁版嵁鍖呯殑闀垮害
{
halSpiReadBurstReg(CCxxx0_RXFIFO, rxBuffer, packetLength); //璇诲嚭鎵€鏈夋帴鏀跺埌鐨勬暟鎹?
*length = packetLength; //鎶婃帴鏀舵暟鎹暱搴︾殑淇敼涓哄綋鍓嶆暟鎹殑闀垮害

// Read the 2 appended status bytes (status[0] = RSSI, status[1] = LQI)
halSpiReadBurstReg(CCxxx0_RXFIFO, status, 2); //璇诲嚭CRC鏍¢獙浣?
halSpiStrobe(CCxxx0_SFRX); //娓呮礂鎺ユ敹缂撳啿鍖?
return (status[1] & CRC_OK); //濡傛灉鏍¢獙鎴愬姛杩斿洖鎺ユ敹鎴愬姛
}
else
{
*length = packetLength;
halSpiStrobe(CCxxx0_SFRX); //娓呮礂鎺ユ敹缂撳啿鍖?
return 0;
}
}
else
return 0;
}

static int Init_CC1100(void)
{
INT8U PaTabel[8] = {0x60 ,0x60 ,0x60 ,0x60 ,0x60 ,0x60 ,0x60 ,0x60};

CpuInit();
POWER_UP_RESET_CC1100();
halRfWriteRfSettings();
halSpiWriteBurstReg(CCxxx0_PATABLE, PaTabel, 8);

return 0;
}

/****************************************************************************************/
#define CC1101_BUFLEN 16
static dev_t cc1101_dev_no = 0;
static volatile int rcv_flag;

/* cc1101设备 */
typedef struct tag_cc1101_dev_t
{
struct cdev cdev;
unsigned char cc1101_buf[CC1101_BUFLEN];
wait_queue_head_t read_wait;
}cc1101_dev_t;

static cc1101_dev_t cc1101_dev;

struct rcv_irq_desc {
int irq;
int pin;
int pin_setting;
char *name;
};

static irqreturn_t cc1101_rcv_interrupt(int irq, void *dev_id)
{
INT8U count = CC1101_BUFLEN;
int ret;
printk("cc1101 handle interrupt!\n");

ret = halRfReceivePacket(cc1101_dev.cc1101_buf, &count);
if (0 != ret)
{
/*
printk("cc1101 receiving .... start\n");
printk("cc1101 receiving .... end\n");
printk("cc1101 receiving %d bytes(s):%s\n", count, cc1101_dev.cc1101_buf);
*/

rcv_flag = 1;
wake_up_interruptible(&cc1101_dev.read_wait);
}

return IRQ_RETVAL(IRQ_HANDLED);
}

static struct rcv_irq_desc cc1101_rcv_irq = {
IRQ_EINT15,
S3C2410_GPG7,
S3C2410_GPG7_EINT15,
"spi_GDO0"};


/*文件打开函数*/
int cc1101_open(struct inode *inode, struct file *filp)
{
int ret;

ret = request_irq(cc1101_rcv_irq.irq, cc1101_rcv_interrupt, IRQ_TYPE_EDGE_FALLING,
cc1101_rcv_irq.name, (void *)&cc1101_rcv_irq);
if (ret)
{
printk("request_irq error!\n");
return -EBUSY;
}

return 0;
}

/*写函数*/
static ssize_t cc1101_write(struct file *filp, const char __user *buf, size_t size, loff_t *ppos)
{
unsigned int count = size;
int ret = 0;

/*分析和获取有效的写长度*/
if (CC1101_BUFLEN != size)
{
printk("cc1101 write wrong len:%d\n", size);
return -ENOMEM;
}

/*用户空间->内核空间*/
if (copy_from_user(cc1101_dev.cc1101_buf, buf, count))
ret = - EFAULT;
else
{
ret = count;
//printk("kernel-space: cc1101 written %d bytes(s):%s\n", count, cc1101_dev.cc1101_buf);
}

/* CC1101硬件发送 */
//printk("kernel-space: cc1101 sending .... start\n");
halRfSendPacket(cc1101_dev.cc1101_buf, count);
//printk("kernel-space: cc1101 sending .... end\n");

return ret;
}

/* 读函数 */
static ssize_t cc1101_waitqueue_read(struct file *filp, char __user *buf, size_t size, loff_t *ppos)
{
unsigned int count = size;
int ret = 0;
DECLARE_WAITQUEUE(wait, current);

if (CC1101_BUFLEN != count)
{
printk("kernel-space: cc1101 read wrong len:%d\n", count);
return -ENOMEM;
}

add_wait_queue(&cc1101_dev.read_wait, &wait);

if (0 == rcv_flag)
{
if (filp->f_flags & O_NONBLOCK)
{
ret = -EAGAIN;
goto out;
}

__set_current_state(TASK_INTERRUPTIBLE);
schedule();
if (signal_pending(current))
{
ret = - ERESTARTSYS;
goto out;
}
}

/* 内核空间->用户空间 */
copy_to_user(buf, cc1101_dev.cc1101_buf, count);

ret = count;

out:
remove_wait_queue(&cc1101_dev.read_wait, &wait);

set_current_state(TASK_RUNNING);
rcv_flag = 0;
return ret;
}

/* poll函数 */
static unsigned int cc1101_poll(struct file *filp, poll_table *wait)
{
unsigned int mask = 0;

poll_wait(filp, &cc1101_dev.read_wait, wait);

if (1 == rcv_flag)
{
mask |= POLLIN | POLLRDNORM;
printk("kernel-space: cc1101_poll rcv_flag = 1!\n");
}

return mask;
}

static int cc1101_close(struct inode *inode, struct file *file)
{
free_irq(cc1101_rcv_irq.irq, (void *)&cc1101_rcv_irq);

printk("kernel-space: cc1101_close!\n");
return 0;
}

struct file_operations cc1101_fops =
{
.owner = THIS_MODULE,
.open = cc1101_open,
.release = cc1101_close,
.write = cc1101_write,
.read = cc1101_waitqueue_read,
.poll = cc1101_poll,
};

/*初始化并注册cdev*/
static int cc1101_setup_cdev(void)
{
int err;

cdev_init(&cc1101_dev.cdev, &cc1101_fops);

cc1101_dev.cdev.owner = THIS_MODULE;
cc1101_dev.cdev.ops = &cc1101_fops;

err = cdev_add(&cc1101_dev.cdev, cc1101_dev_no, 1);
if (err)
printk("cc1101 cc1101_setup_cdev error!");

return err;
}

static int __init cc1101_init(void)
{
int ret = 0;

ret = Init_CC1100();
if (0 != ret)
goto init_fail;

ret = alloc_chrdev_region(&cc1101_dev_no, 0, 1, "cc1101");
if (0 < ret)
goto init_fail;

init_waitqueue_head(&cc1101_dev.read_wait);

ret = cc1101_setup_cdev();
if (0 != ret)
{
unregister_chrdev_region(cc1101_dev_no, 1);
goto init_fail;
}

printk("cc1101 init success!\n");
return 0;

init_fail:
printk("cc1101 init failed!\n");

return ret;
}

static void __exit cc1101_exit(void)
{
unregister_chrdev_region(cc1101_dev_no, 1);
cdev_del(&cc1101_dev.cdev);
printk("cc1101 exit success!\n");
}

module_init(cc1101_init);
module_exit(cc1101_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("forsakening-hdu");
MODULE_DESCRIPTION("cc1101 control for EmbedSky TQ2440 Board");