Month: July 2015

Some facts about Atmel SAM L21 microcontroller

The Atmel SAML21 microcontroller has a complex clock structure, in fact even more complex than some high end processors. This complexity brings more flexibility to enable individually each peripheral clock source.

The SAM L21 has nine Clocks Generator, each generator can select a specific clock input (XOSC, GCLK_IN, GCLK_GEN1, OSCULP32K, OSC32K, OSC16M, DFLL48M or DPLL96M). Exception is Generator1 (GCLK_GEN1) that cannot select GCLK_GEN1 (itself) because its clock output can be used as clock input by other Generators.

Each Generator has a internal prescaler to divide the input clock up to 128 (again CLK_GEN1 is exception because it can divide up to 32768). And the Generator output clock can be used by up to 64 Peripheral channels (in the SAML21 there are “only” 35 channels).

Basic Operation

-The GCLK module has 9 Generic Clock Generators

- Up to 64 Peripheral Channels and the Main Clock signal (GCLK_MAIN) can be sourced from Generator

- The clock source selected as input to a Generator can be used directly or prescaled

- The GCLK Module doesn't have a general enable/disable bit

- The GCLK Module can be reset by setting the Software Reset bit (CTRLA.SWRST)

  - All register from GCLK module will be reset, except Per.Channels and associated Generators

- All Generators can be set to run from 1 of 9 clock sources, except GCLK_GEN[1]
  - GCLK_GEN[1] can be used to supply clock for all others 8 Generators

- Each generator GCLK_GEN[x] can be connected to 1 pin (GCLK_IO[y])

- GCLK_GEN[0] is used as GCLK_MAIN

- Each Genarator can be enabled/disabled by setting Generator Enable bit (GENCTRLn.GENEN = 1/0).

- The clock for of each Generator can be selected by setting the Source Select bit (GENCTRL[n].SRC)

  - When changing of clock source the  register SYNCBUSY.GENCTRL_n will remain 1 until the source is fine

- The clock freq of each generator can be divided setting GENCTRLn.DIV
  - If GENCTRLn.DIVSEL = 0 and GENCTRLn.DIV is 0 or 1 the freq. is not divided

- If division factor is odd the Duty cycle will not be 50/50
  - Setting the Improve Duty Cycle (GENCTRLn.IDC) will result in a 50/50 duty cycle

- If Output Enable (GENCTRLn.OE = 1) and GENCTRLn.GENEN = 1 the clock is outputed to GCLK_IO pin

Peripheral Clock

- Before enabling a Peripheral channel the Generator clock needs to be enabled (GENCTRLn.GEN = 1) and
this Generator is already selected as source for the Peripheral Channel (PCHCTRLm.GEN)

- The Peripheral Channel is enabled in the Channel Enable bit (PCHCTRLm.CHEN = 1)

- The Peripheral Channel's Generator (PCHCTRLm.GEN) needs to be set with Channel disabled (PCHCTRLm.CHEN = 0)

- The Peripheral clock configuration can be locked setting Write Lock bit (PCHCTRLm.WRTLOCK=1)

  - When WRTLOCK is set the Generator will be locked, exception is Generator 0 that is sorce of GCLK_MAIN

- In SAM L21 we have 35 Peripheral channels (index 0 up to 34)

GUI for LinuxCNC/Machinekit

There are some nice GUIs for LinuxCNC.

These GUI make LinuxCNC or MachineKit (LinuxCNC fork) control more user friend.

Here I list three more common options:

This is the original GUI shipped with LinuxCNC LiveCD/Installer distro:

Gmoccapy is an alternative to Axis focuses on Touchscreen devices and supports up to 4 axis CNCs:

QtQuickVcp is the more recent GUI designed to be multi-platform, including Android support:

Using Watchpoints in the GDB to verify register access

Watchpoint is a feature similar to Breakpoint, but instead of stopping when the Program Counter reach a function or code line, watchpoint stops when an address memory is read (rwatch), write (watch) or read/write (awatch).

Watchpoints are very useful when you are doing reverse engineering or when you want to debug a code that access many registers.

First we need to know if our processor supports hardware watchpoints:

(gdb) show can-use-hw-watchpoints
Debugger's willingness to use watchpoint hardware is 1.

Case your uP/uC doesn’t, no problem! It will work, but with Software Watchpoint ( *slow* )

Some processors (i.e. PowerPC) support masking a memory position, then any address accessed in this area will generate a stop condition:

(gdb) watch *0xdeadbeef mask 0xffffff00

Unfortunately my microcontroller (ARM Cortex-M0+) doesn’t support:

(gdb) awatch *0x40000000 mask 0xffff0000
This target does not support masked watchpoints.

In this case I need to add many watchpoints manually:

(gdb) b main
Breakpoint 1 at 0x1c3a: file ../src/qs_i2c_master_basic_use.c, line 108.
(gdb) c

Breakpoint 1, main () at ../src/qs_i2c_master_basic_use.c:108
108		system_init();
(gdb) n
113		configure_i2c_master();
(gdb) awatch *0x40000000 mask 0xffff0000
This target does not support masked watchpoints.
(gdb) awatch *0x40002800
Hardware access (read/write) watchpoint 2: *0x40002800
(gdb) awatch *0x40002804
Hardware access (read/write) watchpoint 3: *0x40002804
(gdb) awatch *0x40002808
Hardware access (read/write) watchpoint 4: *0x40002808
(gdb) awatch *0x40002828
Hardware access (read/write) watchpoint 5: *0x40002828
(gdb) awatch *0x400018d0
Hardware access (read/write) watchpoint 6: *0x400018d0
(gdb) awatch *0x42000800
Hardware access (read/write) watchpoint 7: *0x42000800
(gdb) awatch *0x42000804
Hardware access (read/write) watchpoint 8: *0x42000804
(gdb) awatch *0x4200080c
Hardware access (read/write) watchpoint 9: *0x4200080c
(gdb) awatch *0x42000814
Hardware access (read/write) watchpoint 10: *0x42000814
(gdb) awatch *0x42000816
Hardware access (read/write) watchpoint 11: *0x42000816
(gdb) awatch *0x42000818
Hardware access (read/write) watchpoint 12: *0x42000818
(gdb) awatch *0x4200081a
Hardware access (read/write) watchpoint 13: *0x4200081a
(gdb) awatch *0x4200081c
Hardware access (read/write) watchpoint 14: *0x4200081c
(gdb) awatch *0x42000824
Hardware access (read/write) watchpoint 15: *0x42000824
(gdb) awatch *0x42000828
Hardware access (read/write) watchpoint 16: *0x42000828
(gdb) c

Program received signal SIGTRAP, Trace/breakpoint trap.
0x000016f0 in system_gclk_chan_disable (channel=20 '24')
    at ../src/ASF/sam0/drivers/system/clock/clock_saml21/gclk.c:371
371		GCLK->PCHCTRL[channel].reg &= ~GCLK_PCHCTRL_CHEN;


Cloning NuttX repositories

The NuttX RTOS is moving from SourceForge to BitBucket, during this move Greg Nutt created some separated repositories for NuttX kernel, applications and other submodules.

You can see the steps to clone NuttX repositories in the README page:

Basically all you need to do is this:

$ mkdir nuttx
$ cd nuttx
$ git clone nuttx
$ git clone apps
$ cd nuttx
$ git submodule init
$ git submodule update

Now you can compile your “board” and your “config”:

$ cd tools
$ ./ "<board/config>"

Replace "<board/config>", example:
  $ ./ stm32f4discovery/usbnsh

$ cd ..
$ make oldconfig
$ make menuconfig
$ make

To keep your local repository updated execute:

$ git submodule foreach git pull

That’s all!!!

NuttX board initialization: Where can I put my code to be executed?

Essentially there are 3 levels of board initialization:

1. stm32_board_initialize()
Called immediately on boot up to set what resources are needed to boot this system. This includes a little bit of low level driver initialization if needed by up_initialize().

The OS is not yet initialized the nothing in stm32_board_initialize() can use ANY OS service. Nothing.

2. board_initialize() – (optional)
Called just before the application is started.

Here the OS is fully initialized, but you have to be careful because it is still running on the IDLE thread. That means that there are many things that you cannot do: You cannot wait for anything. You can’t use semaphores for example.

(There is CONFIG_BOARD_INITTHREAD that can be used to run board_intialize() on a separate thread if necessary).

board_initialize() is really only needed by code built with CONFIG_BUILD_KERNEL or CONFIG_BUILD_PROTECTED.

3. board_apps_initialize() via boardctrl()
Called after the application has started. This runs on the thread of the applications so it is always the best when available.

Note: This explanation is from an email from Greg Nutt, I decided to post it here to help other people to decide where to put their code.

More info: