Skip to main content
JReed.1856
Associate II
April 13, 2022
Solved

Quickest way to set multiple port pins

Hi,

I am trying to connect to a 16 bit parallel display interface. To write new data, I have to use pins on five different ports (GPIOs A, B, C, D, E). Right now I am setting these pins like this:

PORT_D15->BSRR = (PIN_D15 << 16) | (((data >> 15) & 0x01) * PIN_D15) ;

repeat for all other 15 pins.

This is causing the display to update slowly, you can see the screen 'rolling in' from the top.

On a previous controller all pins were in one port, and one access to

PORT_DISPLAY->ODR

was enough to set all pins.

Is there a quicker way to set all those port pins?

This topic has been closed for replies.
TDK
TDKBest answer
April 13, 2022

Seems like you could do a little better with:

PORT_D15->BSRR = (PIN_D15 << 16) >> (16 * ((data >> 15) & 0x01));

or possibly

PORT_D15->BSRR = (data & (1 << 15)) ? PIN_D15 : PIN_D15 << 16;

Apart from that, agree with JW's assessment.

"If you feel a post has answered your question, please click ""Accept as Solution""."

18 replies

waclawek.jan
Super User
April 19, 2022

Store data in memory with bits in the order of display.

Or...

...you can increase your pain...

JW

JReed.1856
Associate II
April 19, 2022

unfortunately also not possible since PC12 has bit9 and PB12 has bit 15.

only way would be to have separate data arrays for every port and that would require getting those from the original data variable, which would be just as costly as the usual bit shifts.

It seems increasing my pain is the only outcome here

waclawek.jan
Super User
April 19, 2022

Post the exact layout and your current solution together with disasm (mixed with source would be the best), with some benchmark.

JW

JReed.1856
Associate II
April 19, 2022

So the subjectively quickest way looks like this:

pin defines

#define ILI9341_PORT_D0 GPIOB
#define ILI9341_PORT_D1 GPIOE
#define ILI9341_PORT_D2 GPIOE
#define ILI9341_PORT_D3 GPIOB
#define ILI9341_PORT_D4 GPIOC
#define ILI9341_PORT_D5 GPIOA
#define ILI9341_PORT_D6 GPIOB
#define ILI9341_PORT_D7 GPIOD
#define ILI9341_PORT_D8 GPIOD
#define ILI9341_PORT_D9 GPIOC
#define ILI9341_PORT_D10 GPIOC		//changed, orig GPIOA
#define ILI9341_PORT_D11 GPIOA
#define ILI9341_PORT_D12 GPIOC
#define ILI9341_PORT_D13 GPIOB
#define ILI9341_PORT_D14 GPIOB
#define ILI9341_PORT_D15 GPIOB
 
#define ILI9341_PIN_D0 GPIO_PIN_11
#define ILI9341_PIN_D1 GPIO_PIN_11
#define ILI9341_PIN_D2 GPIO_PIN_9
#define ILI9341_PIN_D3 GPIO_PIN_2
#define ILI9341_PIN_D4 GPIO_PIN_2
#define ILI9341_PIN_D5 GPIO_PIN_0
#define ILI9341_PIN_D6 GPIO_PIN_4
#define ILI9341_PIN_D7 GPIO_PIN_7
#define ILI9341_PIN_D8 GPIO_PIN_4
#define ILI9341_PIN_D9 GPIO_PIN_12
#define ILI9341_PIN_D10 GPIO_PIN_11
#define ILI9341_PIN_D11 GPIO_PIN_8
#define ILI9341_PIN_D12 GPIO_PIN_7
#define ILI9341_PIN_D13 GPIO_PIN_13
#define ILI9341_PIN_D14 GPIO_PIN_14
#define ILI9341_PIN_D15 GPIO_PIN_12
static uint8_t ili9341_Write(uint16_t data) {
	GPIOA->BSRR = (ILI9341_PIN_D5 << 16) >> (((data >> 5) & 0x01) * 16) |
				(ILI9341_PIN_D11 << 16) >> (((data >> 11) & 0x01) * 16);
 
	GPIOB->BSRR = (ILI9341_PIN_D3 << 16) >> (((data >> 3) & 0x01) * 16) |
					(ILI9341_PIN_D0 << 16) >> (((data >> 0) & 0x01) * 16) |
					(ILI9341_PIN_D6 << 16) >> (((data >> 6) & 0x01) * 16) |
					(ILI9341_PIN_D13 << 16) >> (((data >> 13) & 0x01) * 16) |
					(ILI9341_PIN_D14 << 16) >> (((data >> 14) & 0x01) * 16) |
					(ILI9341_PIN_D15 << 16) >> (((data >> 15) & 0x01) * 16);
 
	GPIOC->BSRR = (ILI9341_PIN_D4 << 16) >> (((data >> 4) & 0x01) * 16) |
					(ILI9341_PIN_D9 << 16) >> (((data >> 9) & 0x01) * 16) |
					(ILI9341_PIN_D10 << 16) >> (((data >> 10) & 0x01) * 16) |
					(ILI9341_PIN_D12 << 16) >> (((data >> 12) & 0x01) * 16);
 
	GPIOD->BSRR = (ILI9341_PIN_D8 << 16) >> (((data >> 8) & 0x01) * 16) |
					(ILI9341_PIN_D7 << 16) >> (((data >> 7) & 0x01) * 16);
 
	GPIOE->BSRR = (ILI9341_PIN_D1 << 16) >> (((data >> 1) & 0x01) * 16) |
					(ILI9341_PIN_D2 << 16) >> (((data >> 2) & 0x01) * 16);
 
	ILI9341_PORT_WR->BSRR = (ILI9341_PIN_WR << 16)
			| (ILI9341_WR_LOW * ILI9341_PIN_WR);
	ILI9341_PORT_WR->BSRR = (ILI9341_PIN_WR << 16)
			| (ILI9341_WR_HIGH * ILI9341_PIN_WR);
 
	return 1;
}

disassembly in next post

JReed.1856
Associate II
April 19, 2022
08005512: mov.w r7, #268435456 ; 0x10000000
125 	GPIOB->BSRR = (ILI9341_PIN_D3 << 16) >> (((data >> 3) & 0x01) * 16) |
08005516: ubfx r1, r0, #3, #1
126 					(ILI9341_PIN_D0 << 16) >> (((data >> 0) & 0x01) * 16) |
0800551a: lsls r3, r3, #4
130 					(ILI9341_PIN_D15 << 16) >> (((data >> 15) & 0x01) * 16);
0800551c: lsls r4, r4, #4
0800551e: asr.w r4, r7, r4
125 	GPIOB->BSRR = (ILI9341_PIN_D3 << 16) >> (((data >> 3) & 0x01) * 16) |
08005522: mov.w lr, #262144 ; 0x40000
126 					(ILI9341_PIN_D0 << 16) >> (((data >> 0) & 0x01) * 16) |
08005526: asr.w r3, r12, r3
133 					(ILI9341_PIN_D9 << 16) >> (((data >> 9) & 0x01) * 16) |
0800552a: ubfx r2, r0, #9, #1
125 	GPIOB->BSRR = (ILI9341_PIN_D3 << 16) >> (((data >> 3) & 0x01) * 16) |
0800552e: lsls r1, r1, #4
08005530: asr.w r1, lr, r1
129 					(ILI9341_PIN_D14 << 16) >> (((data >> 14) & 0x01) * 16) |
08005534: orrs r3, r4
133 					(ILI9341_PIN_D9 << 16) >> (((data >> 9) & 0x01) * 16) |
08005536: lsls r2, r2, #4
08005538: asr.w r5, r7, r2
0800553c: orrs r3, r1
132 	GPIOC->BSRR = (ILI9341_PIN_D4 << 16) >> (((data >> 4) & 0x01) * 16) |
0800553e: and.w r2, r0, #16
134 					(ILI9341_PIN_D10 << 16) >> (((data >> 10) & 0x01) * 16) |
08005542: ubfx r1, r0, #10, #1
132 	GPIOC->BSRR = (ILI9341_PIN_D4 << 16) >> (((data >> 4) & 0x01) * 16) |
08005546: asr.w r2, lr, r2
134 					(ILI9341_PIN_D10 << 16) >> (((data >> 10) & 0x01) * 16) |
0800554a: lsls r1, r1, #4
0800554c: asr.w r1, r12, r1
08005550: orrs r2, r5
127 					(ILI9341_PIN_D6 << 16) >> (((data >> 6) & 0x01) * 16) |
08005552: ubfx r6, r0, #6, #1
133 					(ILI9341_PIN_D9 << 16) >> (((data >> 9) & 0x01) * 16) |
08005556: orrs r2, r1
137 	GPIOD->BSRR = (ILI9341_PIN_D8 << 16) >> (((data >> 8) & 0x01) * 16) |
08005558: ubfx r1, r0, #8, #1
127 					(ILI9341_PIN_D6 << 16) >> (((data >> 6) & 0x01) * 16) |
0800555c: mov.w r4, #1048576 ; 0x100000
137 	GPIOD->BSRR = (ILI9341_PIN_D8 << 16) >> (((data >> 8) & 0x01) * 16) |
08005560: lsls r1, r1, #4
08005562: lsls r6, r6, #4
08005564: asr.w r6, r4, r6
128 					(ILI9341_PIN_D13 << 16) >> (((data >> 13) & 0x01) * 16) |
08005568: ubfx r8, r0, #13, #1
137 	GPIOD->BSRR = (ILI9341_PIN_D8 << 16) >> (((data >> 8) & 0x01) * 16) |
0800556c: asrs r4, r1
140 	GPIOE->BSRR = (ILI9341_PIN_D1 << 16) >> (((data >> 1) & 0x01) * 16) |
0800556e: ubfx r1, r0, #1, #1
122 	GPIOA->BSRR = (ILI9341_PIN_D5 << 16) >> (((data >> 5) & 0x01) * 16) |
08005572: ubfx r7, r0, #5, #1
128 					(ILI9341_PIN_D13 << 16) >> (((data >> 13) & 0x01) * 16) |
08005576: mov.w r9, #536870912 ; 0x20000000
123 				(ILI9341_PIN_D11 << 16) >> (((data >> 11) & 0x01) * 16);
0800557a: ubfx lr, r0, #11, #1
128 					(ILI9341_PIN_D13 << 16) >> (((data >> 13) & 0x01) * 16) |
0800557e: mov.w r8, r8, lsl #4
140 	GPIOE->BSRR = (ILI9341_PIN_D1 << 16) >> (((data >> 1) & 0x01) * 16) |
08005582: lsls r1, r1, #4
128 					(ILI9341_PIN_D13 << 16) >> (((data >> 13) & 0x01) * 16) |
08005584: asr.w r8, r9, r8
140 	GPIOE->BSRR = (ILI9341_PIN_D1 << 16) >> (((data >> 1) & 0x01) * 16) |
08005588: asr.w r1, r12, r1
122 	GPIOA->BSRR = (ILI9341_PIN_D5 << 16) >> (((data >> 5) & 0x01) * 16) |
0800558c: mov.w r9, r7, lsl #4
123 				(ILI9341_PIN_D11 << 16) >> (((data >> 11) & 0x01) * 16);
08005590: mov.w r12, #16777216 ; 0x1000000
08005594: mov.w lr, lr, lsl #4
122 	GPIOA->BSRR = (ILI9341_PIN_D5 << 16) >> (((data >> 5) & 0x01) * 16) |
08005598: mov.w r7, #65536 ; 0x10000
123 				(ILI9341_PIN_D11 << 16) >> (((data >> 11) & 0x01) * 16);
0800559c: asr.w lr, r12, lr
080055a0: orrs r3, r6
122 	GPIOA->BSRR = (ILI9341_PIN_D5 << 16) >> (((data >> 5) & 0x01) * 16) |
080055a2: asr.w r7, r7, r9
129 					(ILI9341_PIN_D14 << 16) >> (((data >> 14) & 0x01) * 16) |
080055a6: ubfx r6, r0, #14, #1
080055aa: orr.w r7, r7, lr
080055ae: mov.w r5, #1073741824 ; 0x40000000
080055b2: ldr.w lr, [pc, #120] ; 0x800562c <ili9341_Write+296>
080055b6: lsls r6, r6, #4
080055b8: asr.w r6, r5, r6
135 					(ILI9341_PIN_D12 << 16) >> (((data >> 12) & 0x01) * 16);
080055bc: ubfx r5, r0, #12, #1
122 	GPIOA->BSRR = (ILI9341_PIN_D5 << 16) >> (((data >> 5) & 0x01) * 16) |
080055c0: str.w r7, [lr, #24]
129 					(ILI9341_PIN_D14 << 16) >> (((data >> 14) & 0x01) * 16) |
080055c4: orr.w r3, r3, r8
135 					(ILI9341_PIN_D12 << 16) >> (((data >> 12) & 0x01) * 16);
080055c8: mov.w r7, #8388608 ; 0x800000
080055cc: lsls r5, r5, #4
138 					(ILI9341_PIN_D7 << 16) >> (((data >> 7) & 0x01) * 16);
080055ce: ubfx r8, r0, #7, #1
141 					(ILI9341_PIN_D2 << 16) >> (((data >> 2) & 0x01) * 16);
080055d2: ubfx r0, r0, #2, #1
135 					(ILI9341_PIN_D12 << 16) >> (((data >> 12) & 0x01) * 16);
080055d6: asr.w lr, r7, r5
129 					(ILI9341_PIN_D14 << 16) >> (((data >> 14) & 0x01) * 16) |
080055da: orrs r6, r3
080055dc: mov.w r5, #33554432 ; 0x2000000
125 	GPIOB->BSRR = (ILI9341_PIN_D3 << 16) >> (((data >> 3) & 0x01) * 16) |
080055e0: ldr r3, [pc, #60] ; (0x8005620 <ili9341_Write+284>)
141 					(ILI9341_PIN_D2 << 16) >> (((data >> 2) & 0x01) * 16);
080055e2: lsls r0, r0, #4
080055e4: asr.w r0, r5, r0
138 					(ILI9341_PIN_D7 << 16) >> (((data >> 7) & 0x01) * 16);
080055e8: mov.w r8, r8, lsl #4
132 	GPIOC->BSRR = (ILI9341_PIN_D4 << 16) >> (((data >> 4) & 0x01) * 16) |
080055ec: add.w r5, r5, #1040187392 ; 0x3e000000
125 	GPIOB->BSRR = (ILI9341_PIN_D3 << 16) >> (((data >> 3) & 0x01) * 16) |
080055f0: str r6, [r3, #24]
138 					(ILI9341_PIN_D7 << 16) >> (((data >> 7) & 0x01) * 16);
080055f2: asr.w r8, r7, r8
132 	GPIOC->BSRR = (ILI9341_PIN_D4 << 16) >> (((data >> 4) & 0x01) * 16) |
080055f6: add.w r5, r5, #133120 ; 0x20800
137 	GPIOD->BSRR = (ILI9341_PIN_D8 << 16) >> (((data >> 8) & 0x01) * 16) |
080055fa: ldr r7, [pc, #40] ; (0x8005624 <ili9341_Write+288>)
140 	GPIOE->BSRR = (ILI9341_PIN_D1 << 16) >> (((data >> 1) & 0x01) * 16) |
080055fc: ldr r6, [pc, #40] ; (0x8005628 <ili9341_Write+292>)
134 					(ILI9341_PIN_D10 << 16) >> (((data >> 10) & 0x01) * 16) |
080055fe: orr.w r2, r2, lr
08005602: orrs r1, r0
137 	GPIOD->BSRR = (ILI9341_PIN_D8 << 16) >> (((data >> 8) & 0x01) * 16) |
08005604: orr.w r4, r4, r8
196 	ILI9341_PORT_WR->BSRR = (ILI9341_PIN_WR << 16)
08005608: mov.w lr, #16777472 ; 0x1000100
132 	GPIOC->BSRR = (ILI9341_PIN_D4 << 16) >> (((data >> 4) & 0x01) * 16) |
0800560c: str r2, [r5, #24]
200 }
0800560e: movs r0, #1
137 	GPIOD->BSRR = (ILI9341_PIN_D8 << 16) >> (((data >> 8) & 0x01) * 16) |
08005610: str r4, [r7, #24]
140 	GPIOE->BSRR = (ILI9341_PIN_D1 << 16) >> (((data >> 1) & 0x01) * 16) |
08005612: str r1, [r6, #24]
194 	ILI9341_PORT_WR->BSRR = (ILI9341_PIN_WR << 16)
08005614: str.w r12, [r3, #24]
196 	ILI9341_PORT_WR->BSRR = (ILI9341_PIN_WR << 16)
08005618: str.w lr, [r3, #24]
200 }