Is it wrong or I misunderstood in GPIO introduction
MCU & Boards
No replies yet. Be the first to reply.
Join the discussion.
MCU & Boards
No replies yet. Be the first to reply.
Join the discussion.
Share projects and connect with makers.
Joined before the site update? first.
New to WIZnet Makers?
We sent a verification link to your address. Open it to activate your account, then log in.
Accounts from this email provider are reviewed by an administrator after verification. Approval usually takes one business day.
Already have an account?
Enter your email address. If it belongs to an account, we'll send a link to set a new password. Members who joined before the site update use this to set their password.
If an account uses that address, we sent a link to set a new password. The link works once and expires in 30 minutes.
Know your password?
Need an account?
RE: Is it wrong or I misunderstood in GPIO introduction
by Hooligan0 ·
It is not wrong, the mask is used to define which bit(s) you want to modify. So, to change bits 0,1,6, 7 you create a mask with this bits to ‘1’ (bits 0 and 1 = 0x03 … bits 7 and 6 = 0xC0) ; then after you write a 8 bits value but only the bits set to 1 into the mask are used … it more or less like network mask used to compute network adresse from ip address.
MASK = [color=#FF0000]11[/color]00 00[color=#FF0000]11[/color]
VALUE = [color=#0000FF]00[/color]00 00[color=#0000FF]11[/color]
new GPIO port value = 00xx xx11 (where x values are unchanged)
The mask is not really a register but an array of address. The GPIO peripheral will use a part of the adress to compute the mask. So, to define a mask, you shift the mask value two bits left and you add the array offset.
Example to set the blue led of wizwiki board, connected on GPIO port-C bit 5 :
GPIO-C is at 0x44000000
Lower bits array (bit0 to bit7) is at 0x400 offset
To change only bit5, you create a mask : 0010 0000 (or 0x20)
You shift two bits to get mask address : 1000 0000 (0x80)
Then to set gpio to ‘1’ (led OFF) you write value 00[color=#0000FF]1[/color]0 0000 at adresse 0x44000000 + 0x400 + 0x80 (=0x44000480)
*(volatile unsigned long *)0x44000480 = 0x20;
Then to set gpio to ‘0’ (led ON) you write value 00[color=#0000FF]0[/color]0 0000 at adresse 0x44000000 + 0x400 + 0x80 (=0x44000480)
*(volatile unsigned long *)0x44000480 = 0x00;
Is it clear ?
RE: Is it wrong or I misunderstood in GPIO introduction
by Yake ·
[quote=“Hooligan0”]It is not wrong, the mask is used to define which bit(s) you want to modify. So, to change bits 0,1,6, 7 you create a mask with this bits to ‘1’ (bits 0 and 1 = 0x03 … bits 7 and 6 = 0xC0) ; then after you write a 8 bits value but only the bits set to 1 into the mask are used … it more or less like network mask used to compute network adresse from ip address.
MASK = [color=#FF0000]11[/color]00 00[color=#FF0000]11[/color]
VALUE = [color=#0000FF]00[/color]00 00[color=#0000FF]11[/color]
new GPIO port value = 00xx xx11 (where x values are unchanged)
The mask is not really a register but an array of address. The GPIO peripheral will use a part of the adress to compute the mask. So, to define a mask, you shift the mask value two bits left and you add the array offset.
Example to set the blue led of wizwiki board, connected on GPIO port-C bit 5 :
GPIO-C is at 0x44000000
Lower bits array (bit0 to bit7) is at 0x400 offset
To change only bit5, you create a mask : 0010 0000 (or 0x20)
You shift two bits to get mask address : 1000 0000 (0x80)
Then to set gpio to ‘1’ (led OFF) you write value 00[color=#0000FF]1[/color]0 0000 at adresse 0x44000000 + 0x400 + 0x80 (=0x44000480)
*(volatile unsigned long *)0x44000480 = 0x20;
Then to set gpio to ‘0’ (led ON) you write value 00[color=#0000FF]0[/color]0 0000 at adresse 0x44000000 + 0x400 + 0x80 (=0x44000480)
*(volatile unsigned long *)0x44000480 = 0x00;
Is it clear ?[/quote]
Thank you, Hooligan0, I am very appreciate with your kindly explain.And I have test it with a little more and made it successfully.This time I want to set the Green led, connected on GPIO port-C bit 9:
GPIO-C is at 0x44000000
[color=#FF4000]Higher[/color] bits array (bit15 to bit8) is at 0x800 offset
To change only bit9, I create a mask : 0000 0010 0000 0000(or 0x0200)
shift two bits to get mask address :0000 1000 0000 0000(or 0x0800)([color=#FFBF00]Here I still don’t know why two bits, can you give me some reference[/color]?)
Then to set gpio to ‘1’ (led OFF) I write value 0000 00[color=#0000FF]1[/color]0 0000 0000 at adresse 0x44000000 + 0x800 + 0x0800 (=0x44001000)
*(volatile unsigned long *)0x44001000 = 0x0200;
Then to set gpio to ‘0’ (led ON) I write value 0000 00[color=#0000FF]0[/color]0 0000 0000 at adresse 0x44000000 + 0x800 + 0x0800 (=0x44001000)
*(volatile unsigned long *)0x44001000 = 0x0000;
RE: Is it wrong or I misunderstood in GPIO introduction
by Hooligan0 ·
[quote=“Yake”]This time I want to set the Green led, connected on GPIO port-C bit 9:
GPIO-C is at 0x44000000
[color=#FF4000]Higher[/color] bits array (bit15 to bit8) is at 0x800 offset
To change only bit9, I create a mask : 0000 0010 0000 0000(or 0x0200)
shift two bits to get mask address :0000 1000 0000 0000(or 0x0800)([color=#FFBF00]Here I still don’t know why two bits, can you give me some reference[/color]?)
[/quote]
Why two bits shift : Short answer
Because you use memory address to represent the mask ; and it’s better (and really more simple) to use aligned access.
Why two bits : Long answer
The mask array is a simple and powerfull solution to have two informations into one memory access. The first information is the mask, the second is the value herself.
First, imagine the question without shift. If you want to change bit0 of any port to ‘1’. You create a mask (0000 000[color=#0000FF]1[/color] or 0x01) and you use it directly as array index : you will have 0x400 + 0x01 = 0x401 as offset. Then you write at this memory location :
*(volatile unsigned long *)(PORT + 0x401) = 0x01Because of the “unsigned long” type you will write 4 bytes (at addresses 401, 402, 403, 404). The first problem of doing this is that you overlay other mask values (because 0x402 is the mask produced for bit1 in our example). The second problem is that you made an unaligned memory access (it is really simpler to align all peripheral access on 32 bits values [1])To avoid this, Wiznet has made the choice to convert each mask values to 32 bits memory locations. So, to convert a mask value to a memory offset value you must multiply the mask value by 4. A 2 bit shift is the same than multiply by 4.
The array offset problem
You have made a really small error into offset value computation.
Your mask is 0000 00[color=#0000FF]1[/color]0 0000 0000(or 0x0200) it’s right … BUT … The higher mask array will use only the higher bits. So the array offset is 0000 00[color=#0000FF]1[/color]0 = 0x02 (bits 15 to 8) with two bits shift = 0x08
Green led mask will be : 0x44000000 + 0x800 + 0x08
/* Green led ON */ *(volatile unsigned long *)0x44000808 = 0x00; /* Green led OFF */ *(volatile unsigned long *)0x44000808 = (1 << 9);[1] infocenter.arm.com/help/index.js … FAIGG.html
RE: Is it wrong or I misunderstood in GPIO introduction
by Yake ·
[quote=“Hooligan0”][quote=“Yake”]This time I want to set the Green led, connected on GPIO port-C bit 9:
GPIO-C is at 0x44000000
[color=#FF4000]Higher[/color] bits array (bit15 to bit8) is at 0x800 offset
To change only bit9, I create a mask : 0000 0010 0000 0000(or 0x0200)
shift two bits to get mask address :0000 1000 0000 0000(or 0x0800)([color=#FFBF00]Here I still don’t know why two bits, can you give me some reference[/color]?)
[/quote]
Why two bits shift : Short answer
Because you use memory address to represent the mask ; and it’s better (and really more simple) to use aligned access.
Why two bits : Long answer
The mask array is a simple and powerfull solution to have two informations into one memory access. The first information is the mask, the second is the value herself.
First, imagine the question without shift. If you want to change bit0 of any port to ‘1’. You create a mask (0000 000[color=#0000FF]1[/color] or 0x01) and you use it directly as array index : you will have 0x400 + 0x01 = 0x401 as offset. Then you write at this memory location :
*(volatile unsigned long *)(PORT + 0x401) = 0x01Because of the “unsigned long” type you will write 4 bytes (at addresses 401, 402, 403, 404). The first problem of doing this is that you overlay other mask values (because 0x402 is the mask produced for bit1 in our example). The second problem is that you made an unaligned memory access (it is really simpler to align all peripheral access on 32 bits values [1])To avoid this, Wiznet has made the choice to convert each mask values to 32 bits memory locations. So, to convert a mask value to a memory offset value you must multiply the mask value by 4. A 2 bit shift is the same than multiply by 4.
The array offset problem
You have made a really small error into offset value computation.
Your mask is 0000 00[color=#0000FF]1[/color]0 0000 0000(or 0x0200) it’s right … BUT … The higher mask array will use only the higher bits. So the array offset is 0000 00[color=#0000FF]1[/color]0 = 0x02 (bits 15 to 8) with two bits shift = 0x08
Green led mask will be : 0x44000000 + 0x800 + 0x08
/* Green led ON */ *(volatile unsigned long *)0x44000808 = 0x00; /* Green led OFF */ *(volatile unsigned long *)0x44000808 = (1 << 9);[1] infocenter.arm.com/help/index.js … FAIGG.html[/quote]
I really enjoy it, Thank you again.
Now, my question is: after I have test with the two code, the result is same, both of them can flash the green led.
I have use the break point but didn’t get the point.Thank you for patience.
RE: Is it wrong or I misunderstood in GPIO introduction
by Hooligan0 ·
[quote=“Yake”]I really enjoy it, Thank you again.
Now, my question is: after I have test with the two code, the result is same, both of them can flash the green led.
I have use the break point but didn’t get the point.Thank you for patience.[/quote]
i’m sorry but i don’t understand your new question. What are the “two code” you talk about ?
RE: Is it wrong or I misunderstood in GPIO introduction
by Yake ·
[quote=“Hooligan0”][quote=“Yake”]I really enjoy it, Thank you again.
Now, my question is: after I have test with the two code, the result is same, both of them can flash the green led.
I have use the break point but didn’t get the point.Thank you for patience.[/quote]
i’m sorry but i don’t understand your new question. What are the “two code” you talk about ?[/quote]
sorry the test code is below:
[code] while(1)
{
// *(volatile unsigned long *)0x44000808 = 0x00;
*(volatile unsigned long *)0x44001000 = 0x00;
delay_ms(500);
// *(volatile unsigned long *)0x44000808 = (1 << 9);
*(volatile unsigned long *)0x44001000 = (1 << 9);
}[/code]
the comment one and the uncomment have the same effect.Both of them will flash the green light, it is wired.
RE: Is it wrong or I misunderstood in GPIO introduction
by Hooligan0 ·
[quote=“Yake”]
*(volatile unsigned long *)0x44001000 = 0x00; *(volatile unsigned long *)0x44001000 = (1 << 9);[/quote]
The valid registers for GPIO peripheral are between 0x44000000 and 0x44000BFF (see table 16, GPIOC register map, reference manual page 258)
I think upper bits are simply not conected into peripheral (lawrence may confirm if i’m right) So when you write at offset 0x1000 , the peripheral will decode address 0x0000 (bit 12 ignored). If you write at 0x44000000 this is GPIOC_DATA register. Into the reference manual, this register is used to read port, and bits are “read only” but, i’ve tested to write into, and this change the port value. I don’t know if it is a bug or just a side effect.