Monday, December 2, 2013

Using The CCM Memory on the STM32

The STM32 series have non-contiguous memories divided into blocks, for example the STM32F4, has 2 (contiguous) blocks of SRAM connected to the bus matrix with different interconnects, and a Core Coupled Memory (CCM) block which is connected directly to the core.


This tight coupling of the CCM memory to the core, leads to zero wait states, in other words, the core has exclusive access to this memory block, so for example, while other bus masters are using the main SRAM the core can access the CCM. Therefore, the CCM block is commonly used for the stack and other critical OS data, this partitioning, allows the core to continue executing code while for example, a DMA transfer takes place. However, the CCM could also be used as an extra memory block, doing so is easy, and there are a few examples out there that show how, simply defining a section in the linker script will do:
.ccm : {
  . = ALIGN(4);
  _sccm = .;
  *(.ccm)
  . = ALIGN(4);      
  _eccm = .;
}>CCM

And a section attribute is used to allocate memory into that section :
const int8_t my_array[13] __attribute__ ((section (".ccm")))= {....};

However, what if you want to load initialized data into that section ? some look-up tables for example?  using that section is not enough, see, the linker script makes the distinction between the Load Memory Address  (LMA) where data is stored initially, and the Virtual Memory Address (VMA) where the data should be loaded at runtime, if the LMA is not specified explicitly, it becomes the same as VMA.

You can see here that GDB loads the .ccm data into the CCM block (LMA=VMA=0x10000000) directly, while all other sections are loaded into the flash region (0x8xxxxxx):

Loading section .ccm, size 0x4ebc lma 0x10000000
Loading section .isr_vector, size 0x188 lma 0x8000000
Loading section .text, size 0x9744 lma 0x8000188
Loading section .ARM, size 0x8 lma 0x80098cc
Loading section .init_array, size 0x8 lma 0x80098d4
Loading section .fini_array, size 0x4 lma 0x80098dc
Loading section .data, size 0xa30 lma 0x80098e0
Loading section .jcr, size 0x4 lma 0x800a310

While this may sound right, it's not, if GDB loads the .ccm section is loaded into SRAM directly, it will disappear after a power cycle! So instead, we want the LMA to be somewhere in the FLASH region (0x8xxxxxxx) and the VMA to be (0x10000000):
_eidata = (_sidata + SIZEOF(.data) + SIZEOF(.jcr));
.ccm : AT ( _sidata + SIZEOF(.data) + SIZEOF(.jcr))
{
  . = ALIGN(4);
  _sccm = .;
  *(.ccm)
  . = ALIGN(4);      
  _eccm = .;
}>CCM

Note the .jcr is included in by some startup code for something related to Java, without adding the SIZEOF(.jcr) the .ccm will overlap that section, also note the _eidata symbol which will be referenced later in code. Now, when you try to load the elf, GDB prints:

Loading section .isr_vector, size 0x188 lma 0x8000000
Loading section .text, size 0x9794 lma 0x8000188
Loading section .ARM, size 0x8 lma 0x800991c
Loading section .init_array, size 0x8 lma 0x8009924
Loading section .fini_array, size 0x4 lma 0x800992c
Loading section .data, size 0xa30 lma 0x8009930
Loading section .jcr, size 0x4 lma 0x800a360
Loading section .ccm, size 0x4ebc lma 0x800a364

Great, now the .ccm data is loaded into the FLASH region, we just need something to load it from FLASH to CCM in runtime, if you look at the startup code, there's an assembly function that copies initialized data from the flash to where it should be loaded in SRAM (the VMA), you need to do the same for the .ccm data, by either modifying the startup code, or perferrably, copying the data with a C function, so here it is:
void load_ccm_section () __attribute__ ((section (".init")));
void load_ccm_section (){
    extern char _eidata, _sccm, _eccm;

    char *src = &_eidata;
    char *dst = &_sccm;
    while (dst < &_eccm) {
        *dst++ = *src++;
    }
}
Note that the function is placed into the .init section so it executes before main. Now in runtime, this function will load the data from FLASH into SRAM using the pointer defined in the linker script.
Read more ...

Thursday, November 28, 2013

STM32F4xx Libraries



I wrote a tutorial before on how to setup a toolchain and build the STM32F4xx standard peripheral drivers into one convenient library, since then, a few people have asked me about the library, so to make life easier, I downloaded the latest StdPeriph/CMSIS, in addition to a few other libraries that I might need later, and shared everything in one repository, which currently has the following libraries:
Cortex-M  CMSIS      V3.20
STM32F4xx CMSIS      V1.3.0
STM32F4xx StdPeriph  V1.3.0
STM32_USB_Device     V1.1.0
STM32_USB_OTG        V2.1.0
In addition to those, the repository also includes a simple USB device library  (stm32f4xx/USB_Generic) which abstracts all the horrible details of the USB libraries into a very simple generic USB device implementation with just two Bulk endpoints...

To use this library you just pass a struct with two callback functions and the library will call those functions whenever data is received or requested, it's as simple as that, note that it's configured for OTG FS only, it could still be useful if you just want to get USB working and don't have time to go through all the examples.

Finally, repository also includes some examples, a Blinky, a USB_Generic example and some user-space code with libusb.

Building The Libraries:
To build the libraries and examples just type make in the top directory, the top Makefile will pass along all the flags and variables, here are some options you can pass on the command line:

make DEBUG=0
This will build everything with -O2 and no debugging symbols (not recommended)

make DEBUG=1 CFLAGS="-DOSC=xx"
This will build the library with debugging enabled, no optimization and using the given crystal frequency in MHz (for example -DOSC=16)

Repository:
https://github.com/iabdalkader/stm32f4xx.git
Read more ...

Sunday, November 17, 2013

FT231X Breakout

This is a breakout board for FTDI's latest USB-to-Serial bridge, the FT231X. This one comes in a smaller package (SSOP20) and it's cheaper than its predecessor the FT232R/L, it also offers a charging detection feature, which I'm not really interested in, but anyway see this post for more details.


I've seen a couple of good breakout boards out there, but this one has a few advantages over the others,  it has a solder jumper to switch VCCIO between 3.3V and 5.0V, a 500mA PTC fuse for over-current protection and it's pin compatible with the Arduino mini programming header.

Repo:
https://github.com/iabdalkader/ft231x-breakout.git

Read more ...

Sunday, November 10, 2013

Color Tracking With OpenMV

So I finally had some free time to work on OpenMV, for those of you who haven't been following this project, OpenMV is an open-source tiny machine vision module based on an STM32F4 ARM Cortex-M4 micro and an OV9650 sensor. I started this project mainly because I find the existing cameras are either too limited for their price or too expensive if they do some image processing, so one of my main goals was to make this as cheap as possible, the total cost of this module so far is around $20 for a single board, and could go as low as $15 for 500 pieces.

I wrote a simple color tracking algorithm for the camera, which I tested using an Arduino, the Arduino sends out a few commands via the serial port to the camera telling it to capture and process a frame, it then receives back the coordinates of the object and controls the servos accordingly. I was able to process around 15FPS, which is not bad given the current naive implementation. This is a video of the camera tracking a ball:

You can find the code and schematics here in a single repository, keep in mind that I'm still working on it, and I'm also considering a new revision to fix some minor issues and add an SPI flash for storage. If you have any suggestions/feedback please feel free to leave a comment. 
hg clone https://code.google.com/p/openmv-camera/
Update: I've created a new repo on github, this has the most recent version:
git clone https://github.com/iabdalkader/openmv.git
Read more ...

Thursday, October 17, 2013

OpenMV Update

Another quick update on my project OpenMV. I've finally managed to get the sensor working in QQVGA/RGB565 mode:


I'm using the discovery board as a debugger and a smart LCD to display the frames via USART. I've also implemented a simple color tracking algorithm, as a proof of concept:


I'm currently cleaning up the code, and I will share it with the schematics next time.. Thanks for all your support :)

Read more ...