Correct syntax/method for setting IOCON bits

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Correct syntax/method for setting IOCON bits

953 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by deevee on Thu Sep 26 14:55:02 MST 2013
Evening - hoping that someone can shed a little light on something I read in another post (http://www.lpcware.com/content/forum/unable-configure-gpio045-etc-input)

With reference to setting bits in a GPIO's IOCON, NXP_Paul mentions:


Quote:
So the configuration to get this working is minimal:
LPC_IOCON->PIO0_4 &= ~(1<<4); // disable internal pull-up
Make sure you don't set IOCON using:
LPC_IOCON->PIO0_4 = 0;
or else this bit will always read back as a '0' when reading the PIN register (reserved bit 7 must remain 1).



Please can someone explain why the top method is 'better' than the bottom method? Is it actually 'better', is there a convention?

I see that the first version of that line specifically clear bit 4 of that register, where as the second sets its value, in total, to 0. I understand that by clearing a single bit you leave bit 7 alone, as it has to set to one for the stuff that was being discussed there to work.

In the project I am working on, for example, I have an active low input, connected to Port1 Bit0 of my LPCXpresso LPC1114 - which is IOCON_R_PIO1_0

From the data sheet:

This is a 32bit register which initialises as xxxxxxxxxxxxxxxxxxxxx00011010000
bits 11 thru 31 are reserved, so we don't care about them
bits 0 thru 2 set the function, a value of 0x1 here is digital I/O : 001b
bits 3 thru 4 set the mode, this is an active low switch so we need the pull up to be enabled (0x2) : 10b
bit 5 sets the Hysteresis, the opto switch as a Schmitt trigger on it so we don't need it (0) : 0b
bit 7 sets A or D mode, its a switch so let's have D (1) : 1b
bits 8 thru 9 are reserved : 00b
bit 10 sets the open-drain mode, its an input so we don't care, lets leave it as a standard GPIO (0) : 0b
config bits thus are 0001010001 which is 0x0051

From here I seem to have a number of options of setting those bits.

I could:

LPC_IOCON->R_PIO1_0 = 0x51;  //simple enough, right? But will it mess with other things?


or:

LPC_IOCON_R_PIO1_0 &= ~(0xff);   //clear the bits we are about to set, we don't know what they were, best start with zeros. Bitwise AND-equals NOT (~) the bits you want to clear
LPC_IOCON_R_PIO1_0 |= 0x51 & 0xff; //ANDing the value with the mask from above means we don't accidentally set any of the wrong bits
//this seems like the safest way to do this, but its a bit long winded


or:
LPC_IOCON_R_PIO1_0 &= ~(0xff) | (0x51<<8)  //if I've understood the bitmasking thing properly, this should shift 0x51 into the bottom 8bits of the register without touching anything else


So - which method of setting those bits is the 'most correct'/best practice/follows convention? Is my bit mask okay, and, is it actually any more succinct than the two line clear and OR method above?

For reference, I'm extremely new to LPCXpresso/programming for ARM etc. I'm coming from a background of writing ASM for PICs and prototyping with Arduinos (so C 'programming short cuts' will be lost on me a little). Please let me know if you need any further information, to help you help me.

Thanks folks!
Labels (1)
0 Kudos
5 Replies

812 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by deevee on Thu Oct 03 08:03:58 MST 2013
OK cool, thought I was going crazy there for a moment...

Thanks again
D
0 Kudos

812 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by NXP_Paul on Thu Oct 03 07:07:31 MST 2013
My apologies.  You're correct.  I was looking at pull-down rather than pull-up.  The value should be 0xD1.
0 Kudos

812 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by deevee on Wed Oct 02 15:15:52 MST 2013
Just to clarify something with that register config...

This register starts up as 00011010000 (0xD0)
With this value you get StandardGPIO/Reserved/AD-Digital/Reserved/NoHysteresis/PullUPenabled/FuncReserved

The value you mentioned the register should have was (0x9C) which comes out as 00011001001
Which sets things up as StandardGPIO/Reserved/AD-Digital/Reserved/NoHysteresis/PullDOWNenabled/DigitalIO
This value has the IO resistor set up the wrong way round for my application.

As you say, for this register, I only want to flip a single bit, to set the pin function which gives 00011010001 (0xD1)
StandardGPIO/Reserved/AD-Digital/Reserved/NoHysteresis/PullUPenabled/DigitalIO

So - is 0xD1 correct or have I mis-read something somewhere and actually (0x9C) is correct. I'm looking at the UM10398 data sheet at table 134 on page 125.

Let me know what you think
Best
D
0 Kudos

812 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by deevee on Tue Oct 01 07:05:39 MST 2013
That's great, thanks Paul!


0 Kudos

812 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by NXP_Paul on Mon Sep 30 12:33:31 MST 2013
The problem with the first solution is that it does not leave reserved bit 6 set to 1.  Also, the mode bits [4:3] are 01, so you should use 0xC9 rather than 0x51:
LPC_IOCON->R_PIO1_0 = 0xC9;
I do not see a problem using this method to configure the IOCON register, as long as the value is calculated correctly.

The second method is okay, but again, don't clear the reserved bit 6.  The ANDing shouldn't be necessary.
LPC_IOCON_R_PIO1_0 &= ~(0xbf);
LPC_IOCON_R_PIO1_0 |= 0x89 & 0xff;
Since your example only requires changing the FUNC bits [2:0], it would probably be best to only change these 3 bits, minimizing the chance of an error:
LPC_IOCON_R_PIO1_0 &= ~0x07;
LPC_IOCON_R_PIO1_0 |= 0x01;

The third method is okay but you don't need to shift the value by 8 bits.

Most of the NXP example code uses the second method.

0 Kudos