Gpio problem


#1
adl_ioDefs_t MyGpioConfig1[2] =
{
		ADL_IO_GPIO | 9 | ADL_IO_DIR_OUT,
		ADL_IO_GPIO | 10 | ADL_IO_DIR_OUT,
	    // ADL_IO_GPIO | 20 | ADL_IO_DIR_IN 
};

MyGpioHandle1 = adl_ioSubscribe(2, MyGpioConfig1, 0, 0, 0);

Above is the code I use to subscribe to the gpio service. When I only use GPIO 9 and 10 (SL6087) I can perform an adl_ioWriteSingle function call.
However when I add the third line with GPIO 20 (Also adjusting the array size and the first parameter of the adl_ioSubscribe call) then open AT throws an exception when the execution reaches the same adl_ioWriteSingle call.

R7.45.0 is the firmware I’m using.

Can anyone tell me what the problem could be? Much appreciated :slight_smile:

EDIT: I’m figuring out the return value of the subscribe function
EDIT: adl_ioSubscribe returns 11. That’s odd, it is not ADL_RET_ERR_ALREADY_SUBSCRIBED, ADL_RET_ERR_FATAL or ADL_RET_ERR_PARAM.
EDIT: 11 matches ADL_RET_ERR_DONE (found in adl_gpio.h)
EDIT: From adl_gpio.h:

<b>#ADL_RET_ERR_DONE</b> refers to the field #adl_ioError_e for more informations.

I don’t know what field this is about, but it might be a clue?
EDIT: The adl_ioError_e refers to the 3 MSB bits of the elements of the adl_ioDefs_t array.
EDIT: the adl_ioError field is GPIO20 is ADL_IO_ERR, for GPIO10 it is ADL_IO_ERR_USED (Weird because this is the only adl_ioSubscribe call)


#2

That ARM exception looks like a memory violation. When you add the third record to the adl_ioDefs_t structure, do you change the size to 3 and the first argument of the adl_ioSubscribe function to 3, like so:

adl_ioDefs_t MyGpioConfig1[3] =
{
      ADL_IO_GPIO | 9 | ADL_IO_DIR_OUT,
      ADL_IO_GPIO | 10 | ADL_IO_DIR_OUT,
      ADL_IO_GPIO | 20 | ADL_IO_DIR_IN 
};

MyGpioHandle1 = adl_ioSubscribe(3, MyGpioConfig1, 0, 0, 0);

#3

Yes I do tom.

The code works fine for less than 3 array elements, but the adl_ioSubscribe does not return a valid handle, as I mentioned.

Edit: I believe these GPIO’s are multiplexed on the SL6087. Could this be my problem? Do I have to disable a UART, do I have to subscribe to the gpio service BEFORE opening the UART? I have no clue …

Edit: For example GPIO11 is multiplexed with UART1’s DCD. The error for this GPIO is ADL_IO_ERR_USED


#4

May I ignore the The adl_ioError_e field if the handle of the adl_ioSubscribe is valid? Because it still seems to contains an error after successful subscription.


#5

I think you have to disable UART 1 using AT+WMFM, and reset the module. Note that you will no longer have comms over UART 1, so make sure you have UART2 or USB enabled and connected.


#6

I started with a clean project. The only code being executed is:

s32 MyGpioHandle;

adl_ioDefs_t MyGpioConfig[1] =
{
		//ADL_IO_GPIO | 9 | ADL_IO_DIR_OUT, 	// OUT1
		//ADL_IO_GPIO | 10 | ADL_IO_DIR_OUT   // OUT2
		//ADL_IO_GPIO | 20 | ADL_IO_DIR_OUT 	// 3V3 Enable
		//ADL_IO_GPIO | 19 | ADL_IO_DIR_IN	// IN2

		//ADL_IO_GPIO | 24 | ADL_IO_DIR_OUT, 	// Niet gebruikt
	    ADL_IO_GPIO | 20 | ADL_IO_DIR_OUT	// LED
		//ADL_IO_GPIO | 11 | ADL_IO_DIR_IN, 	// IN1

	//	CHGONOFF ontbreekt!
	//	CHARGESTAT ontbreekt!
	//  Watchdog signaal ontbreekt!
};

void try()
{
	MyGpioHandle = adl_ioSubscribe(1, MyGpioConfig, 0, 0, 0);
    TRACE((28, "GpioHandle: %d", MyGpioHandle));

	switch (MyGpioConfig[0] & ADL_IO_ERR_MSK)
	{
		case ADL_IO_ERR:
			TRACE((28, "ADL_IO_ERR"));
			break;

		case ADL_IO_ERR_UNKWN:
			TRACE((28, "ADL_IO_ERR_UNKWN"));
			break;

		case ADL_IO_ERR_USED:
			TRACE((28, "ADL_IO_ERR_USED"));
			break;

		case ADL_IO_ERR_BADDIR:
			TRACE((28, "ADL_IO_ERR_BADDIR"));
			break;

		case ADL_IO_ERR_NIH:
			TRACE((28, "ADL_IO_ERR_NIH"));
			break;

		default:
			TRACE((28, "Default %u", (u32)(MyGpioConfig[0] | ADL_IO_ERR_MSK) >> 28));
			TRACE((28, "Default %d", (MyGpioConfig[0] | ADL_IO_ERR_MSK) >> 28));
			break;
	}

	switch (MyGpioConfig[0] | ADL_IO_GERR_MSK)
	{
	    case ADL_IO_GNOERR:
	    	TRACE((28, "GNOERR"));
	    	break;

	    case ADL_IO_GERR:
	    	TRACE((28, "GERR"));
	    	break;

		default:
			TRACE((28, "Default"));
			break;
	}

	adl_ioDefs_t gpio_to_write =  ADL_IO_GPIO | 21;
	s32 result = adl_ioWriteSingle(MyGpioHandle, &gpio_to_write, TRUE);

	switch (result)
	{
		case OK:
			TRACE((28, "OK"));
			break;

		case ADL_RET_ERR_UNKNOWN_HDL:
			TRACE((28, "UNKNOWN HANDLE"));
			break;

		case ADL_RET_ERR_PARAM:
			TRACE((28, "ERR PARAM"));
			break;

		case ADL_RET_ERR_BAD_STATE:
			TRACE((28, "BAD STATE"));
			break;

		default:
			TRACE((28, "writesingle: %d", result));
			break;
	}

}

These are the traces:


#7

You might want to try with newer firmware.

I’m using GPIO 20 as an input without issues with R7.2a, R7.44 and R7.46.

(R7.44.0 should be avoided as it is extremely buggy)


#8

You are subscribing to GPIO 20, but are then trying to write GPIO 21. Change your code to this:

s32 result = adl_ioWriteSingle(MyGpioHandle, &MyGpioConfig[0], TRUE);

#9

Ok, thank you for pointing that out Tom. When I fixed my code it worked, I got a valid handle ans I was able to set an output.

Next I tried to subscribe to the service for 4 GPIOS, this did not work:

adl_ioDefs_t MyGpioConfig[4] =
{
		ADL_IO_GPIO | 9 | ADL_IO_DIR_OUT, 	// OUT1
		ADL_IO_GPIO | 10 | ADL_IO_DIR_OUT,   // OUT2
		ADL_IO_GPIO | 20 | ADL_IO_DIR_OUT, 	// 3V3 Enable
		//ADL_IO_GPIO | 19 | ADL_IO_DIR_IN	// IN2

		//ADL_IO_GPIO | 24 | ADL_IO_DIR_OUT, 	// Niet gebruikt
	    ADL_IO_GPIO | 21 | ADL_IO_DIR_OUT	// LED
		//ADL_IO_GPIO | 11 | ADL_IO_DIR_IN, 	// IN1

	//	CHGONOFF ontbreekt!
	//	CHARGESTAT ontbreekt!
	//  Watchdog signaal ontbreekt!
};

void try()
{
	MyGpioHandle = adl_ioSubscribe(4, MyGpioConfig, 0, 0, 0);
    TRACE((28, "GpioHandle: %d", MyGpioHandle));

	switch (MyGpioConfig[0] & ADL_IO_ERR_MSK)
	{
		case ADL_IO_ERR:
			TRACE((28, "ADL_IO_ERR"));
			break;

		case ADL_IO_ERR_UNKWN:
			TRACE((28, "ADL_IO_ERR_UNKWN"));
			break;

		case ADL_IO_ERR_USED:
			TRACE((28, "ADL_IO_ERR_USED"));
			break;

		case ADL_IO_ERR_BADDIR:
			TRACE((28, "ADL_IO_ERR_BADDIR"));
			break;

		case ADL_IO_ERR_NIH:
			TRACE((28, "ADL_IO_ERR_NIH"));
			break;

		default:
			TRACE((28, "Default %u", (u32)(MyGpioConfig[0] | ADL_IO_ERR_MSK) >> 28));
			TRACE((28, "Default %d", (MyGpioConfig[0] | ADL_IO_ERR_MSK) >> 28));
			break;
	}

	switch (MyGpioConfig[0] | ADL_IO_GERR_MSK)
	{
	    case ADL_IO_GNOERR:
	    	TRACE((28, "GNOERR"));
	    	break;

	    case ADL_IO_GERR:
	    	TRACE((28, "GERR"));
	    	break;

		default:
			TRACE((28, "Default"));
			break;
	}

	adl_ioDefs_t gpio_to_write;
	s32 result;

	gpio_to_write =  ADL_IO_GPIO | 20;
	result = adl_ioWriteSingle(MyGpioHandle, &gpio_to_write, TRUE);

	gpio_to_write =  ADL_IO_GPIO | 21;
	result = adl_ioWriteSingle(MyGpioHandle, &gpio_to_write, TRUE);

	switch (result)
	{
		case OK:
			TRACE((28, "OK"));
			break;

		case ADL_RET_ERR_UNKNOWN_HDL:
			TRACE((28, "UNKNOWN HANDLE"));
			break;

		case ADL_RET_ERR_PARAM:
			TRACE((28, "ERR PARAM"));
			break;

		case ADL_RET_ERR_BAD_STATE:
			TRACE((28, "BAD STATE"));
			break;

		default:
			TRACE((28, "writesingle: %d", result));
			break;
	}

}

The modem keeps restarting

The problem seems to be with GPIO 9 and 10, note thhat tese are muxed with UART1 for the SL6087. DTR1 and RI1 more precisely.
Am I able to use the UART1, if I’m only using Rx and Tx, and these IO’s at the same time?


#10

I think not.


#11

Ah well, that’s settled then :slight_smile:


#12

On further thought, it might depend on what you mean by “use” UART1.

What I said applies to FCM and AT commands - it might not hold for direct access…