The external Interface
---------- > D0 D1 | | D2 D3 | | D4 D5 | | D6 D7 | | A0 A1 | | A2 A3 | |+5V /CS | |/RD /WR | |INT GND | | NC NC | ----------
where: D0 - D7: are the data lines A0 - A3: are the address lines +5V: +5V Supply Voltage /CS: chip select (active low) /RD: read strobe (avtice low) /WR: write strobe (active low) INT: Interrupt input GND: Signal Ground NC: Not connected Note: all signals are 3.3V signals!
But adding a UART
EXT_IF -> UART -> uC -> Display & Keys
is somehow stupid. Because it could look like that:
EXT_IF -> Display & Keys
So I started reading though the kernel sources and found the UART initialisation process in sbmips.c somewhere in the arch/mips/bcm9….. directory. But the function that where used like sb_gpioin didn’t leed me to success.
So i had a look at gpio.c (same directory as above). This is a kernel module for accessing GPIO (general purpose input output). Here the sb_gpioin and so functions were used again. I tried to hack some new lines there but, let us go to the next try:
kmod-diag: OpenWRT comes with a small module that is used to turn on/off the LED’s and to fetch some keypresses. While reading the source (diag.c) I realized the function: set_led_extif.
volatile u8 *addr = (volatile u8 *) KSEG1ADDR(EXTIF_UART) + (led->gpio & ~GPIO_TYPE_MASK);
The adress of the external interface is between 0xBF800000 and 0xBF80000F. Only the low nibble (the 0×0-0xF) will be seen at the external interface on address lines A0-A3.
volatile u8 *addr = (volatile u8 *) KSEG1ADDR(EXTIF_UART) + (address & 0x0F);
Where address is the low nibble. Using the pointer *addr data can be read and written.
*addr = 0xFF; // write 0xFF data = *addr; // read data
So that’s the trick.
But what do /WR, /RD and /CS do?
/WR: The slash (“/”) before the signals name tells you that the signal is active low. This means if a write transfer is handled by the bus this signals changes from HIGH to LOW before the transmission and changes back to HIGH after the transmission.
/RD: Same as above but signals that it’s a read instead of a write operation.
/CS: This signal goes low whenever an address between 0xBF800000 and 0xBF80000F is read or written. This additional signal is necassary do differ between for example 0xBF80000A and 0x2AD3456A (because only the last nibble the “A” would be seen on the address lines A0-A3).