Code: Select all
// GPIO setup macros. Always use INP_GPIO(x) before using OUT_GPIO(x) or SET_GPIO_ALT(x,y)
1)#define INP_GPIO(g) *(gpio+((g)/10)) &= ~(7<<(((g)%10)*3))
2)#define OUT_GPIO(g) *(gpio+((g)/10)) |= (1<<(((g)%10)*3))
3)#define SET_GPIO_ALT(g,a) *(gpio+(((g)/10))) |= (((a)<=3?(a)+4:(a)==4?3:2)<<(((g)%10)*3))
4)#define GPIO_SET *(gpio+7) // sets bits which are 1 ignores bits which are 0
5)#define GPIO_CLR *(gpio+10) // clears bits which are 1 ignores bits which are 0
I don't quite understand the above macro.
GPSET0 is at address 0x7E20 001C
GPCLR0 is at address 0x7E20 0028
why's 4 & 5 have them gpio+7, gpio+10 respectively.
Can some one explain 1, 2, 3 also to me?
The gpio memory map starts at 0x7E20 0000.
The GPSET0 resgister is at ( gpio + 0x1C bytes ), which is 28 decimal bytes. C pointers are mapped to 4-byte words, so the index has to be divided by 4 to give the word number. 28/4 is 7, so GPSET0 is at 0x7E20 0000 + ( 7 * 4 ).
The same goes for GPCLR0, which is the 10th word, stored at gpio + (10 * 4).
I'll have a go at 1 next.
Code: Select all
#define INP_GPIO(g) *(gpio+((g)/10)) &= ~(7<<(((g)%10)*3))
This is defining a macro that sets the mode of gpio number "g" to Input mode. It does this by clearing the relevant mode bits in words 0 to 5 of the gpio registers (the first 24 bytes). Input mode is function "0".
Each of these words hold the current mode for 10 of the 54 gpios, the first word has gpio 0 to gpio 9, the second has gpio 10 to gpio 19.
The mode uses 3 bits, so gpio 0 will be bits 0-2 of word 0, gpio 16 is bits 18-20 of word 1 etc.
So the "((g)/10)" in the code is getting the word number for the gpio "g".
Lets use gpio 16 as an example.
The "(((g)%10)*3))" is getting the low bit number for gpio "g" (16%10)*3 = 18.
The the constant "7" is shifted left by this number of bits (7<<), to get a value where all 3 bits are set. 0x001C 0000. Then it is inverted (~) to make a bitmask of bit that we don't want to clear. 0xFFE3 FFFF. Then that value is ANDed with the contents of the word and stored back in the same location.
That explains 1. It was a bit longer than I intended. From that you should be able to work out what 2 and 3 are doing. INP_GPIO should always be called before OUT_GPIO or SET_GPIO_ALT to clear the bits first, as OUT_GPIO is ORing the word with "1" shifted left the right number of bits, so the mode flags for that gpio will be 1, which is Write mode. The ALT macro sets the mode flag to the value "a".