Wednesday, March 30, 2011

TCM8230MD Breakout

TCM8230MD
The TCM8230MD is a tiny camera from Toshiba theoretically capable of outputting 640x480@30FPS! This post is to document my experience with this devilish cam. 


Breakout
This is my second breakout board for the camera, this one is designed to be connected as a module to another board and doesn't use a crystal oscillator for the clock, I'm using one of the PWM channels instead. However, the older breakout is still in the repo. Both boards were designed with eagle and fabricated at BatchPCB.
Interfacing
The camera has an I2C interface for configuring its registers. A few basic registers must be set for the camera to start outputting frames. Mainly, 0x02 sets the FPS and 0x03 sets the image size/mode and enables the camera.

Next step, is reading frame data, the camera has three interrupt lines, VD, HD and DCLK, when VD is asserted a new frame is ready, each HD edge indicates a new scanline is available, finally, while HD is high each DCLK edge indicates a valid byte on the parallel port.


I enable VD initially and when VD is triggered only then HD is enabled in the IRQ handler. On each HD interrupt the whole scan line is read in a loop inserting some nop's to sync with DCLK. Finally, the whole frame is sent using DMA to the OLED screen.

Eagle files
hg clone https://code.google.com/p/tcm8230md-breakout/

Read more ...

Tuesday, March 29, 2011

Binary Counters

Binary counters can be used for a variety of things from time keeping to generating/measuring frequencies. Today, we will talk about the concepts behind binary counters using an atmega328 for practice.

Logic!
Let's start with a simple 4-bit counter based on JK flip-flops. A JK flip-flop has the following truth table:

J K Qt+1 State
0 0 Qt No change
0 1 0 Clear
1 0 1 Set
1 1 Qt` Complement

Where Qt is the current output Qt+1 is the output after the next clock edge.

The idea behind it is quite simple, the output of each flip-flop is feed to one input of an AND gate (the other input is the enable signal) so at the next raising-edge of the clock JKn is complemented only if all the least significant JKs are set/high and this is basically how you count in binary.

The following is a snapshot of the counter, I paused the simulation at the count of 3, at the next rising-edge of the clock the first three flip-flops are complemented output of the counter becomes 100b.
The last AND gate is the carry bit it can be used to extend the counter or even as an interrupt, note that the JK flip-flop inputs are connected  this is practically equivalent to a T flip-flop, so it's also possible to use a T flip-flop for the same counter.

The next counter is slightly more complex. It's a 4-bit counter with parallel load and synchronous clear:

It's basically the same counter with the addition of a couple of subcircuits, we could see how this counter works using boolean algebra to evaluate J and K and comparing the results with the JK truth table:

J  = ICL + CLE
K = C + ICL + CLE

Enable Load Clear
Input Output
0 0 0  J=0, K=0 No change
1 0 0  J=1, K=1 Complement
1 0 1  J=0, K=1 Clear
1 1 0 J=I,  K=I Load


AVR Timer/Counter
The atmega328 has 2 8-bit timers and 1 16-bit timer.  We will use Timer/Counter2 to generate a 1Hz square wave. That is, the event of the line going from low to high and then low again occurs once per second, so we need to switch the line state every 500ms.

First, set the clock source (prescalar) in  TCCR2. Setting the prescalar to 0 disables the timer, 1 means no prescaling, any other value will divide the system clock into smaller frequencies, e.g. assuming a clock frequency of 16Mhz and a 1:1024 prescalar the clock frequency is
f  = 16Mhz / 1024 = 15.6Khz
And the period is
T = 1/15.6Khz = 64us
Next we need to set the Output Compare Register (OCR2). The value contained in this register is continuously compared with the counter value, when the counter matches this value it will trigger an interrupt. If we load OCR2 with 250 the counter will will match this value every 16ms
250 * 64us = 16.0ms

Finally, we need to set the compare match interrupt enable flag in TIMSK. Given the clock frequency, 31 interrupts, roughly speaking, are needed for 500ms to pass. The following example demonstrates using TIMER2:
ISR(TIMER2_COMPA_vect) 
{
    if (ticks++ == 31) { 
      ticks = 0;
      toggle_pin(OUT_PIN);      
    }  
}

void main()
{   
    /**
      * f = 16Mhz / 1024 = 15.6Khz
      * p = 1/f
      * p = 1/15.6Khz = 64us
      * interrupt every = 250 * 64us = 16.0ms
      * round(500 / 16) = 31 interrupts
      **/
    TCCR2B = 0;            /*choose timer clock source, 0 = timer disabled*/
    TCCR2A = ((1<<WGM21)|~(1<<WGM20));/*CTC mode WGM22:0 = 2*/
    TCNT2  = 0;            /*clear timer*/
    OCR2A  = 250;          /*load output compare register with 255*/
    TIFR2  |= (1<<OCF2A);  /*Clear compare match flag*/    
    TIMSK2 |= (1<<OCIE2A); /*enable compare match interrupt*/
    TCCR2B = ((1<<CS22)|(1<<CS21)|(1<<CS20));/*1:1024 prescalar*/
    while(1);
}
Using a logic analyzer to sample the signal, we should see something like the following snapshot:



References
atmega328 datasheet 
Computer System Architecture-Morris Mano 
Read more ...

Saturday, January 1, 2011

Introduction to ARM Cortex-M3 Part 2-Programming

Welcome to the second part of the Introduction to ARM Cortex-M3, in part 1 we went through the core features of the Cortex-M3 and the LPC1768. In this part we will focus more on programming the LPC1768 by covering the following points:
  • Toolchain overview
  • Library Tweaks
  • Hardware Interfaces
  • Software Stacks
we have a lot to cover so let's get started...

Toolchain overview
The toolchain of choice is the CodeSourcery toolchain, CodeSourcery is  a gnu-based ARM toolchain developed in partnership with ARM, it's freely available both in source and pre-compiled and uses the embedded C library newlib (by Redhat) as the standard C library.

We're almost good to go, however, we still need drivers. Fortunately, NXP provides a nice driver library for the LPC1768, the library is based on the Cortex Microcontroller Standard Interface (CMSIS) developed by ARM as an abstraction for the core layers, it comes with the startup code, system initialization code, linker script, drivers for all the peripherals plus many examples.

Library Tweaks
I tweaked the Makefile a little bit to build the drivers, startup and system code into a single library, I then installed this library and headers in /usr/local/lpc17xx I think this greatly simplifies my Makefiles since I only need to link one library.

I also added some common initialization code mostly to system_LPC17xx.c to avoid duplicating it in every project. Finally, I tweaked the linker script a little bit. Let's have a detailed look at this code

Logging
First order of business is to enable logging. printf, puts and similar routines found in libc eventually call the low-level funciton _write and since it can not really have any useful implementation in newlib, because it's platform dependant, you will need to provide your own to redirect output somewhere. For example, the following redefines _write to redirect output to UART0:
#define stduart (LPC_UART_TypeDef *)LPC_UART0_BASE
int _write(int fd, const void *buf, uint32_t nbyte)
{
    UART_Send(stduart, buf, nbyte, BLOCKING);
    return nbyte;
}
Sleep
Almost all the code I see regardless of the embedded platform needs some sort of a delay/sleep function to wait on some event or just waste time.  There are two ways you can have delays, one is by using loops of instructions that have a known execution time, which is highly inaccurate and could be interrupted, the other way is using counters.

The SysTick timer counts down from the value loaded into one of its registers until it reaches 0 and then it asserts the SysTick IRQ, the value then is reloaded and the timer counts down again and so on.

The following example demonstrates using the SysTick timer for delays. The system tick count is kept in sys_ticks, when sleep is called the value of sys_ticks is saved and then we keep subtracting this value from the current tick count until the difference is equal to or greater than the required delay:
volatile uint32_t sys_ticks; 
void SysTick_Handler(void)__attribute__((weak));

void SysTick_Handler(void) 
{
    ++sys_ticks;
}

void sleep(uint32_t ms) 
{
    uint32_t curr_ticks = sys_ticks;
    while ((sys_ticks - curr_ticks) < ms);
}

int main(void) 
{
    /*Setup SysTick to interrupt every 1 ms*/
    SysTick_Config((SystemCoreClock / 1000) * 1 - 1);
}
A few things to note here, first, SysTick_Handler is declared weak, when a weak symbol is redefined the second definition is linked instead, so basically,  it can be overridden by the application, later you will see that I redefine it in the RTOS scheduler.

Second thing to note is that setting the timer to interrupt every 1 ms gives reasonable resolution but not necessarily the best throughput so you may wish to tweak that depending on your application, or disable it altogether,  but keep in mind that it affects your timer's resolution.

More RAM
We mentioned before in part1 that the LPC17xx has a second 32k block of SRAM for the Ethernet and USB controllers, however, if you're not using either you may wish utilize this extra memory to your application, you can do so by accessing the memory directly at 0x2007C000 or, more neatly, by defining a new memory region and a new section in the linker script:
/*linker script*/
MEMORY
{
  rom (rx)   : ORIGIN = 0x00000000, LENGTH = 512K
  ram (rwx)  : ORIGIN = 0x10000000, LENGTH = 32K
  ram2 (rwx) : ORIGIN = 0x2007C000, LENGTH = 32K   /*define memory region*/ 
}

SECTIONS
{  
  .ram2 : /*define section*/
  {
    *(.ram2)
  } >ram2  
 .text : /*other sections*/
  {
    ...
}
And then using the gcc section attribute to place stuff into this section:
/*place buffer in section .ram2*/
uint8_t buffer[BUFFER_SIZE] __attribute__ ((section (".ram2")))={0};
Hardware Interfaces
Next, we will look at initializing and using some of the common hardware interfaces available on the LPC1768, using the NXP driver library.

USART
The serial interface is the most common interface out there, we've seen how to use _write to redirect the output to the USART, now we look at initializing it. The following is an excerpt from my SystemInit function:
#define stduart (LPC_UART_TypeDef *)LPC_UART0_BASE

void SystemInit()
{
  /*some init code here*/

  PINSEL_CFG_Type pin_cfg={ /*pinsel config*/
      .Funcnum      = 1,
      .Portnum      = 0,
      .Pinmode      = PINSEL_PINMODE_PULLUP,
      .OpenDrain    = PINSEL_PINMODE_NORMAL,
  };

  UART_CFG_Type uart_cfg={ /*UART config*/
      .Baud_rate    = 57600,
      .Databits     = UART_DATABIT_8,
      .Parity       = UART_PARITY_NONE,
      .Stopbits     = UART_STOPBIT_1,
  };
  
  /*setup tx*/
  pin_cfg.Pinnum  = 2; 
  PINSEL_ConfigPin(&pin_cfg);

  /*setup rx*/
  pin_cfg.Pinnum  = 3;
  PINSEL_ConfigPin(&pin_cfg);

  /*Initialize uart*/
  UART_Init(stduart, &uart_cfg);
  UART_TxCmd(stduart, ENABLE);
}
More advanced things can be done with the USART of course. For example, there are 16 byte  RX/TX hardware FIFOs that can be set to trigger an interrupt or a DMA transfer at a certain level you can find more about this in the datasheet.

Note that when you mount the mbed you may need  to set the baud rate of /dev/ttyACMx using the following command:
stty -F /dev/ttyACM0 speed 57600
SPI
SPI is a full duplex serial interface that uses four wires for data transfer, Master In Salve Out (MISO), Master Out Slave In (MOSI), Serial Clock (SCLK) and Slave Select (SSEL).

Slave Select, or Chip Select (CS), is used to select the active slave when multiple slaves are present on the bus.  A few things  about SPI are worth mentioning. First, both end points have shift registers, when one is  loaded with a byte and shifted the other gets shifted too, i.e. exchanged, and so in order to read a byte you must write one too, however, when writing you may ignore the received byte.


Second, the clock polarity (CPOL) and clock phase (CPHA), the clock polarity determines the idle state of the clock, if CPOL = 0 the clock is low when it's idle and high when it's active, CPOL = 1 the clock is high when it's idle and low when it's active. Clock phase determines edge at which the data is sampled, for CPHA = 0 the data is sampled at the first edge, for CPHA = 1 the data is sampled on second edge.

The four combinations of the CPOL and CPHA are called SPI modes, you need to select a mode when configuring SPI, depending on your hardware, note that if CPOL = 0 and CPHA = 0 the clock transitions form low to high when active and the data is sampled on the raising edge of the clock this is the same as when CPOL =1 and CPHA = 1 because data will still be sampled on the raising edge of the clock



A real life example is the oled driver SSD1339 that samples data on the raising edge of the clock, that is, two modes work equally well CPOL = 0/CPHA = 0 and CPOL = 1/CPHA = 1.

Finally, note that the maximum frequency you can set SPI to, according to the datasheet, is 1/8 of the peripheral clock (PCLK) selected in PCLKSEL0/1. Setting  PCLK_SPI to 10b selects the CPU clock (CCLK) as the peripheral clock source  and so f = (CCLK)/8 = 100Mhz/8 that is 12.5 Mhz.

Now this is an example of initializing and using SPI, note that the legacy SPI interface is replaced by SSP which supports SPI among other protocols:
void ssp_init()
{
    PINSEL_CFG_Type pin_cfg={
        .Portnum    = SSP_PORT,
        .Pinmode    = PINSEL_PINMODE_PULLUP,
        .OpenDrain  = PINSEL_PINMODE_NORMAL,
    };
    
    SSP_CFG_Type  ssp_cfg ={
        .CPHA           = SSP_CPHA_FIRST,
        .CPOL           = SSP_CPOL_HI,
        .ClockRate      = SSP_CLCK,
        .Databit        = SSP_DATABIT_8,
        .Mode           = SSP_MASTER_MODE,
        .FrameFormat    = SSP_FRAME_SPI
    };

    /*SSP PINSEL configuration*/
    pin_cfg.Funcnum = 2;
    pin_cfg.Pinnum = SSP_MISO;
    PINSEL_ConfigPin(&pin_cfg);

    pin_cfg.Pinnum = SSP_MOSI;
    PINSEL_ConfigPin(&pin_cfg);
    
    pin_cfg.Pinnum = SSP_SCLK;
    PINSEL_ConfigPin(&pin_cfg);

    pin_cfg.Pinnum = SSP_SSEL;
    PINSEL_ConfigPin(&pin_cfg);
    
    /*initialize SSP*/
    SSP_Init(SSP_BASE, &ssp_cfg);
    SSP_Cmd(SSP_BASE, ENABLE);
}

uint8_t ssp_read()
{
    while(SSP_GetStatus(SSP_BASE, SSP_STAT_BUSY));
    SSP_SendData(SSP_BASE, 0xFF);
    return SSP_ReceiveData(SSP_BASE);
}

void ssp_write(uint8_t c)
{
    while(SSP_GetStatus(SSP_BASE, SSP_STAT_BUSY));
    SSP_SendData(SSP_BASE, c);
}
I2C
I2C is a half duplex low speed serial interface, I2C uses two wires Serial Data Line (SDA) and Serial Clock Line (SCL). Both lines are open-collector, an open-collector pin can only pull the signal line low (sink) thus it's active low and requires a pull-up resistor to keep the line high in idle state.
I2C doesn't use a chip select instead each slave on the bus has a unique  7-bit address to which it only responds to. The following excerpt is from the bma180 accelerometer driver I wrote demonstrating the use of I2C:
void bma180_init()
{
    PINSEL_CFG_Type pin_cfg={
        .Funcnum    = 3,
        .Portnum    = BMA180_I2C_PORT, /*port0 I2C1*/
        .Pinmode    = PINSEL_PINMODE_PULLUP,
        .OpenDrain  = PINSEL_PINMODE_NORMAL
    };

    /*SDA*/
    pin_cfg.Pinnum = BMA180_I2C_SDA;
    PINSEL_ConfigPin(&pin_cfg);
    /*SCL*/
    pin_cfg.Pinnum = BMA180_I2C_SCL;
    PINSEL_ConfigPin(&pin_cfg);

    I2C_Init(BMA180_I2C_BASE, BMA180_I2C_CLCK);
    I2C_Cmd(BMA180_I2C_BASE, ENABLE);

    printf("bma180 chip id %d\n", bma180_read_id());
}

/*reads chip id*/
int8_t bma180_read_id()
{
    int8_t buf = 0x00;

    I2C_M_SETUP_Type tfr_cfg = {
        .tx_data     = &buf,
        .tx_length   = sizeof(buf),
        .rx_data     = &buf,
        .rx_length   = sizeof(buf),
        .sl_addr7bit = BMA180_I2C_ADDR,
        .retransmissions_max = 3,
    };

    /*write register address/read register value*/
    I2C_MasterTransferData(BMA180_I2C_BASE, &tfr_cfg, I2C_TRANSFER_POLLING);

    return buf;
}
EMAC
The LPC1769 has a full fledged 10/100 Ethernet Controller with WOL and other capabilities. Due to it's length I did not include the example here, however, it's  available  in the sources section.

Software Stacks
Nice so we now have a working toolchain and drivers, and we know a bit  on how to initialize and use some common hardware interfaces. Next we look at some essential software stacks.

FatFS
FatFS is a fat filesystem implementation that is abstracted from the underlying hardware layer, that is, to use it you'll need to provide your own low-level disk initialization and I/O routines that will eventually be called by the FatFS library to read/write sectors from a disk, or from whatever medium you choose to store your data.

I personally use an SDC for my projects, you can find an SDC driver online and port it, or you can use mine, you can find it below in the sources section. The driver is already  integrated with FatFS and tested so it should save you some time.

If you decide to write your own driver, or just want to know how SDC work, I highly recommend the tutorial on the FatFS homepage along with the sdc Simplified Physical Layer Spec.

Once you have managed the low-level I/O, you'll find that FatFS has a really familiar and easy to use interface, here's a small example:
#include <stdio.h>
#include "ff.h"
int main()
{
    FIL     fp;
    FATFS   ffs;
    UINT    len;
    const char *path = "0:test.txt";
    const char *text = "SDC Test";

    f_mount(0, &ffs);   /*mount ffs work area*/
    f_open(&fp, path, FA_WRITE|FA_CREATE_ALWAYS);
    f_write(&fp, text, strlen(text), &len);
    f_close(&fp);
}
FreeRTOS
FreeRTOS is an open-source real time OS, A few things worth mentioning when using FreeRTOS, first, the choice of heap allocator, FreeRTOS comes with 3 allocators the first one doesn't free memory, second one allows freeing memory but doesn't handle fragmentations, third and last one is just a wrapper around malloc/free this is the one you should use unless you want FreeRTOS and libc both poking holes in the heap.

Second issue, is the SysTick_Handler, not really an issue since we declared it as weak we can override it here, simply change xPortSysTickHandler to SysTick_Handler.

Finally, we can't use our sleep function because a) SysTickCnt is not updated anymore b) RTOS needs to know about tasks that yield the processor, i.e. go to sleep, so it can schedule other tasks, so I define the following macro in FreeRTOS.h
#define sleep(ms) vTaskDelay(ms) 
This a small FreeRTOS example that schedules two task
#include <stdio.h>
#include "FreeRTOS.h"
#include "task.h"

void task_one(void *args)
{
  while (1) {    
      printf("task1\n");
      sleep(1000);
  }
}

void task_two(void *args)
{
  while (1) {    
      printf("task2\n");
      sleep(1000);
  }
}

void vApplicationStackOverflowHook(xTaskHandle *pxTask, signed char *pcTaskName)
{
    printf("task stack overflow\n", pcTaskName);
}

int main(void)
{   
    xTaskCreate(task_one,   /*task function              */
                "task_one", /*task name                  */
                256,        /*task stack size in words 1k*/
                NULL,       /*task parameters            */
                1,          /*task priority              */
                NULL);      /*task handle                */
 
    xTaskCreate(task_two,   /*task function              */
                "task_two", /*task name                  */
                256,        /*task stack size in words 1k*/
                NULL,       /*task parameters            */
                2,          /*task priority              */
                NULL);      /*task handle                */
    
    vTaskStartScheduler();
}
uIP
uIP is an open-source embedded TCP/IP stack. uIP implements ARP, SLIP, IP, TCP, UDP and ICMP and provides two APIs a BSD socket like API and an event-based API. In the sources section you will find a bare minimum example of an ARP-enabled echo server using the event-based API. 

Conclusion
A very powerful MCU like the LPC1768 opens up a lot of possibilities I hope this introduction is enough to help you explore those possibilities. Any feedback is more than welcome & Thank you.

Sources
FatFs-SDC driver
hg clone https://code.google.com/p/lpc17xx-fatfs-sdc
uIP echo server and client
hg clone https://code.google.com/p/lpc17xx-uip-echo
Sparkfun OLED driver
hg clone https://code.google.com/p/lpc17xx-oled-driver
References
The LPC1768 datasheet 
The Definitive Guide to the ARM Cortex-M3
ARM System Developer's Guide: Designing and Optimizing System Software
Designing Embedded Hardware
Read more ...

Sunday, November 21, 2010

Arduino Sonar

This is a fun project I made with an Arduino UNO. It's a simple Sonar using an ultrasonic sensor.

 

Arduino
Arduino is an open-source hardware/software platform based on Atmel ATmega, being an open-source fanatic I couldn't resist buying it :) it's remarkably easy to learn, given that this is my first Arduino project and it took just a couple of hours ! Arduino is  programmed in a language based on Wiring.  At the time of this writing UNO is the latest Arduino board based on ATmega328.
Arduino Sonar
The idea behind the project quite simple, the servo rotates the ultrasonic sensor 180 degrees back and forth while sending/receiving ultrasonic pulses, objects are displayed on LCD by drawing lines proportionally to the time it takes the pulse to travel back to the sensor. This type of Sonar is called an Active Sonar because it initiates the ultrasonic  waves and listens for the echo as opposed to a passive one that listens to  incoming waves from other sources.



I used the PING Ultrasonic Sensor from parallax, however, any sensor should work equally well, even an Infrared sensor, as for the LCD I used the Nokia 6100 Knock-off color LCD from sparkfun. Here are some pictures showing the results of scanning the test subjects :)




The whole project can be found here, I ported the LCD driver it was originally written for mbed.

hg clone https://arduino-sonar.googlecode.com/hg/ arduino-sonar
Read more ...

Tuesday, September 7, 2010

Introduction to ARM Cortex-M3 Part 1-Overview

Hello, this is an introduction to the ARM Cotrex-M3 microprocessor. In the first part we'll talk about the core features of the Cortex-M3, the LPC1768 MCU and the prototyping board mbed, if you decide to get started with ARM this series should have a fair amount of information to help you do so quickly... have fun :)

Cortex-M3 overview
The Cortex-M3 is a 32-bit microprocessor made by ARM based on the ARMv7 architecture, this a Harvard architecture, i.e. separate code and data buses allowing parallel instruction and data fetches, with three profiles, A for high-end applications, R for real time applications and the microcontroller targeted M profile.

The Cortex-M3 is based on the M profile it has a 3 stage pipeline, an advanced interrupt controller (NVIC ) with low interrupt latency, DMA controller with 8 32-bit channels, support for an optional MPU (the LPC17xx has one), support for two operation and two access modes and support for the Thumb2 instruction set.

Thumb2
Generally speaking, ARM processors support two instruction sets, the 32-bit ARM and the 16-bit Thumb instruction sets, when executing ARM code the processor is said to be in ARM state and when executing Thumb code it's said to be in Thumb state.

The ARM state offers more performance for speed-critical tasks, also certain operations require the ARM state e.g. interrupt handlers, while the thumb state offers higher code density (more instructions in less memory).

ARM and Thumb code live in separate source files, switching the processor between the two states frequently could complicate things and become an overhead on both the development and execution time.

The Cortex-M3 supports the Thumb2 set (a superset of the Thumb) which allows mixing 16/32 bit instructions, thus it offers the best of both worlds, performance and high code density in one instruction set without the need  for state switching to do so, in fact, it's not even supported by the Cortex-M3, i.e. it's always in Thumb state.

Operation Modes
The Cortex-M3 supports two operation modes the thread mode for process execution and the handler mode for exception handlers code, each mode has its own stack pointer, the process stack pointer (PSP) and the main stack pointer (MSP).

Usually the thread and handler modes use the same stack pointer thus sharing the stack memory, however, by configuring the processor to use different stack pointers, the stack memory for those two modes can be separated, consequently protecting the system stack memory form a faulty user process.

The two stack pointers are banked, that is only one can be accessed at a time, SP accesses the currently used stack pointer.In an interrupt handler MSP is always used, access to the PSP maybe still be needed for several reasons, mainly when an OS, e.g. RTOS, is running things it may need to change the PSP for context switching or fetch the SVC number from the program counter (PC) when an SVC interrupt is made.

Other reasons for accessing the PSP in an interrupt handler may include locating a faulty instruction, e.g. an instruction that caused a bus fault can be fetched in the bus fault handler from the process stack using the stacked PC.

Access Modes
The Cortex-M3 supports two access modes, user and privileged access, in user mode access to certain registers and instructions is restricted and if an MPU is available access to memory regions, containing OS data or another process data, can also be restricted for a user process. This is mainly intended for use by a multitasking OS.

After executing the rest handler the processor is running in a privileged thread mode, a switch to user level should occur shortly after, when entering an exception handler the processor switches to a privileged level and then back to the previous level upon exiting the handler. This could serve very well when implementing system calls.
A user level thread cannot switch back to a privileged level except through an exception handler (running in handler mode) that changes the access level to privileged on behalf of the thread before returning to thread mode.

NVIC
The Nested Vectored Interrupt Controller (NVIC) is an advanced interrupt controller that allows nesting interrupts with higher priorities, that is if an interrupt handler is currently executing when a higher priority interrupt occurs, the lower priority interrupt is preempted and the higher priority interrupt executes next.

Some priorities are fixed, like the reset exception which is the highest (lowest number) priority, other are programmable and can be changed dynamically, i.e at run time, however, this requires the interrupt vector to be relocated from flash to ram and then patched with the new handler.

The NVIC handles stacking (pushing registers onto the stack) and un-stacking (popping registers from the stack) at the hardware level, this does not only relief the programmer from doing so himself, it also allows the handler to be normal C function and decreases the overall interrupt latency.

Vectored means that when an interrupt is asserted its number is known to the processor and used to index into the interrupt vector to obtain the handler address directly, as opposed to having a shared handler and enumerating devices to know which one interrupted the processor.

This is part of the interrupt vector from the startup code of the Cortex-M3, the first word is the initial MSP value, second is the address of the first interrupt  handler and so on... The interrupt vector is located at address 0x0 in flash:
.long   __cs3_stack                 /* Top of Stack                 */
.long   __cs3_reset                 /* Reset Handler                */
.long   NMI_Handler                 /* NMI Handler                  */
.long   HardFault_Handler           /* Hard Fault Handler           */
.long   MemManage_Handler           /* MPU Fault Handler            */
.long   BusFault_Handler            /* Bus Fault Handler            */

.....

/* Dummy Exception Handlers */

    .weak   NMI_Handler
    .type   NMI_Handler, %function
NMI_Handler:
    B       .
    .size   NMI_Handler, . - NMI_Handler

    .weak   HardFault_Handler
    .type   HardFault_Handler, %function
HardFault_Handler:
    B       .
    .size   HardFault_Handler, . - HardFault_Handler
The __cs3_stack symbol is the address of the start of the stack region in ram, this address is loaded into MSP on startup, since the Cortex-M3 uses a descending stack, i.e. the stack grows downwards while the heap grows upwards, this address is the last memory address:

In the linker script, which is basically the memory layout, __cs3_stack symbol is defined as start of ram + ram size:
PROVIDE(__cs3_stack = __cs3_region_start_ram + __cs3_region_size_ram);

Near the end of the startup code dummy interrupt handlers, branches to same address (B "."), are provided for all the interrupt handlers, those are defined as weak so when linking the binary they can be overridden by user defined handlers (if any).

Two interesting techniques used by the NVIC to further decrease the interrupt latency, tail-chaining and late arrivals.

Tail-Chaining
When two interrupts arrive at the same time, or a lower priority interrupt occurs while executing a same or higher priority interrupt i.e. non pre-empting, the higher priority interrupt executes first while the other remains pending and as soon as the higher priority interrupt finishes executing the pending interrupt is executed immediately, i.e. tail-chained to the first one, without un-stacking and then stacking the registers again which is not necessary because the contents of the stack has not changed, Thus saving a significant amount of time on  executions of subsequent interrupt handlers.


Notice that due to the Harvard architecture, the stacking of the registers can take place simultaneously with the fetches of the interrupt vector and isr code.

Late Arrivals
When a high priority interrupt is asserted while entering a lower priority interrupt, and it happens to occur between stacking and before executing the  first handler instruction, the higher priority interrupt vector is fetched stacking is allowed to finish, and as soon as it does, the processor executes the higher priority interrupt immediately, when it finishes executing, the lower priority interrupt is then tail-chained to the higher priority interrupt and allowed to execute.


Similarly, if the interrupt occurs while un-stacking is taking place, the un-stacking is abandoand and the lower priority interrupt is tail-chained to the higher priority interrupt and allowed to execute.


Bit-Banding
A Bit-Band region allows atomic bit manipulation through another memory region called the alias region, each bit in the Bit-Band region is addressable through a 32-bit aligned address in the alias region, that is each word in the Bit-Band is mapped to 32 addresses in the alias region.

Bit-Banding can shorten a read-modify-write operation, say you wish to set a bit in some device register, e.g. to enable interrupts, you usually do a read-modify-write operation that is you would read a word, mask it and then write it back, you may also need to make sure this operation won't be interrupted, i.e. atomic, to ensure data consistency, so your final code might look like this:
#define DEVICE_BASE_ADDR    ((uint32_t*)0x2007C000)
#define ENABLE_INT_MASK     (0x01)

void enable_int()
{
    // tag for exclusive access
    // wait while it's locked
    while (__LDREXW(DEVICE_BASE_ADDR)); 

    uint32_t i = *DEVICE_BASE_ADDR;
    i |= ENABLE_INT_MASK;
    __STREXW(i, DEVICE_BASE_ADDR);      //exclusive write    
}
Note that ldrex and strex are the newer exclusive access instructions, starting from ARMv6 they replaced SWP instruction for several reasons mainly that they don't lock the bus, anyway, using Bit-Banding it's just a simple matter of writing to the alias address of the bit:
#define DEVICE_BASE_ALIAS   ((uint32_t*)0x22000000)

void enable_int()
{
   *DEVICE_BASE_ALIAS = 1;
}

Next we will talk about the LPC1768 Cortex-M based MCU.

NXP  LPC1768
The LPC1768, manufactured by NXP/Philips, is an MCU based on Cortex-M3 it has just about every peripheral you could think of UARTs USB, SPI, I2C, ADC/DAC, PWM, CAN, Ethernet... well you get the picture. It also has an MPU, as mentioned before, which can be used to define memory regions with access attributes like (rwx).

The LPC1768 has an on-chip 512k Flash and 64k SRAM 32k of those are reserved for USB and Ethernet, however, they can still be used as general purpose ram when either of those peripherals is not used.

The LPC1768 has an 8 channel DMA, each can be configured independently to handle a transfer from memory to memory, memory to peripheral, peripheral to memory and peripheral to peripheral. The DMA allows the CPU to be free for number crunching while it handles transfers by taking control of the bus, saving the cycles required if the CPU were to handle the transfer itself.

The DMA controller has a separate IRQ line that, when configured to so, interrupts when a transfer is complete, it can handle either a single transfer or multiple transfers chained using a linked list. it also supports different source and destination transfer width by packing and unpacking data.

There are many prototyping boards based on NXP's microcontrollers, one of  those is the mbed board.

mbed
The mbed is a prototyping board for the NXP LPC1768 MCU. It is a complete development platform for rapid prototyping that provides high-level C++ drivers for the peripherals, protocol stacks, code samples and a cloud-based based compiler.


The mbed makes programming the MCU really easy, it has a small 2MBs flash with FAT fs, to program the LPC1768 you mount the flash, copy the binary  image and then reset the mbed, the binary image is then copied to the mcu flash and started. That's basically all you need to do! you'll definitly appreciate this if you tried JTAG with openocd before.

This provides an easy way into ARM hacking, although I must say that I don't prefer C++ and I definitely hate the online compiler altogether ! Therefore I've taken a different approach, leaving the mbed libraries and compiler and using NXP's driver library, CMSIS and a GNU based toolchain. I highly recommend you do so too, this way you'll learn more about your processor.

That's all for today, in part 2 we'll talk about more fun stuff like CodeSourcery, NXP driver library, CMSIS, SPI and other things... Also we will make a couple of simple applications to put everything together, see you soon :)
Read more ...