Thursday, July 24, 2014

Debugging U-boot on RiotBoard using eclipse and JLink under Linux

RiotBoard has a JTAG header on board. So I connected Jlink Ultra and tried my luck. The StartJLinkExe.sh utility available from segger website could detect "Cortex-A9" core.  



After this, using eclipse I wanted to debug U-Boot. For this, I used KEPLER. Initial step is to create a workspace for building and debugging U-boot.



Select a workspace location, Select File -> Import -> Existing Code as Makefile project.


In next window, Browse into U-boot's location as shown in image below.


Click Finish. Now the project can be seen in Project Explorer. To successfully build U-boot sources environment variables should be updated. Right Click on the project and click on properties. Select Environment under C/C++ Build 



Add new variable ARCH as arm.


Create an environment variable CROSS_COMPILE as arm-linux-gnueabihf- . I used linaro toolchain. 


Update already available PATH variable to contain the path of the toolchain binaries.


Add a new make target to configure u-boot for riot board.


Then add a make target to build and cleaning u-boot sources.



After addition of make targets, now it's time to build. To start with, double click on the make target for configuring u-boot for RiotBoard. The message on the console confirms that u-boot is configured for RiotBoard.



Now double click on make all to start building the u-boot sources. Once this process is complete you can see the binaries in the root folder of u-boot. This is confirmed on the console too.


In order to debug the u-boot, we need the GDB Hardware Debugging plugin to be installed. Goto Help -> Install New Software. Update Work with field as shown below. Make sure that you have stable internet connection.

Under CDT Optional Features select C/C++ GDB Hardware Debugging and click on Next.


Once the installation is complete you can confirm the installation by looking into already installed software dialog as shown below.


Now if you open the Debug configurations window, a new GDB Hardware Debugging configuration can be created.


In C/C++ Application field, "Browse" to the file "u-boot" present in the root directory of u-boot.


Update GDB command field with the toolchain gdb as shown below. Change the port number to 2331. Because by default, JLink listens on TCP/IP port 2331.


In Startup Window, uncheck Reset and Delay and Halt.



Note that we have Load Image checked. But JLink has no driver for the on board memory. So the trick is to use "imx_usb_loader". This utility is useful to flash binaries. The build steps are as follows,

$ cd imx_usb_loader
$ make

Once the build process is complete, two binaries can be found one for loading via USB and other for UART. Now configure the RiotBoard to enter USB serial Download mode.


After setting the DIP switches appropriately, connect the USB cable to the usb connector next to ethernet port. Then run the following command,

$ ./imx_usb <path to your u-boot.bin>


Following was my console out for above command

config file <./imx_usb.conf>
vid=0x066f pid=0x3780 file_name=mx23_usb_work.conf
vid=0x15a2 pid=0x004f file_name=mx28_usb_work.conf
vid=0x15a2 pid=0x0052 file_name=mx50_usb_work.conf
vid=0x15a2 pid=0x0054 file_name=mx6_usb_work.conf
vid=0x15a2 pid=0x0061 file_name=mx6_usb_work.conf
vid=0x15a2 pid=0x0063 file_name=mx6_usb_work.conf
vid=0x15a2 pid=0x0041 file_name=mx51_usb_work.conf
vid=0x15a2 pid=0x004e file_name=mx53_usb_work.conf
vid=0x15a2 pid=0x006a file_name=vybrid_usb_work.conf
vid=0x066f pid=0x37ff file_name=linux_gadget.conf
config file <./mx6_usb_work.conf>
parse ./mx6_usb_work.conf
15a2:0061(mx6_qsb) bConfigurationValue =1
Interface 0 claimed
HAB security state: development mode (0x56787856)
== work item
filename ../u-boot-imx-embest_imx_3.0.35_4.0.0/u-boot.bin
load_size 0 bytes
load_addr 0x00000000
dcd 1
clear_dcd 0
plug 1
jump_mode 2
jump_addr 0x00000000
== end work item
main dcd length 1e0
sub dcd length 1dc


loading binary file(../u-boot-imx-embest_imx_3.0.35_4.0.0/u-boot.bin) to 27800000, skip=0, fsize=69a68 type=aa


<<<432744, 432744 bytes>>>
succeeded (status 0x88888888)
jumping to 0x27800400


The u-boot.bin was loaded to 0x27800000. Now time to run GDB server!!! This can be done using following command,

$ cd <to JLink folder>
$ ./StartJLinkGDBServer.sh -device MCIMX6U8



Launch the debug configuration from eclipse. Below is screenshot where the image loading happens at 0x27800000 soon after the launch of debug session.
.

Below is the screenshot after debug session launch in eclipse.


All register except PC are zero. PC is updated to 0x27800000 where the u-boot is loaded.



Disassembly view shows that the jump to 0x27800620 instruction is present at 0x27800000.


Enable instruction mode debugging and issue step into command. After few step into commands, the control jumps into the lowlevel_init.S file as shown below.



Board initialization can be debugged by opening mx6solo_RiotBoard.c file and placing a breakpoint in board_init().



Happy Debugging!!!

Wednesday, July 9, 2014

Bare metal programming using LPC1768-Xplorer and CodeSourcery toolchain

LPC1768-Xplorer from NGX Technologies is a good board for experimentation. It is compatible with LPC1768-mbed plus it has on board uSD slot and ethernet port to play with.


In this tutorial I would like to take on the very minimal and basic requirements to compile a code that can run on LPC1768-Xplorer.

First, it is necessary to know the memory layout of the microcontroller. For writing linker script, we need to know the boundaries of flash and ram. LPC1768 has 512k of flash and 64k for ram. Flash base address is 0x00000000 and 64k of ram is distributed in 2 banks of 32k each. First bank starts from 0x10000000 and second bank is from 0x2007c000. For this exercise, we shall consider on the first ram bank. So the memory segment in the linker script should be as follows,

MEMORY
{
flash (rx) : ORIGIN = 0x00000000, LENGTH = 512K
ram (wr) : ORIGIN = 0x10000000, LENGTH = 32K
}
Cortex-M3 expects the vector table to be present in the base address of flash which is from 0x00000000. And the first entry in vector table should be top of the ram address which in our case is as follows,

vTopRam = ORIGIN(ram) + LENGTH(ram);

Next, sections should be defined in the linker script so that code and data sections gets placed appropriately during linking.

SECTIONS
{
.text :
{
  . = ALIGN(4);
  *(.isrvectors)
  *(.text)
  *(.rodata)
  *(.rodata*)
  . = ALIGN(4);
  _endflash = .;
} > flash
.data :
{
  . = ALIGN(4);
  _start_data = .;
  *(.data)
  . = ALIGN(4);
  _end_data = .;
} > ram AT > flash
.bss :
{
  . = ALIGN(4);
  _start_bss = .;
  *(.bss)
  . = ALIGN(4);
  _end_bss = .;
 } > ram
}
The first section is .text section where the vector table, code, read only data(constant data) shall reside. Next is the initialized data segment where the initialized globals and static variables resides. Finally, .bss section which holds the uninitialized globals, static variables, globals initialized to zero and static variables initialized to zero. The statement AT > flash indicates that the initialization value of .data segment is stored in the flash after the placement of .text section.
The variables _endflash, _start_data, _end_data, _start_bss, _end_bss can be used to write the initialization logic for .data and .bss segments. This logic is not covered in this tutorial.

Next thing which is required is startup.c which has the vector table and Reset Handler. Below is the code snippet.

#include <stdio.h>
#include <stdint.h>
#include "LPC17xx.h"
extern unsigned int vTopOfRam;
extern int main(void);
void ResetISR(void);
__attribute__((section(".isrvectors")))
void *vecTable[] =
{
&vTopOfRam,
ResetISR
};
void ResetISR(void)
{
LPC_SC->FLASHCFG = (LPC_SC->FLASHCFG & ~0x0000F000) | 0x00004000;
main();
while (1)
  ;
}

As mentioned earlier, the first entry in the vector table is top of the ram address. next entry should be Reset Handler. So we have only two entries in the vector table. Using "__attribute__", it is made sure that this vector table is placed at the flash base during linking. Reset handler, ResetISR contains minimal logic for setting the flash accesses to use 5 CPU clocks and then jumping to main().

The led blinky logic resides in main.c file. The LED on LPC1769-Xplorer is connected to P0.10. Below is the main.c file,

#include <stdio.h>
#include "LPC17xx.h"
#define LED_BIT_POS 10
int main(void)
{
int i;
LPC_GPIO0->FIODIR |= (1 << LED_BIT_POS);
LPC_GPIO0->FIOCLR |= (1 << LED_BIT_POS);
while(1)
{
LPC_GPIO0->FIOCLR |= (1 << LED_BIT_POS);
for (i = 0; i < 0xFFFF ; i++);
LPC_GPIO0->FIOSET |= (1 << LED_BIT_POS);
for (i = 0; i < 0xFFFF ; i++);
}
return 0;
}
The file  LPC17xx.h can be found in the cmsis package provided by NXP Semiconductors/LPCXpresso. These sources can be built using following set of commands,

arm-none-eabi-gcc -c startup.c -mthumb -mcpu=cortex-m3 -O1 -std=c99 -g -o startup.o
arm-none-eabi-gcc -c main.c -mthumb -mcpu=cortex-m3 -O1 -std=c99 -g -o main.o
arm-none-eabi-gcc -nostartfiles -mthumb -mcpu=cortex-m3 -O1 -std=c99 -g -T lpc1769.ld  startup.o  main.o -o app.axf
arm-none-eabi-objcopy -O binary app.axf app.bin

Hope this tutorial provides enough information for a beginner to understand firmware development on cortex-M series controllers. The files related to this project can be found here.

Wednesday, June 25, 2014

BeagleBone Black Radio for element14 design challenge

20140328_005742.jpg

Thanks to element14 for shortlisting my idea for BeagleBone Black Radio Design Challenge. It was basically a roadtest and my review is here. I could successfully implement my design and following are the chapters covering my implementation,

1. Setting up the software defined radio
2.USB Audio and Listening to FM radio
3.The Graphical user interface
4.Playback of recorded audio

It was a good learning for me. I was new to wxPython and Display managers in Linux, this project helped me explore different dimensions altogether. I am happy that I could complete the implementation well within time.