Hi L4 Hackers, Since i sadly still cant get the uart to work i have some more questions.
1. I've noticed that the offsets of all the registers in the /drivers-frst/uart/src/uart_pxa.cc are are incorrect by a multiple of 4. So if IER is defined to be at 0x01 it is actually at 0x04, respectivly the LCR which is said to be at 0x03 is actually at 0x0C. After I changed these values to reflect the allwinner A20 manual, the kernel stopped loading properly. It gets stuck on bootup at "Starting kernel...". In fact it does continue although at a pace of one character every 5 to 6 minutes. So after 30mins i had "L4 Bootstra" in the next line. My assumption is that my UART0 from which i run the console on my linux pc actually uses the uart_pxa driver with the incorrect register offset and it works for it. By changing the registers I somehow break my UART0. If I'm correct then I should be able to find the routine which the kernel uses to initilize UART0, to help me understand how to get UART3 to work. Sadly I couldn't find anything alike.
2.So i went on by writing a new uart_16550bananapi.cc with changed registers. It did infact solve the kernel not starting issue. I can now access and write to all of the uart registers... apart from the Line Control Register(LCR). It starts off with 0x03 written to it although it has a default of 0x00(in the a20 manual) as soon as i write 0x00 to it my console starts throwing out seemingly random chars:
This code in the uart startup() function:
scratch = _regs->read<unsigned char>(LCR); printf("\ncurrent LCR: %#010x\n", scratch); printf("Setting LCR to 0\n"); printf("This gets overritten\n"); _regs->write<unsigned char>(LCR, 0); /* clear line control register */ printf("It worked\n");
gives me this outpot on console:
Maestro | Maestro | current LCR: 0x00000003 Maestro | Setting LCR to 0 Maese|iw�k�{m{[e|{m{[e|pp`'br�l�z{mos�pppppn{m{[e��r|{m{[e p�ot[ lLzppppp{m{[e|pq`�rppppp{m{ێm[e|pqlNzppppv{m{[e|pq`�rppppp{m{ێm[e q
The same thing happens if i write 0x80 to it to add the DLAB bit that i need to access the two Divisor Latch registers to initilize the Baudrate for the first time. The 0x03 in LCR means that i run my Uart in 8N1 mode setting which my UART0 console is running aswell. Setting it to 0 means to run 5N1. So I assume for some reason it might somehow change my UART0 settings if i write to UART3 LCR reg. But the same error occurs if i write 0x83 to it to leave 8N1 on and set the DLAB bit, so that cant be the case can it? Without setting Baudrate however i obviously cant hope for UART3 to work.
Thanks for any answers in advance,
Clemens
On Sat Apr 25, 2015 at 13:56:16 +0200, Pflaum, Clemens wrote:
Hi L4 Hackers, Since i sadly still cant get the uart to work i have some more questions.
- I've noticed that the offsets of all the registers in the
/drivers-frst/uart/src/uart_pxa.cc are are incorrect by a multiple of 4. So if IER is defined to be at 0x01 it is actually at 0x04, respectivly the LCR which is said to be at 0x03 is actually at 0x0C. After I changed these values to reflect the allwinner A20 manual, the kernel stopped loading properly. It gets stuck on bootup at "Starting kernel...". In fact it does continue although at a pace of one character every 5 to 6 minutes. So after 30mins i had "L4 Bootstra" in the next line. My assumption is that my UART0 from which i run the console on my linux pc actually uses the uart_pxa driver with the incorrect register offset and it works for it. By changing the registers I somehow break my UART0. If I'm correct then I should be able to find the routine which the kernel uses to initilize UART0, to help me understand how to get UART3 to work. Sadly I couldn't find anything alike.
The Io_register_block_mmio has a shift parameter for spreading out the register offsets, i.e. you should set it two 2. No need to change the register values or clone the driver.
2.So i went on by writing a new uart_16550bananapi.cc with changed registers. It did infact solve the kernel not starting issue. I can now access and write to all of the uart registers... apart from the Line Control Register(LCR). It starts off with 0x03 written to it although it has a default of 0x00(in the a20 manual) as soon as i write 0x00 to it my console starts throwing out seemingly random chars:
This code in the uart startup() function:
scratch = _regs->read<unsigned char>(LCR); printf("\ncurrent LCR: %#010x\n", scratch); printf("Setting LCR to 0\n"); printf("This gets overritten\n"); _regs->write<unsigned char>(LCR, 0); /* clear line control
register */ printf("It worked\n");
gives me this outpot on console:
Maestro | Maestro | current LCR: 0x00000003 Maestro | Setting LCR to 0 Maese|iw�k�{m{[e|{m{[e|pp`'br�l�z{mos�pppppn{m{[e��r|{m{[e p�ot[ lLzppppp{m{[e|pq`�rppppp{m{ێm[e|pqlNzppppv{m{[e|pq`�rppppp{m{ێm[e q
The same thing happens if i write 0x80 to it to add the DLAB bit that i need to access the two Divisor Latch registers to initilize the Baudrate for the first time. The 0x03 in LCR means that i run my Uart in 8N1 mode setting which my UART0 console is running aswell. Setting it to 0 means to run 5N1. So I assume for some reason it might somehow change my UART0 settings if i write to UART3 LCR reg. But the same error occurs if i write 0x83 to it to leave 8N1 on and set the DLAB bit, so that cant be the case can it? Without setting Baudrate however i obviously cant hope for UART3 to work.
Is there any documented difference between UART0 and UART3? I wonder why changing values in the MMIO of UART3 should affect UART0.
Adam
Hi Adam, Thank you for your answer.
The Io_register_block_mmio has a shift parameter for spreading out the register offsets, i.e. you should set it two 2. No need to change the register values or clone the driver.
Works like a charm, though doesnt solve my actual problem.
Is there any documented difference between UART0 and UART3?
http://dl.linux-sunxi.org/A20/A20%20User%20Manual%202013-03-22.pdf at page 645 says uart3 is the same as uart0 apart from it having two extra data flow control signals(RTS and CTS). But they should be deactivated since i wrote 0 to the MCR register. Nevertheless I tried out all the different UARTS (0-7) and noticed that i cant access any of the registers on UART4-7 which have only RX and TX like UART0. On UARTS1-3 I can access the registers but get the same wierd error as soon as I try to change the LCR register to access the BRD_LOW and _HIGH registers. Obviously I get an IRQ error if I use UART0 since IRQ 33 is already taken, but i can still read and write to the registers and get the same error as with UART1-3.
I wonder why changing values in the MMIO of UART3 should affect UART0.
This was just my assumption at what could cause the console to crash. In theory ofcourse it shouldnt affect UART0. I just cant think of any other possible cause.
Any Ideas?
Regards, Clemens
Hi,
On Wed Apr 29, 2015 at 13:35:29 +0200, Pflaum, Clemens wrote:
Is there any documented difference between UART0 and UART3?
http://dl.linux-sunxi.org/A20/A20%20User%20Manual%202013-03-22.pdf at page 645 says uart3 is the same as uart0 apart from it having two extra data flow control signals(RTS and CTS). But they should be deactivated since i wrote 0 to the MCR register. Nevertheless I tried out all the different UARTS (0-7) and noticed that i cant access any of the registers on UART4-7 which have only RX and TX like UART0.
How does the 'no access' show? J12 is described as having UART7 so I'd assume the UART is there. (UART4 starts on a new page, you have mapped that too?)
On UARTS1-3 I can access the registers but get the same wierd error as soon as I try to change the LCR register to access the BRD_LOW and _HIGH registers. Obviously I get an IRQ error if I use UART0 since IRQ 33 is already taken, but i can still read and write to the registers and get the same error as with UART1-3.
I wonder why changing values in the MMIO of UART3 should affect UART0.
This was just my assumption at what could cause the console to crash. In theory ofcourse it shouldnt affect UART0. I just cant think of any other possible cause.
Any Ideas?
Hmm, does it work with on Linux, i.e. it's not something hardware-related?
Adam
Hi,
How does the 'no access' show? J12 is described as having UART7 so I'd assume the UART is there. (UART4 starts on a new page, you have mapped that too?)
If I try to read any register like I usally do: char sc = regs->read<unsigned char>(LCR); printf("0x0C LCR: %#010x\n", sc); All i get is 0x00 even if i try writing to it before. I have had the exact same problem with UART0-3 before manually adjusting the Registers to their actual offsets or setting the shift parameter of Io_register_block_mmio to 2. So its actually like I'm looking at/writing to the wrong places. I map the memory similar to the serial-drv example only ever one UART at a time: #define IRQ_NUM 52 //currently set to UART7, 36 for UART3 #define UART_BASE 0x01C29C00 //currently set to UART7, 0x01C28C00 for UART3
bool Maestro_server::init() { printf("init start\n"); l4_addr_t virt_base = 0;
if (l4io_request_iomem((l4_addr_t)UART_BASE, 0x0400, L4IO_MEM_NONCACHED, &virt_base)) { printf("maestro-drv: request io-memory from l4io failed.\n"); return false; } printf("maestro-drv: virtual base at:%lx\n", virt_base);
L4::Io_register_block_mmio *regs = new L4::Io_register_block_mmio(virt_base, 2); printf("registered regs\n");
_uart = new (malloc(sizeof(L4::Uart_bpi16550))) L4::Uart_bpi16550((unsigned long) 115200); printf("malloc for _uart\n"); printf("\n");
if(!(_uart->startup(regs))){ printf("failed to startup uart regs!\n"); }
}
Hmm, does it work with on Linux, i.e. it's not something hardware-related?
I have tested the UARTS with the Bananian linux and they work just fine, so it cant be hardware-related.
Regards, Clemens
Hi,
How does the 'no access' show? J12 is described as having UART7 so I'd assume the UART is there. (UART4 starts on a new page, you have mapped that too?)
If I try to read any register like I usally do: char sc = regs->read<unsigned char>(LCR); printf("0x0C LCR: %#010x\n", sc); All i get is 0x00 even if i try writing to it before. I have had the exact same problem with UART0-3 before manually adjusting the Registers to their actual offsets or setting the shift parameter of Io_register_block_mmio to 2. So its actually like I'm looking at/writing to the wrong places. I map the memory similar to the serial-drv example only ever one UART at a time: #define IRQ_NUM 52 //currently set to UART7, 36 for UART3 #define UART_BASE 0x01C29C00 //currently set to UART7, 0x01C28C00 for UART3
bool Maestro_server::init() { printf("init start\n"); l4_addr_t virt_base = 0;
if (l4io_request_iomem((l4_addr_t)UART_BASE, 0x0400, L4IO_MEM_NONCACHED, &virt_base)) { printf("maestro-drv: request io-memory from l4io failed.\n"); return false; } printf("maestro-drv: virtual base at:%lx\n", virt_base);
L4::Io_register_block_mmio *regs = new L4::Io_register_block_mmio(virt_base, 2); printf("registered regs\n");
_uart = new (malloc(sizeof(L4::Uart_bpi16550))) L4::Uart_bpi16550((unsigned long) 115200); printf("malloc for _uart\n"); printf("\n");
if(!(_uart->startup(regs))){ printf("failed to startup uart regs!\n"); } . . }
Together with the folling in my .devs file
local Hw = Io.Hw local Res = Io.Res Io.hw_add_devices { UART7 = Hw.Device { hid = "UART7"; Res.irq(52); Res.mmio(0x01C29C00, 0x01C29FFF); } }
Hmm, does it work with on Linux, i.e. it's not something hardware-related?
I have tested the UARTS with the Bananian linux and they work just fine, so it cant be hardware-related.
Regards, Clemens
I have almost identical code except I'm running on a mips based platform with a 16550 UART so I don't use the shift parameter. I do the regs->writes() but when I peek at the physical memory with GDB I don't see the values I wrote. The l4io_request_iomem() is called with L4IO_MEM_NONCACHED (and there is no enabled cache in my setup) and it doesn't return an error. I doesn't look like the values are getting written to the mmio block.
On Mon, May 4, 2015 at 4:05 AM, Pflaum, Clemens clemens.pflaum@mytum.de wrote:
Hi,
How does the 'no access' show? J12 is described as having UART7 so I'd
assume the UART is there. (UART4 starts on a new page, you have mapped that too?)
If I try to read any register like I usally do: char sc = regs->read<unsigned char>(LCR); printf("0x0C LCR: %#010x\n", sc); All i get is 0x00 even if i try writing to it before. I have had the exact same problem with UART0-3 before manually adjusting the Registers to their actual offsets or setting the shift parameter of Io_register_block_mmio to 2. So its actually like I'm looking at/writing to the wrong places. I map the memory similar to the serial-drv example only ever one UART at a time: #define IRQ_NUM 52 //currently set to UART7, 36 for UART3 #define UART_BASE 0x01C29C00 //currently set to UART7, 0x01C28C00 for UART3
bool Maestro_server::init() { printf("init start\n"); l4_addr_t virt_base = 0;
if (l4io_request_iomem((l4_addr_t)UART_BASE, 0x0400,
L4IO_MEM_NONCACHED, &virt_base)) { printf("maestro-drv: request io-memory from l4io failed.\n"); return false; } printf("maestro-drv: virtual base at:%lx\n", virt_base);
L4::Io_register_block_mmio *regs = new
L4::Io_register_block_mmio(virt_base, 2); printf("registered regs\n");
_uart = new (malloc(sizeof(L4::Uart_bpi16550)))
L4::Uart_bpi16550((unsigned long) 115200); printf("malloc for _uart\n"); printf("\n");
if(!(_uart->startup(regs))){ printf("failed to startup uart regs!\n"); } . .
}
Together with the folling in my .devs file
local Hw = Io.Hw local Res = Io.Res Io.hw_add_devices { UART7 = Hw.Device { hid = "UART7"; Res.irq(52); Res.mmio(0x01C29C00, 0x01C29FFF);
} }
Hmm, does it work with on Linux, i.e. it's not something
hardware-related?
I have tested the UARTS with the Bananian linux and they work just fine, so it cant be hardware-related.
Regards, Clemens
l4-hackers mailing list l4-hackers@os.inf.tu-dresden.de http://os.inf.tu-dresden.de/mailman/listinfo/l4-hackers
On Tue May 05, 2015 at 10:36:59 -0400, teclis High Elf wrote:
I have almost identical code except I'm running on a mips based platform with a 16550 UART so I don't use the shift parameter. I do the regs->writes() but when I peek at the physical memory with GDB I don't see the values I wrote. The l4io_request_iomem() is called with L4IO_MEM_NONCACHED (and there is no enabled cache in my setup) and it doesn't return an error. I doesn't look like the values are getting written to the mmio block.
I'm wondering, the offsets are 1-byte apart or more? I might be wrong but one byte variant it typically quite x86-ish. Otherwise check the mapping as described in the previous mail.
Adam
Hi,
On Mon May 04, 2015 at 10:05:39 +0200, Pflaum, Clemens wrote:
How does the 'no access' show? J12 is described as having UART7 so I'd assume the UART is there. (UART4 starts on a new page, you have mapped that too?)
If I try to read any register like I usally do: char sc = regs->read<unsigned char>(LCR); printf("0x0C LCR: %#010x\n", sc); All i get is 0x00 even if i try writing to it before. I have had the exact same problem with UART0-3 before manually adjusting the Registers to their actual offsets or setting the shift parameter of Io_register_block_mmio to 2. So its actually like I'm looking at/writing to the wrong places. I map the memory similar to the serial-drv example only ever one UART at a time: #define IRQ_NUM 52 //currently set to UART7, 36 for UART3 #define UART_BASE 0x01C29C00 //currently set to UART7, 0x01C28C00 for UART3
bool Maestro_server::init() { printf("init start\n"); l4_addr_t virt_base = 0;
if (l4io_request_iomem((l4_addr_t)UART_BASE, 0x0400,
L4IO_MEM_NONCACHED, &virt_base)) { printf("maestro-drv: request io-memory from l4io failed.\n"); return false; } printf("maestro-drv: virtual base at:%lx\n", virt_base);
What is this line printing? So the question is whether the virtual address really points to 0x01C29C00? You can check via jdb, show all tasks with s, go to your program, press p which shows the page-table of your program, navigate to the second level.
L4::Io_register_block_mmio *regs = new
L4::Io_register_block_mmio(virt_base, 2); printf("registered regs\n");
_uart = new (malloc(sizeof(L4::Uart_bpi16550)))
L4::Uart_bpi16550((unsigned long) 115200); printf("malloc for _uart\n"); printf("\n");
if(!(_uart->startup(regs))){ printf("failed to startup uart regs!\n"); } . .
}
Together with the folling in my .devs file
local Hw = Io.Hw local Res = Io.Res Io.hw_add_devices { UART7 = Hw.Device { hid = "UART7"; Res.irq(52); Res.mmio(0x01C29C00, 0x01C29FFF); } }
Looks ok.
Hmm, does it work with on Linux, i.e. it's not something hardware-related?
I have tested the UARTS with the Bananian linux and they work just fine, so it cant be hardware-related.
Ok, good.
Adam
l4-hackers@os.inf.tu-dresden.de