This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] RTOS/CC2650:Hwi/Swi上下文中的I2C总线使用问题

Guru**** 2515175 points
Other Parts Discussed in Thread: PCA9534A, Z-STACK, CC2650MODA, PCA9534

请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/wireless-connectivity/zigbee-thread-group/zigbee-and-thread/f/zigbee-thread-forum/581113/rtos-cc2650-i2c-bus-usage-in-hwi-swi-context-issue

部件号:CC2650
主题中讨论的其他部件: Z-stackPCA9534APCA9534

工具/软件:TI-RTOS

您好,

我使用的是一个自定义板,其中包含运行 Z-Stack 1.2 .2a (BIOS_6_41_02_41 ,driverlib cc26xxware_2_20_06_1.4829万, xdctools_3_30_06_67)的CC2650MODA模块。 我正在尝试与TI PCA9534A 8位I2C IO扩展器通信。 我的自定义PCA9534设备驱动程序使用 分别位于\tirtos_simplelink_2_11_01_09\packages\ti\boards\SensorTag\Interfaces的BSP-stack演示代码随附的传感器软件模块实现。sensor.h/.c只是 BSP_i2c.

只要我在任务上下文中调用通信函数,只要我尝试读取Hwi/Swi上下文readIOs()中的寄存器返回FALSE,通信就会完美运行。 在PCA9534初始化过程中动态配置Hwi。 连接到CC2650MODA模块的PCA8534中断引脚触发Hwi上下文中的寄存器读取。 一旦PCA9534驱动一个下降边缘 GPIO _InterruptISR(...)被调用,但 sensorReadReg (...) (它只是 bspI2cWriteRead()的包装程序,总是返回false。

我已经检查了I2C帧是否按应有的方式发送/接收,物理通信在I2C上显示了针对HWI/Swi的呼叫和任务上下文中的频繁呼叫的正确请求/响应帧。 因此,该问题必须位于TI-RTOS上下文中的某个位置

BTW.: IAR嵌入式工作台IDE ARM 7.70 v.2。

#include "BSP_i2c.h"
#include "sensor.h"
#include "Board.h"

#include <stddef.h>
#include <ti/SysBIOS/family/arm/m3/HWi.h>
#include <xDC/cfg/Gall.h>
#include <ti/drivers/pin/pinfi-----
--><x/!---->---

----------------------------------------------------------------------------------------------------------------------------------------------------------
* 常量
*----------------------------------
*/

/*从属地址*/
#define device_I2C_address 0x38

/*注册地址*/
#define REG_INPUT												0x00
#define REG_OUTPUT											0x01
#define REG_POL_INFTPUT								0x02
#define REG_CONFIGURATION								0x03	

#define REG_LENG_LENGTH											0x01	//注册长度

#define DEVICE_SELECT() bspI2cSelect(BSP_I2C_interface_0,device_I2C_address)
#define device_Deselect () bspI2cDeselect()

static uint8_t gIoConfig =0;
static uint8_t gInputRegVal = 0x00;
static bool gInit = false;


/*中断引脚*/
PIN_handle interruptPinHandle;
static PIN_State interState;
static PIN_Config interruptPinTable[]=
{
Board_InterrupT_In | PIN_INPUT_EN | PIN_NOPULL | PIN_IRQ_NEGEDGE | PIN_hysteresis,//扩展器中断引脚
PIN_TERMINATE /* TERMINATE列表*/
};/*

----------------------------------
* 本地函数
*----------------------------------
*/*----------------------------------


* 公共职能
*----------------------------------
*/

// hwi
void gPIO_InterruptISR(PIN_handle interruptPinHandle, PIN_ID interruptPinId){Swi_post(swiExpanderInterrupt);}//
	


Swi
void interruptStatusSwi(){uint8_t
	readVal =0;
	if(!readIOs(&readV))){ 
//我们返回:/ 返回;}
//一些要做的事情 }// 初始化 bool setIOCfg(eBoardID const config){ 布尔成功= false; uint8_t cfg; uint8_t buf; // ...一些初始化 ////// Hwi 配置 中断PinHandle = PIN_open(&interruptPinState, interpinTable); if (PinruptPin_Close){_Pin_PIN= 返回<pin } gInit =成功; 返回成功; } bool getIOCfg(uint8_t * const data){ IF(data == NULL){ 返回FALSE; } bool成功; device_select(); 成功= sensorReadReg(REG_input, data, reg_length); device_unecure(); *data =~(*data);// 输入返回1,输出返回0 ->反向更直观。 返回成功; } #pragma optime=none bool readIOs(uint8_t * data){ IF(data == NULL){ 返回FALSE; } bool成功;IF(!device_select=) 回写<rag_reg),reg_restorag_reg =返回<_reopen;<_reprox_re> *DATA =*DATA & gIoConfig; //掩码输出引脚。 返回成功; } 布尔writeIOs (uint8_t const data, uint8_t const mask){// 读取当前值 bool成功; uint8_t readReg; uint8_t reg eReg =数据;//读取当前输出寄存器device_select();reg 读数=读数=读数 掩码,&writeReg); writeReg ==~gIoConfig; //掩码输出所有输入 成功&= sensorWriteReg (REG_OUTPUT,&writeReg,REG_length); DEVICE_DESICA(); 返回成功 ;}
静态交换机在配置文件

/*=================中初始化 SWI配置================= */
var expanderInterruptParams = new Swi.Params();
expanderInterruptParams.arg0 = 1;
expanderInterruptParams.arg1 = 0;
expanderInterruptParams.priority = 1;
expanderInterruptParams.trigger = 0;
program.global.swiExpanderInterrupt = swi.create("&derruptStatusSwi", expanderInterruptParams); 

无论我在Hwi或Swi上下文中调用REGISTER READ,都返回FALSE。

我的问题是,我是否错过了Hwi/Swi的任何配置? 我是否需要考虑任何先决条件,以便我可以在中断上下文中使用I2C通信?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好,Robert:

    您是否尝试过增加堆栈大小?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    事实上,这也是我想到的第一点。 据我所知,Hwi/Swi使用自己的通用中断堆栈,但我找不到任何选项来专门增加IAR工作台链接器配置中的HWi堆栈大小。 所以我希望链接器.icf文件中的符号stack_size能够实现这个目的。 我将其从最初的1024字节增加到1536字节,但不幸的是我看到了同样的行为。  

    ICF文件:

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    //存储器大小
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    
    如果( isdefinedsymbol(CC2630)||
    Isdefinedsymbol(CC2650)
    {
    定义符号RAM_SIZE = 0x0.5万;// 20K
    定义符号flash_size = 0x2万;// 128K
    定义符号ROM_SIZE = 0x0001C000;// 115K
    }////////////////////////////////////////////////////////////////////////////////////////
    
    //缺省
    值否则
    {
    定义符号RAM_SIZE = 0x0.4万;// 16K
    定义符号flash_size = 0x2万;// 128K
    定义符号ROM_SIZE = 0x1.8万;// 96K
    }//////////////////////////////////////////////////////////////////////////////////////////////////
    
    
    //存储器定义
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // RAM
    //
    
    定义符号RAM_START = 0x2000万;
    
    IF ( isdefinedsymbol(CC2650)
    {
    IF ( isdefinedsymbol(ICALL_ram0_ADDR))
    {
    定义符号RAM_END =(ICALL_RAM0_ADDR-1);
    }
    其他//默认
    值{
    定义符号RAM_END = 0x20.0037万FF;
    }
    
    else // CC2650 PG1
    {
    IF ( isdefinedsymbol(ICALL_ram0_ADDR))
    {
    定义符号RAM_END =(ICALL_RAM0_ADDR-1);
    }
    其他//默认
    值{
    定义符号RAM_END = 0x20.0029万FF;
    }//////////////////////////////////////////////////////////////////////////////////////////////////////
    
    
    
    // Flash
    //
    
    定义符号flash_start = 0x0万000000;0万;
    
    IF ( isdefinedsymbol(ICALL_STACK0_ADDR)
    {
    定义SYMBOL FLASH_END =(ICALL_STACK0_ADDR-1);
    }
    ELSE //缺省
    值{
    定义符号FLASH_END = 0x0.0007万FFF;
    }//////////////////////////////////////////////////////////////////////////////////////////////////////
    
    
    //堆栈
    //
    
    定义符号stack_size = 0x600;
    定义符号stack_start = RAM_END + 1;
    定义符号STACK_END = stack_start - stack_size;
    定义对齐=8的块CSTACK,size = stack_size { section .stack };
    //
    定义符号stack_top = RAM_END + 1;
    导出符号STACK_TOP;
    
    //////////////////////////////////////////////////////////////////////////////////////
    //堆
    //
    
    定义符号heap_size = 0x800;
    使用对齐= 8定义块堆,大小=堆大小{}//////////////////////////////////////////////////////////////////////////////
    
    
    //闪存中断矢量表
    //
    
    定义符号INTVEC_NUM_entries =50+1;//第一个条目是栈位置
    定义符号INTVEC_SIZE = INTVEC_NUM_entries + 4;
    
    ///////////////////////////////////////////////////////////////////////////////////////
    //客户配置区域(CCA)
    //
    
    定义符号CCA_NUM_entries = 21;
    定义符号CCA_SIZE =(CCA_NUM_entries * 4);
    定义符号CCA_START =(FLASH_SIZE -1)- CCA_SIZE + 1;
    定义符号CCA_END =(flash_size-1);
    
    //////////////////////////////////////////////////////////////////////////////////////////////
    //内存区域
    /////////////////////////////////////////////////////////////////////////////////////////////////////////////
    
    使用size = 4G定义内存内存;
    
    定义区域RAM = MEM:[从RAM_START到RAM_END];
    定义区域闪存 = mem:[从flash_start到flash_end];
    定义区域flash_cca = mem:[从cca_start到cca_end];
    
    ////////////////////////////////////////////////////////
    //存储器放置
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    
    //在
    flash_cca的开头放置cca {只读部分.ccfg };
    保留 {只读部分.ccfg);//
    
    中断向量表
    位置在地址mem:flash_start {只读部分.intvec };
    保持 { readonly section .intvec };
    
    // RAM Vector Table
    Place at start of RAM { section .vtable_ram };
    
    // Stack
    Place at end of RAM { BLOCK CSTACK };
    
    //堆
    置入RAM {块堆};
    
    置入闪存{只读};
    置入RAM { readwrite };
    
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    //初始化
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    
    通过copy { readwrite }初始化;
    
    不要初始化
    {
    section .noinit,
    section .stack,
    };
    

    是否有任何方法可以查看IAR工作台中的Hwi堆栈使用情况? 遗憾的是,我只能从iCall任务,(我的)主任务和空闲任务监控静态创建的堆栈,但不能中断。

    据我所知,这是一个选择

    /* main()和hwi, Swi堆栈大小*/
    program.stack = 1024;  

    在app.cfg中,IAR编译器/链接器将忽略该选项。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好,Robert:

    我进一步研究了这个问题,似乎您不能在HWI或带TI-RTOS的SWI中进行阻塞函数调用(如此i2c驱动程序所做的那样),您只能在任务上下文中进行。

    如果您仍然需要某种具有中断上下文的通知,我建议将其发布到此SWI (或HWI)中的任务信号库。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    感谢Jason的澄清。 我同时在内核用户指南中找到了描述SWI非阻塞限制的文档。 我将遵循您的建议,使用由hwi例程发布的信号控制的任务。

    巴西

    罗伯特