![]() |
C GPIO - Printable Version +- PINE64 (https://forum.pine64.org) +-- Forum: PINE A64(+) (https://forum.pine64.org/forumdisplay.php?fid=4) +--- Forum: Pine A64 Hardware, Accessories and POT (https://forum.pine64.org/forumdisplay.php?fid=32) +---- Forum: Pi2, Euler and Exp GPIO Ports (https://forum.pine64.org/forumdisplay.php?fid=34) +---- Thread: C GPIO (/showthread.php?tid=1327) |
RE: C GPIO - martind1983 - 09-01-2016 (09-01-2016, 05:29 AM)MarkHaysHarris777 Wrote:Hi Mark(09-01-2016, 05:08 AM)martind1983 Wrote: Very nice and comprehensively answered and also works as you know. In my opinion. When the programmer uses correct type casting. What I haven't done in my first case you can easily access all registers in the chip. As our colleague implied to us. This works perfectly. I just wanted to say for example: If PIO address 0x01c20800 would be possible to map (as it is not possible because of page size alignment). It would be easily possible to access any register from PIO peripheral just by adding its order number to mapped PIO address. Let's say PB_CFG0_REG register you could access by adding 1 to PIO base address what is 0x01c20800, like normal pointer arithmetic. However, as you cannot map PIO base address, you can only map CCU address what is 0x01c20000 and there are not any registers you could manually count like I described in previous lines or maybe it would be possible but it would be laborious. The aforementioned way KnReLe did is very goog and as I said you should be able to access any register in the chip. I should review my typecasting a bit ![]() Thank you to all ![]() RE: C GPIO - KnReLe - 09-01-2016 martind1983 In my opinion. When the programmer uses correct type casting. What I haven't done in my first case you can easily access all registers in the chip. As our colleague implied to us. This works perfectly. I just wanted to say for example: If PIO address 0x01c20800 would be possible to map (as it is not possible because of page size alignment). It would be easily possible to access any register from PIO peripheral just by adding its order number to mapped PIO address. Let's say PB_CFG0_REG register you could access by adding 1 to PIO base address what is 0x01c20800, like normal pointer arithmetic. However, as you cannot map PIO base address, you can only map CCU address what is 0x01c20000 and there are not any registers you could manually count like I described in previous lines or maybe it would be possible but it would be laborious. The aforementioned way KnReLe did is very goog and as I said you should be able to access any register in the chip. I should review my typecasting a bit ![]() Thank you to all ![]() (not sure what happened to the quoting ) Actually, if you want to automate the masking and handling of fact that the IO-address is not aligned to the page size, something like this would do: /* Base address for PB-PH */ #define GPIO_BASE_ADDR_PB 0x01c20800 /* Base address for PL */ #define GPIO_BASE_ADDR_PL 0x01f02c00 Then in the function there could be something like this using variables (or even passing in the port_io_base as an argument): uint64_t addr_offset; uint64_t addr_start; /* page-aligned start-address of mmapped space. */ uint64_t page_size; /* Page-size from system, it reports 0x1000 here. */ uint64_t page_mask; /* Mask to separate out page-alignment bits */ uint64_t port_io_base; /* input GPIOs base-address, doesn't have to be page-aligned */ port_io_base = GPIO_BASE_ADDR_PB; /* For example for ports PB-PH */ page_size = sysconf(_SC_PAGESIZE); /* 0x1000 */ page_mask = (~(page_size-1)); /* 0xFFFFFFFFFFFFF000 */ addr_start = port_io_base & page_mask; /* gives the page-aligned start address 0x01c20000, last 24 bits are 0 */ addr_offset = port_io_base & ~page_mask; /* mask with 0FFF so we get the 0800 offset into the page */ Then to the mmap (after the opening of the file of course) p_mem = mmap(NULL, page_size * 2, PROT_READ | PROT_WRITE, MAP_SHARED, fd, addr_start); Later you aim at the various registers, with the offset included, pretty much the same as before except no longer hardcoded: offset = addr_offset + 0x48; /* Will aim at the first of the PC control registers, which controls PC7--PC0 */ gpio = (volatile uint32_t *) ( (char *) (p_mem) + offset); Or slighlty more compact as that extra variable offset isn't really necessary gpio = (volatile uint32_t *) ( (char *) (p_mem) + addr_offset + 0x48); With this masking, this will work on any of the register addresses. RE: C GPIO - martind1983 - 09-01-2016 (09-01-2016, 08:52 AM)KnReLe Wrote: martind1983 |