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.

AM5728: GPIO control from DSP

Part Number: AM5728

Hi ,

I am in 5728 through ipc and dsp communication, and let dsp control gpio.

I am using a custom board.

My code is based on TI's ex02_messageq and gpio_led_blink.

The following is my core code,

/*
 *  ======== Server.c ========
 *
 */

/* this define must precede inclusion of any xdc header file */
#define Registry_CURDESC Test__Desc
#define MODULE_NAME "Server"

/* xdctools header files */
#include <xdc/std.h>
#include <xdc/runtime/Assert.h>
#include <xdc/runtime/Diags.h>
#include <xdc/runtime/Log.h>
#include <xdc/runtime/Registry.h>

//C include
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <stdint.h>

/* package header files */
#include <ti/ipc/MessageQ.h>
#include <ti/ipc/MultiProc.h>

#include <ti/sysbios/BIOS.h>
#include <ti/sysbios/knl/Task.h>

/* local header files */
#include "../shared/AppCommon.h"

/* module header file */
#include "Server.h"

/* GPIO header file */
#include <ti/drv/gpio/GPIO.h>
#include <ti/drv/gpio/soc/GPIO_v1.h>

#include <ti/csl/src/ip/gpio/V1/gpio_v2.h>
#include <ti/drv/gpio/src/GPIO_osal.h>

#define NUM_PORTS           (8u)
#define NUM_PINS_PER_PORT    (32u)
#define CALLBACK_INDEX_NOT_CONFIGURED (0xFFu)

/* Macro to extract GPIO pin number from the gpio pin configuration */
#define GPIO_GET_PIN_NUM(gpioConfig)  (((gpioConfig) & GPIO_CFG_PIN_NUM_MASK) >> \
		GPIO_CFG_PIN_NUM_SHIFT)

/* Macro to extract GPIO port number from the gpio pin configuration */
#define GPIO_GET_PORT_NUM(gpioConfig) (((gpioConfig) & GPIO_CFG_PORT_NUM_MASK) \
		>> GPIO_CFG_PORT_NUM_SHIFT)

/** \brief Mask for all pins of single gpio port */
#define GPIO_PIN_MASK_ALL           (0xFFFFFFFFU)


typedef struct GPIO_PortCallbackInfo_s {
	/* The port's 8 corresponding user defined pinId indices */
	uint8_t pinIndex[NUM_PINS_PER_PORT];
} GPIO_PortCallbackInfo;

/* Table of callbacks per port. */
GPIO_PortCallbackInfo gpioCallbackInfo[NUM_PORTS];

uint32_t portHwiCreatedBitMask = 0;

volatile bool initCalled = false;

void GPIO_setConfig_v1(uint32_t index, GPIO_PinConfig pinConfig);
void GPIO_v1_hwiFxn(uintptr_t portIdx);
inline uint32_t getPinNumber(uint32_t x);
void GPIO_init_v1(void);
void GPIO_write_v1(uint32_t index, uint32_t value);
uint8_t getGpioIntIndex(GPIO_PinConfig pinConfig);

/* module structure */
typedef struct {
    UInt16              hostProcId;         // host processor id
    MessageQ_Handle     slaveQue;           // created locally
} Server_Module;

App_Msg *           msg;

/* private data */
Registry_Desc               Registry_CURDESC;
static Server_Module        Module;

char *liatest = "0000";
/*
 *  ======== Server_init ========
 */
Void Server_init(Void)
{

    Registry_Result result;

    /* register with xdc.runtime to get a diags mask */
    result = Registry_addModule(&Registry_CURDESC, MODULE_NAME);
    Assert_isTrue(result == Registry_SUCCESS, (Assert_Id)NULL);

    /* initialize module object state */
    Module.hostProcId = MultiProc_getId("HOST");

	GPIO_init_v1();

}
/*
 *  ======== Server_create ========
 */
Int Server_create()
{
    Int                 status = 0;
    MessageQ_Params     msgqParams;
    char                msgqName[32];

    /* enable some log events */
    Diags_setMask(MODULE_NAME"+EXF");

    /* create local message queue (inbound messages) */
    MessageQ_Params_init(&msgqParams);
    sprintf(msgqName, App_SlaveMsgQueName, MultiProc_getName(MultiProc_self()));
    Module.slaveQue = MessageQ_create(msgqName, &msgqParams);

    if (Module.slaveQue == NULL) {
        status = -1;
        goto leave;
    }

    Log_print0(Diags_INFO,"Server_create: server is ready");

leave:
    Log_print1(Diags_EXIT, "<-- Server_create: %d", (IArg)status);
    return (status);
}
/*
 *  ======== Server_exec ========
 */
Int Server_exec()
{
    Int                 status;
    Bool                running = TRUE;
    MessageQ_QueueId    queId;
	int 				flg = 0;

    Log_print0(Diags_ENTRY | Diags_INFO, "--> Server_exec:");

    while (running) {

        /* wait for inbound message */
        status = MessageQ_get(Module.slaveQue, (MessageQ_Msg *)&msg,
            MessageQ_FOREVER);

        if (status < 0) {
            goto leave;
        }

#if 1
		if(strstr(msg->lia,"host") == NULL)
			flg = 1;
		else
			flg = 2;

#endif

        if (msg->cmd == App_CMD_SHUTDOWN) {
            running = FALSE;
        }

        /* process the message */
        Log_print1(Diags_INFO, "Server_exec: processed cmd=0x%x", msg->cmd);

        /* send message back */
        queId = MessageQ_getReplyQueue(msg); /* type-cast not needed */

		if(flg == 1 ){
			GPIO_write_v1((AM572X_LED0),GPIO_PIN_VAL_HIGH);
        MessageQ_put(queId, (MessageQ_Msg)msg);
		}
		if(flg == 2){
			GPIO_write_v1((AM572X_LED0),GPIO_PIN_VAL_LOW);
        MessageQ_put(queId, (MessageQ_Msg)msg);
		}

		Task_sleep(1000);
    } /* while (running) */

leave:
    Log_print1(Diags_EXIT, "<-- Server_exec: %d", (IArg)status);
    return(status);
}

/*
 *  ======== Server_delete ========
 */

Int Server_delete()
{
    Int         status;

    Log_print0(Diags_ENTRY, "--> Server_delete:");

    /* delete the video message queue */
    status = MessageQ_delete(&Module.slaveQue);

    if (status < 0) {
        goto leave;
    }

leave:
    if (status < 0) {
        Log_error1("Server_finish: error=0x%x", (IArg)status);
    }

    /* disable log events */
    Log_print1(Diags_EXIT, "<-- Server_delete: %d", (IArg)status);
    Diags_setMask(MODULE_NAME"-EXF");

    return(status);
}

/*
 *  ======== Server_exit ========
 */
Void Server_exit(Void)
{
    /*
     * Note that there isn't a Registry_removeModule() yet:
     *     https://bugs.eclipse.org/bugs/show_bug.cgi?id=315448
     *
     * ... but this is where we'd call it.
     */
}

void GPIO_init_v1(void)
{
	uint32_t i, j;
	uint32_t portCfgDone[NUM_PORTS] = {0U,0U,0U,0U,0U,0U,0U,0U};
	uint32_t pinConfig;
	GPIO_v1_HwAttrs *hwAttrs = NULL;
	uint32_t portNum;

	portHwiCreatedBitMask = 0;

	/* Initialize all entries with 'not configured' key */
	for (i = 0; i < NUM_PORTS; i++) {
		for (j = 0; j < NUM_PINS_PER_PORT; j++) {
			gpioCallbackInfo[i].pinIndex[j] = CALLBACK_INDEX_NOT_CONFIGURED;
		}
	}

	    /* Perform GPIO Reset and Module Enable only once for port */
	    for(i = 0; i < GPIO_v1_config.numberOfPinConfigs; i++)
		{   
			pinConfig = GPIO_v1_config.pinConfigs[i];
			if ((pinConfig & GPIO_DO_NOT_CONFIG) !=
					GPIO_DO_NOT_CONFIG)
			{
				portNum   = GPIO_GET_PORT_NUM(pinConfig);
				if ((portNum > 0U) && (portNum <= NUM_PORTS))
				{
					hwAttrs = (GPIO_v1_HwAttrs *)&GPIO_v1_hwAttrs[(portNum - 1U)];
					if(portCfgDone[portNum - 1] == 0U)
					{
						portCfgDone[portNum - 1] = 1U;

						/* Enable the GPIO module. */
						GPIOModuleEnable(hwAttrs->baseAddr);
					}
				}
			}
		}

		/* Configure pins and create Hwis per static array content */
		for (i = 0; i < GPIO_v1_config.numberOfPinConfigs; i++) {
			if ((GPIO_v1_config.pinConfigs[i] & GPIO_DO_NOT_CONFIG) !=
					GPIO_DO_NOT_CONFIG) {
				GPIO_setConfig_v1(i, GPIO_v1_config.pinConfigs[i]);
			}
		}

		initCalled = (bool)true;
}

void GPIO_write_v1(uint32_t index, uint32_t value)
{
	uint32_t key;
	GPIO_v1_HwAttrs *hwAttrs = NULL;
	uint32_t pinConfig;
	uint32_t pinNum;
	uint32_t portNum;

	/* Input parameter validation */
	GPIO_osalAssert(!((((bool)true) == initCalled) &&
				(index < GPIO_v1_config.numberOfPinConfigs)));

	pinConfig = GPIO_v1_config.pinConfigs[index];
	portNum   = GPIO_GET_PORT_NUM(pinConfig);
	pinNum    = GPIO_GET_PIN_NUM(pinConfig);

	if (((portNum > 0U) && (portNum <= NUM_PORTS)) &&
			(pinNum < NUM_PINS_PER_PORT))
	{
		hwAttrs   = (GPIO_v1_HwAttrs *)&GPIO_v1_hwAttrs[(portNum - 1U)];

		key = GPIO_osalHardwareIntDisable();

		/* Clear output from pinConfig */
		GPIO_v1_config.pinConfigs[index] &= ~GPIO_CFG_OUT_HIGH;

		if (value) {
			/* Set the pinConfig output bit to high */
			GPIO_v1_config.pinConfigs[index] |= GPIO_CFG_OUT_HIGH;

		}

		GPIOPinWrite(hwAttrs->baseAddr, pinNum, value);

		GPIO_osalHardwareIntRestore(key);
	}
	sprintf(msg->lia, " *** led%d %x %x 0x%x ",index,portNum,pinNum,hwAttrs->baseAddr);
}

void GPIO_setConfig_v1(uint32_t index, GPIO_PinConfig pinConfig)
{
	uint32_t   key;
	void *         hwiHandle;
	uint32_t       gpioBase;
	uint32_t       evtType;
	uint32_t       intrEvtType;
	/* there exist a variable with same name "gpioDirection". changed to solve the misra warning "MISRA.CT.UNIQUE.ID"*/
	uint8_t        gpio_Direction;
	uint8_t        gpioPin;
	uint8_t        gpioPortIntIdx;
	uint32_t       gpioPortIntBitMask;
	GPIO_PinConfig gpioPinConfig;
	OsalRegisterIntrParams_t interruptRegParams;
	uint32_t intrLineNum = GPIO_INT_LINE_1;
	uint32_t pinConfigVal;
	uint32_t portNum;
	uint32_t pinNum;
	GPIO_v1_HwAttrs *hwAttrs = NULL;
	uint8_t ret_flag = 0U;

	GPIO_osalAssert(!(index < GPIO_v1_config.numberOfPinConfigs));

	pinConfigVal = GPIO_v1_config.pinConfigs[index];
	portNum      = GPIO_GET_PORT_NUM(pinConfigVal);
	pinNum       = GPIO_GET_PIN_NUM(pinConfigVal);

	if (((portNum > 0U) && (portNum <= NUM_PORTS)) &&
			(pinNum < NUM_PINS_PER_PORT))
	{
		hwAttrs  = (GPIO_v1_HwAttrs *)&GPIO_v1_hwAttrs[(portNum - 1U)];

		gpioBase = hwAttrs->baseAddr;
		gpioPin  = (uint8_t)pinNum;

		if ((pinConfig & GPIO_CFG_IN_INT_ONLY) == 0) {
			/* Get GPIO configuration settings */

			/* Determine settings for GPIO as input or output */
			if (pinConfig & GPIO_CFG_INPUT) {
				gpio_Direction = (uint8_t)GPIO_DIR_INPUT;
			}
			else {
				gpio_Direction = (uint8_t)GPIO_DIR_OUTPUT;
			}

			/* Make atomic update */
			key = GPIO_osalHardwareIntDisable();

			/* Set output value */
			if (gpio_Direction == GPIO_DIR_OUTPUT) {
				GPIOPinWrite(gpioBase, (uint32_t)gpioPin,
						((pinConfig & GPIO_CFG_OUT_HIGH) ? 1U : 0U));
			}

			/* Configure the GPIO pin */
			GPIODirModeSet(gpioBase, (uint32_t)gpioPin, (uint32_t)gpio_Direction);

			/* Update pinConfig with the latest GPIO configuration */
			gpioPinConfig = GPIO_v1_config.pinConfigs[index];
			gpioPinConfig &= ~GPIO_CFG_IO_MASK;
			gpioPinConfig |= (pinConfig & GPIO_CFG_IO_MASK);
			GPIO_v1_config.pinConfigs[index] = gpioPinConfig;

			GPIO_osalHardwareIntRestore(key);
		}

		/* Set type of interrupt and then clear it */
		if (pinConfig & GPIO_CFG_INT_MASK) {
			/* Calculate the gpioInterruptVectors index for the GPIO pin */
			gpioPortIntIdx = getGpioIntIndex(pinConfigVal);
			gpioPortIntBitMask = (((uint32_t)1U) << (gpioPortIntIdx - 1u));

			/* If Hwi has not already been created, do so */
			if ((portHwiCreatedBitMask & gpioPortIntBitMask) == 0) {

				/* Initialize with defaults */
				Osal_RegisterInterrupt_initParams(&interruptRegParams);

				interruptRegParams.corepacConfig.isrRoutine  = (&GPIO_v1_hwiFxn);
				interruptRegParams.corepacConfig.arg         = (uintptr_t)(portNum);

				interruptRegParams.corepacConfig.priority = GPIO_v1_config.intPriority;
				interruptRegParams.corepacConfig.name=NULL;
				interruptRegParams.corepacConfig.corepacEventNum=hwAttrs->line1EventId; /* Event going in to CPU */
				interruptRegParams.corepacConfig.intVecNum=hwAttrs->line1IntNum; /* Host Interrupt vector */

				/* Register interrupts */
				GPIO_osalRegisterInterrupt(&interruptRegParams,&(hwiHandle));

				if (hwiHandle == NULL) {
					/* error constructing the Hwi for GPIO Port */
					ret_flag = 1U;
				}
			}

			if(ret_flag == 0u)
			{
				key = GPIO_osalHardwareIntDisable();

				/* Mark the Hwi as created */
				portHwiCreatedBitMask |= gpioPortIntBitMask;

				/* Map correct interrupt type event based on the flag */
				evtType = (pinConfig & GPIO_CFG_INT_MASK) >> GPIO_CFG_INT_LSB;

				switch(evtType)
				{
					case 1U:
						intrEvtType = GPIO_INT_TYPE_FALL_EDGE;
						break;
					case 2U:
						intrEvtType = GPIO_INT_TYPE_RISE_EDGE;
						break;
					case 3U:
						intrEvtType = GPIO_INT_TYPE_BOTH_EDGE;
						break;
					case 4U:
						intrEvtType = GPIO_INT_TYPE_LEVEL_LOW;
						break;
					case 5U:
						intrEvtType = GPIO_INT_TYPE_LEVEL_HIGH;
						break;
					default:
						/** If event type is none of the above then it will be forced to
						 * FALLING EDGE interrupt event type.
						 */
						intrEvtType = GPIO_INT_TYPE_FALL_EDGE;
						break;
				}

				GPIOIntTypeSet(hwAttrs->baseAddr, (uint32_t)gpioPin, intrEvtType);
				GPIOPinIntClear(hwAttrs->baseAddr, intrLineNum, (uint32_t)gpioPin);

				/* Update pinConfig with the latest interrupt configuration */
				gpioPinConfig = GPIO_v1_config.pinConfigs[index];
				gpioPinConfig &= ~(GPIO_CFG_INT_MASK);
				gpioPinConfig |= (pinConfig & GPIO_CFG_INT_MASK);
				GPIO_v1_config.pinConfigs[index] = gpioPinConfig;

				GPIO_osalHardwareIntRestore(key);
			}
		}
	}
	return;
}

void GPIO_v1_hwiFxn(uintptr_t portIdx)
{
	uint32_t          gpioPins;
	uint32_t          gpioBase;
	uint32_t          gpioIndex;
	uint32_t          bitNum;
	uint32_t portNo = (uint32_t)portIdx;
	GPIO_PortCallbackInfo *portCallbackInfo;
	GPIO_v1_HwAttrs *hwAttrs = (GPIO_v1_HwAttrs *)&GPIO_v1_hwAttrs[portNo - 1U];    
	uint32_t intrLineNum = GPIO_INT_LINE_1;
	portCallbackInfo = &gpioCallbackInfo[portNo -1U];
	gpioBase = hwAttrs->baseAddr;

	/* Find out which pins have their interrupt flags set */
	gpioPins = GPIORawIntStatus(gpioBase, intrLineNum, GPIO_PIN_MASK_ALL);

	/* Clear all the set bits at once */
	GPIOIntrClearMask(gpioBase, intrLineNum, gpioPins);

	/* Match each set bit to its corresponding callback function */
	while (gpioPins) {
		/* Gets the lowest order set bit number */
		bitNum = getPinNumber(gpioPins);
		gpioIndex = portCallbackInfo->pinIndex[bitNum];
		if (gpioIndex != CALLBACK_INDEX_NOT_CONFIGURED) {
			GPIO_v1_config.callbacks[gpioIndex]();
		}
		gpioPins &= ~(((uint32_t)1U) << bitNum);
	}
}

uint32_t getPinNumber(uint32_t x) {
	uint32_t idx = 0;

	while((x & 0x1U) == 0)
	{
		idx++;
		x = x>>1;
	}

	return idx;
}

uint8_t getGpioIntIndex(GPIO_PinConfig pinConfig) {

	return ((uint8_t)GPIO_GET_PORT_NUM(pinConfig));
}

GPIO_v1.h

I had a problem while controlling different gpio.

I tested a lot of gpio and found several problems.

1   I can control gpio4_4, 4_7, 7_7, 7_8, but can't control 4_10, 4_11, 7_10 pins with values greater than 10.

2   When I try to control gpio5 (5-2,5-3,5-10...), the following error occurs.

[ 1149.475766] ------------[ cut here ]------------
[ 1149.480422] WARNING: CPU: 1 PID: 27 at drivers/bus/omap_l3_noc.c:147 l3_interrupt_handler+0x25c/0x36c
 *** led0 5 10 0x4805b000   #### 0000 [ 1149.489689] 44000000.ocp:L3 Custom Error: MASTER DSP1_MDMA TARGET L4_PER1_P3 (Idle): Data Acces
s in User mode during Functional access
[ 1149.505131] Modules linked in:
 bc_example(O) xhci_plat_hcd xhci_hcd pru_rproc pruss_intc usbcore dwc3 pruss udc_core usb_common sha512_generic sha512_arm sha256_gener
ic rpmsg_proto sha1_generic sha1_arm_neon sha1_arm md5 cbc xfrm_user xfrm4_tunnel ipcomp xfrm_ipcomp esp4 ah4 af_key xfrm_algo rpmsg_rpc
 bluetooth snd_soc_simple_card snd_soc_simple_card_utils snd_soc_omap_hdmi_audio pvrsrvkm(O) omap_aes_driver ahci_platform libahci_platf
orm libahci pruss_soc_bus omap_sham libata omap_wdt scsi_mod ti_vpe ti_sc ti_csc ti_vpdma dwc3_omap rtc_omap extcon_palmas extcon_core r
tc_ds1307 rtc_palmas omap_des snd_soc_tlv320aic3x des_generic crypto_engine omap_remoteproc virtio_rpmsg_bus rpmsg_core remoteproc sch_f
q_codel uio_module_drv(O) uio gdbserverproxy(O) cryptodev(O) cmemk(O)
App_exec: message received, sending message 13
[ 1149.573758] CPU: 1 PID: 27 Comm: irq/23-l3-app-i Tainted: G        W  O    4.9.28-rt16-g786e64041b #23
[ 1149.573760] Hardware name: Generic DRA74X (Flattened Device Tree)
[ 1149.573764] Backtrace: 
[ 1149.573778] [<c020b2a8>] (dump_backtrace) from [<c020b564>] (show_stack+0x18/0x1c)
[ 1149.573783]  r7:00000009 r6:60000113 r5:00000000 r4:c1024a40
[ 1149.573793] [<c020b54c>] (show_stack) from [<c04d141c>] (dump_stack+0x8c/0xa0)
[ 1149.573801] [<c04d1390>] (dump_stack) from [<c022d880>] (__warn+0xec/0x104)
[ 1149.573806]  r7:00000009 r6:c0bbb9c4 r5:00000000 r4:ee625e20
[ 1149.573811] [<c022d794>] (__warn) from [<c022d8d8>] (warn_slowpath_fmt+0x40/0x48)
[ 1149.573817]  r9:00000006 r8:ee604b10 r7:c0bbbcb8 r6:00000000 r5:c0bbb8f0 r4:c0bbb994
[ 1149.573826] [<c022d89c>] (warn_slowpath_fmt) from [<c05013ec>] (l3_interrupt_handler+0x25c/0x36c)
[ 1149.573829]  r3:ee604980 r2:c0bbb994
[ 1149.573831]  r4:80080003
[ 1149.573840] [<c0501190>] (l3_interrupt_handler) from [<c0281c48>] (irq_forced_thread_fn+0x28/0x7c)
[ 1149.573846]  r10:c0281c20 r9:ee604e80 r8:ee609000 r7:00000001 r6:00000000 r5:ee609000
[ 1149.573848]  r4:ee604e80
[ 1149.573854] [<c0281c20>] (irq_forced_thread_fn) from [<c0281fb0>] (irq_thread+0x124/0x1f8)
[ 1149.573858]  r7:00000001 r6:00000000 r5:ee624000 r4:ee604ea4
[ 1149.573865] [<c0281e8c>] (irq_thread) from [<c024ad18>] (kthread+0x100/0x118)
[ 1149.573870]  r10:00000000 r9:00000000 r8:c0281e8c r7:ee604e80 r6:ee624000 r5:ee604ec0
[ 1149.573872]  r4:00000000
[ 1149.573880] [<c024ac18>] (kthread) from [<c0207c90>] (ret_from_fork+0x14/0x24)
[ 1149.573885]  r8:00000000 r7:00000000 r6:00000000 r5:c024ac18 r4:ee604ec0
[ 1149.573887] ---[ end trace 000000000000002c ]---

3   When I try to control these gpio 3-29, 4-29, 7-29..., the printed address is incorrect and the value is always changing.

Whether it is 3-29,4-29, the print value is 9514****.

What causes these problems to arise.

Is there a relationship between decimal and hexadecimal conversions?

Or dsp can not control some gpio.

Thanks!