Monday, July 27, 2015

Phase 1: Complete




blogger.com actually allows you to upload a video. cool. first time trying out this feature .. without specifying a youtube link.

video above is the completion of phase 1. was out on sick day today ... took the time to bug hunt after I got some sleep. system/pll/systick/interrupts/gpio all configured. but there were issues:

found a bug with my interrupt vector table initialization for the 256 positions (the maximum possible) though the lpc17xx only provides 40 peripheral interrupts for a total of 56 when you include the 16 core exceptions.

I was stupidly overwriting portions of the code in SRAM. this bug was easy to catch  ... it was a silly mistake because I actually wanted to cover the best case scenario and reserve the first 1k for the IVT.
then I later decided what the hell thats a waste of space when only 224 bytes will be used I could save almost 700 bytes to use for program memory or a thread stack

in my Makefile now specifying
-fno-inline
and
-fno-implement-inlines

to decrease code size bloat. although I have 512kb of flash ROM, i am loading the code into the 64k of SRAM to make debugging easier. in flash rom i would be limited to 4 or 6 hardware break points verses an unlimited amount when I load into SRAM ... so I am sticking to SRAM for now, but to pull that off I have to stick to non macro functions to keep the size of the program in check.


changed NVIC pre-rempt priority grouping to 2. Allowing me to use all 32 interrupt priority levels.

Configured exceptions 4 + 5 + 6   to priority level 0
                                     11+14        to priority level 1
                                     15 (systick)to priority level 2
all peripheral interrupts will start from priority level 3 (highest)  to 31 (lowest)

Absolutely no interrupt nesting ... keep interrupts small and simple. The NVIC does handle that feature (nesting and tail chaining) in hardware  ... a big plus

bug in failing to call
Calling  NVIC_EnableIRQ(15) after setting up systick registers. Dumped the interrupt SET/ENA registers and realized it wasnt set

Found a bug in how lpcopen' Chip_GPIO_GetPinState() works. Decided to read the pin directly and write it out to toggle the keep-alive-LED



//wdTemp = Chip_GPIO_GetPinState(LPC_GPIO1, LPC_LED_PORT, LPC_LED_PIN);
//Chip_GPIO_SetPinState(LPC_GPIO1, LPC_LED_PORT, LPC_LED_PIN, wdTemp);

wdTemp = (((LPC_GPIO1->PIN) >> LPC_LED_PIN) & 0x1);
wdTemp ^= 0x1;
if(wdTemp == 0)
        (LPC_GPIO1->CLR) = (1 << LPC_LED_PIN); 
else
        (LPC_GPIO1->SET) = (1 << LPC_LED_PIN); 




Phase 2 begins now. Need to write a useful serial terminal monitor program to ease communication with this board.

2:40am ... powering down ... engaging sleep mode routines

Sunday, July 19, 2015

Phase 1: Interrupt Vector Table not being initialized

the offending lines are in egwu_setup_nvic(). here is the gdb dump:

target halted due to debug-request, current mode: Thread
xPSR: 0x01000000 pc: 0x1fff0080 msp: 0x10001ffc
(gdb) load
Loading section .text, size 0x1c78 lma 0x10000000
Start address 0x10000e38, load size 7288
Transfer rate: 1 KB/sec, 3644 bytes/write.
(gdb) c
Continuing.

Breakpoint 1, egwu_setup_nvic () at core/IE_egwu_setup.c:167
167        ptrTemp = (volatile unsigned int *)EGWU_IVT;
(gdb) p /x EGWU_IVT
$1 = 0x10010000
(gdb) monitor mdw 0x10000000
0x10000000: 10010000
(gdb) monitor mdw 0x10000004
0x10000004: 10000e39
(gdb)

And of course EGWU_IVT is declared in IE_egwu_ivt.S. This is where the vector table is placed along with the labels EGWU_IVT and EGWU_IVT_END. I also created an extern int EGWU_IVT in IE_setup.h

But the value of the label EGWU_IVT resolves to the first value in the table (the address of the stack pointer on reset). but in the map file flash.map

 .text        0x0000000010000000       0xe0 ivt.o
                0x0000000010000000                EGWU_IVT
                0x00000000100000e0                EGWU_IVT_END


Just now noticed that &EGWU_IVT resolves to 0x10000000 as expected.

(gdb) p /x &EGWU_IVT
$2 = 0x10000000


Very odd, will need to go reread the "as" assembler documentation. Its customary for the value of a label to represent the value of the location counter at that point.


Anyway this is resolved ... moving on

Friday, July 10, 2015

Phase 1: No external clock

ran into the following problem last night when I ran my initialization code, that I decided to manually check this out myself:

arm-none-eabi-gdb
JTAG tap: lpc1788.cpu tap/device found: 0x4ba00477 (mfg: 0x23b, part: 0xba00, ver: 0x4)
Only resetting the Cortex-M core, use a reset-init event handler to reset any peripherals or configure hardware srst support.
target state: halted
target halted due to debug-request, current mode: Thread
xPSR: 0x01000000 pc: 0x1fff0080 msp: 0x10001ffc

(gdb) monitor mdw 0x400fc1b0
0x400fc1b0: 00000003
(gdb) monitor mdw 0x400fc1a0
0x400fc1a0: 00000009
(gdb) monitor mww 0x400fc1a0 0x39
(gdb) monitor mdw 0x400fc1a0
0x400fc1a0: 00000039
(gdb)

Basically after setting bits 4 and 5 of the system control register I checked to see if bit 6 (OSC status) would return a 1 ... meaning the external crystal/clock driver is enabled and I can switch clock sources from the internal 8Mhz RC clock to the precise 24Mhz external clock source Ill need later.

No dice

Looked at section 3.8.2 of the lpc1778 reference manual. Noticed that Cx1 and Cx2 should be either 18pf each or 39pf each depending on what the crystal (JF VNY 24Mhz) Cs and Rl parameters are.

Brought up my schematic and noticed this mistake:



Dont know what I was thinking when I put in a 12pf capacitor where an 18pf or 39pf cap was needed. Knowing my luck its probably the latter ... Ill know once I track down the crystal data sheet.

In either case I bought both on ebay (50 of each) but it wont get here until at least another two or three weeks ($1.50 for 50 ... cheaper from China but long wait times. I could have gotten it from Mouser but I dont need it that quick).

Fortunately all isnt lost. I dont need a precise time piece for well into Phase 3 when I start configuring the USB and External Memory controller blocks. And the lpc1778 provides an 8Mhz RC clock on chip for simple applications ... use able well into developing the terminal monitor program

Monday, July 6, 2015

Phase 1: openocd woes - resolution

I printed the openocd 0.10.0 manual and decided to log unto IRC ' #freenode server and #openocd channel to get some pointers in the right direction.

As luck would have it I met up with Paul Frertser, as I happened to be reading his response to another openocd user's question on lpc17xx configuration at:
comments.gmane.org/gmane.comp.debugging.openocd.devel/25169

Actually I posted my question on the main channel (#openocd) and he responded and during that conversation I was able to point to my blog and entries related to script file setup for openocd. I sent him a copy of the section of EGWU schematic where the ft2232 ' channel 0 is interfaced to the lpc1788' JTAG lines

He responded with the following suggestions
1. replace my current ftdi_layout_init assignment with
ftdi_layout_init 0x0008 0x000b
ftdi_layout_signal nTRST -data 0x0010
use reset_config trst_only in the board script

*** this worked
openocd_ftdi
Open On-Chip Debugger 0.9.0 (2015-07-05-17:44)
Licensed under GNU GPL v2
For bug reports, read
    http://openocd.org/doc/doxygen/bugs.html
Info : auto-selecting first available session transport "jtag". To override use 'transport select <transport>'.
adapter speed: 10 kHz
adapter_nsrst_delay: 1000
jtag_ntrst_delay: 1000
cortex_m reset_config sysresetreq
cortex_m reset_config sysresetreq
Info : clock speed 10 kHz
Info : JTAG tap: lpc1788.cpu tap/device found: 0x4ba00477 (mfg: 0x23b, part: 0xba00, ver: 0x4)
Info : lpc1788.cpu: hardware has 6 breakpoints, 4 watchpoints
Info : accepting 'gdb' connection on tcp/3333
Error: Target not halted
undefined debug reason 7 - target needs reset
Info : JTAG tap: lpc1788.cpu tap/device found: 0x4ba00477 (mfg: 0x23b, part: 0xba00, ver: 0x4)
target state: halted
target halted due to debug-request, current mode: Thread
xPSR: 0x01000000 pc: 0x1fff0080 msp: 0x10001ffc


2. use "extended-remote" in .gdbinit script and replace arm-linux-gnueabi-gdb with gdb-arm-none-eabi as the latter is more stable and caters to what I am doing and will lively resolve the error messages about unknown architecture in file

***this worked
as a side note
apt-get install gdb-arm-none-eabi also installs
arm-none-eabi-binutils
arm-none-eabi-gcc
arm-none-eabi-ld
libnewlib-arm-none-eabi

so I am going to modify my Makefile to use the above instead of the linux-eabi
versions

also gdb-arm-none-eabi ./app.out
JTAG tap: lpc1788.cpu tap/device found: 0x4ba00477 (mfg: 0x23b, part: 0xba00, ver: 0x4)
target state: halted
target halted due to debug-request, current mode: Thread
xPSR: 0x01000000 pc: 0x1fff0080 msp: 0x10001ffc
Reading symbols from app.out...done.
(gdb) load
Loading section .data, size 0xe0 lma 0x10000000
Loading section .text, size 0x1ca8 lma 0x100000e0
Start address 0x10000f48, load size 7560
Transfer rate: 1 KB/sec, 2520 bytes/write.
(gdb) start
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Temporary breakpoint 1 at 0x10000f4c: file app/main.c, line 29.


3. dispense with running openocd as root ... copy contrib/99-openocd.rules into my /etc/udev/rules.d

*** to be done tomorrow


4. consider adding the following flags to CFLAGS/LDFLAGS
-ffunction-sections -fdata-sections -Wl, --gc-sections

*** to be done tomorrow
I hadnt looked at the gcc/ld manual for over 3 years. So the current CFLAGS/LDFLAGS were created from when I worked on the arm7tdmi but later modified slightly to support the cortex-m3 which has no arm (thumb2 only) mode


As I just returned from the laundromat (30 mins ago) and in need of some serious sleep (still wanted to test out these suggestions)  ... its time to pack it in for the night

Sunday, July 5, 2015

Phase 1: openocd woes

encountered some problems getting openocd + jtag interface up and running. the ftdi driver has superceeded the ft2232 but the latter at least produces a connection ... example:


using recently upgraded 0.9.0 (openocd)
***using "interface ft2232" script
openocd_ft2232
Open On-Chip Debugger 0.9.0 (2015-07-05-17:44)
Licensed under GNU GPL v2
For bug reports, read
    http://openocd.org/doc/doxygen/bugs.html
Info : only one transport option; autoselect 'jtag'
adapter speed: 10 kHz
adapter_nsrst_delay: 1000
jtag_ntrst_delay: 1000
cortex_m reset_config sysresetreq
cortex_m reset_config sysresetreq
Warn : Using DEPRECATED interface driver 'ft2232'
Info : Consider using the 'ftdi' interface driver, with configuration files in interface/ftdi/...
Info : max TCK change to: 30000 kHz
Info : clock speed 10 kHz
Info : inter: 0.000102, inter2: 0.000102 end: 0.069985
Info : JTAG tap: lpc1788.cpu tap/device found: 0x4ba00477 (mfg: 0x23b, part: 0xba00, ver: 0x4)
Info : inter: 0.000163, inter2: 0.000163 end: 0.001911
Info : inter: 0.000134, inter2: 0.000134 end: 0.033913
Info : inter: 0.000154, inter2: 0.000154 end: 0.017895
Info : inter: 0.000180, inter2: 0.000180 end: 0.057936
Info : inter: 0.000155, inter2: 0.000155 end: 0.031909
Info : inter: 0.000160, inter2: 0.000160 end: 0.019909
Info : inter: 0.000102, inter2: 0.000102 end: 0.023956
Info : inter: 0.000063, inter2: 0.000063 end: 0.019930
Info : inter: 0.000063, inter2: 0.000064 end: 0.019930
Info : inter: 0.000092, inter2: 0.000092 end: 0.019954
Info : inter: 0.000166, inter2: 0.000167 end: 0.020112
Info : inter: 0.000122, inter2: 0.000122 end: 0.019744
Info : inter: 0.000076, inter2: 0.000076 end: 0.019959
Info : inter: 0.000050, inter2: 0.000050 end: 0.019932
Info : inter: 0.000041, inter2: 0.000041 end: 0.019923
Info : inter: 0.000067, inter2: 0.000068 end: 0.023947
Info : inter: 0.000042, inter2: 0.000042 end: 0.019936
Info : inter: 0.000160, inter2: 0.000160 end: 0.019910
Info : inter: 0.000060, inter2: 0.000060 end: 0.019952
Info : inter: 0.000143, inter2: 0.000143 end: 0.019890
Info : lpc1788.cpu: hardware has 6 breakpoints, 4 watchpoints

arm-linux-gnueabi-gdb ./app.out produces
target state: halted
target halted due to debug-request, current mode: Thread
xPSR: 0x01000000 pc: 0x1fff0080 msp: 0x10001ffc
inter: 0.000265, inter2: 0.000266 end: 0.019667
inter: 0.000043, inter2: 0.000043 end: 0.019801
(gdb) load
Loading section .data, size 0xe0 lma 0x10000000
Loading section .text, size 0x1ca8 lma 0x100000e0
Start address 0x10000f49, load size 7560
Ignoring packet error, continuing...
Reply contains invalid hex digit 79



***using "interface ftdi" script
at least this turns on the BILED segment i chose in "data" argument to ftdi_layout
openocd_ftdi
Open On-Chip Debugger 0.9.0 (2015-07-05-17:44)
Licensed under GNU GPL v2
For bug reports, read
    http://openocd.org/doc/doxygen/bugs.html
Info : auto-selecting first available session transport "jtag". To override use 'transport select <transport>'.
adapter speed: 10 kHz
adapter_nsrst_delay: 1000
jtag_ntrst_delay: 1000
cortex_m reset_config sysresetreq
cortex_m reset_config sysresetreq
Info : clock speed 10 kHz
Error: JTAG scan chain interrogation failed: all ones
Error: Check JTAG interface, timings, target power, etc.
Error: Trying to use configured scan chain anyway...
Error: lpc1788.cpu: IR capture error; saw 0x0f not 0x01
Warn : Bypassing JTAG setup events due to errors
Warn : Invalid ACK 0x7 in JTAG-DP transaction
Warn : Invalid ACK 0x7 in JTAG-DP transaction
Warn : Invalid ACK 0x7 in JTAG-DP transaction
Warn : Invalid ACK 0x7 in JTAG-DP transaction
Warn : Invalid ACK 0x7 in JTAG-DP transaction
Warn : Invalid ACK 0x7 in JTAG-DP transaction
Warn : Invalid ACK 0x7 in JTAG-DP transaction
Warn : Invalid ACK 0x7 in JTAG-DP transaction
Warn : Invalid ACK 0x7 in JTAG-DP transaction
Warn : Invalid ACK 0x7 in JTAG-DP transaction

Need to resolve this before going forward. And for now I think it best I stick to using the ftdi interface



now that I have moved and settled into a new place. attaching an updated picture of a section of the lab. parts are still in bins inside the closets


Phase 1: app



/*
 ***********************************************************************
 *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
main()
{
asm ("ldr sp, =0x10010000");

egwu_setup_pll();
egwu_setup_gpio();
egwu_setup_nvic();
egwu_setup_uart();

egwu_set_lpc_biled(0x3);
while(1)
 ;
}
 
 
 

Phase 1: core

/*
 **********************************************************************
 *name:         IE_EGWU_IVT.S
 *author:       Samuel Igwe
 *date:         06/30/2015
 *description:  Igbo Embedded EGWU_IVT.S source
 *              the interrupt vector table starts with the initial 
 *              stack address followed by the addresses of the function
 *              and ISR's. just allocate the space - leave it vacant
 *note:  this must be linked in first when building the .out file
 *              since i plan on remmapping VTOR to point to the IVT at
 *  the start of SRAM memory
 **********************************************************************
 */


#ifndef IE_EGWU_IVT_H

.global EGWU_IVT
.global EGWU_IVT_END
.extern main
.equ LPC177X_SRAM_BASE, 0x10000000
.equ    LPC177X_NUM_INT  , 40
.data
.align 4
EGWU_IVT:       .word   LPC177X_SRAM_BASE + (64 * 1024)
                .word   (main + 1)
                .skip   (14 * 4)
                .skip   (LPC177X_NUM_INT * 4)
EGWU_IVT_END:
#endif

 
 
 
 
/*
 ****************************************************************************
 *name:         IE_egwu_setup.h
 *author:       Samuel Igwe
 *date:         06/30/2015
 *description:  pll/clock/iopin initialization
 ****************************************************************************
 */
#ifndef IE_EGWU_SETUP_H
    #define     LPC177X_NUM_INT                 40
    #define     EGWU_CPU_CLK_RATE               120000000
    #define     EGWU_CPU_OSC_RATE               24000000
    #define     EGWU_SYSTICK_RATE               (EGWU_CPU_CLK_RATE/1000)

    #define     LPC177X_SRAM_BASE               0x10000000


    #define     LPC_BILED_PORT                  1
    #define     LPC_BILED_PIN1                  23
    #define     LPC_BILED_PIN2                  24

    #define     LPC_LED_PORT                    1
    #define     LPC_LED_PIN                     8

    #define     EGWU_NVIC_USER_BILED_MASK       0x1
    #define     EGWU_NVIC_FAULT_BILED_MASK      0x2



    #include "chip.h"
    #include "chip_lpc177x_8x.h"


    struct      STR_EGWU_SYSTICK        {
        volatile unsigned int wdSeconds;
        volatile unsigned int wdTicks;
        }strSysTick;

    

    #define     EGWU_UART_BUFFER_SIZE           64
    struct      STR_EGWU_UART           {
        volatile unsigned int  wdMutex;
        volatile unsigned int  wdCount;
        volatile unsigned int  wdIndex;
        volatile unsigned char sbBuf[EGWU_UART_BUFFER_SIZE];
        }strUart;

 
    extern      int     EGWU_IVT;
    const       uint32_t OscRateIn;


    void        egwu_setup_pll(void);
    void        egwu_setup_nvic(void);
    void        egwu_setup_gpio(void);
    void        egwu_setup_uart(void);

    void        egwu_nvic_systick_isr(void);
    void        egwu_nvic_fault_isr(void);
    void        egwu_nvic_user_isr(void);

    void        egwu_set_lpc_biled(unsigned int wdLedMask);

#endif
 
 
 
 
 
/*
 ****************************************************************************
 *name:         IE_egwu_setup.c
 *author:       Samuel Igwe
 *date:         06/30/2015
 *description:  pll/clock/iopin/nvic initialization
 ****************************************************************************
 */
#ifndef IE_EGWU_SETUP_C
#include "IE_egwu_setup.h"





/*
 ****************************************************************************
 *description:  pll/clock.
 *inputs:       none
 *note:         main pll (0)        m=5        p=1    
 *                              pllin=24  pllout=120  fcco=240  
 *               alt pll (1)        m=2        p=2
 *                              pllin=24  pllout48    fcco=192
 *
 *              the condition pllin  = 1 < 25Mhz and fcco = 156 -> 320 has 
 *              has been satisfied
 *              cpu = 120Mhz
 *              emc =  60Mhz
 *              gpio=  40Mhz
 *
 *              when using the internal oscillator aim for 120Mhz as well
 *              main pll (0)        m=10       p=1
 *                              pllin=12  pllout=120  fcco=240
 ****************************************************************************
 */
void
egwu_setup_pll(void)
{
    /*
     ************************************************************************
     *switch to using default clock source
     ************************************************************************
     */
    Chip_Clock_SetMainPLLSource(SYSCTL_PLLCLKSRC_IRC);
    Chip_Clock_SetCPUClockSource(SYSCTL_CCLKSRC_SYSCLK);
    Chip_Clock_DisablePLL(SYSCTL_MAIN_PLL, SYSCTL_PLL_ENABLE);
    Chip_Clock_DisablePLL(SYSCTL_USB_PLL,  SYSCTL_PLL_ENABLE);


    /*
     ************************************************************************
     *use the internal rc clock for phase 1 and 2, while await replacement
     *caps for the crystal oscillator driver
     ************************************************************************
     */
#ifdef  EXT_CLK
    Chip_Clock_SetCrystalRangeHi();
    Chip_Clock_EnableCrystal();

    if((Chip_Clock_IsCrystalEnabled()) == TRUE)
        Chip_Clock_SetCPUClockSource(SYSCTL_CCLKSRC_MAINPLL);

    Chip_Clock_SetupPLL(SYSCTL_MAIN_PLL, 5, 1);
    Chip_Clock_SetupPLL(SYSCTL_USB_PLL,  2, 2);

    Chip_Clock_EnablePLL(SYSCTL_MAIN_PLL, SYSCTL_PLL_ENABLE);
    Chip_Clock_EnablePLL(SYSCTL_USB_PLL,  SYSCTL_PLL_ENABLE);
#else
    Chip_Clock_SetupPLL(SYSCTL_MAIN_PLL, 10, 1);
    Chip_Clock_EnablePLL(SYSCTL_MAIN_PLL, SYSCTL_PLL_ENABLE);
#endif


    /*
     ************************************************************************
     *delay a bit to let the logic do its thing
     ************************************************************************
     */
    while(Chip_Clock_IsMainPLLLocked() == 0)
        ;

#ifdef  EXT_CLK
    Chip_Clock_SetMainPLLSource(SYSCTL_PLLCLKSRC_MAINOSC);
    while(Chip_Clock_IsUSBPLLLocked() == 0)
        ;
#endif


    /*
     ************************************************************************
     *resume initialization
     ************************************************************************
     */
    Chip_Clock_SetCPUClockDiv(1);
    Chip_Clock_SetCPUClockSource(SYSCTL_CCLKSRC_MAINPLL);

#ifdef  EXT_CLK
    Chip_Clock_SetUSBClockDiv(1);
    Chip_Clock_SetUSBClockSource(SYSCTL_USBCLKSRC_USBPLL);
    Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_USB);
#endif

    Chip_Clock_SetPCLKDiv(3);


    /*
     ************************************************************************
     *enable all the peripherals
     ************************************************************************
     */
    Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_TIMER0);
    Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_TIMER1);

    Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_UART0);
    Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_UART1);

    Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_RTC);

    Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_EMC);

    Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_I2C0);
    Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_I2C1);
    Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_I2C2);

    Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_SSP0);
    Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_SSP1);

    Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_USB);

    Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_GPDMA);

    Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_GPIO);


    /*
     ************************************************************************
     *enable emc and clkout
     ************************************************************************
     */
    Chip_Clock_SetEMCClockDiv(SYSCTL_EMC_DIV2); 
    Chip_Clock_SetCLKOUTSource(SYSCTL_CLKOUTSRC_MAINOSC, 3);
    Chip_Clock_EnableCLKOUT();
}





/*
 ****************************************************************************
 *description:  configure nvic
 *inputs:       none
 *notes:        assume vector table is the global "egwu_ivt"
 *              skip stack and reset positions
 *              default isrs
 *              egwu_nvic_fault_isr()
 *              egwu_nvic_systic_isr()
 *              egwu_nvic_user_isr()
 ****************************************************************************
 */
void
egwu_setup_nvic(void)
{
    volatile unsigned int wdTemp, *ptrTemp, wdCount;


    ptrTemp = (volatile unsigned int *)&EGWU_IVT;
    for(wdCount = 2; wdCount < (LPC177X_NUM_INT + 16); wdCount++)
        {
        if(wdCount < 15)                        /*faults*/
                wdTemp  = (int) egwu_nvic_fault_isr;
        else
                {
                if(wdCount == 15)               /*systick*/
                        wdTemp  = (int) egwu_nvic_systick_isr;
                else
                        wdTemp  = (int) egwu_nvic_user_isr;
                }

        
        wdTemp |= 1;                            /*thumb*/
        *(ptrTemp + wdCount) = wdTemp;
        }


    /*
     ************************************************************************
     *selecting nvic priority group 1  (there are 32 pre-rempt priority 
     *levels on the lpc17xx)
     *[7:3]     = preempt priority field (5 bits)
     *[2:0] = sub priority field         (3 bits)
     *
     *this allows me to allocate 32 interrupt priority levels thought I doubt
     *Id use that many interrupts in this project but one never knows
     *
     *for now set interrupts 
     *4 + 5 + 6 to priority level 0
     *11+14     to priority level 1
     *15 (timer)to priority level 2
     *interrupts 1 through 3 are fixed (reset to fault)
     ************************************************************************
     */
    NVIC_SetPriorityGrouping(1);
    for (wdCount = 4; wdCount <= 15; wdCount++)
        {
        if(wdCount <= 6)
                wdTemp = NVIC_EncodePriority(1, 0, (wdCount - 4));

        if(wdCount == 11 || wdCount == 14)
                wdTemp = NVIC_EncodePriority(1, 1, (wdCount - 11));

        if(wdCount == 15)
                wdTemp = NVIC_EncodePriority(1, 1, 0);


        NVIC_SetPriority(wdCount, wdTemp);
        }


    /*
     ************************************************************************
     *setup systick timer for 1mS tick
     *configure variables
     ************************************************************************
     */
    SysTick_Config(EGWU_CPU_CLK_RATE/1000);
    strSysTick.wdSeconds = 0;
    strSysTick.wdTicks   = 0;
    NVIC_EnableIRQ(15);


    /*
     ************************************************************************
     *cpu synchronization
     ************************************************************************
     */
    asm("dsb");
    asm("isb");


    /*
     ************************************************************************
     *enable mem/bus/usage fault interrupts
     ************************************************************************
     */
    wdTemp  = SCB_SHCSR_MEMFAULTENA_Msk;
    wdTemp |= SCB_SHCSR_BUSFAULTENA_Msk;
    wdTemp |= SCB_SHCSR_USGFAULTENA_Msk;
    SCB->SHCSR = wdTemp;


    /*
     ************************************************************************
     *remap vector table
     *enable interrupts on the processor level
     ************************************************************************
     */
    SCB->VTOR = LPC177X_SRAM_BASE;
    asm("cpsie i");
}





/*
 ****************************************************************************
 *description:  gpio configuration
 *inputs:       none
 *note:         mapping is as follows
 *              p0[00] - p0[01] =       fx4     =uart0
 *              p0[02] - p0[11] =       fx2     =sspi + i2c
 *              p0[12] - p0[13] =       fx1     =usb
 *              p0[15] - p0[18] =       fx2     =spi
 *              p0[23] - p0[25] =       fx1     =adc
 *              p0[26]          =       fx2     =dac
 *              p0[30]          =       fx0     =gpio1
 *              p0[31]          =       fx1     =usb
 *
 *              p1[02] - p1[10] =       fx0     =gpio
 *              p1[11] - p1[12] =       fx3     =pwm
 *              p1[14]          =       fx0     =gpio
 *              p1[18] - p1[19] =       fx0     =gpio3 and gpio4
 *              p1[23] - p1[24] =       fx0     =gpio (bi-led anode)
 *              p1[27]          =       fx4     =clkout
 *              p1[30] - p1[31] =       fx1     =usb
 *
 *              p2[00] - p[01]  =       fx1     =uart1
 *
 *              p2[10]          =       fx0     =isp_mode (dont use)
 *              p2[11]          =       fx1     =gbl_int
 *
 *              p2[14] - p2[31] =       fx1     =emc
 *
 *              p3[00] - p3[31] =       fx0     =emc
 *
 *              p4[00] - p4[31] =       fx0     =emc
 *
 *              p5[00] - p5[01] =       fx0     =emc
 ****************************************************************************
 */
void
egwu_setup_gpio(void)
{
    volatile unsigned int wdCount;


    /*
     ************************************************************************
     *port 3 and port 4 to function 1 and port 2 (14-31)
     ************************************************************************
     */
    for(wdCount = 0; wdCount < 32; wdCount++)
        {
        Chip_IOCON_PinMuxSet(LPC_IOCON, 3, wdCount, IOCON_FUNC1);
        Chip_IOCON_PinMuxSet(LPC_IOCON, 4, wdCount, IOCON_FUNC1);
        if(wdCount >= 14)
                Chip_IOCON_PinMuxSet(LPC_IOCON, 2, wdCount, IOCON_FUNC1);
        }


    /*
     ************************************************************************
     *port 0
     ************************************************************************
     */
    for(wdCount = 0; wdCount < 32; wdCount++)
        {
        if(wdCount <= 1)
                Chip_IOCON_PinMuxSet(LPC_IOCON, 0, wdCount, IOCON_FUNC4);
        else
                {
                if((wdCount >= 6  && wdCount <= 11) ||
                   (wdCount >= 15 && wdCount <= 18) ||
                   (wdCount == 26))
                        Chip_IOCON_PinMuxSet(LPC_IOCON, 0, wdCount, IOCON_FUNC2);
                else
                        {
                        if((wdCount >= 12 && wdCount <= 13) ||
                           (wdCount >= 23 && wdCount <= 25) ||
                           (wdCount == 31))
                                Chip_IOCON_PinMuxSet(LPC_IOCON, 0, wdCount, IOCON_FUNC1);
                        }
                }
        }


    /*
     ************************************************************************
     *port 1
     ************************************************************************
     */
    for(wdCount = 0; wdCount < 32; wdCount++)
        {
        if((wdCount >= 2  && wdCount <= 10) ||
           (wdCount >= 23 && wdCount <= 24) ||
           (wdCount == 14))
                Chip_IOCON_PinMuxSet(LPC_IOCON, 1, wdCount, IOCON_FUNC0);
        else
                {
                if(wdCount >= 11 &&  wdCount <= 12)
                        Chip_IOCON_PinMuxSet(LPC_IOCON, 1, wdCount, IOCON_FUNC3);
                else
                        {
                        if(wdCount  >= 30 && wdCount <= 31)
                                Chip_IOCON_PinMuxSet(LPC_IOCON, 1, wdCount, IOCON_FUNC1);
                        else
                                {
                                if(wdCount == 27)
                                        Chip_IOCON_PinMuxSet(LPC_IOCON, 1, wdCount, IOCON_FUNC4);
                                }
                        }
                }
        }


    /*
     ************************************************************************
     *port 2
     ************************************************************************
     */
    for(wdCount = 0; wdCount < 14; wdCount++)
        {
        if(wdCount <= 1)
                Chip_IOCON_PinMuxSet(LPC_IOCON, 2, wdCount, IOCON_FUNC2);
        else
                {
                if(wdCount >= 14)
                        Chip_IOCON_PinMuxSet(LPC_IOCON, 2, wdCount, IOCON_FUNC1);
                }
        }


    /*
     ************************************************************************
     *set direction for ports configured as gpio
     ************************************************************************
     */
    Chip_GPIO_SetPinDIRInput(LPC_GPIO, 0, 30);

    for(wdCount =0; wdCount < 32; wdCount++)
        {
        switch(wdCount)
                {
                case    2:
                case    5:
                case    9:
                case    10:
                case    14:
                        {
                        Chip_GPIO_SetPinDIRInput(LPC_GPIO, 1, wdCount);
                        break;
                        }
                case    3:
                case    4:
                case    6:
                case    7:
                case    8:
                case    23:
                case    24:
                        {
                        Chip_GPIO_SetPinDIROutput(LPC_GPIO, 1, wdCount);
                        break;
                        }
                }
        }
}





/*
 ****************************************************************************
 *description:  uart configuration
 *inputs:       none
 *notes:        using 40Mhz peripheral clock (cpuclock/3) to derive 115200 baud
 ****************************************************************************
 */
void
egwu_setup_uart(void)
{
    volatile unsigned int wdTemp;


    /*
     ************************************************************************
     *governing formula is as follows:
     *Uart(baudrate) =  PCLK (40Mhz)/16 x (256 x DLM) + DLL x (1 + DivVal/MulVal)
     *constraints
     *                  1 <= MulVal     <= 16
     *                  0 <= DivAddVal  <= 14
     *                  DivAddVal       <  MulVal
     ************************************************************************
     *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)
     ************************************************************************
     *many fractional dividers can work so I chose FRest = 1.1 from table 398
     *FRest =  1.1
     ************************************************************************
     *DLest =  INT(40Mhz/(16 x 115200 x 1.1) = 19
     *FRest =  40Mhz/(16 x 115200 x 19)      = 1.142
     *this satisfies the condition 1.1 < Frest < 1.9
     ************************************************************************
     *DivAdd  = 1
     *MulVal  = 7
     ************************************************************************
     *technical baud rate = 40Mhz/(16 x 115200 x z) z = 21 
     ************************************************************************
     */

    Chip_UART_EnableDivisorAccess(LPC_UART0);
    Chip_UART_SetDivisorLatches(LPC_UART0, 21, 0);
    Chip_UART_DisableDivisorAccess(LPC_UART0);


    /*
     ************************************************************************
     *8-N-1
     ************************************************************************
     */
    wdTemp  = UART_LCR_WLEN8;
    wdTemp |= UART_LCR_SBS_1BIT;
    wdTemp |= UART_LCR_PARITY_DIS;
    Chip_UART_ConfigData(LPC_UART0, wdTemp);

    LPC_UART0->FDR = (UART_FDR_MULVAL(7) | UART_FDR_DIVADDVAL(1)); 


    /*
     ************************************************************************
     *reset RX and TX blocks and enable fifos
     ************************************************************************
     */
    wdTemp  = UART_FCR_FIFO_EN;
    wdTemp |= UART_FCR_RX_RS;
    wdTemp |= UART_FCR_TX_RS;
    wdTemp |= UART_FCR_TRG_LEV1;
    Chip_UART_SetupFIFOS(LPC_UART0, wdTemp);

    Chip_UART_TXEnable(LPC_UART0);
 

    /*
     ************************************************************************
     *enable interrupts
     ************************************************************************
     */
    wdTemp  = UART_IER_RBRINT;
    Chip_UART_IntEnable(LPC_UART0, wdTemp);
}



 

/*
 ****************************************************************************
 *description:  nvic systic handler
 *inputs:       none
 *note:         toggle P1[8] = 190 uC led used as heartbeat monitor
 ****************************************************************************
 */
void
egwu_nvic_systick_isr(void)
{
    volatile unsigned int wdTemp;

    strSysTick.wdTicks++;
    if(strSysTick.wdTicks == 1000)
        {
        strSysTick.wdTicks = 0;
        strSysTick.wdSeconds++;

        //wdTemp = Chip_GPIO_GetPinState(LPC_GPIO1, LPC_LED_PORT, LPC_LED_PIN);
        //Chip_GPIO_SetPinState(LPC_GPIO1, LPC_LED_PORT, LPC_LED_PIN, wdTemp);

        wdTemp = (((LPC_GPIO1->PIN) >> LPC_LED_PIN) & 0x1);
        wdTemp ^= 0x1;
        if(wdTemp == 0)
                (LPC_GPIO1->CLR) = (1 << LPC_LED_PIN);  
        else
                (LPC_GPIO1->SET) = (1 << LPC_LED_PIN);  
        }
}





/*
 ****************************************************************************
 *description:  nvic fault handler
 *inputs:       none
 ****************************************************************************
 */
void
egwu_nvic_fault_isr(void)
{
        egwu_set_lpc_biled(EGWU_NVIC_FAULT_BILED_MASK);
}





/*
 ****************************************************************************
 *description:  nvic user handler
 *inputs:       none
 ****************************************************************************
 */
void
egwu_nvic_user_isr(void)
{
egwu_set_lpc_biled(EGWU_NVIC_USER_BILED_MASK);
}





/*
 ****************************************************************************
 *description:  set the bi-led connected to the LPC
 *inputs:       unsigned int wdLedMask = led mask only lower two bits matter
 ****************************************************************************
 */
void
egwu_set_lpc_biled(unsigned int wdLedMask)
{
    wdLedMask &= 0x3;

    Chip_GPIO_SetPinState(LPC_GPIO, LPC_BILED_PORT, LPC_BILED_PIN1, wdLedMask);
    Chip_GPIO_SetPinState(LPC_GPIO, LPC_BILED_PORT, LPC_BILED_PIN2, (wdLedMask >> 1));
}




#endif

Phase 1: tclib

/*
 *****************************************************************
 *name:         tclib.h
 *author:       Samuel Igwe
 *date:         06/07/2015 (c) copyright
 *description:  tclib (my thumb) library header.
 *****************************************************************
 */
#ifndef TCLIB_H
#define TCLIB_H


    extern  int     IE_tclib_atoi(unsigned char *ptrAscStr);
    extern  void    IE_tclib_itoa(unsigned int wdValue,\
                                  unsigned char *ptrAscStr);
    extern  int     IE_tclib_bswap(unsigned int wdValue);
    extern  int     IE_tclib_swap(unsigned int wdValue);
    extern  int     IE_tclib_strlen(unsigned char *ptrStrSrc);
    extern  int     IE_tclib_strcmp(unsigned char *ptrStrSrc,\
                                    unsigned char *ptrStrDst);
    extern  void    IE_tclib_memset(unsigned char *ptrString,\
                                    unsigned int wdValue,\
                                    unsigned int wdSize);
    extern  void    IE_tclib_memcpy(unsigned char *ptrDstStr,\
                                    unsigned char *ptrSrcStr,\
                                    unsigned int wdSize);
    extern  int     IE_tclib_acquire_semaphore(unsigned int *ptrWord);
    extern  int     IE_tclib_release_semaphore(unsigned int *ptrWord);


#endif
 



 
 
 
 

/*
 *****************************************************************
 *name:         tclib.S
 *author:       Samuel Igwe
 *date:         06/07/2015
 *description:  my thumb2 library. asm optimized generic routines
 *
 *notes:        from ARM technical reference manual
 *              instructions are conditional
 *              eq/ne (eq = 0, ne = not 0)
 *              ge/gt/le/lt
 *              memory addressing formats ldr(s)/str
 *              pre-index with writeback   ldr r0, [r1,#4]!
 *                              data = mem[base+offset] 
 *                      base addr reg= base+offset
 *              pre-index                  ldr r0, [r1,#4]
 *                              data = mem[base+offset]
 *                      base addr reg= not updated
 *              post-index                 ldr r0, [r1],#4
 *                              data = mem[base]
 *                      base addr reg= base+offset 
 *
 *              #4 above could be replaced by another register
 *****************************************************************
 */
#ifndef TCLIB_S
    .thumb
    .text
    .syntax unified


/*
 *****************************************************************
 *description:  C initializer. basically just setups up the stack
 *note:         not really needed since offset 0 of the ivt setups
 *              up the main stack pointer. this routine exists for
 *              when i want to change it which is UNLIKELY
 *****************************************************************
 */
    .align      2
    .global tclib_cinit
    .thumb_func
    .equ        LPC177X_SRAM_BASE, 0x10000000
    .equ        SRAM_TOP, (LPC177X_SRAM_BASE + (64*1024))
    tclib_cinit:
    ldr sp, =SRAM_TOP
    mov pc, lr





/*
 *****************************************************************
 *description:  software divider. meanth to be called from asm
 *              takes 
 *inputs:       r0 = dividend
 *              r1 = divisor
 *outputs:      r0 = quotient
 *              r1 = remainder
 *output:       0 on error 1 on success
 *****************************************************************
 */
    .align  2
    .global tclib_softdiv
    .thumb_func
    tclib_softdiv:
    push    {r2, lr}

    mov r2, r0                                  /*put r0 in r2*/
    mov r0, #0                                  /*zero out quotient*/

    tclib_softdiv_loop:
    cmp r2, r1
    blt tclib_softdiv_exit
    sub r2, r2, r1
    add r0, r0, #1
    b tclib_softdiv_loop

    tclib_softdiv_exit:
    mov r1, r2                                  /*r1 remainder*/

    pop {r2, lr}
    mov pc, lr





/*
 *****************************************************************
 *description:  acquire semaphore
 *input:        char *ptrWord   = pointer to memory word
 *output:       0 on error 1 on success
 *void
 *tclib_acquire_semaphore(unsigned char *ptrWord)
 *****************************************************************
 */
    .align  2
    .global tclib_acquire_semaphore
/*
 *****************************************************************
 *r0 = ptrWord
 *****************************************************************
 */
    .thumb_func
    tclib_acquire_semaphore:
    push    {r1-r2}


    mov     r1, #1
    mov     r2, r0

    ldrexb  r0, [r2]                        /*get value*/
    cmp     r0, #0
    itt     ne
    eorne   r0, #1
    bne     tclib_get_mutex_exit

    strexb  r0, r1, [r2]
    eor     r0, #1

    tclib_get_mutex_exit:
    clrex

    pop     {r1-r2}
    mov     pc, lr





/*
 *****************************************************************
 *description:  release semaphore
 *input:        char *ptrWord   = pointer to memory word
 *output:       0 on error 1 on success
 *void
 *tclib_release_semaphore(unsigned char *ptrWord)
 *****************************************************************
 */
    .align  2
    .global tclib_release_semaphore
/*
 *****************************************************************
 *r0 = ptrWord
 *****************************************************************
 */
    .thumb_func
    tclib_release_semaphore:
    push    {r1-r2}


    mov     r1, #0
    mov     r2, r0

    ldrexb  r0, [r2]                        /*get value*/
    cmp     r0, #0
    ite     ne
    eorne   r0, #1
    beq     tclib_release_mutex_exit

    strexb  r0, r1, [r2]
    eor     r0, #1

    tclib_release_mutex_exit:
    clrex

    pop     {r1-r2}
    mov     pc, lr





/*
 *****************************************************************
 *description:  sets a string buffer to a certain value
 *input:        char *ptrString =pointer to string
 *              int  wdValue    =value
 *              int  wdSize     =maximum length of string
 *void
 *tclib_memset(unsigned char *ptrString, int wdValue, int wdSize)
 *{
 *while ((wdSize--) >0)
 *       *(ptrString++) = (char)wdValue;
 *}
 *****************************************************************
 */
    .align  2
    .global tclib_memset
/*
 *****************************************************************
 *r0 = ptrString
 *r1 = wdValue
 *r2 = wdSize
 *r3 = scratch
 *****************************************************************
 */
    .thumb_func
    tclib_memset:
    push    {r0-r3, lr}

    mov     r3, r1, lsl #8
    orr     r1, r1, r3                      /*put byte into word*/
    mov     r3, r1, lsl #16
    orr     r1, r1, r3                      /*put word into dword*/

/*
 *****************************************************************
 *the instructions below
 orr     r1, r1, lsl #8                 
 orr     r1, r1, lsl #16
 *
 *generate the error
 tclib/tclib.S: Assembler messages:
 tclib/tclib.S:203: Error: garbage following instruction -- `orr r1,r1,lsl#8'
 tclib/tclib.S:204: Error: garbage following instruction -- `orr r1,r1,lsl#16'
 *under arm-linux-gnueabi-gcc version 4.4.5
 *so I revised it to the instructions above this comment
 *****************************************************************
 */

    andS    r3, r0, #0x3                /*determine dword alignment*/
    beq     tclib_memset_loop        /*take action if aligned*/


        tclib_memset_align:
        strb    r1, [r0], #1            /*store one byte - autoincr*/
        subS    r2, r2, #1              /*decrement counter*/
        itt     EQ
        popeq   {r0-r3, lr}             /*exit*/
        moveq   pc, lr                  /*exit*/

        andS    r3, r0, #0x3            /*determine dword alignment*/
        bne     tclib_memset_align


        tclib_memset_loop:           /*optimization*/
        cmp     r2, #4                  /*r2 >= 4*/
        blt     tclib_memset_align
                                        /*else*/
        str     r1, [r0], #4            /*dword*/
        subS    r2, #4                  /*decrement counter*/
        bne     tclib_memset_loop      
        pop     {r0-r3, lr}             /*exit*/
        mov     pc, lr                  /*exit*/




/*
 *****************************************************************
 *description:  copy from source to destination buffer
 *input:        char *ptrDstStr =pointer to dst string
 *              char *ptrSrcStr =pointer to src string
 *              int  wdSize     =max length of string
 *void
 *tclib_memcpy(unsigned char *ptrDstStr,\
 *              unsigned char *ptrSrcStr, \
 *              int wdSize)
 *{
 *while ((wdSize--) >0)
 *       *(ptrDstStr++) = *(ptrSrcStr++);
 *}
 *****************************************************************
 */
    .align  2
    .global tclib_memcpy
/*
 *****************************************************************
 *r0 = ptrDst
 *r1 = ptrSrc
 *r2 = wdSize
 *r3 = scratch
 *****************************************************************
 */
    .thumb_func
    tclib_memcpy:
    push    {r0-r3, lr}

    andS    r3, r0, #0x3                /*check if dst aligned*/                        
    bne     tclib_memcpy_bcopy
    andS    r3, r1, #0x3                /*check if src aligned*/
    bne     tclib_memcpy_bcopy


        tclib_memcpy_loop:           /*optimization*/
        cmp     r2, #4                  /*check if size >= 4*/
        blt     tclib_memcpy_bcopy
                                        /*else*/
        ldr     r3, [r1], #4            /*get from src*/
        str     r3, [r0], #4            /*put in   dst*/
        subS    r2, #4                  /*decrement counter*/
        bne     tclib_memcpy_loop
        pop     {r0-r3, lr}             /*exit*/
        mov     pc, lr                  /*exit*/


        tclib_memcpy_bcopy:
        ldrb    r3, [r1], #1            /*get from src*/
        strb    r3, [r0], #1            /*put in   dst*/
        subS    r2, #1                  /*decrement counter*/
        bne     tclib_memcpy_bcopy
        pop     {r0-r3, lr}             /*exit*/
        mov     pc, lr                  /*exit*/





/*
 *****************************************************************
 *description:  ascii to integer
 *input:        char *ptrAscStr =pointer to string
 *output:       int             =value
 *int
 *tclib_atoi(unsigned char *ptrAscStr)
 *{
 *unsigned char     *ptrTemp;
 *volatile int wdValue,wdWeight,wdTemp;
 *
 *wdValue =0;
 *wdWeight=1;
 *ptrTemp =ptrAscStr;
 *
 *while ((*ptrTemp) != NULL)
 *       ptrTemp++;
 *
 *while ((--ptrTemp) >= ptrAscStr)
 *       {
 *       wdTemp = *ptrTemp;
 *       if (wdTemp >= '0' && wdTemp <='9')
 *               wdTemp-= '0';
 *       else
 *               {
 *               if (wdTemp >='a' && wdTemp <='f')
 *                       {
 *                       wdTemp-= 'a';
 *                       wdTemp+= 10;
 *                       }
 *               else
 *                       {
 *                       if (wdTemp >= 'A' && wdTemp <= 'F')
 *                               {
 *                               wdTemp-= 'A';
 *                               wdTemp+= 10;
 *                               }
 *                       else
 *                               return 0;
 *                       }
 *               }
 *
 *       wdValue  += wdTemp * wdWeight;
 *       wdWeight<<= 4;
 *       }
 *
 *return wdValue;
 *}
 *****************************************************************
 */
    .align  2
    .global tclib_atoi
/*
 *****************************************************************
 *r0 = ptrString
 *returns r0
 *r1 = r0 - address
 *r2 = scratch - wdValue
 *r3 = scratch - wdWeight
 *r4 = scratch
 *****************************************************************
 */
    .thumb_func
    tclib_atoi:
    push    {r1-r4, lr}

    mov     r1, r0                      /*to be return value*/
    bl      tclib_strlen                /*of strlen()*/
    cmp     r0, #0                      /*is it zero?*/
    itt     EQ
    popeq   {r1-r4, lr}
    moveq   pc, lr

    mov     r3, #1                      /*init wdWeight*/
    mov     r2, #0                      /*zero out*/


        tclib_atoi_loop:
        subS    r0, r0, #1              /*decrement loop*/
        ittt    LT
        movlt   r0, r2                  /*copy out arg when done*/
        poplt   {r1-r4, lr}
        movlt   pc, lr

        ldrb    r4, [r1,r0]             /*preindex without update*/
        and     r4, r4, #0x0ff          /*clear upper bits*/

        cmp     r4, #'0'
        ittt    LT
        movlt   r0, #0                  /*zero out before exiting*/
        poplt   {r1-r4, lr}             /*exit if less than '0'*/
        movlt   pc, lr                  /*exit*/

        cmp     r4, #'9'
        bgt     tclib_atoi_lcase
        sub     r4, r4, #'0'
        mla     r2, r4, r3, r2          /*r2=(r3*r4)+r2*/
        mov     r3, r3, lsl #4          /*adjust 16^x*/
        b       tclib_atoi_loop


        tclib_atoi_lcase:
        cmp     r4, #'a'
        blt     tclib_atoi_ucase
        cmp     r4, #'f'
        ittt    GT
        movgt   r0, #0                  /*zero out before exiting*/
        popgt   {r1-r4, lr}             /*exit if greater than 'f'*/
        movgt   pc, lr                  /*exit*/

        sub     r4, r4, #'a'
        add     r4, r4, #10
        mla     r2, r4, r3, r2          /*r2=(r3*r4)+r2*/
        mov     r3, r3, lsl #4
        b       tclib_atoi_loop

                
        tclib_atoi_ucase:
        cmp     r4, #'A'
        ittt    LT
        movlt   r0, #0                  /*zero out before exiting*/
        poplt   {r1-r4, lr}
        movlt   pc, lr

        cmp     r4, #'F'
        ittt    GT
        movgt   r0, #0                  /*zero out before exiting*/
        popgt   {r1-r4, lr}             /*exit if greater than 'F'*/
        movgt   pc, lr                  /*exit*/

        sub     r4, r4, #'A'
        add     r4, r4, #10
        mla     r2, r4, r3, r2          /*r2=(r3*r4)+r2*/
        mov     r3, r3, lsl #4
        b       tclib_atoi_loop
        




/*
 *****************************************************************
 *description:  integer to ascii. convert nibbles
 *input:        int     wdValue     =value
 *              char    *ptrAscStr  =pointer to string
 *void
 *tclib_itoa(int wdValue, unsigned char *ptrAscStr)
 *{
 *volatile int wdIndex,wdTemp;
 *
 *if (wdValue < 0)
 *       wdIndex =8;
 *else
 *       {
 *       if (wdValue < (1 << 8))
 *               wdIndex =2;
 *       else
 *               {
 *               if (wdValue < (1 << 16))
 *                       wdIndex =4;
 *               else
 *                       {
 *                       if (wdValue < (1 << 24))
 *                               wdIndex =6;
 *                       else
 *                               wdIndex =8;
 *                       }
 *               }
 *       }
 *
 *ptrAscStr[wdIndex--] =NULL;
 *while (wdIndex >=0)
 *       {
 *       wdTemp   = wdValue;
 *       wdTemp  &= 0x0f;
 *       wdValue>>= 4;
 *
 *       if (wdTemp >=0 && wdTemp < 10)
 *               ptrAscStr[wdIndex--] = wdTemp +'0';
 *       else
 *               {
 *               wdTemp -=10;
 *               ptrAscStr[wdIndex--] = wdTemp +'A';     
 *               }
 *       }
 *}
 *****************************************************************
 */
    .align  2
    .global tclib_itoa
/*
 *****************************************************************
 *r0 = value
 *r1 = ptrString
 *r2 = scratch - index
 *r3 = scratch
 *r4 = 1
 *****************************************************************
 */
    .thumb_func
    tclib_itoa:
    push    {r0-r4, lr}

    mov     r4, #1
    mov     r3, r4, lsl #8              /*(wdValue< (1<<8))*/
    cmp     r0, r3
    itt     LO
    movlo   r2, #2
    blo     tclib_itoa_prep_loop

    mov     r3, r4, lsl #16             /*(wdValue< (1<<16))*/
    cmp     r0, r3
    itt     LO
    movlo   r2, #4
    blo     tclib_itoa_prep_loop

    mov     r3, r4, lsl #24             /*(wdValue< (1<<24))*/
    cmp     r0, r3
    ite     LO
    movlo   r2, #6
    movhs   r2, #8


    tclib_itoa_prep_loop:
    add     r1, r1, r2                  /*setup addresses*/
    mov     r3, #0
    strb    r3, [r1],#-1                /*nullify string*/


        tclib_itoa_loop:
        sub     r2, r2, #1              /*decrement counter*/
        cmp     r2, #0
        itt     LT
        poplt   {r0-r4, lr}             /*exit*/
        movlt   pc, lr                  /*exit*/

        mov     r3, r0                  /*save r0 temporarily*/
        mov     r0, r0, lsr #4          /*new value to work on*/
        and     r3, r3, #0x0f           /*nibble*/

        cmp     r3, #10                 /*prepare to adjust*/
        itee    LT
        addlt   r3, r3, #'0'
        subge   r3, r3, #10
        addge   r3, r3, #'A'
        
        strb    r3, [r1],#-1            /*store with auto-decr*/
        b       tclib_itoa_loop





/*
 *****************************************************************
 *description:  word swap
 *input:        int wdValue = value 
 *output:       int
 *int
 *tclib_word_swap(int wdValue)
 *{
 *unsigned int dwTemp;
 *
 *(dwTemp = 0;
 *dwTemp|= (wdValue << 24) & 0xff000000;
 *dwTemp|= (wdValue << 8 ) & 0x00ff0000;
 *dwTemp|= (wdValue >> 24) & 0x0ff;
 *dwTemp|= (wdValue >> 8 ) & 0x0ffff;
 *
 *return dwTemp;
 *}
 *****************************************************************
 */
    .align  2
    .global tclib_swap
/*
 *****************************************************************
 *r0 = value
 *returns r0 = word swapped value
 *r1 = scratch
 *r2 = scratch
 *r3 = 0x0ff
 *****************************************************************
 */
    .thumb_func
    tclib_swap:
    push    {r1, lr}

    mov     r1, r0                      /*safe keep - r0 = return*/
    rev     r0, r1                      /*theres a single thumb ins*/
                                        /*for this now*/
    pop     {r1, lr}                    /*exit*/
    mov     pc, lr                      /*exit*/





/*
 *****************************************************************
 *description:  byte swap
 *input:        int wdValue = value 
 *output:       int
 *int
 *tclib_byte_swap(int wdValue)
 *{
 *unsigned int dwTemp;
 *
 *dwTemp = 0;
 *dwTemp|= (wdValue << 8 ) & 0xff00;
 *dwTemp|= (wdValue >> 8 ) & 0x0ff;
 *
 *return dwTemp;
 *}
 *****************************************************************
 */
    .align  2
    .global tclib_bswap
/*
 *****************************************************************
 *r0 = value
 *returns r0 = byte swapped value
 *r1 = scratch
 *r2 = scratch old value
 *****************************************************************
 */
    .thumb_func
    tclib_bswap:
    push    {r1, lr}

    mov     r1, r0
    rev     r0, r1                          /*save original value*/
    mov     r0, r0, lsl #16

    pop     {r1, lr}                        /*exit*/
    mov     pc, lr                          /*exit*/
 




/*
 *****************************************************************
 *description:  string len computation function
 *inputs:       char *ptrStrSrc
 *output:       int  = lenght of string
 *int
 *tclib_strlen(unsigned char *ptrStrSrc)
 *{
 *unsigned int wdCount;
 *for (wdCount=0; ptrStrSrc[wdCount]!=NULL; wdCount++)
 *      ;
 *
 *return wdCount;
 *}
 *****************************************************************
 */
    .align  2
    .global tclib_strlen
/*
 *****************************************************************
 *r0 = ptrString
 *returns r0 = byte length
 *r1 = ptrString
 *r2 = scratch
 *****************************************************************
 */
    .thumb_func
    tclib_strlen:
    push    {r1-r2, lr}

    mov     r1, r0                      /*put pointer in r1*/
    mov     r0, #0                      /*zero out r0*/


        tclib_strlen_loop:
        ldrb    r2, [r1], #1            
        andS    r2, r2, #0x0ff          /*clear lower bits*/
            
        itee    NE
        addne   r0, r0, #1              /*track strlen results*/

        popeq   {r1-r2, lr}             /*exit*/
        moveq   pc, lr                  /*exit*/

        b       tclib_strlen_loop              





/*
 *****************************************************************
 *description:  string comparison 
 *inputs:       char *ptrStrSrc=string 1
 *              char *ptrStrDst=string 2
 *              int  wdCount   =number of characters to compare 
 *output:       int = 0 on success failing index on error
 *int
 *tclib_strcmp(unsigned char *ptrStrSrc,\
 *             unsigned char *ptrStrDst,\
 *             int wdCount)
 *{
 *unsigned int wdIndex;
 *
 *for(wdIndex=0; wdIndex <wdCount; wdIndex++)
 *      {
 *      if (ptrStrSrc[wdIndex] == NULL || \
 *           ptrStrDst[wdIndex] == NULL || \
 *          (ptrStrSrc[wdIndex] - ptrStrDst[wdIndex]) !=0)
 *              return wdIndex;
 *      }
 *
 *return 0;          
 *}
 *****************************************************************
 */
    .align  2
    .global tclib_strcmp
/*
 *****************************************************************
 *r0 = ptrDst
 *r1 = ptrSrc
 *returns r0 strcmp value
 *r1 = src1
 *r2 = src2
 *r3 = scratch
 *r4 = scratch
 *r0 = cmp
 *****************************************************************
 */
    .thumb_func
    tclib_strcmp:
    push    {r1-r4, lr}

    mov     r2, r0                      /*save src1 in r2*/
    mov     r0, #0                      /*zero out r0*/


        tclib_strcmp_loop:
        ldrb    r3, [r1], #1            
        andS    r3, r3, #0x0ff          /*clear upper bits*/
        orrS    r3, r3, #0              /*end of string?*/
        beq     tclib_strcmp_exit

        ldrb    r4, [r2], #1
        andS    r4, r4, #0x0ff          /*clear upper bits*/
        orrS    r4, r4, #0              /*end of string?*/
        beq     tclib_strcmp_exit

        cmp     r4, r3
        it      EQ
        beq     tclib_strcmp_loop
                                        /*else*/
        ite     HI
        addhi   r0, r0, #1              /*track strcmp results*/
        subls   r0, r0, #1              /*ditto*/

        itt     NE
        popne   {r1-r4, lr}             /*exit*/
        movne   pc, lr                  /*exit*/
        
        
        tclib_strcmp_exit:
        itt     EQ
        popeq   {r1-r4, lr}             /*exit*/
        moveq   pc, lr                  /*exit*/

        b       tclib_strcmp_loop





    .end
#endif

Phase 1: Script files

$HOME/.gdbinit
set history filename ~/.gdb_history
set history save
set architecture arm
target remote localhost:3333
monitor reset halt 
 
 
 
$HOME/.bashrc
alias openocd_ft2232='sudo /usr/local/bin/openocd -s /home/rombios/DEVEL/EGWU/openocd/scripts -f interface/egwu_interface_usb.cfg -f board/egwu_board.cfg'
alias openocd_ftdi='sudo /usr/bin/openocd -s /home/rombios/DEVEL/EGWU/openocd/scripts -f interface/ftdi/egwu_interface_usb.cfg -f board/egwu_board.cfg' 
 
 
 
$HOME/DEVEL/EGWU/openocd/scripts/board
# egwu_board.cfg

set WORKAREASIZE 0x10000
source [find target/egwu_target_1788.cfg] 
 
 
  
$HOME/DEVEL/EGWU/openocd/scripts/interface
#
# embedded projects openocd usb adapter v3
#
# http://shop.embedded-projects.net/index.php?module=artikel&action=artikel&id=14
#

#gdb_port        10000
interface  ft2232
ft2232_vid_pid  0x0403 0x6010
ft2232_device_desc "Dual RS232-HS"
ft2232_layout  "usbjtag"
ft2232_latency  2  
 
 
 
$HOME/DEVEL/EGWU/openocd/scripts/interface/ftdi
#
# embedded projects openocd usb adapter v3
#
# http://shop.embedded-projects.net/index.php?module=artikel&action=artikel&id=14
#

interface   ftdi
ftdi_vid_pid   0x0403 0x6010
#ftdi_channel     0
ftdi_layout_init 0x1000 0x3d1b 
 
 
 
$HOME/DEVEL/EGWU/openocd/scripts/target
# egwu_target_1788.cfg

set CHIPNAME  lpc1788
set CPUTAPID  0x4ba00477
set CPURAMSIZE  0x10000
set CPUROMSIZE  0x80000

# CCLK is the core clock frequency in KHz

set CCLK 8000
source [find target/egwu_target_17xx.cfg];
cortex_m reset_config sysresetreq
 
 
 
# egwu_target_17xx.cfg

if { [info exists CHIPNAME] } {
 set _CHIPNAME $CHIPNAME
} else {
 error "_CHIPNAME not set. Please do not include lpc17xx.cfg directly, but the specific chip configuration file (lpc1751.cfg, lpc1764.cfg, etc)."
}

# After reset the chip is clocked by the ~4MHz internal RC oscillator.
# When board-specific code (reset-init handler or device firmware)
# configures another oscillator and/or PLL0, set CCLK to match; if
# you don't, then flash erase and write operations may misbehave.
# (The ROM code doing those updates cares about core clock speed...)
#
# CCLK is the core clock frequency in KHz
if { [info exists CCLK] } {
 set _CCLK $CCLK
} else {
 set _CCLK 12000
}

if { [info exists CPUTAPID] } {
 set _CPUTAPID $CPUTAPID
} else {
 error "_CPUTAPID not set. Please do not include lpc17xx.cfg directly, but the specific chip configuration file (lpc1751.cfg, lpc1764.cfg, etc)."
}

if { [info exists CPURAMSIZE] } {
  set _CPURAMSIZE $CPURAMSIZE
} else {
 error "_CPURAMSIZE not set. Please do not include lpc17xx.cfg directly, but the specific chip configuration file (lpc1751.cfg, lpc1764.cfg, etc)."
}

if { [info exists CPUROMSIZE] } {
  set _CPUROMSIZE $CPUROMSIZE
} else {
 error "_CPUROMSIZE not set. Please do not include lpc17xx.cfg directly, but the specific chip configuration file (lpc1751.cfg, lpc1764.cfg, etc)."
}

jtag newtap $_CHIPNAME cpu -irlen 4 -expected-id $_CPUTAPID

set _TARGETNAME $_CHIPNAME.cpu
target create $_TARGETNAME cortex_m -chain-position $_TARGETNAME

# The LPC17xx devices have 8/16/32kB of SRAM In the ARMv7-M "Code" area (at 0x10000000)
$_TARGETNAME configure -work-area-phys 0x10000000 -work-area-size $_CPURAMSIZE

# The LPC17xx devies have 32/64/128/256/512kB of flash memory, managed by ROM code
# (including a boot loader which verifies the flash exception table's checksum).
# flash bank <name> lpc2000 <base> <size> 0 0 <target#> <variant> <clock> [calc checksum]
set _FLASHNAME $_CHIPNAME.flash
flash bank $_FLASHNAME lpc2000 0x0 $_CPUROMSIZE 0 0 $_TARGETNAME \
 lpc1700 $_CCLK calc_checksum

# Run with *real slow* clock by default since the
# boot rom could have been playing with the PLL, so
# we have no idea what clock the target is running at.
adapter_khz 2000
#adapter_khz 1000

# delays on reset lines
adapter_nsrst_assert_width 50
adapter_nsrst_delay  100

jtag_ntrst_assert_width  50
jtag_ntrst_delay   100

$_TARGETNAME configure -event reset-init {
 mww 0x400FC040 0x01
 mww 0xe000ed08 0x10000000
}

# perform a soft reset
#cortex_m reset_config sysresetreq
cortex_m reset_config trst_only
 
 
 
$HOME/DEVEL/EGWU/linker/IE_lpc17xx.ld
/*
 ***********************************************************************
 *name:         IE_lpc177x.ld
 *author:       Samuel Igwe
 *date:         06/10/2015
 *description:  linker script that I have created for use in egwu
 *              development related matters on this board
 *
 *  first this is the memory map I had decided on 
 *    
 *         0xa1ff ffff  +++++++++++++++++++++++++++++++
 *                  +ext sdram  = 64Mb            +
 *              0xa000 0000   +++++++++++++++++++++++++++++++
 *                 +                             +
 *         0x8001 ffff  +++++++++++++++++++++++++++++++
 *                  +ext sram   = 128k            +
 *              0x8000 0000   +++++++++++++++++++++++++++++++
 *                 +                             +
 *         0x1000 ffff  +++++++++++++++++++++++++++++++
 *                  +int sram   = 64k             +
 *              0x1000 0000   +++++++++++++++++++++++++++++++
 *                 +                             +
 *  0x0007 ffff  +++++++++++++++++++++++++++++++
 *                 +int flash  = 512k            +
 *  0x0000 0000  +++++++++++++++++++++++++++++++
 *
 *
 *              for now I will be debugging from SRAM until the code 
 *  matures
 *
 *  adding the variable _loadaddr_data_section_ to the end
 *  of the .text along with the AT> directive places a copy
 *  of the .data right after .text but leaves the virtual
 *  addresses pointing at .data in ram
 *  
 *  in the assembler initialization file I can copy .data 
 *  from bottom of .text into .data in sram
 ***********************************************************************
 */
MEMORY  {
        LPC177X_RAM    : ORIGIN = 0x10000000,   LENGTH = (64K - 1024)
        }



SECTIONS
        {
        .data :   
                {
                *(.data);
                } > LPC177X_RAM

        .text :   
  {
                *(.text);
                *(.rodata);
                } > LPC177X_RAM

        .bss :
                {
                *(.bss);
                } > LPC177X_RAM
        }




  
 

Phase 1: Makefile

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

CC     = arm-linux-gnueabi-gcc
LD     = arm-linux-gnueabi-ld
OBJCPY = arm-linux-gnueabi-objcopy

AR     = arm-linux-gnueabi-ar
RM     = rm -f
MV     = mv -f


#CFLAGS = -g -c -Wall -nostdlib -mcpu=cortex-m3 -mlittle-endian -mthumb -mabi=atpcs -O0 -DDEBUG
CFLAGS = -g -c -Wall -nostdlib -mcpu=cortex-m3 -mlittle-endian -mthumb  -mabi=atpcs -DDEBUG -fno-inline\
         -fno-inline-small-functions -O0
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)                                       -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 app.out  ivt.o\
                                                                                     setup.o\
                                                                                     uartio.o\
                                                                                     tclib.o\
                                                                                     main.o\
                                                                                     lpcopen.lib


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

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