Part Number:LAUNCHXL-CC1310Other Parts Discussed in Thread:CC1310, CC1350, UNIFLASH
1. 板子上没有接iic设备时,调用iic接口会卡死,在调试模式是正常的,断开调试器,直接上电会卡死!rfPacketTx_CC1310_LAUNCHXL_nortos_ccs.zip
2.
/* * Copyright (c) 2019, Texas Instruments Incorporated * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright *notice, this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright *notice, this list of conditions and the following disclaimer in the *documentation and/or other materials provided with the distribution. * * * Neither the name of Texas Instruments Incorporated nor the names of *its contributors may be used to endorse or promote products derived *from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /***** Includes *****/ /* Standard C Libraries */ #include <stdlib.h> #include <unistd.h> /* TI Drivers */ #include <ti/drivers/rf/RF.h> #include <ti/drivers/PIN.h> #include <ti/drivers/I2C.h> #include <ti/drivers/pin/PINCC26XX.h> /* Driverlib Header files */ #include DeviceFamily_constructPath(driverlib/rf_prop_mailbox.h) /* Board Header files */ #include "Board.h" #include "CC1310_LAUNCHXL.h" #include "smartrf_settings/smartrf_settings.h" #include <ti/drivers/ADCBuf.h> #include <ti/drivers/adcbuf/ADCBufCC26XX.h> /***** Defines *****/ /* Do power measurement */ //#define POWER_MEASUREMENT #define M117_ENABLE 1 /* Packet TX Configuration */ #define PAYLOAD_LENGTH10 #ifdef POWER_MEASUREMENT #define PACKET_INTERVAL5 /* For power measurement set packet interval to 5s */ #else #define PACKET_INTERVAL500000 /* Set packet interval to 500000us or 500ms */ #endif /***** Prototypes *****/ /***** Variable declarations *****/ static RF_Object rfObject; static RF_Handle rfHandle; /* Pin driver handle */ static PIN_Handle ledPinHandle; static PIN_State ledPinState; static uint8_t packet[PAYLOAD_LENGTH]; static uint16_t seqNumber; /* * Application LED pin configuration table: *- All LEDs board LEDs are off. */ PIN_Config pinTable[] = {Board_PIN_LED1 | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX, #ifdef POWER_MEASUREMENT #if defined(Board_CC1350_LAUNCHXL)Board_DIO30_SWPWR | PIN_GPIO_OUTPUT_EN | PIN_GPIO_HIGH | PIN_PUSHPULL | PIN_DRVSTR_MAX, #endif #endifPIN_TERMINATE }; /***** Function definitions *****/ extern void iic_map(uint8_t sclPin,uint8_t sdaPin); void *mainThread(void *arg0) { #if M117_ENABLE// One-time init of I2C driverI2C_init();// initialize optional I2C bus parametersI2C_Params params;I2C_Params_init(¶ms);params.bitRate = I2C_100kHz;params.transferMode = I2C_MODE_BLOCKING;// Open I2C bus for usage//I2C_Handle i2cHandle = I2C_open(0, ¶ms);// Initialize slave address of transactionI2C_Transaction transaction = {0};transaction.slaveAddress = 0x44;I2C_Handle i2cHandle;I2C_Handle i2cHandle2;i2cHandle = I2C_open(0, ¶ms); #endifRF_Params rfParams;RF_Params_init(&rfParams);/* Open LED pins */ledPinHandle = PIN_open(&ledPinState, pinTable);if (ledPinHandle == NULL){while(1);} #ifdef POWER_MEASUREMENT #if defined(Board_CC1350_LAUNCHXL)/* Route out PA active pin to Board_DIO30_SWPWR */PINCC26XX_setMux(ledPinHandle, Board_DIO30_SWPWR, PINCC26XX_MUX_RFC_GPO1); #endif #endifRF_cmdPropTx.pktLen = PAYLOAD_LENGTH;RF_cmdPropTx.pPkt = packet;RF_cmdPropTx.startTrigger.triggerType = TRIG_NOW;/* Request access to the radio */ #if defined(DeviceFamily_CC26X0R2)rfHandle = RF_open(&rfObject, &RF_prop, (RF_RadioSetup*)&RF_cmdPropRadioSetup, &rfParams); #elserfHandle = RF_open(&rfObject, &RF_prop, (RF_RadioSetup*)&RF_cmdPropRadioDivSetup, &rfParams); #endif// DeviceFamily_CC26X0R2/* Set the frequency */RF_postCmd(rfHandle, (RF_Op*)&RF_cmdFs, RF_PriorityNormal, NULL, 0);while(1){ #if M117_ENABLE//i2cHandle = I2C_open(0, ¶ms);uint8_t iic_write_data[] = {0xCC,0x44};uint8_t iic_read_data[3];// Write to I2C slave devicetransaction.writeBuf = iic_write_data;transaction.writeCount = sizeof(iic_write_data);transaction.readCount = 0;I2C_transfer(i2cHandle, &transaction);//I2C_close(i2cHandle);usleep(10000);//i2cHandle = I2C_open(0, ¶ms);// Read from I2C slave devicetransaction.readBuf = iic_read_data;transaction.readCount = sizeof(iic_read_data);transaction.writeCount = 0;I2C_transfer(i2cHandle, &transaction);packet[2] = iic_read_data[0];packet[3] = iic_read_data[1];packet[4] = iic_read_data[2];//I2C_close(i2cHandle);//usleep(5000);//屏蔽这行会死机//I2C_cancel(i2cHandle); #if 1//iic_map(IOID_20,IOID_21);//i2cHandle = I2C_open(0, ¶ms);// Write to I2C slave devicetransaction.writeBuf = iic_write_data;transaction.writeCount = sizeof(iic_write_data);transaction.readCount = 0;I2C_transfer(i2cHandle, &transaction);//I2C_close(i2cHandle);usleep(10000);//i2cHandle = I2C_open(0, ¶ms);// Read from I2C slave devicetransaction.readBuf = iic_read_data;transaction.readCount = sizeof(iic_read_data);transaction.writeCount = 0;I2C_transfer(i2cHandle, &transaction);packet[2] = iic_read_data[0];packet[3] = iic_read_data[1];packet[4] = iic_read_data[2];//I2C_close(i2cHandle);//iic_map(IOID_4,IOID_5); #endif #if 0//iiC_map(IOID_20,IOID_21);i2cHandle2 = I2C_open(1, ¶ms);// Write to I2C slave devicetransaction.writeBuf = iic_write_data;transaction.writeCount = sizeof(iic_write_data);transaction.readCount = 0;I2C_transfer(i2cHandle2, &transaction);//I2C_close(i2cHandle2);usleep(10000);//i2cHandle2 = I2C_open(0, ¶ms);// Read from I2C slave devicetransaction.readBuf = iic_read_data;transaction.readCount = sizeof(iic_read_data);transaction.writeCount = 0;I2C_transfer(i2cHandle2, &transaction);packet[2] = iic_read_data[0];packet[3] = iic_read_data[1];packet[4] = iic_read_data[2];I2C_close(i2cHandle2);//iiC_map(IOID_4,IOID_5); #endif #endif/* Create packet with incrementing sequence number and random payload */packet[0] = (uint8_t)(seqNumber >> 8);packet[1] = (uint8_t)(seqNumber++);//uint8_t i;//for (i = 2; i < PAYLOAD_LENGTH; i++)//{//packet[i] = rand();//}packet[2] = 2;packet[3] = 3;packet[4] = 4;/* Send packet */RF_EventMask terminationReason = RF_runCmd(rfHandle, (RF_Op*)&RF_cmdPropTx,RF_PriorityNormal, NULL, 0);switch(terminationReason){case RF_EventLastCmdDone:// A stand-alone radio operation command or the last radio// operation command in a chain finished.break;case RF_EventCmdCancelled:// Command cancelled before it was started; it can be caused// by RF_cancelCmd() or RF_flushCmd().break;case RF_EventCmdAborted:// Abrupt command termination caused by RF_cancelCmd() or// RF_flushCmd().break;case RF_EventCmdStopped:// Graceful command termination caused by RF_cancelCmd() or// RF_flushCmd().break;default:// Uncaught error eventwhile(1);}uint32_t cmdStatus = ((volatile RF_Op*)&RF_cmdPropTx)->status;switch(cmdStatus){case PROP_DONE_OK:// Packet transmitted successfullybreak;case PROP_DONE_STOPPED:// received CMD_STOP while transmitting packet and finished// transmitting packetbreak;case PROP_DONE_ABORT:// Received CMD_ABORT while transmitting packetbreak;case PROP_ERROR_PAR:// Observed illegal parameterbreak;case PROP_ERROR_NO_SETUP:// Command sent without setting up the radio in a supported// mode using CMD_PROP_RADIO_SETUP or CMD_RADIO_SETUPbreak;case PROP_ERROR_NO_FS:// Command sent without the synthesizer being programmedbreak;case PROP_ERROR_TXUNF:// TX underflow observed during operationbreak;default:// Uncaught error event - these could come from the// pool of states defined in rf_mailbox.hwhile(1);} #ifndef POWER_MEASUREMENTPIN_setOutputValue(ledPinHandle, Board_PIN_LED1,!PIN_getOutputValue(Board_PIN_LED1)); #endif/* Power down the radio */RF_yield(rfHandle); #ifdef POWER_MEASUREMENT/* Sleep for PACKET_INTERVAL s */sleep(PACKET_INTERVAL); #else/* Sleep for PACKET_INTERVAL us */usleep(PACKET_INTERVAL); #endif} }
Alex Zhang:
您好,我需要一些时间来查看并测试您的代码,谢谢。
,
Alex Zhang:
您好,如果您这边外接iic设备呢,会出现什么现象
,
genyi liu:
就不会死机,正常工作
,
genyi liu:
通过led是否在闪烁,来判断是否被卡死
,
Alex Zhang:
现在我这边运行代码,led是闪烁状态。
,
genyi liu:
你是直接跑的是压缩包的工程吗。
,
Alex Zhang:
您好,您的代码中rfPacket.c文件中,第156行代码开始至189行,
#if M117_ENABLE//i2cHandle = I2C_open(0, ¶ms);uint8_t iic_write_data[] = {0xCC,0x44};uint8_t iic_read_data[3];// Write to I2C slave devicetransaction.writeBuf = iic_write_data;transaction.writeCount = sizeof(iic_write_data);transaction.readCount = 0;I2C_transfer(i2cHandle, &transaction);//I2C_close(i2cHandle);usleep(10000);//i2cHandle = I2C_open(0, ¶ms);// Read from I2C slave devicetransaction.readBuf = iic_read_data;transaction.readCount = sizeof(iic_read_data);transaction.writeCount = 0;I2C_transfer(i2cHandle, &transaction);packet[2] = iic_read_data[0];packet[3] = iic_read_data[1];packet[4] = iic_read_data[2];//I2C_close(i2cHandle);//usleep(5000);//ÆÁ±ÎÕâÐлáËÀ»ú//I2C_cancel(i2cHandle);#if 1//iic_map(IOID_20,IOID_21);//i2cHandle = I2C_open(0, ¶ms);// Write to I2C slave devicetransaction.writeBuf = iic_write_data;transaction.writeCount = sizeof(iic_write_data);transaction.readCount = 0;I2C_transfer(i2cHandle, &transaction);我看到您的#define M117_ENABLE 1 也是1
这段代码是什么意思,我不太明白。
,
Alex Zhang:
对的 跑的是您这边发的工程代码。
,
genyi liu:
表明那段代码也要执行,实际代码就是运行那段代码就出问题了。发现iic读失败后,继续读写就会错
,
Alex Zhang:
那您定义的 #if 1 可以解释一下吗
,
genyi liu:
就是使能,方便注释代码用的
,
Alex Zhang:
还有就是 我现在开发板状态是 闪烁,这个状态是 您这边说的 “锁死” 状态吗?
,
genyi liu:
压缩包应该有已经生成的固件,能否直接对比下,跟你生成的固件有没有区别
,
genyi liu:
闪烁就说明有正常发数据,程序的逻辑是每隔500ms 执行下iic,并发送数据出去。闪烁了说明程序在正常工作的
,
Alex Zhang:
genyi liu said:表明那段代码也要执行,实际代码就是运行那段代码就出问题了。发现iic读失败后,继续读写就会错
iic在读取数据时,如果某一个时序在通信过程中,没有接收到反馈或者是您这边说的没有接入外设,可能会使引脚电平跳变引起通信错误,导致iic通信死锁。
另外:
IIC的SDA和SCL在空闲时都处于高电平状态。
在实际使用中,IIC比较容易出现一个问题就是死锁,主要表现是:SCL为高,SDA一直为低。
在IIC主设备进行读写操作的过程中,主设备在开始信号后控制SCL生产8个时钟脉冲,然后拉低SCL信号为低电平,在这个时候,从设备输出应答信号,将SDA信号拉为低电平。
如果这个时候主设备异常复位,SCL就会被释放为高电平。此时,如果从设备没有复位,就会继续IIC的应答,将SDA一直拉为低电平,直到SCL变为低电平,才会结束应答信号。而对于IIC主设备来说,复位后检测SCL和SDA信号,如果发现SDA信号为低电平,则会认为IIC总线被占用,会一直等待SCL和SDA信号变为高电平。
这样,IIC主设备等待从设备释放SDA信号,而同时IIC从设备又在等待主设备将SCL信号拉低以释放应答信号,两者相互等待,IIC总线进入一种死锁状态。
同样的,当IIC进行读操作,从设备应答后输出数据,如果在这个时候IIC主设备异常复位而此时从设备输出的数据正好为0,也会导致IIC总线进入死锁状态。
在下面我为您这边解决死锁问题提供了一些思路:
1. 主设备在检测到SDA被拉低超过一段时间后,主动复位从设备从而使之释放SDA。这种方法的前提是主设备连接了从设备的复位引脚,主设备就可以控制从设备的复位管脚使之复位。
2. 主设备在检测到SDA被拉低超过一段时间后,推送9个Clock到时钟总线上,取走从设备的ACK位,从而使从设备释放SDA为高电平。
3. 在主从设备之间串联一个IIC缓冲器,该缓冲器可以自动检测死锁状态。当检测到死锁时会主动断开与主设备的连接,并发送9个Clock给从设备,等从设备释放SDA线后重新与主设备建立连接。
IIC的死锁问题无法从根本上避免,除了主设备的异常复位导致IIC死锁,从设备在正常通信过程中也有可能异常拉低SDA导致死锁。所以软件在设计时要考虑当死锁发生时能够从死锁中恢复,使得IIC通信可以继续进行。
,
Alex Zhang:
您好,我这边没有compare软件,是这样,我把生成的文件,给您上传,您这边下载之后可以自行比较。
我给您邮箱发过去,提供一个邮箱地址。
,
genyi liu:
1. 有没有测试那个压缩包的固件,并且出现iic卡死的现象?
2. 想先知道这个问题的根源是软件问题还是eclipse编译器问题?
,
genyi liu:
1. 好的,我的邮箱 liugenyi@jupiter-i.com
2. 麻烦你测试下压缩包的固件,这样好分析下问题根源
,
Alex Zhang:
是这样,判断问题的出现,您这边可以提供邮箱,你用自己的开发板去烧录我的out文件,然后看看是不是正常。
如果这样是正常的,那就是编译器的问题。
,
genyi liu:
out 要怎么烧录
,
Alex Zhang:
直接烧录就行了。uniflash软件打开,连接开发板,然后选择out文件,然后load。
1.
2.
,
genyi liu:
好的,那我去下载uniflash软件
,
Alex Zhang:
我给您发链接,直接下载
www.ti.com.cn/…/UNIFLASH
,
genyi liu:
好的,最好还是双向确认下,就是互相烧录下对方的固件,测试下比较好定位问题
,
genyi liu:
我对比下代码,固件是不一样的
,
genyi liu:
我用的CCS9.0软件
sdksimplelink_cc13x0_sdk_4_20_02_07
,
Alex Zhang:
那就是这边编译器出现问题了
我的ccs版本号: Version: 12.2.0.00009
跟sdk版本没太大关系
,
genyi liu:
用ccs12也编译下,错误还是出现了
,
genyi liu:
方便烧录下压缩包的文件,测试下bug是否能复现
,
genyi liu:
这个是没有接iic从设备,出现这个bug,要怎么恢复iic
,
genyi liu:
解决这个bug的一种方法,就是在读后面加延时就可以恢复正常,我觉得这有可能是潜在一个大bug.
出现bug的现象是有条件的,把中间的写操作去掉,bug就消失了
,
Alex Zhang:
genyi liu said:好的,最好还是双向确认下,就是互相烧录下对方的固件,测试下比较好定位问题
好的 我需要一些时间。
,
genyi liu:
用逻辑分析查看波形,卡死时,SCL 和SDA 都是高电平
,
Alex Zhang:
Alex Zhang said:
IIC的SDA和SCL在空闲时都处于高电平状态。
在实际使用中,IIC比较容易出现一个问题就是死锁,主要表现是:SCL为高,SDA一直为低。
在IIC主设备进行读写操作的过程中,主设备在开始信号后控制SCL生产8个时钟脉冲,然后拉低SCL信号为低电平,在这个时候,从设备输出应答信号,将SDA信号拉为低电平。
如果这个时候主设备异常复位,SCL就会被释放为高电平。此时,如果从设备没有复位,就会继续IIC的应答,将SDA一直拉为低电平,直到SCL变为低电平,才会结束应答信号。而对于IIC主设备来说,复位后检测SCL和SDA信号,如果发现SDA信号为低电平,则会认为IIC总线被占用,会一直等待SCL和SDA信号变为高电平。
这样,IIC主设备等待从设备释放SDA信号,而同时IIC从设备又在等待主设备将SCL信号拉低以释放应答信号,两者相互等待,IIC总线进入一种死锁状态。
同样的,当IIC进行读操作,从设备应答后输出数据,如果在这个时候IIC主设备异常复位而此时从设备输出的数据正好为0,也会导致IIC总线进入死锁状态。
在下面我为您这边解决死锁问题提供了一些思路:
1. 主设备在检测到SDA被拉低超过一段时间后,主动复位从设备从而使之释放SDA。这种方法的前提是主设备连接了从设备的复位引脚,主设备就可以控制从设备的复位管脚使之复位。
2. 主设备在检测到SDA被拉低超过一段时间后,推送9个Clock到时钟总线上,取走从设备的ACK位,从而使从设备释放SDA为高电平。
3. 在主从设备之间串联一个IIC缓冲器,该缓冲器可以自动检测死锁状态。当检测到死锁时会主动断开与主设备的连接,并发送9个Clock给从设备,等从设备释放SDA线后重新与主设备建立连接。
IIC的死锁问题无法从根本上避免,除了主设备的异常复位导致IIC死锁,从设备在正常通信过程中也有可能异常拉低SDA导致死锁。所以软件在设计时要考虑当死锁发生时能够从死锁中恢复,使得IIC通信可以继续进行。
还是我在上面提到的这个内容,您可以尝试使用上述思路解决问题。但是我仍然好奇我的编译器去编译您的工程进行烧录,为什么是正常的。
,
Alex Zhang:
您这边使用uniflash烧录out文件之后,什么现象?
,
Alex Zhang:
烧录我给您发的out文件是什么现象。
,
genyi liu:
还是卡死,灯也不闪烁。我那个有问题的固件还会闪一下,所以要确认下你用的是什么板子来测试的?
,
genyi liu:
这是我测试的主板
,
Alex Zhang:
我这边用的开发板跟您的是一样的。只不过是跳线帽我全部都插上了。
,
genyi liu:
那Green的灯正常闪烁?看起来是板子的问题
,
Alex Zhang:
您更换一个开发板试一下。
,
genyi liu:
更换了,问题还是一样出现!
,
Alex Zhang:
有点奇怪 我明天到公司再看一下。看看到底是哪个地方出现的问题。
,
genyi liu:
好的,期待你的结果
,
Alex Zhang:
您好,您这边使用您的开发板去跑sdk中的例程,有问题吗?
因为我看到我们的开发板同样是cc1310 pad但是仔细看版本是有区别的,我的是Rev 1.4.1 PG2.1 FW Rev 1.0
,
Alex Zhang:
我今天在我的这个版本的开发板烧录您编译生成的固件,测试效果,led绿灯闪烁。
,
genyi liu:
版本是rev A
,
Alex Zhang:
您好,很抱歉我这边没有revA版本的开发板所以没办法进行测试
您这边如果使用ti的例程烧录进您的revA版本的开发板中,可以实现示例代码中的实验现象吗?
,
genyi liu:
死机、死机,还是死机,开发CC1310有点难哦?
,
Alex Zhang:
您好,很抱歉我这边没有revA版本的开发板所以没办法进行测试
您这边如果使用ti的例程烧录进您的revA版本的开发板中,可以实现示例代码中的实验现象吗?