Saturday, November 28, 2015

Phase 2: Makefile

########################################################################
#name:          Makefile
#description:   IgboEmbedded' EGWU Makefile
#date:          06/09/2015
#author:        Samuel Igwe
########################################################################

CC     = arm-none-eabi-gcc
LD     = arm-none-eabi-ld
OBJCPY = arm-none-eabi-objcopy

AR     = arm-none-eabi-ar
RM     = rm -f
MV     = mv -f


CFLAGS = -g -c -Wall -nostdlib -mcpu=cortex-m3 -mlittle-endian -mthumb  -mabi=atpcs -DDEBUG \
         -O2 -DEXT_CLK 
         #-O2 -DEXT_CLK -DDIVADDVAL=1 -DMULVAL=2
LDFLAGS= -nostdlib -e main  -Map flash.map -L linker -T IE_lpc177x.ld --cref 
ARFLAGS= -r



all:
        make lpcopen.lib
        make egwu_core
        make egwu_app
        make clean


        
lpcopen.lib:
        $(CC)   $(CFLAGS) -DCORE_M3 -I lpcopen/include lpcopen/source/*.c
        $(AR)   $(ARFLAGS) lpcopen.lib *.o
        $(RM)   *.o



egwu_core:      
        $(CC)   $(CFLAGS)                                                -o ivt.o     core/IE_egwu_ivt.S
        $(CC)   $(CFLAGS) -DCORE_M3  -I core -I lpcopen/include -I tclib -o setup.o   core/IE_egwu_setup.c
        $(CC)   $(CFLAGS) -DCORE_M3  -I core -I lpcopen/include -I tclib -o uartio.o  core/IE_egwu_uartio.c
        $(CC)   $(CFLAGS) -DCORE_M3  -I core -I lpcopen/include -I tclib -o monitor.o core/IE_egwu_monitor.c
        $(CC)   $(CFLAGS)                                       -I tclib -o tclib.o   tclib/IE_tclib.S
        


egwu_app:
        $(CC)   $(CFLAGS) -DCORE_M3  -I core -I lpcopen/include -I tclib -o main.o   app/main.c
        $(LD)   $(LDFLAGS)                                               -o main.out ivt.o\
                                                                                     setup.o\
                                                                                     uartio.o\
                                                                                     monitor.o\
                                                                                     tclib.o\
                                                                                     main.o\
                                                                                     lpcopen.lib


clean:
        $(RM)   *.o
        $(RM)   lpcopen.lib
     

binimage: 
        $(OBJCPY) -O binary flash.out flash.bin







Phase 2: UART not out of the woods yet

I modified the fractional divide test some more ... to write and check for 3 values. Everything held in place with 0/1 and 1/1 as the DivAddVal/MulVal values using a loop back cable (paper clip on pins 2 and 3 of serial null modem cable).

However when I connected to my PC's serial port and ran minicom  ... I still got back gibberish ...  I have to consider that perhaps I left something out ... the PC's rs232 level converter is damaged ? or I should be driving the db9 ttl-to-rs232 adapter with 5v and not 3v?

One other small note:
start compiling with -O2 optimization!!!

/*
 ***********************************************************************
 *name:         Samuel Igwe
 *date:         07/04/2015
 *description:  main ... what else
 *              phase 1:        system initialization
 *                              led + timer
 *              phase 2:        the above with 
 *                              uart communication 115200
 *                              simple monitor program 
 *              phase 3:        the above with
 *                              fpga setup in order to control LED's 
 *                              enabling static and dram memory controller
 *              phase 4:        the above with
 *                              usb host support in place for gamepads
 *                              /mouse/keyboards        
 *              phase 5:        the above with
 *                              extended fpga support for usb controller
 *                              glue logic. 
 ***********************************************************************
 */
#include "main.h"

void    test_determine_fractional_divider_values(void);


int
main(void)
{
    volatile unsigned int wdTemp;
    const             int wdGpio=18, wdTestVal='0';
    asm ("ldr sp, =0x10010000");

    setup_pll();
    setup_nvic();
    setup_gpio();

    setup_gpdma();
    setup_uart();
        
    gpio_set_lpc_biled(0);
    while(1)
        {
        //wdTemp++;
        //uartio_printf("%d\r", wdTemp);
        //      (LPC_GPIO1->SET) = (1 << wdGpio); 
        //uartio_putc(wdTestVal);
        //      (LPC_GPIO1->CLR) = (1 << wdGpio); 

        test_determine_fractional_divider_values();
        }
}





/*
 ***********************************************************************
 description:   fractional divider test routine. used to tweak the uart
                baud rate clock
 notes:         for this to work - put a paper clip between pin 2(rx) 
                and pin 3(tx) of the serial cable. which effectively 
                creates a loop back.
                then set a break point where the "if" test of the data
                read back evaluates as true
 ***********************************************************************
 */
void
test_determine_fractional_divider_values(void)
{
    volatile unsigned int wdTemp, wdCount, wdErrorFlag;
    volatile unsigned int wdMulVal, wdDivAddVal;
    const    int          wdGpio=18, wdTestVal='0';


        
    /*
     *******************************************************************
     cycle through the 14 x 15 fractional divider values
     reset RX fifo
     wait 1mS after setting fractional dividers

     write and read back three values in succession
     turn on flag if any error
   
     evaluate results
     *******************************************************************
     */
    for(wdMulVal = 1; wdMulVal <= 15; wdMulVal++)
        {
        for(wdDivAddVal = 0; wdDivAddVal <= 15; wdDivAddVal++)
                {
                wdTemp  = (wdMulVal << 4);
                wdTemp |=  wdDivAddVal;
                EGWU_ONBOARD_UART->FDR = wdTemp;
                timer_delay_mS(1);              
                EGWU_ONBOARD_UART->FCR |= UART_FCR_RX_RS;


                for(wdCount = 0, wdErrorFlag = 0; wdCount < 3; wdCount++)
                        {
                        uartio_putc(wdTestVal + wdCount);
                        if((uartio_getc()) != (wdTestVal + wdCount))
                                wdErrorFlag++;
                        }


                if(wdErrorFlag == 0)
                        {
                        uartio_putc(wdMulVal);
                        uartio_putc(wdDivAddVal);
                        }
                }
        }



    /*
     *******************************************************************
     flash bi-LED in a sequence every 500mS
     *******************************************************************
     */
    do
        {
        wdTemp++;
        gpio_set_lpc_biled(wdTemp);
        timer_delay_mS(500);
        }while(1);
}
 
 
 
 
 

Friday, November 27, 2015

Phase 2: UART the sunshine of my life ...

I took thanksgiving week off (as I do every year) and decided to put an end to a problem that has plagued me off and on for almost a month. I would love to say I was focused on it in all that time but alas I wasnt ... but this week I was.

So I modified the test program to toggle a GPIO pin that I am to use as external trigger for the scope. I needed a clear picture of what the output looked like. Then I simple configured the uart channel 0 and wrote '0' or 0x30 (ascii code) to the data register

Originally my configuration settings for the LPC1788 uart is based on the peripheral clock which is the cpu clock/4 (for my test case). Thats 40Mhz.

So if you did the math based on the data sheet you can generate both a Uart clock divider and a fractional divider (divaddval and mulval).

This is nicely summarized in the comment section of the function setup_uart in the file IE_egwu_setup.c

     ************************************************************************
     *governing formula is as follows:
     *Uart(baudrate) =  PCLK (40Mhz)/16 x (256 x DLM) + DLL x (1 + DivVal/MulVal)
     *constraints
     *                  1 <= MulVal     <= 15
     *                  0 <= DivAddVal  <= 14
     *                  DivAddVal       <  MulVal
     *[for 115200]
     ************************************************************************
     *115200 = 40Mhz/16 x [(256 x DLM) + DLL x (1 + D/M)
     *115200 = 40Mhz/16 x DLest
     *DLest  = 21.7
     *FRest  = 1.5
     ************************************************************************
     *DLest  = INT(40Mhz/(16 x 115200 x FRest)
     *FRest  = 40Mhz/(16 x 115200 x DLest)
     ************************************************************************
     *DLest  = INT(14.46) = 14
     *FRest  = 1.55
     ************************************************************************
     *this satisfies the condition 1.1 < Frest < 1.9
     *DL     = INT(40Mhz/(16 x 115200 x 1.55) = 14
     *DL*FR  = 14 x 1.55 =  21.7
     ************************************************************************
     *from the table
     *DivAdd = 5
     *MulVal = 9
     ************************************************************************
 
The problem however is that this setting the the fractional dividers above and below the chosen value above ... produce gibberish under minicom on my PC. Transmits and Receives have FRAMING errors - alignment issues.

A close look at the scope showed that value 0x30 was there, but compressed in time.



It occupied 3.6*20e-6 or 72uS. That means there are 13,888 bytes transmitted in one second. Thats verses the ideal of 115200/10 (1 start bit, 8 bits of data and 1 stop bit) = 11,520

The MulVal and DivAddVal fractional clock divider  values can be experimented with. The result is an improvement in uart baud clock and a reduction of bit error rates. But there are 14 such values for MulVal and 15 for DivAddVal.

My first thought was to modify my test program to cycle through the 210 possible combinations while writing 0x30 or '0'. Then I can look at the minicom logs searching for when '0' occurs.

That worked but was tedious in terms of finding out which combination generated that.

A further modification of my program involved
1. setting fractional divider values
2. writing '0'
3. in a loop - emptying receiver fifo
4. looking for '0'
5. displaying the value of MulVal and DivAddVal


On the cable end I just put a paper clip between pins 2 and 3 (RX and TX) creating a loop back. Then just set a break point for when the "if" statement becomes true.

#include "main.h"

#define FRAC_TEST       1
#define TEST_VALUE      '0'



int
main(void)
{
volatile unsigned int wdTemp, wdCount, wdLast;
volatile unsigned int wdMulVal, wdDivAddVal;
const    int          wdGpio=18;
unsigned char sbString[10];


asm ("ldr sp, =0x10010000");

setup_pll();
setup_nvic();
setup_gpio();
gpio_set_lpc_biled(0x3);

wdTemp = 0;

setup_gpdma();
setup_uart();
        
gpio_set_lpc_biled(0x0);

while(1)
        {
        //wdTemp++;
        //uartio_printf("%d\r", wdTemp);
#ifdef  FRAC_TEST
        for(wdMulVal = 1; wdMulVal <= 15; wdMulVal++)
                {
                for(wdDivAddVal = 0; wdDivAddVal <= 15; wdDivAddVal++)
                        {
                        wdTemp  = (wdMulVal << 4);
                        wdTemp |=  wdDivAddVal;
                        EGWU_ONBOARD_UART->FDR = wdTemp;

#endif

                        (LPC_GPIO1->SET) = (1 << wdGpio); 
                        uartio_putc(TEST_VALUE);
                        (LPC_GPIO1->CLR) = (1 << wdGpio);  
                        wdLast = 0;
                        while((wdTemp = uartio_getch()) != 0)
                                wdLast = wdTemp;

                        if(wdLast == TEST_VALUE)
                                {
                                sbString[0] = 'D';
                                sbString[1] = '=';
                                IE_tclib_itoa(wdDivAddVal,sbString+2);

                                uartio_putc(0xd);
                                for(wdCount = 0; wdCount <10; wdCount++)
                                        {
                                        if(sbString[wdCount] == 0)
                                                break;
                                        else
                                                uartio_putc(sbString[wdCount]);
                                        }

                                sbString[0] = 'M';
                                sbString[1] = '=';
                                IE_tclib_itoa(wdMulVal,sbString+2);

                                uartio_putc(0xd);
                                for(wdCount = 0; wdCount <10; wdCount++)
                                        {
                                        if(sbString[wdCount] == 0)
                                                break;
                                        else
                                                uartio_putc(sbString[wdCount]);
                                        }

                                        
                                while(1)
                                        ;
                                }

#ifdef  FRAC_TEST
                        timer_delay_mS(1);
                        }
                }
#endif
        }
}



That worked marvelously.
When the breakpoint hit, I examined wdMulVal and wdDivAddVal (both equal to 1). Fearing a mistake, I then proceeded to write a read a bunch of values to the uart data register (both RX and TX fifos are 16 bytes wide).


(gdb) load
Loading section .data, size 0x160 lma 0x10000000
Loading section .text, size 0x3470 lma 0x10000160
Start address 0x10001a54, load size 13776
Transfer rate: 20 KB/sec, 2755 bytes/write.
(gdb) c
Continuing.

Breakpoint 1, main () at app/main.c:34
34 const    int          wdGpio=18;
(gdb) c
Continuing.

Breakpoint 2, main () at app/main.c:76
76     sbString[0] = 'D';
(gdb) p wdDivAddVal 
$1 = 15
(gdb) p wdMulVal 
$2 = 1
(gdb) 



I was satisfied with the results.


Breakpoint 2, main () at app/main.c:76
76     sbString[0] = 'D';
(gdb) p wdMulVal 
$5 = 1
(gdb) p wdDivAddVal 
$6 = 1
(gdb) monitor mdw 0x4000c000 
0x4000c000: 00000030 
(gdb) 
0x4000c000: 00000000 
(gdb) monitor mww 0x4000c000 0x34
(gdb) monitor mdw 0x4000c000 
0x4000c000: 00000034 
(gdb) monitor mww 0x4000c000 0x32
(gdb) monitor mdw 0x4000c000 
0x4000c000: 00000032 
(gdb) monitor mww 0x4000c000 'a'
Invalid command argument
value option value (''a'') is not valid
in procedure 'mww'
(gdb) monitor mww 0x4000c000 0xd
(gdb) monitor mdw 0x4000c000 
0x4000c000: 0000000d 
(gdb) set wdTemp = 'c'
(gdb) print /x wdTemp
$7 = 0x63
(gdb) monitor mww 0x4000c000 0x61
(gdb) monitor mww 0x4000c000 0x62
(gdb) monitor mww 0x4000c000 0x63
(gdb) monitor mww 0x4000c000 0x30
(gdb) monitor mww 0x4000c000 0xd
(gdb) monitor mww 0x4000c000 0x0
(gdb) monitor mdw 0x4000c000 
0x4000c000: 00000061 
(gdb) 
0x4000c000: 00000062 
(gdb) 
0x4000c000: 00000063 
(gdb) 
0x4000c000: 00000030 
(gdb) 
0x4000c000: 0000000d 
(gdb) 
0x4000c000: 00000000 
(gdb) 
0x4000c000: 00000000 
(gdb) 
0x4000c000: 00000000 
(gdb) print wdDivAddVal 
$8 = 1
(gdb) print wdMulVal 
$9 = 1
(gdb) monitor mdw 0x4000c000 10
0x4000c000: 00000000 00000001 000000c1 00000003 00000000 00000060 00000000 00000000 
0x4000c020: 00000000 00000000 
(gdb) monitor mdw 0x4000c000 20
0x4000c000: 00000000 00000001 000000c1 00000003 00000000 00000060 00000000 00000000 
0x4000c020: 00000000 00000000 00000011 00000000 00000080 00000000 00000000 00000000 
0x4000c040: 00000000 00000000 00000000 00000000 
 

I looked at the scope output to verify what I expected to see ~4.2 * 20e-6 = 84uS. Which means a new character is generated roughly 11,904 times a second. I can live with that and so can the UART ;)










Things should move more swiftly after this. I can proceed with the monitor program (already written in my notebook) after I test DMA controlled UART transmission later this weekend ... Phase 3 cant come soon enough for me ....

Monday, November 9, 2015

Phase 2: RS-232 blues continued ...

To make debugging with the scope easier ... I modified the code to toggle a pin high before writing to the uart, so I can use it as an external trigger for scope channel A.

while(1)
        {
        //wdTemp++;
        //uartio_printf("%d\r", wdTemp);

        (LPC_GPIO1->SET) = (1 << wdGpio); 
        //timer_delay_mS(1);
        uartio_putc(0x30);
        (LPC_GPIO1->CLR) = (1 << wdGpio);  
        //timer_delay_mS(1);
        }
 
Was able to verify UART TTL output on the TX line and later the level converted value out of the MAX232. But there were problems with the db9 connector so I set that aside to test out connector K1 the second serial port (uart0) (db9 was uart1) and the ttl-to-uart adapter pictured below







But I discovered problems with its MAX232 part and had it replaced, then I got the expected output. The pin out of a DB9 viewed from left to right is (female)  x = dont care
1. x
2. RX
3. TX
4. x
5. GND

ON this part I detected output on pin 2 which meanth it had a NULL modem wiring (RX-to-TX) so I needed a straight feed through serial cable between it and my development PC' serial port.




The ascii code above represents the value 0x30 or '0' (decimal 0). The length of the character transmission (on the scope) is ~70uS (3.5 bars at 20uS). That means ~14,285 characters are transmitted a second.

Makes sense since 115200/8 bits = 14,400 and I was eyeballing the above values.

On the scope everything looks fine for uart-TTL and uart-RS232. But I see gibberish under minicom and the uart line status register on the lpc1778 reports framing errors (missing stop/start bits?)

`�H `�H �

I even switched the baud rate down to 9600 to the same results.
Ill start looking at cabling later this week. I already tested one set of cables with an stm32 devel board I had lying around ... and it was fine.

Note to self:
here is a method for reading raw values out of the serial port
stty raw
cat >/tmp/received.dat </dev/ttyS0  
(i wonder what setting it inherits for baudrate)
hexdump -n 256 /tmp/received.dat
stty normal or stty sane
returns the terminal emulator to its sane setting

Phase 2: RS-232 blues

Waylaid by my need to get the terminal and monitor program tested. First the serial port. Found two errors ... after hours on the scope


1. I had mistakenly tied one end of one of the charge pump capacitors to ground. That would be capacitor C81 between pin 2 of the MAX232 level converter and ground instead of VCC



2. Digging through the MAX232 datasheet, I realized the charge pump capacitors I chose were 0.1uF. These are recommended when VCC is 3.3v. When its 5v (as in my design) the charge pump capacitors must not be less than 1uF.

So I had them replaced along with the ttl-to-rs232 level converter.








Went back and checked and double checked the UART baud rate clock and fractional divider parameters for both 9600 baud and 115200 baud. The peripheral clock is 40Mhz ... derived from the base 120Mhz system clock.