TDA4 R5F核的GPIO外部中断基于SDK7.1的实现

目前在TDA4 main domain R5F1_0上需要开发两个GPIO脚的外部输入中断,这两个pin脚的ball name分别为 AB23 和 AG27,但是TI的AUTOSAR MCAL不支持ICU相关的配置,因此只能手动去调用sciclient接口去配置中断和GPIO。

目前不知道怎么配,PDK包中的example也没有相关的功能,目前有许多疑问:
疑问1: AB23和AG27这两个引脚都是一个bank的,TI的手册上写着同一个bank的引脚,中断回调都是同一个入口,如果要做成两个单独的中断回调函数是否不支持?
疑问2:pin脚和中断号以及中断回调函数如何用sciclient接口进行捆绑?
疑问3:外部输入的边沿的捕获触发条件如何设置?
疑问4:能不能用这两个引脚做个sample给我看看?

目前用的是CCS10.0的编译器,AUTOSAR操作系统(vector),SDK7.1

基于最新版ChatGPT4的回答,望采纳!!!有其他问题也可以询问我哦💕(最新版更智能,功能更加强大):
疑问1: 在TDA4 main domain R5F1_0上,如果AB23和AG27这两个引脚都是一个bank的,那么它们共用同一个中断入口。如果需要将它们做成两个单独的中断回调函数,则需要在中断服务程序中进行判断,以区分不同的中断来源。

疑问2: 要使用sciclient接口进行GPIO中断的配置,你需要先调用Sciclient_init函数进行初始化。然后,通过调用Sciclient_pmSetModuleState函数开启GPIO模块的电源和时钟,再通过调用Sciclient_pmSetResourceState函数使能引脚相应的GPIO资源。最后,调用GPIO_socGetInitCfg函数获取GPIO的默认配置,修改其中的相关参数,例如设置外部输入的边沿捕获触发条件等,最后调用GPIO_socSetInitCfg函数完成GPIO的初始化配置。

疑问3: 外部输入的边沿捕获触发条件可以通过设置GPIO的InterruptType或者EventDetect属性来实现。例如,如果需要在上升沿触发中断,则可以通过将InterruptType属性设置为GPIO_INT_TYPE_RISING_EDGE来实现。

疑问4: 可以通过以下代码片段初始化AB23和AG27两个引脚,并设置它们的中断回调函数:

#include <ti/drv/gpio/GPIO.h>
#include <ti/drv/sciclient/sciclient.h>

#define AB23_PIN_NUM (23)
#define AG27_PIN_NUM (27)
#define APP_GPIO_INTERRUPT_ID1 (10U)
#define APP_GPIO_INTERRUPT_ID2 (11U)

/* 中断回调函数 */
static void gpioCallbackFxn1(uintptr_t arg)
{
    /* 你的中断处理代码 */
}

static void gpioCallbackFxn2(uintptr_t arg)
{
    /* 你的中断处理代码 */
}

void gpioInterruptInit()
{
    int32_t retVal;
    GPIO_v0_HwAttrs gpioCfg;

    /* 初始化Sciclient */
    retVal = Sciclient_init(NULL);
    if (retVal != CSL_PASS) {
        /* 错误处理 */
    }

    /* 设置GPIO模块的电源和时钟 */
    retVal = Sciclient_pmSetModuleState(TISCI_DEV_GPIO0, TISCI_MSG_VALUE_DEVICE_SW_STATE_ON, SCICLIENT_SERVICE_WAIT_FOREVER);
    if (retVal != CSL_PASS) {
        /* 错误处理 */
    }

    /* 使能引脚相应的GPIO资源 */
    retVal = Sciclient_pmSetResourceState(TISCI_DEV_GPIO0, AB23_PIN_NUM, TISCI_MSG_VALUE_DEVICE_SW_STATE_ON, SCICLIENT_SERVICE_WAIT_FOREVER);
    if (retVal != CSL_PASS) {
        /* 错误处理 */
    }
    retVal = Sciclient_pmSetResourceState(TISCI_DEV_GPIO0, AG27_PIN_NUM, TISCI_MSG_VALUE_DEVICE_SW_STATE_ON, SCICLIENT_SERVICE_WAIT_FOREVER);
    if (retVal != CSL_PASS) {
        /* 错误处理 */
    }

    /* 获取GPIO的默认配置 */
    GPIO_socGetInitCfg(0, &gpioCfg);
    /* 修改相关参数 */
    gpioCfg.interruptCfg[APP_GPIO_INTERRUPT_ID1].intrNum = APP_GPIO_INTERRUPT_ID1;
    gpioCfg.interruptCfg[APP_GPIO_INTERRUPT_ID1].intcFxn = gpioCallbackFxn1;
    gpioCfg.interruptCfg[APP_GPIO_INTERRUPT_ID1].intcObj = NULL;
    gpioCfg.interruptCfg[APP_GPIO_INTERRUPT_ID1].eventType = GPIO_INTR_CFG_EVENT_RISING_EDGE;

    gpioCfg.interruptCfg[APP_GPIO_INTERRUPT_ID2].intrNum = APP_GPIO_INTERRUPT_ID2;
    gpioCfg.interruptCfg[APP_GPIO_INTERRUPT_ID2].intcFxn = gpioCallbackFxn2;
    gpioCfg.interruptCfg[APP_GPIO_INTERRUPT_ID2].intcObj = NULL;
    gpioCfg.interruptCfg[APP_GPIO_INTERRUPT_ID2].eventType = GPIO_INTR_CFG_EVENT_FALLING_EDGE;

    /* 初始化GPIO */
    retVal = GPIO_init(0, &gpioCfg);
    if (retVal != GPIO_RET_OK) {
        /* 错误处理 */
    }

    /* 配置AB23和AG27两个引脚,以捕获外部输入的中断信号 */
GPIO_setConfig(0, AB23_PIN_NUM, GPIO_CFG_INPUT | GPIO_CFG_IN_INT_RISING | GPIO_CFG_IN_INT_FALLING);
GPIO_setConfig(0, AG27_PIN_NUM, GPIO_CFG_INPUT | GPIO_CFG_IN_INT_RISING | GPIO_CFG_IN_INT_FALLING);

/* 使能GPIO中断 */
GPIO_enableInt(0, APP_GPIO_INTERRUPT_ID1);
GPIO_enableInt(0, APP_GPIO_INTERRUPT_ID2);
}

需要注意的是,在使用这段代码之前,你需要先在板子上连接AB23和AG27两个引脚,并将它们分别连接到外部输入的信号源。此外,还需要将APP_GPIO_INTERRUPT_ID1和APP_GPIO_INTERRUPT_ID2两个中断ID与相应的中断控制器进行绑定,来确保中断服务程序能够正确地响应这两个中断。

希望这些回答能够对你有所帮助。如果你还有其他问题或者疑惑,欢迎随时向我提问。

以芯片手册的为准。芯片手册应该是GPIO0_31。如有冲突,疑问,最好的解决思路是与芯片商进行线上沟通。

回答引用ChatGPT:
根据TDA4芯片的手册,R5F1_0域中的AB23引脚的编号应该是GPIO0_31,而不是GPIO0_23。因此,您在查找有关该引脚的信息时应该使用GPIO0_31。

同样地,AG27引脚的编号应该是GPIO0_58。请注意,芯片手册中的引脚编号通常以引脚所在的功能模块和引脚的物理位置来命名,因此在查找引脚信息时应该查看完整的引脚图表以获得正确的引脚编号。

该回答引用ChatGPT
针对上述问题,可以按照以下步骤进行实现:
1. 配置GPIO引脚
使用sciclient接口配置GPIO引脚,将AB23和AG27配置为输入模式,具体代码如下:
c
#include
#include
#define GPIO_INSTANCE_ID (0U)
#define GPIO_PIN_NUM (23U)
int32_t gpioInit(void)
{
int32_t ret = 0;
Sciclient_ConfigPrms_t config;
/* Initialize the SCI Client */
ret = Sciclient_configPrmsInit(&config);
if (ret != CSL_PASS)
{
return ret;
}
ret = Sciclient_init(&config);
if (ret != CSL_PASS)
{
return ret;
}
/* Enable GPIO */
ret = Sciclient_pmSetModuleState(TISCI_DEV_GPIO0, TISCI_MSG_VALUE_DEVICE_SW_STATE_ON, TISCI_MSG_FLAG_AOP, SCICLIENT_SERVICE_WAIT_FOREVER);
if (ret != CSL_PASS)
{
return ret;
}
/* Configure GPIO pin as input */
GPIO_v0_HwAttrs gpioCfg;
GPIO_socGetInitCfg(GPIO_INSTANCE_ID, &gpioCfg);
gpioCfg.baseAddr = CSL_GPIO0_BASE;
GPIO_socSetInitCfg(GPIO_INSTANCE_ID, &gpioCfg);
GPIO_init();
GPIO_setConfig(GPIO_INSTANCE_ID, GPIO_PIN_NUM, GPIO_CFG_INPUT);
return ret;
}

2. 配置中断
使用sciclient接口配置中断,将AB23和AG27对应的中断号配置为不同的中断,具体代码如下:
c
#include
#include
#define GPIO_INSTANCE_ID (0U)
#define GPIO_PIN_NUM (23U)
#define GPIO_INT_NUM (0U)
void gpioCallback(uintptr_t arg)
{
/* GPIO interrupt callback function */
}
int32_t gpioInterruptInit(void)
{
int32_t ret = 0;
Sciclient_ConfigPrms_t config;
/* Initialize the SCI Client */
ret = Sciclient_configPrmsInit(&config);
if (ret != CSL_PASS)
{
return ret;
}
ret = Sciclient_init(&config);
if (ret != CSL_PASS)
{
return ret;
}
/* Enable GPIO */
ret = Sciclient_pmSetModuleState(TISCI_DEV_GPIO0, TISCI_MSG_VALUE_DEVICE_SW_STATE_ON, TISCI_MSG_FLAG_AOP, SCICLIENT_SERVICE_WAIT_FOREVER);
if (ret != CSL_PASS)
{
return ret;
}
/* Configure GPIO pin as input */
GPIO_v0_HwAttrs gpioCfg;
GPIO_socGetInitCfg(GPIO_INSTANCE_ID, &gpioCfg);
gpioCfg.baseAddr = CSL_GPIO0_BASE;
GPIO_socSetInitCfg(GPIO_INSTANCE_ID, &gpioCfg);
GPIO_init();
GPIO_setConfig(GPIO_INSTANCE_ID, GPIO_PIN_NUM, GPIO_CFG_INPUT);
/* Configure GPIO interrupt */
OsalRegisterIntrParams_t intrPrms;
OsalInterruptRetCode_e osalRetVal;
HwiP_Handle hwiHandle;
Osal_RegisterInterrupt_initParams(&intrPrms);
intrPrms.corepacConfig.arg = (uintptr_t)NULL;
intrPrms.corepacConfig.name = "GPIO interrupt";
intrPrms.corepacConfig.isrRoutine = &gpioCallback;
intrPrms.corepacConfig.priority = 0U;
intrPrms.corepacConfig.corepacEventNum = GPIO_INT_NUM;
intrPrms.corepacConfig.intVecNum = CSL_GIC0_INTR_GPIO0_INTR_REQ_0 + GPIO_INT_NUM;
intrPrms.corepacConfig.triggerSensitivity = OSAL_ARM_GIC_TRIG_TYPE_EDGE;
osalRetVal = Osal_RegisterInterrupt(&intrPrms, &hwiHandle);
if (osalRetVal != OSAL_INT_SUCCESS)
{
return -1;
}
/* Enable GPIO interrupt */
GPIO_enableInt(GPIO_INSTANCE_ID, GPIO_PIN_NUM);
return ret;
}

3. 设置边沿触发条件
使用GPIO_setConfig函数设置GPIO的边沿触发条件,具体代码如下:
c
GPIO_setConfig(GPIO_INSTANCE_ID, GPIO_PIN_NUM, GPIO_CFG_INT_EDGE_BOTH | GPIO_CFG_INPUT);

4. 示例代码
下面是一个完整的示例代码,其中包含了GPIO引脚和中断的配置,以及中断回调函数的实现:
c
#include
#include
#include
#define GPIO_INSTANCE_ID (0U)
#define GPIO_PIN_NUM (23U)
#define GPIO_INT_NUM (0U)
void gpioCallback(uintptr_t arg)
{
/* GPIO interrupt callback function */
}
int32_t gpioInit(void)
{
int32_t ret = 0;
Sciclient_ConfigPrms_t config;
/* Initialize the SCI Client */
ret = Sciclient_configPrmsInit(&config);
if (ret != CSL_PASS)
{
return ret;
}
ret = Sciclient_init(&config);
if (ret != CSL_PASS)
{
return ret;
}
/* Enable GPIO */
ret = Sciclient_pmSetModuleState(TISCI_DEV_GPIO0, TISCI_MSG_VALUE_DEVICE_SW_STATE_ON, TISCI_MSG_FLAG_AOP, SCICLIENT_SERVICE_WAIT_FOREVER);
if (ret != CSL_PASS)
{
return ret;
}
/* Configure GPIO pin as input */
GPIO_v0_HwAttrs gpioCfg;
GPIO_socGetInitCfg(GPIO_INSTANCE_ID, &gpioCfg);
gpioCfg.baseAddr = CSL_GPIO0_BASE;
GPIO_socSetInitCfg(GPIO_INSTANCE_ID, &gpioCfg);
GPIO_init();
GPIO_setConfig(GPIO_INSTANCE_ID, GPIO_PIN_NUM, GPIO_CFG_INT_EDGE_BOTH | GPIO_CFG_INPUT);
/* Configure GPIO interrupt */
OsalRegisterIntrParams_t intrPrms;
OsalInterruptRetCode_e osalRetVal;
HwiP_Handle hwiHandle;
Osal_RegisterInterrupt_initParams(&intrPrms);
intrPrms.corepacConfig.arg = (uintptr_t)NULL;
intrPrms.corepacConfig.name = "GPIO interrupt";
intrPrms.corepacConfig.isrRoutine = &gpioCallback;
intrPrms.corepacConfig.priority = 0U;
intrPrms.corepacConfig.corepacEventNum = GPIO_INT_NUM;
intrPrms.corepacConfig.intVecNum = CSL_GIC0_INTR_GPIO0_INTR_REQ_0 + GPIO_INT_NUM;
intrPrms.corepacConfig.triggerSensitivity = OSAL_ARM_GIC_TRIG_TYPE_EDGE;
osalRetVal = Osal_RegisterInterrupt(&intrPrms, &hwiHandle);
if (osalRetVal != OSAL_INT_SUCCESS)
{
return -1;
}
/* Enable GPIO interrupt */
GPIO_enableInt(GPIO_INSTANCE_ID, GPIO_PIN_NUM);
return ret;
}
int main(void)
{
gpioInit();
while (1)
{
/* Main loop */
}
return 0;
}
不知道你这个问题是否已经解决, 如果还没有解决的话:

如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^

以下答案由GPT-3.5大模型与博主波罗歌共同编写:
针对您的问题,以下是具体的解答:

  1. 如果AB23和AG27这两个引脚都是同一个bank的,那么它们中断回调的入口是一样的。如果您想要实现不同的中断回调函数,您可以使用较短的触发时间,使引脚在一个时钟周期内转换两次来区分两个中断。

  2. 您可以通过以下sciclient接口代码将pin脚和中断号以及中断回调函数捆绑在一起:

#include <ti/drv/sciclient/sciclient.h>
#include <ti/drv/gpio/GPIO.h>
Void isr_callback(uintptr_t GPIO_in)
{
    // your code here for handling the interrupt
}
Int32_t setup_gpio_interrupt()
{
    /* setup GPIO driver instance */
    GPIO_init();

    /* use sciclient to allocate interrupt */
    Sciclient_ConfigPrms_t    config;
    Sciclient_configPrmsInit(&config, SYSTEM_CLOCK_FREQ);
    Sciclient_init(&config);

    Uint32_t GpioInterruptNumber = 111; // replace this with the desired interrupt number
    Uint32_t GpioPinNumber = 23; // replace this with the desired GPIO pin
    GPIO_CallbackFxn callbackFn = &isr_callback; // replace this with your own ISR

    /* allocate the interrupt */
    Sciclient_rmIrqSet(
        (Sciclient_RmIrqSetParams_t*)&gpio_irq_set_params,
        1);

    /* open the gpio interrupt */
    GPIO_Params gpioParams;
    GPIO_Params_init(&gpioParams);

    gpioParams.direction = GPIO_DIRECTION_INPUT;
    gpioParams.interruptType = GPIO_INTERRUPT_TYPE_EDGE_BOTH;
    gpioParams.callbackFxn = callbackFn;
    gpioParams.callbackContext = (uintptr_t) NULL;

    gpioHandle = GPIO_open(GpioPinNumber, &gpioParams);

    if (!gpioHandle)
    {
        return -1;
    }

    /* enable the interrupt */
    GPIO_enableInt(gpioHandle);

    return 0;
}
  1. 通过gpioParams.interruptType指定触发条件即可,其中 GPIO_INTERRUPT_TYPE_EDGE_RISING 表示上升沿触发,GPIO_INTERRUPT_TYPE_EDGE_FALLING 表示下降沿触发,GPIO_INTERRUPT_TYPE_EDGE_BOTH 表示上升沿和下降沿触发。

  2. 这两个引脚的示例代码如下:

#define GPIO1  AB23
#define GPIO2  AG27

static uint32_t gpioPinNum[] = {GPIO1, GPIO2};
static uint32_t gpioIntNum[] = {61, 62}; // replace with the desired interrupt number

Void isr_callback1(uintptr_t GPIO_in)
{
    // your code here for handling the interrupt 1
}

Void isr_callback2(uintptr_t GPIO_in)
{
    // your code here for handling the interrupt 2
}

Int32_t setup_gpio_interrupts()
{
    /* setup GPIO driver instance */
    GPIO_init();

    /* use sciclient to allocate interrupt */
    Sciclient_ConfigPrms_t    config;
    Sciclient_configPrmsInit(&config, SYSTEM_CLOCK_FREQ);
    Sciclient_init(&config);

    GPIO_CallbackFxn callbackFn[] = {&isr_callback1, &isr_callback2};

    /* allocate the interrupts */
    int i;
    for (i = 0; i < 2; i++)
    {
        Sciclient_rmIrqSetInput((Sciclient_RmIrqSetParams_t*)&gpio_irq_set_params[i], 1, &gpioIntNum[i], 1);
    }

    /* open the gpio interrupts */
    GPIO_Params gpioParams;
    GPIO_Params_init(&gpioParams);

    int handleNum = 0;
    for (i = 0; i < 2; i++)
    {
        gpioParams.direction = GPIO_DIRECTION_INPUT;
        gpioParams.interruptType = GPIO_INTERRUPT_TYPE_EDGE_BOTH;
        gpioParams.callbackFxn = callbackFn[i];
        gpioParams.callbackContext = (uintptr_t) NULL;

        GPIO_Handle gpioHandle;

        gpioHandle = GPIO_open(gpioPinNum[i], &gpioParams);

        if (gpioHandle == NULL)
        {
            return -1;
        }

        GPIO_enableInt(gpioHandle);
        handleNum++;
    }

    return 0;
}

如果我的回答解决了您的问题,请采纳!