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.

[参考译文] 无法调用 GPIO 中断回调函数内的函数

Guru**** 2589300 points


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

https://e2e.ti.com/support/tools/code-composer-studio-group/ccs/f/code-composer-studio-forum/982968/not-able-to-call-a-function-inside-the-gpio-interrupt-callback-function

器件型号:CC3235S

尊敬的 TI:  

我在程序中遇到了一个问题、我要键入以调用 GPIO 中断回调函数内的函数。 每当 发生中断时、我可以在 GPIO 回调函数中设置/清除布尔标志。 但是、每当我尝试调用函数时、我的程序都会崩溃。

这个运行良好

*
==== gpiointerrupt.c ====
*/
#include 
#include 
#include 
#include 
#include "MFRC522.h"
/*驱动程序头文件*/
#include 
#include 

/*驱动程序配置*/
#include "ti_drivers_config.h"

SPI_Params spiParams;
字节状态;

volatile bNewInt = false;
字节 regVal = 0x7F;

静态空 SPI_Initializer (void);
静态空 RF_Detector (void);

uint8_t myKeyId[]={0、0xaa、0x20b、0xealizer (void)= 0x25);

/= 0xbb = 6、25'=*= 0x25
transferCompleteFxn ===
* SPI_TRANSFCTION ()的回调函数。
//
静态空 transferCompleteFxn (SPI_Handle handle、SPI_Transaction *事务)
{
SEM_POST (&masterSem);
}


静态空 SPI_Initializer ()
{
/*将 SPI 作为主器件打开(默认)*/
SPI_Params_init (&spiParams);
spiParams.dataSize = 8;
spiParams.frameFormat = SPI_POL1_PHA1;
spiParams.bitrate = 80000;//8MHz
spiParams.transferMode = SPI_MODE_CALLACK;
spiParams.transferCallbackFxn = transferCompleteFxn;
// spiParams.transferCallbackFxn =空;
spiParams.mode = SPI_MASTER;

masterSpi = SPI_open (CONFIG_SPI_0、&spiParams);

if (masterSpi ==空)
{
Display_printf (display、0、0、"初始化主器件 SPI\n"时出错);
while (1)
;
}
其他
{
display_printf (display、0、0、"Master SPI initialized");
}
}

/*
=== gpioButtonFxn0 ===
* CONFIG_GPIO_button_0上 GPIO 中断的回调函数。
*/
void gpioButtonFxn0 (uint_least8_t index)
{
/*清除 GPIO 中断并切换 LED *//
GPIO_DisableInt (RF_IRQ_PIN);
// GPIO_clearInt (RF_IRQ_PIN);
// RF_Detector ();
bNewInt = true;
}

/*
==== mainThread ====
//
void * mainThread (void * arg0)
{
/*调用驱动程序初始化函数*/
GPIO_init();
spi_init();

Display_Params 参数;
Display_Params_init (&params);

Display = Display_open (Display_Type_UART、params);
if (显示== NULL)
{
/*无法打开显示*/
while (1);
}
其他
{
display_printf (display、0、0、"Hello Serial!");
}

状态= SEM_INIT (&masterSem、0、0);
如果(状态!= 0)
{
while (1)
;
}

SPI_Initializer ();

MFRC522_PCD_Init();//重置 MFRC522或从断电状态唤醒*/

/*读取并打印 MFRC522版本(有效值0x91和0x92)*/
字节 readReg = PCD_ReadRegister (VersionReg);
Display_printf (display、0、0、"Ver:0x%x"、readReg);

/*启用中断*/
GPIO_enableInt (RF_IRQ_PIN);

/*
*允许... IRQ 被传播至 IRQ 引脚
*出于测试目的,传播 IdleIrq 和 loAlert
*
regVal = 0xA0;//Rx IRQ
PCD_WriteRegister (ComIEnReg、regVal);

bNewInt = false;//中断标志

在开始时执行{//清除一个 spoulous 中断
;
} while (bNewInt);
bNewInt = false;

display_printf (display、0、0、"end setup!");


/*配置 LED 和按钮引脚*
// GPIO_setConfig (CONFIG_GPIO_LED_0、GPIO_CFG_OUT_STD | GPIO_CFG_OUT_LOW);
// GPIO_setConfig (CONFIG_GPIO_BUT_0、GPIO_CFG_IN_PU | GPIO_CFG_IN_INT_INT_FALLING);

/*打开用户 LED *//
GPIO_write (CONFIG_GPIO_LED_0、CONFIG_GPIO_LED_ON);

/*安装按钮回调*/
GPIO_setCallback (RF_IRQ_PIN、gpioButtonFxn0);

while (1)
{
if (bNewInt)//新的读取中断
{
GPIO_DisableInt (RF_IRQ_PIN);
GPIO_clearInt (RF_IRQ_PIN);
Display_printf (display、0、0、" 中断******** ");
PICC_ReadCardSerial();//读取标签数据
Display_printf (display、0、0、"卡 UID:");//显示 PICC 的一些详细信息(即:标签/卡)
if (dump_Byte_array (uid.uidByte、uid.size))
{
display_printf (display、0、0、"ID 匹配!");
}
其他
{
display_printf (display、0、0、"ID 不匹配!");
}
clearInt();
PICC_Halta();
bNewInt = false;
GPIO_enableInt (RF_IRQ_PIN);
}
其他
{
display_printf (display、0、0、".");
}
activateRec();
usReg (500000);
}
//返回(空);
}

//
*向 MFRC522发送所需命令以激活接收
的函数*/
void WritateRec(){
PCD_WriteRegister (FIFODataleep、PICC_CMD_REQA);
PCD_WriteRegister (CommandReg、WriteTransive);
Bittle_FringRegister (PCD) 0x87);
}

//
*在中断服务例程之后清除挂起的中断位的函
数*/
void clearInt(){PCD_WriteRegister(ComIrqReg
,0x7F);
}//*


Helper 例程将字节数组作为十六进制值转储到 Serial。
//
extern bool dump_Byte_array (字节*缓冲区、字节 buffersize)
{
字节 I = 0;
对于(i = 0;i < buffersize;i++)
{
display_printf (display、0、0、"0x%x"、buffer[i]);
}

if (!strcmp ((char*) buffer、(char*) myKeyId))
{
返回1;
}
其他
{
返回0;
}

}

静态空 RF_Detector ()
{
GPIO_DisableInt (RF_IRQ_PIN);
GPIO_clearInt (RF_IRQ_PIN);
// Display_printf (display、0、0、" 中断******** ");
PICC_ReadCardSerial ();//读取标签数据
// Display_printf (display、0、0、"Card UID:");//显示 PICC 的一些详细信息(即:标签/卡)
if (dump_Byte_array (uid.uidByte、uid.size))
{
display_printf (display、0、0、"ID 匹配!");
}
其他
{
display_printf (display、0、0、"ID 不匹配!");
}
clearInt();
PICC_Halta();
bNewInt = false;
GPIO_enableInt (RF_IRQ_PIN);
}

但这也只是轮询。 我想停止主循环任务、每当中断发生时、它应该进入中断函数并执行 RFID 身份验证任务、一旦完成、就会返回主循环任务。

为此、我必须在中断发生时调用身份验证。 为此、我更改了 gpioButtonFxn0 。  

/*
=== gpioButtonFxn0 ===
* CONFIG_GPIO_button_0上 GPIO 中断的回调函数。
*/
void gpioButtonFxn0 (uint_least8_t index)
{
/*清除 GPIO 中断并切换 LED *//
GPIO_DisableInt (RF_IRQ_PIN);
// GPIO_clearInt (RF_IRQ_PIN);
RF_Detector ();
// bNewInt = true;
} 

但它会崩溃  

静态空 RF_Detector ()
{
GPIO_DisableInt (RF_IRQ_PIN);
GPIO_clearInt (RF_IRQ_PIN);
// Display_printf (display、0、0、" 中断******** ");
PICC_ReadCardSerial ();//读取标签数据
// Display_printf (display、0、0、"Card UID:");//显示 PICC 的一些详细信息(即:标签/卡)
if (dump_Byte_array (uid.uidByte、uid.size))
{
display_printf (display、0、0、"ID 匹配!");
}
其他
{
display_printf (display、0、0、"ID 不匹配!");
}
clearInt();
PICC_Halta();
bNewInt = false;
GPIO_enableInt (RF_IRQ_PIN);
} 

我的 RFID (MFRC522)通过 SPI 连接。  

为了找出崩溃的原因、我通过放置断点和调试代码来开始跟踪代码。 我发现它崩溃了  

SEM_WAIT (masterSem); 

SPI 传递函数的说明

extern uint8_t SPI_transfer (uint8_t add)
{
uint8_t returnData;

masterTxBuffer[0]= ADD;
// masterTxBuffer[1]= 0x01;

memset(((void*) masterRxBuffer,'\0',sizeof (masterRxBuffer));
TRANS.COUNT = 1;
TRANS.txBuf =(void*) masterTxBuffer;
TRANS.rxBuf =(void*) masterRxBuffer;

// GPIO_write (SPI_CS、0);

/*执行 SPI 传输*/
transferOK = SPI_transfer (masterSpi、&trans);
如果(!transferOK)
{
display_printf (display、0、0、"unsuccessful SPI transfer n");
while (1)
;
}
其他
{
/*等待传输完成*/
SEM_WAIT (&masterSem);
}

返回数据= masterRxBuffer[0];
// GPIO_WRITE (SPI_CS、1);
//睡眠(0.5);
返回返回数据;
}

请务必告诉我问题的位置、或者当 GPIO 中断回调函数出现标签检测中断时、如何执行 RFID 身份验证函数。

提前感谢。

Sarju Bhatnagar

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

    有些操作(例如 SEM_WAIT)无法在中断上下文中完成。

    由于您已经在使用操作系统,因此您可以使用高优先级线程(即优先级高于主线程),该线程将从中断上下文触发以运行 RF_Detetctor ()。

    例如、假设您使用全局 gpioSem (提前初始化、即在引导时初始化)。

    GpioTask()

      while (1)

      {

         SEM_WAIT (gpioSem);

         (笑声)

         RF_Detector ();

      }

    GpioIntHandler()

       SEM_post (gpioSem);