Back to all threads

Setting GPIO state with bit banding

Post reply

Tom  Harris
(10 posts)

Posted: 29 Mar 2012, 16:03

Thanks to the LPC Expresso support in the LPC1114 codebase, I am using the codebase now!

I note that the API to set/clear GPIO bits uses read/modify/write to the GPIO data register at 0x500x3ffc, with a clever use of the ternary operator to avoid an if statement.

write(bit, state):
   state ? (*(uint32_t*)0x500x3ffc |= (1 << bit)) : (*(uint32_t*)0x500x3ffc &= ~(1 << bit))

Since this register is bit banded across the lower 12 bits of the address range, why not do
 *((uint32_t*)0x500x0000 + (1<<bit)) = state ? 0x03ff : 0

This avoids the read of the GPIODATA register, which can flip bits if the corresponding pin is set to input.
 

Reply

microBuilder 
Administrator
(135 posts)

Posted: 30 Mar 2012, 00:03

Tom:

You're right that this can probably be improved.  Thanks for bringing it up ... I'll have a better look at this, and update in the next push on Github. 

In general, though, these GPIO functions are going to be much slower than addressing the registers directly, and they're provided more for convenience sake than anything.  Just the overhead of pushing and popping the stack when calling the functions adds a lot of wasted cycles, etc.  But that's still not an excuse for slow code if it can be avoided.

Reply

microBuilder 
Administrator
(135 posts)

Posted: 31 Mar 2012, 16:03

It'll get pushed with the next update for the 1114 and 1343, but this is what I ended up with.  It also allows me to drop the switch to select the appropriate register:

// Take advantage of the fact the GPIO registers are bit-banded 
(*(pREG32 ((GPIO_GPIO0_BASE + (portNum << 16)) + ((1 << bitPos) << 2)))) = bitVal ? 0xFFF : 0; 
 

Reply

Tom  Harris
(10 posts)

Posted: 01 Apr 2012, 17:04

microbuilder said:

It'll get pushed with the next update for the 1114 and 1343, but this is what I ended up with.  It also allows me to drop the switch to select the appropriate register:

// Take advantage of the fact the GPIO registers are bit-banded 
(*(pREG32 ((GPIO_GPIO0_BASE + (portNum << 16)) + ((1 << bitPos) << 2)))) = bitVal ? 0xFFF : 0; 
 

Why not define the function as inline? If the arguments are constants then it will optimise to a single write to a memory location, which is as efficient as it can get. With non-constant arguments it will be a bit more involved.

At least it will not be like the PIC18 compiler I am using, which calls a function to shift a value by 1 bit! I shake my head...

Reply

microBuilder 
Administrator
(135 posts)

Posted: 02 Apr 2012, 05:04

Tom:

I indeed changed it to inline (which I should have done in the first place, but usually when performance matters I just used the registers directly).  It just hasn't been pushed yet on the 1343 since I'm in the middle of tearing up some of the graphics code, though it should get pushed later this week.

I just pushed an update to the 1114 code where I added the inline, though.  Thanks for the prodding to improve this. :)

Kevin

Reply

Tom  Harris
(10 posts)

Posted: 03 Apr 2012, 19:04

microbuilder said:

Tom:

I indeed changed it to inline (which I should have done in the first place, but usually when performance matters I just used the registers directly).  It just hasn't been pushed yet on the 1343 since I'm in the middle of tearing up some of the graphics code, though it should get pushed later this week.

I just pushed an update to the 1114 code where I added the inline, though.  Thanks for the prodding to improve this. :)

Kevin
Kevin,

Thanks for the quick response. Actually I won't use this part of the library, as our projects use a code generator to write little inline functions for accessing IO, so for example I would write setGpioPfcSoftstartRelay(1), and the code would expand to an inline call to write the correct value to the IO part. The advantage is that the pins can be reallocated during development by editing a spreadsheet, which the hardware guys read as well, and I don't have to remember to change the bit definitions in the code.

Still, I need to understand how the IO port works to add support for the LPC1114 chips.

Reply

Post reply