How to configure new UARTs on uCLinux

On this tutorial, we will configure new UARTs on uCLinux, based on Embedded Artists LPC2468 development board. I am using the 32 bits board, but the procedure is the same for 16 bits board.

These are the steps:

  • Bootloader configuration
  • Compile and update the bootloader
  • ucLinux kernel configuration
  • Compile and update kernel image

Introduction


On this example we will configure LPC2468 UART2 on pins P0.10 e P0.11 and also configure uCLinux to access it on /dev/ttyS2.

Bootloader configuration


UART configuration is done in the bootloader, using the processor registers. So, it is very important to read the processor manual to be aware on how the UART works. Chapters 16 and 17 are about UARTs.

LPC24xx User Manual - UM10237

To change and compile the bootloader, it is necessary the source code and the compiler, you can find out how to download and install both of them on the manual Updating the bootloader.

After all set, change the file lowloevel.c on u-boot-1.1.6/board/LPC2468OEM_Board as below:

1. Add this function

/*****************************************************************************
** Function name:   uart_2_init
**
** Description:     Configure UART #2 to 38400 bps, 8N1 on pins P0.10 and P0.11
** Parameters:      None
** Returned value:  None
**
*****************************************************************************/
void uart_2_init ( void )
{
  PINSEL0 |= 0x00500000; //configure uart2 on pins P0.10 and P0.11
  PCONP |= (1<<24);         //enable uart2 power/clock

  U2LCR = 0;
  U2IER = 0;
  U2LCR = 0x00000083;             // DLAB=1
  U2DLL = Fpclk/(16 * 38400);            //baudrate for 38400
  U2DLM = 0;
  U2LCR = 0x00000003;            // 8N1, DLAB=0
  U2FCR = 0x07;                    //enable RX and TX FIFOs

  U2THR = '\n';
}

2. Call the new function in lowlevel_init. To make it easier, you can call it just after the UART0 call, like the example below:

//initialize UART #0 to 38400, 8N1
UART0init();

//initialize UART #2 to 38400, 8N1
uart_2_init ();

Now compile and update the bootloader. If you don't know how to do that, read the tutorial Updating the bootloader.

Let's do a test to check the new configuration:

1. Start uCLinux using the new bootloader
2. Find out a way to monitor the P0.10 pin. You can use an oscilloscope, for example.
3. Send the command:

#echo U2THR:0x55 >/dev/sfr

4. This command should send a "U".

ucLinux kernel configuration


On this topic, I assume that you know already how to compile and update a new kernel image. Since it is a complex issue, I will not discuss it here.

Edit the file serial.h on uClinux-dist-20051014/include/asm-arm-lpc24xx. Note that ttyS1 interface is configured to work with UART3 and ttyS2 to work with UART2, this is not the default configuration. By default ttyS1 is set to UART1. I changed that to better fit my application, you can change it too as wish.
All the address (UART2_BASE) and interrupt (IRQ) can be found on LPC2468 user manual.

#ifndef __ASM_ARCH_SERIAL_H__
#define __ASM_ARCH_SERIAL_H__

#define BASE_BAUD  (57600000 / 16)
#define UART0_BASE  0xE000C000        //UART0
#define UART1_BASE  0xE007C000        //UART3
#define UART2_BASE  0xE0078000         //UART2

/* Standard COM flags */
#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST)

#define RS_TABLE_SIZE 4

/*
 * Rather empty table...
 * Hardwired serial ports should be defined here.
 * PCMCIA will fill it dynamically.
 */
#define STD_SERIAL_PORT_DEFNS    \
       /* UART    CLK         PORT        IRQ    FLAGS        */ \
    { 0,    BASE_BAUD,    UART0_BASE,     6,    STD_COM_FLAGS,    \
    .iomem_reg_shift = 2,        \
    .iomem_base = UART0_BASE,    \
    .io_type = SERIAL_IO_MEM},    \
    { 0,    BASE_BAUD,    UART1_BASE,     29,    STD_COM_FLAGS,    \
    .iomem_reg_shift = 2,        \
    .iomem_base = UART1_BASE,    \
    .io_type = SERIAL_IO_MEM},    \
    { 0,    BASE_BAUD,    UART2_BASE,     28,    STD_COM_FLAGS,  \
    .iomem_reg_shift = 2,        \
    .iomem_base = UART2_BASE,    \
    .io_type = SERIAL_IO_MEM}

#define EXTRA_SERIAL_PORT_DEFNS

#define SERIAL_PORT_DFNS    \
    STD_SERIAL_PORT_DEFNS    \
    EXTRA_SERIAL_PORT_DEFNS

#endif

Now edit the Makefile file on uClinux-dist-20051014/vendor/EmbeddedArtists/LPC2468OEM_Board and add the ttyS2 interface as below:

#Modify the line below adding ttyS2 interface
ttyS0,c,4,64   ttyS1,c,4,65       ttyS2,c,4,66 \

Compile and update the new kernel image.

To test it, fisrt let's check if the interface is there:

#ls /dev/ttyS*
/dev/ttyS2  /dev/ttyS1  /dev/ttyS0

Now, send some data to it:

#echo UUUUUUUU >/dev/ttyS2

Conclusion


Congratulations !!! You can use your serial port as you wish !!!!
Please, comment if you get any error or if you find one. Even for English error, since it is not my mother language, this text should have a lot of mistakes.

I also want to thanks Frank from the lpc2400_uclinux mail group for helping the bootloader configuration.

Add a New Comment
Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License