mrvn/raspbootin

UART initialization fails from loaded kernel

jjfahner opened this issue · 2 comments

After porting raspbootcom to Windows I wanted to use your UART code as a basis instead of the MiniUART (which I was having reliability issues with) for a project on a RPi B+. I've scoured the internet for other info but find the same basic code for initialization of the UART.

For some reason though, after the UART has been initialized by raspbootin, I can't re-initialize it from the kernel_main in the kernel loaded by raspbootin. I can use the UART without issues from the loaded kernel, since it's already been initialized.

Debugging doesn't get me further than the call to disable pin 14/15, which never returns (basically the MMIO::write(GPPUDCLK0, (1 << 14) | (1 << 15))). Or maybe it causes an exception, but I'm trapping them so I should have noticed that.

I'm probably just not aware of an important detail (like needing to de-initialize something first), but I'm stuck. Hope there's something you can tell me!

When I was using rapbootin, I used this code to initialize UART from my own kernel booted by raspbootin.
Now, I use a special version of my kernel to work same as raspbootin and I still don't have any problem to reinitialize

    // Disable UART0.
    memory::write32(UART0_CR, 0x00000000);
    // Setup the GPIO pin 14 && 15.

    // Disable pull up/down for all GPIO pins & delay for 150 cycles.
    memory::write32(GPIO::GPPUD, 0x00000000);
    delay(150);

    // Disable pull up/down for pin 14,15 & delay for 150 cycles.
    memory::write32(GPIO::GPPUDCLK0, (1 << 14) | (1 << 15));
    delay(150);

    // Write 0 to GPPUDCLK0 to make it take effect.
    memory::write32(GPIO::GPPUDCLK0, 0x00000000);

    // Clear pending interrupts.
    memory::write32(UART0_ICR, 0x7FF);

    memory::write32(UART0_IBRD, 1); // divider
    memory::write32(UART0_FBRD, 0); // fraction

    // Enable FIFO & 8 bit data transmissio (1 stop bit, no parity).
    memory::write32(
        UART0_LCRH, 
        (1 << 4) | // FEN - enable FIFO */ 
        (1 << 5) | (1 << 6) // WLEN
    );

    memory::write32(UART0_IMSC, 
        IMSC_RXI |  // enable interrupt on RX
        IMSC_RTI |  // enable receive timeout
        IMSC_PEI |  // enable parity error interrupt
        IMSC_BEI |  // enable Break error interrupt
        IMSC_OEI |  // enable Overrun error interrupt
        0
    );

    // Enable UART0, receive & transfer part of UART.
    memory::write32(UART0_CR, (1 << 0) | (1 << 8) | (1 << 9));

    interrupt::enableIrq(interrupt::uartInt);

I only got problem when trying to initialize mmu stuff before uart. Are you initializing uart before everything?
Or maybe you can share more of your code to try it out.

mrvn commented

Must be a problem with the kernel code, not raspbootin. Best guess the MMIO registers are not mapped or the address is wrong and the exception catching code doesn't work.