Thursday, June 18, 2015

Understanding Bit Banding in ARM Cortex-M

Bit Banding is a method of performing atomic bit manipulation. Usually, manipulating a bit in a word requires read-modify-write cycle which is interruptible, potentially causing data coherency issue. To avoid this, interrupts should be disabled before bit manipulation to overcome data coherency issues. This will result in unnecessary usage of CPU cycles. So ARM introduced "Bit Banding" in Cortex-M3 and Cortex-M4.

This allows every bit in bit banding region to be directly accessible from a word aligned address using simple LDR instruction. The memory map of Cortex-M3 has two 32MB alias region that map to two 1MB of bit banding region. One is for SRAM bit banding and other is for peripheral bit banding. Each bit in bit banding region is accessible from a word aligned address. It is the responsibility of system bus to map alias address to appropriate bit in bit banding region.

SRAM bit banding region is from 0x20000000 to 0x200FFFFF and its respective alias is from 0x22000000 to 0x23FFFFFC. Peripheral bit banding region is from 0x40000000 to 0x400FFFFF and its respective alias is from 0x42000000 to 0x43FFFFFC.

LPC1768 has two 16kB SRAM and GPIO block available for bit banding within the address region of SRAM. SRAM bit banding region on LPC1768 is from 0x2007C000 to 0x20083FFF(32kB). GPIO bit banding region on LPC1768 is from 0x2009C000 to 0x2009FFFF. APB0 and APB1 peripheral are available on peripheral bit banding region.

Calculating alias address for bit banding region is pretty simple,

alias_addr = alias_base_addr + ((bit_banding_addr - bit_banding_base_addr) * 32) + (bit * 4)

where,


  • alias_base_address is base address of alias which is 0x22000000 for SRAM bit banding region.
  • bit_banding_addr  is actual bit banding address.
  • bit_banding_base_addr is base address of bit banding region which for SRAM bit banding region is 0x20000000.
  • bit is the bit in bit_banding_addr.
Lets consider that I want to set bit 0 at 0x2007C000. So the alias address would be,

0x22000000 + ((0x2007C000 - 0x20000000) * 32) + (0 * 4) which would result in 0x22F80000.

So, *((volatile unsigned int *)0x22F80000) = 1; would set 0th bit of SRAM memory at 0x2007C000 and *((volatile unsigned int *)0x22F80004) = 1; would set first bit of SRAM memory at 0x2007C000.

Happy bit banding....

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.

Thursday, June 21, 2012

Getting started with mX-LPC1343-S board from NGX Technologies

The mX-LPC1343-S is a low cost board on LPC1343 from NGX technologies. To get started with this board you need to upgrade the firmware of the debugger(I am not sure whether this is necessary, but I did it!!!). First short the jumper JP1, you can do this by a single wire as shown below.

Jumper JP1 shorted using a wire

After this, connect your board to your PC. This board will be listed as 'USB Mass Storage' in your device manager. When you go inside the drive you can see something similar as shown below. Factory fresh board will have default debugger bin file.


Screenshot of the drive contents
Download the latest firmware from here.
Download ColinkEx USB driver v1.2.0 from here.
Install the downloaded USB drivers and replace the previous version of firmware with the latest firmware in the mounted drive.

Screenshot of drive with the latest firmware.
After pasting, unplug and re-plug the usb cable. Now you can find two additional devices in your device manager as shown below. One is a virtual COM port and other is the CooCox ColinkEx Debug Interface.



Screenshot of Device manager after upgrading the firmware.

Now you are good to go!!! Using CoFlash, you can download the bin to the uC's flash as shown below. You can also debug your code using CoIDE.


CoFlash in action
You can find CooCox MDK plugin in CooCox website, using which you can debug with the Keil IDE.

Good Luck!!!

Monday, June 18, 2012

Programming LPC4330 - Xplorer using DFU download/upload tool



As mentioned in my previous blog, LPC4330 Xplorer can be programmed in different modes. Now using DFU download/upload tool we can download .bin file onto the ram for execution. In order to using this tool the DIP switches on Xplorer board should be configured in following configuration,

SW1 - OFF
SW2 - ON
SW3 - OFF
SW4 - ON

Download winusb drivers from here
Download DFU tool from here

Connect the usb cable provided with the Xplorer to USB0 connector and then update the driver with the downloaded winusb drivers. After successful installation, extract the DFU tool to a folder and run the application


Screenshot of the DFU tool running on my machine
If everything is fine, then you will get "HIGH SPEED USB" as shown in above screenshot. Provide the path to the binary file and click on 'Generate binary file with header'. Finally, click on 'Start'. Soon after download is done, You can see your code in execution.

Screenshot after the download is complete

Once the download is done, connection with the board is lost as shown is above screenshot. Reset the board and you are good to go again.




Blinky running on Xplorer, programmed using DFU

Good Luck....







Thursday, May 31, 2012

LPC4330 - Xplorer Review

LPC4330 is cortex M4 device from NXP semiconductors and NGX technologies were one among few board manufacturers who designed a board for LPC4330 controllers. LPC4330 has asymmetric dual core, one cortex M0 and other cortex M4. Both cores have independent program memories.




LPC4330-Xplorer



LPC4330-Xplorer is the board manufactured by NGX Technologies Pvt. Ltd. It costs about 2500 INR($50). This low cost board comes along with two usb cables, one for usb Device and other for usb Host connection. The board has two USB ports, either of them can be used to power up the board. Two user LED's, one user input switch and one Reset switch can be used by user. It has audio in-out capabilities too. User can select different boot modes depending upon the DIP switches. But not all boot combinations are not support. LPC4330-Xplorer has 32MB SPI Quad flash which can be used to store program code. Ethernet connectivity is well supported by this board. The board comes with pre-loaded peripheral test program which can be used to test the capabilities of the boards. The Example codes provided at the NGX Technologies website are good enough to get started with this board. But none of them uses the cortex M0 core. User guide provided is also very precise. But the Reset switch on the board works every alternate time. This is a silicon issue! This board can be used along with Xpresso baseboard by NGX technologies for peripheral extension. The board also has 10-pin cortex debug header which provides the flexibility to debug using LPC link.


Pros:
  1. Low cost
  2. Asymmetric Dual core
  3. Peripheral enriched 
Cons:
  1. Reset works every alternate time(Silicon issue) 
  2. Debug header is not hobbyist friendly.