high12noon blog

Adventures with NuttX

Back to main page

This page is a work in progress. I am documenting my adventures with the Real Time Operating System (RTOS) NuttX in "Real Time" as I learn the system. Last updated December 5th, 2024.

Table of Contents

Video: NuttX RTOS Beginnings

This is a video of a presentation by Gregory Nutt, the creator of NuttX, at the NuttX 2019 International Workshop at Gouda, South Holland.

Conventions Used In This Article

In this article, $HOME will refer to the Linux user's home directory (/home/your-user-name-here).

$TOPDIR will refer to the NuttX RTOS source repository's top-level directory. We'll clone several NuttX-related Git repositories under $HOME/NuttX, so $TOPDIR would resolve to $HOME/NuttX/nuttx in our case.

July 11, 2019: The Adventure Begins

This section last updated November 25, 2022 to indicate moved repositories command lines that changed in recent versions of NuttX.

Okay, so I have a cacophony of different microcontroller architectures around here, including: formerly Atmel now Microchip AVR and XMega, Microchip PIC32 (MIPS core), Texas Instruments Tiva-C Series (TM4C12x, ARM core), ST Microelectronics STM32 (ARM core), and probably a few others that have fallen by the wayside. And I also write programs for the PC side of things.

The problem with writing programs for all these different chips is that the programming is different and non-portable between them. That goes for low-level stuff like register programming to operate the various on-chip peripherals as well as high-level stuff like network or USB support.

The different hardware vendors have tried to address portability by implementing software libraries, but generally this is only good within one part family. It's not helpful if your next board uses a different vendor's part.

Why not stick with just one part family then? Well I've tried that. But it's not realistic. Every project has different requirements and ultimately you have to pick the MCU that best fits the requirements.

So recenty I discovered a RTOS called NuttX. It's been around for well over a decade, supports chips from all the part families I mentioned (and then some), has some features I consider very interesting, and comes with a permissive open-source-friendly and business-friendly BSD license. Whether NuttX is the answer to my microcontroller software needs is something I don't know yet, but I've decided to document my adventures...

Getting Started

I have Mac, Windows, and Linux (among others) available to me. The NuttX documentation states that the development environment must be POSIX such as Linux or macOS. It could be Windows if a POSIX layer is installed, such as Cygwin, MSYS, MSYS2, Ubuntu/Bash shell on Windows 10, etc. But it looked to me like the path of least resistance would be to go with Linux. I might try on the other operating systems in the future and document that as well... we'll see.

My preferred Linux distribution is Debian because it's arguably the biggest one in terms of distribution. It seems like most Linux distributions are based on Debian (including Ubuntu and all the ones that are based on it). Debian just released Debian 10 "Buster" but I am still using Debian 9 "Stretch."

In my home directory I made a directory to hold all the NuttX stuff:

$ mkdir NuttX
$ cd NuttX

NuttX and related things come in a bunch of different Git repos hosted on BitBucket.

(On a side note, I've seen projects get split across multiple repositories before; one of these days in my writings on Version Control I'll explain why that's less than optimal. I will say, here, that I strongly prefer Apache Subversion over Git because Subversion is both more capable and much simpler and easier to use than Git. That's a subject for another day.)

Anyway so I cloned the Git repos:

$ git clone https://bitbucket.org/nuttx/nuttx.git
$ git clone https://bitbucket.org/nuttx/apps.git
$ git clone https://bitbucket.org/nuttx/buildroot.git
$ git clone https://bitbucket.org/nuttx/tools.git
$ git clone https://bitbucket.org/nuttx/pascal.git
$ git clone https://bitbucket.org/nuttx/uclibc.git

Update (November 25, 2022): In the time since this section of the article was written, the NuttX project joined the Apache Software Foundation. The nuttx and apps repositories are now at https://github.com/apache/nuttx and https://github.com/apache/nuttx-apps. If following along, make sure to make the necessary changes in your command lines. Note that the above-mentioned buildroot, tools, and uclibc repositories did not move to the ASF and are still at bitbucket.org. The pascal repository was removed entirely at some point. (I never used it so I cannot say whether there is any significance to that.)

I don't know if there are others but I wanted to have all the code available on my system.

Now to get something built.

I have a Texas Instruments (TI) Tiva C Series Crypto Connected LaunchPad, specifically called EK-TM4C129EXL, so I wanted to build NuttX for it. The latest NuttX release at this writing, 7.30, does not contain a port for that specific board but does contain one for the similar Tiva C Series Connected LaunchPad, EK-TM4C1294XL. So I thought I'd start with that.

$ cd $HOME/NuttX/nuttx
$ tools/configure.sh -l tm4c1294-launchpad/nsh

Update (November 25, 2022): At some point (around NuttX 8.0 or 9.0, I think?), the board subdirectories were re-organized, owing (I think) to the growth in the number of boards supported by NuttX. To obviate the need to specify longer paths on the command line, the configuration script was modified to introduce a level of abstraction. The command to configure the above-shown board is now tools/configure.sh -l tm4c1294-launchpad:nsh. Notice that a colon (:) now separates the board name from the configuration. The script automatically finds the board and configuration within the new directory structure.

And I was met with an error related to lack of kconfig-conf.

After some searching, I found this page and this page, which led me to install some additional Linux packages that I was missing:

$ sudo apt-get install \
      bison \
      flex \
      gperf \
      libgmp-dev \
      libmpc-dev \
      libmpfr-dev \
      libisl-dev \
      binutils-dev \
      libelf-dev \
      libexpat-dev

(My system has numerous other packages on it which are related to development. I'll try to update this page later with all the ones needed, from a default Debian install, to work with NuttX.)

Even after installing all that stuff, kconfig-conf remained missing. After more searching I discovered that this tool is actually packaged with NuttX, in the "tools" repository. I had it under my $HOME/NuttX/tools/kconfig-frontends). So...

$ cd $HOME/NuttX/tools/kconfig-frontends
$ ./configure --enable-mconf --disable-gconf --disable-qconf
$ make
$ sudo make install

Back in $HOME/NuttX/nuttx, when I tried to use it:

cd $HOME/NuttX/nuttx
$ tools/configure.sh -l tm4c1294-launchpad/nsh

Update (November 25, 2022): Same note as above: tools/configure.sh -l tm4c1294-launchpad:nsh.

It failed with:

kconfig-mconf: error while loading shared libraries: libkconfig-parser-3.8.0.so:
cannot open shared object file: No such file or directory
make: *** [menuconfig] Error 127

I found a clue in $HOME/NuttX/tools/README.txt, under "kconfig-mconf Path Issues" where it mentioned that exact error. It turns out that ld didn't know where to find the shared library. There's a file called /etc/ld/so.conf that lists places ld should search, but ld doesn't read that file; you have to run ldconfig as root to make those settings take effect. It turns out that kconfig-conf was installed in /usr/local/bin, the library was installed in /usr/local/lib, and /etc/ld.so.conf did have /usr/local/lib in it (via /etc/ld.so.conf.d/libc.conf). I ran ldconfig as root and the problem went away:

$ sudo ldconfig

Having successfully configured NuttX for this board, I now needed a toolchain.

$ cd $HOME/NuttX/buildroot
$ cp configs/cortexm4f-eabi-defconfig-7.3.0 .config
$ make menuconfig
$ make

Well, that ran for a while but failed somewhere in the middle because texinfo wasn't installed. So:

$ sudo apt-get install texinfo
$ make

After a while, that succeeded.

To be continued! I'm going to call it quits for today. Let's recap where we are so far. I have cloned all the NuttX repositories into a NuttX directory under my home directory. I installed a bunch of needed packages and need to come back and make an exhaustive list. I built an ARM Cortex M4F EABI toolchain using the NuttX-provided buildroot, and now I think I'm ready to start building NuttX to run a test on my LaunchPad. Check back for more and feel free to write me with questions, comments, suggestions, criticisms, etc., at high12noon (the name of this blog), at mail, dot com.

July 18, 2019: The Adventure Continues

Building NuttX:

$ cd $HOME/NuttX/nuttx
$ export TOOLCHAIN_BIN=(path to buildroot binaries)
$ export PATH=$TOOLCHAIN_BIN:$PATH
$ make menuconfig

In make menuconfig, make sure System type, Toolchain selection is set to buildroot.

$ make

This ran for a surprisingly short time! I expected a lengthy build given the size of the repository and the sheer number of source files. But then again, this is an operating system for very resource constrained devices and therefore it stands to reason that only a fraction of that code actually gets built.

It produced the files nuttx and nuttx.bin under $HOME/NuttX/nuttx.

Now, to get the code flashed to my microcontroller...

After my first post on July 11, 2019, and this one a week later, I found a bunch of resources regarding NuttX specifically, toolchains, developing for microcontrollers on Linux, etc. Until now, my development has always taken place on a Windows platform using MCU vendor-supplied IDE (Integrated Development Environments, usually based on Eclipse, NetBeans, MS Visual Studio, or a custom interface). This is the first time that I really have to get into the nitty gritty of getting all these different details setup and working. Suddenly compiling, flashing, and debugging are separate things supplied by separate unrelated pieces of software. That's why this is an adventure!

Among other things, I watched some videos on the NuttX YouTube channel, including:

I also watched the following:

I opted to build OpenOCD (Open On Chip Debugger) from source as shown in #001 - Setting the Development Environment for NuttX. Note that my commands below contain some modification to the commands shown in the video based on differences in my Linux install (such as installed packages) and the newer available version of OpenOCD since the video was made.

First I needed these packages:

$ sudo apt-get install \
  minicom \
  libncurses5-dev \
  libusb-dev \
  libusb-1.0-0-dev

Clone the OpenOCD Git repository:

$ cd $HOME/NuttX
$ git clone http://repo.or.cz/r/openocd.git
$ cd openocd/
$ ./bootstrap

There are many options. To list them all:

$ ./configure --help

This is how I configured it:

$ ./configure \
  --enable-internal-jimtcl \
  --enable-maintainer-mode \
  --disable-werror \
  --disable-shared \
  --enable-stlink \
  --enable-ti-icdi \
  --enable-xds110 \
  --enable-jlink \
  --enable-rlink \
  --enable-vsllink \
  --enable-remote-bitbang
$ make
$ sudo make install
$ sudo cp contrib/60-openocd.rules /etc/udev/rules.d/
$ sudo udevadm control --reload

With the board NOT connected to the computer's USB port:

$ lsusb

Showed a bunch of USB devices.

I connected the board to the computer's USB port and:

$ lsusb

Showed a bunch of USB devices, which now included (on my computer):

Bus 001 Device 005: ID 1cbe:00fd Luminary Micro Inc. In-Circuit Debug Interface

Starting up OpenOCD requires either a bunch of command line options or some configuration files that encapsulate the needed options.

According to the OpenOCD documentation, if no configuration files or commands are given on the command line (that is, no -f or -c options), OpenOCD will try to read a configuration file called openocd.cfg by default. In any event, it searches for the configuration file(s) at the following locations, until it finds one with the name it's looking for:

My computer didn't have a .openocd directory under $HOME. I guessed that pkgdatadir would be something like /usr/local/share/openocd/scripts so:

$ ls /usr/local/share/openocd/scripts/interface

shows:

altera-usb-blaster2.cfg  imx-native.cfg           stlink.cfg
altera-usb-blaster.cfg   jlink.cfg                stlink-v1.cfg
arm-jtag-ew.cfg          jtag_vpi.cfg             stlink-v2-1.cfg
at91rm9200.cfg           kitprog.cfg              stlink-v2.cfg
buspirate.cfg            nds32-aice.cfg           sysfsgpio-raspberrypi.cfg
calao-usb-a9260.cfg      opendous.cfg             ti-icdi.cfg
chameleon.cfg            openjtag.cfg             ulink.cfg
cmsis-dap.cfg            osbdm.cfg                usb-jtag.cfg
dummy.cfg                parport.cfg              usbprog.cfg
estick.cfg               parport_dlc5.cfg         vsllink.cfg
flashlink.cfg            raspberrypi2-native.cfg  xds110.cfg
ft232r.cfg               raspberrypi-native.cfg
ftdi                     rlink.cfg

And

$ ls /usr/local/share/openocd/scripts/target

shows:

1986ве1т.cfg                       lpc1xxx.cfg
adsp-sc58x.cfg                     lpc2103.cfg
aduc702x.cfg                       lpc2124.cfg
aducm360.cfg                       lpc2129.cfg
allwinner_v3s.cfg                  lpc2148.cfg
alphascale_asm9260t.cfg            lpc2294.cfg
altera_fpgasoc_arria10.cfg         lpc2378.cfg
altera_fpgasoc.cfg                 lpc2460.cfg
am335x.cfg                         lpc2478.cfg
am437x.cfg                         lpc2900.cfg
amdm37x.cfg                        lpc2xxx.cfg
ar71xx.cfg                         lpc3131.cfg
armada370.cfg                      lpc3250.cfg
arm_corelink_sse200.cfg            lpc40xx.cfg
at32ap7000.cfg                     lpc4350.cfg
at91r40008.cfg                     lpc4357.cfg
at91rm9200.cfg                     lpc4370.cfg
at91sam3ax_4x.cfg                  lpc84x.cfg
at91sam3ax_8x.cfg                  lpc8nxx.cfg
at91sam3ax_xx.cfg                  lpc8xx.cfg
at91sam3nXX.cfg                    ls1012a.cfg
at91sam3sXX.cfg                    marvell
at91sam3u1c.cfg                    max32620.cfg
at91sam3u1e.cfg                    max32625.cfg
at91sam3u2c.cfg                    max3263x.cfg
at91sam3u2e.cfg                    mc13224v.cfg
at91sam3u4c.cfg                    mdr32f9q2i.cfg
at91sam3u4e.cfg                    nds32v2.cfg
at91sam3uxx.cfg                    nds32v3.cfg
at91sam3XXX.cfg                    nds32v3m.cfg
at91sam4c32x.cfg                   nhs31xx.cfg
at91sam4cXXX.cfg                   nrf51.cfg
at91sam4lXX.cfg                    nrf51_stlink.tcl
at91sam4sd32x.cfg                  nrf52.cfg
at91sam4sXX.cfg                    nuc910.cfg
at91sam4XXX.cfg                    numicro.cfg
at91sam7a2.cfg                     omap2420.cfg
at91sam7se512.cfg                  omap3530.cfg
at91sam7sx.cfg                     omap4430.cfg
at91sam7x256.cfg                   omap4460.cfg
at91sam7x512.cfg                   omap5912.cfg
at91sam9260.cfg                    omapl138.cfg
at91sam9260_ext_RAM_ext_flash.cfg  or1k.cfg
at91sam9261.cfg                    pic32mx.cfg
at91sam9263.cfg                    psoc4.cfg
at91sam9.cfg                       psoc5lp.cfg
at91sam9g10.cfg                    psoc6.cfg
at91sam9g20.cfg                    pxa255.cfg
at91sam9g45.cfg                    pxa270.cfg
at91sam9rl.cfg                     pxa3xx.cfg
at91samdXX.cfg                     qualcomm_qca4531.cfg
at91samg5x.cfg                     quark_d20xx.cfg
atheros_ar2313.cfg                 quark_x10xx.cfg
atheros_ar2315.cfg                 readme.txt
atheros_ar9331.cfg                 renesas_r7s72100.cfg
atheros_ar9344.cfg                 renesas_r8a7790.cfg
atmega128.cfg                      renesas_r8a7791.cfg
atmega128rfa1.cfg                  renesas_r8a7794.cfg
atsame5x.cfg                       renesas_rcar_gen3.cfg
atsaml1x.cfg                       renesas_s7g2.cfg
atsamv.cfg                         samsung_s3c2410.cfg
avr32.cfg                          samsung_s3c2440.cfg
bcm281xx.cfg                       samsung_s3c2450.cfg
bcm4706.cfg                        samsung_s3c4510.cfg
bcm4718.cfg                        samsung_s3c6410.cfg
bcm47xx.cfg                        sharp_lh79532.cfg
bcm5352e.cfg                       sim3x.cfg
bcm6348.cfg                        smp8634.cfg
bluenrg-x.cfg                      spear3xx.cfg
c100.cfg                           stellaris.cfg
c100config.tcl                     stellaris_icdi.cfg
c100helper.tcl                     stm32f0x.cfg
c100regs.tcl                       stm32f0x_stlink.cfg
cc2538.cfg                         stm32f1x.cfg
cs351x.cfg                         stm32f1x_stlink.cfg
davinci.cfg                        stm32f2x.cfg
dragonite.cfg                      stm32f2x_stlink.cfg
dsp56321.cfg                       stm32f3x.cfg
dsp568013.cfg                      stm32f3x_stlink.cfg
dsp568037.cfg                      stm32f4x.cfg
efm32.cfg                          stm32f4x_stlink.cfg
efm32_stlink.cfg                   stm32f7x.cfg
em357.cfg                          stm32h7x.cfg
em358.cfg                          stm32h7x_dual_bank.cfg
epc9301.cfg                        stm32l0.cfg
esi32xx.cfg                        stm32l0_dual_bank.cfg
exynos5250.cfg                     stm32l1.cfg
faux.cfg                           stm32l1x_dual_bank.cfg
feroceon.cfg                       stm32l4x.cfg
fm3.cfg                            stm32lx_stlink.cfg
fm4.cfg                            stm32_stlink.cfg
fm4_mb9bf.cfg                      stm32w108_stlink.cfg
fm4_s6e2cc.cfg                     stm32w108xx.cfg
gp326xxxa.cfg                      stm32xl.cfg
hi3798.cfg                         stm8l152.cfg
hi6220.cfg                         stm8l.cfg
hilscher_netx10.cfg                stm8s003.cfg
hilscher_netx500.cfg               stm8s105.cfg
hilscher_netx50.cfg                stm8s.cfg
icepick.cfg                        str710.cfg
imx21.cfg                          str730.cfg
imx25.cfg                          str750.cfg
imx27.cfg                          str912.cfg
imx28.cfg                          swj-dp.tcl
imx31.cfg                          test_reset_syntax_error.cfg
imx35.cfg                          test_syntax_error.cfg
imx51.cfg                          ti-ar7.cfg
imx53.cfg                          ti_calypso.cfg
imx6.cfg                           ti_cc13x0.cfg
imx6sx.cfg                         ti_cc13x2.cfg
imx6ul.cfg                         ti_cc26x0.cfg
imx7.cfg                           ti_cc26x2.cfg
imx7ulp.cfg                        ti_cc3220sf.cfg
imx8m.cfg                          ti_cc32xx.cfg
imx.cfg                            ti-cjtag.cfg
is5114.cfg                         ti_dm355.cfg
ixp42x.cfg                         ti_dm365.cfg
k1921vk01t.cfg                     ti_dm6446.cfg
k40.cfg                            ti_msp432.cfg
k60.cfg                            ti_rm4x.cfg
ke0x.cfg                           ti_tms570.cfg
ke1xf.cfg                          ti_tms570ls20xxx.cfg
ke1xz.cfg                          ti_tms570ls3137.cfg
kl25.cfg                           tmpa900.cfg
kl25z_hla.cfg                      tmpa910.cfg
kl46.cfg                           u8500.cfg
klx.cfg                            vybrid_vf6xx.cfg
ks869x.cfg                         xilinx_zynqmp.cfg
kx.cfg                             xmc1xxx.cfg
lpc11xx.cfg                        xmc4xxx.cfg
lpc12xx.cfg                        xmos_xs1-xau8a-10_arm.cfg
lpc13xx.cfg                        zynq_7000.cfg
lpc17xx.cfg                        к1879xб1я.cfg
lpc1850.cfg

When I tried to start OpenOCD with:

$ openocd -f interface/ti-icdi.cfg -f target/stellaris.cfg

it didn't work. After some searching, I somehow figured out to start it like this:

$ openocd -f interface/ti-icdi.cfg -c "transport select hla_jtag" -f target/stellaris.cfg
Open On-Chip Debugger 0.10.0+dev-00921-g263deb38 (2019-07-18-17:17)
Licensed under GNU GPL v2
For bug reports, read
	http://openocd.org/doc/doxygen/bugs.html
hla_jtag
Info : The selected transport took over low-level target control. The results might differ compared to plain JTAG/SWD
Info : Listening on port 6666 for tcl connections
Info : Listening on port 4444 for telnet connections
Info : clock speed 21847 kHz
Info : ICDI Firmware version: 1224
Info : lm3s.cpu: hardware has 6 breakpoints, 4 watchpoints
Info : Listening on port 3333 for gdb connections

And of course I have no idea if that's the right way to do it but it seems to indicate that it connected to the board and is able to communicate.

To be continued! Once again I'm going to call it quits for the day... So far, I have cloned all the NuttX repositories and the OpenOCD repository into a NuttX directory under my home directory. I installed all kinds of needed packages and still need to come back and make that exhaustive list I promised. I built an ARM Cortex M4F EABI toolchain using the NuttX-provided buildroot. I built the NuttX nsh (Nutt Shell) example for TM4C1294 (which is very similar to the TM4C129ENCPDT on my EK-TM4C129EXL Crypto Connected LaunchPad). I built OpenOCD from source and I think it's actually communicating with my board. Check back for more and feel free to write me with questions, comments, suggestions, criticisms, etc., at the name of this blog, which is high12noon, of course, at mail dot com.

July 21, 2019: Using Code::Blocks IDE

Code::Blocks is a free, open source, cross platform, Integrated Development Environment (IDE). It is cross platform and is written with a graphics toolkit I like very much, wxWidgets. Also, it is much lighter weight than Eclipse.

Last time I built OpenOCD from source in preparation to use Code::Blocks IDE to edit, compile, flash program, and single-step debug NuttX. I even built NuttX successfully on the command line but sadly I didn't document it here. I think it was pretty straightforward. The only important thing was to set the PATH environment variable so that make could find the toolchain I built with buildroot. Once I did that, NuttX built.

But I like to work in an IDE. So I watched the following videos:

So I configured Code::Blocks approximately as described in those videos:

I installed Code::Blocks with:

$ sudo apt-get install codeblocks codeblocks-contrib

The NuttX Channel video did not show installing codeblocks-contrib but I thought what the heck, I might as well.

Once Code::Blocks was installed, I ran it and began configuring it to use the buildroot-based GCC ARM compiler and OpenOCD tools that I built earlier, as shown in the above-mentioned NuttX Channel video. I will repeat the steps I took (as well as I can given my sometimes hazy memory) because I diverged in some areas and also for my future reference in case the video becomes inaccessible or something. Most of the following instructions are very similar to the video, though:

  1. From the menu, I opened "Settings" → "Debugger..." The "Debugger settings" dialog appeared. In its sidebar, I highlighted "GDB/CDB debugger" which caused three buttons to appear to the right: "Create Config," "Delete Config," and "Reset defaults." I created a new configuration using "Create Config" and named it OpenOCD. For the Executable path, I entered $HOME/NuttX/buildroot/build_arm_hf/staging_dir/bin/arm-nuttx-eabi-gdb (I actually entered the full "hardcoded" path without the $HOME variable because I don't know if that would work). I left the settings at their defaults, which were:
    • Debugger Type was set to GDB
    • Disable startup scripts (-nx) (GDB only) (checked)
    • Watch function arguments (checked)
    • Watch local variables (checked)
    • Enable watch scripts (checked)
    • Catch C++ exceptions (checked)
    • The other items were not checked.
    • As for "Choose disassembly flavor (GDB only)" I left the value "System default."
    I closed this dialog with OK.
  2. From the menu, I opened "Settings" → "Compiler..." For this step, I diverged a bit from what was shown in the video. With "Global compiler settings" highlighted in the sidebar, I set "Selected compiler" to "GNU GCC Compiler for ARM." Because I have so many different ARM-based platforms, I decided to create a specific one for NuttX and for ARM Cortex M4F. So I used the Copy button to make a copy of the GNU GCC Compiler for ARM profile and named my copy "NuttX GCC ARM Cortex M4F." I then went to the "Toolchain executables" tab and configured the compiler as follows:
    • For "Compiler's installation directory" I set: $HOME/NuttX/buildroot/build_arm_hf/staging_dir (once again I actually entered the full "hardcoded" path without the $HOME variable)
    • C compiler: arm-nuttx-eabi-gcc
    • C++ compiler: arm-nuttx-eabi-g++
    • Linker for dynamic libs: arm-nuttx-eabi-g++
    • Linker for static libs: arm-nuttx-eabi-gcc-ar
    • Debugger: GDB/CDB debugger : OpenOCD
    • Resource compiler: (left blank)
    • Make program: make
    Now, I will say that for whatever reason(s), I had trouble with Code::Blocks accepting this. I tried various things and eventually tried rebooting and redoing the setup. I'm not exactly sure whether rebooting "fixed" anything or whether I had made a typo earlier. But I kept at it and eventually Code::Blocks accepted this compiler setup. I closed the dialog with OK.
  3. I created a new empty project by going to "File" → "New" → "Project..." and selecting "Empty project" in the dialog that appeared. In the project wizard, I gave the project the title "nuttx" and placed it in the $HOME/NuttX directory, which is the parent directory of my nuttx repository. I think it was significant that the project was named nuttx with the same spelling and lowercase letters as the binary file produced by NuttX's makefile. As the above-mentioned NuttX Channel video shows, I removed the values from "Output dir" and "Objects output dir" for the Debug configuration. I renamed the Debug configuration to "all" (in the text field next to "Create 'Debug' configuration." I removed the Release configuration by removing the checkmark from "Create 'Release' configuration." I exited this dialog by clicking "Finish."
  4. In the Projects view, which by default runs down the left side of the Code::Blocks window, I right-clicked the "nuttx" project and opened Properties from the context menu. This opened the "Project/targets options" dialog. In the "Project settings" tab, I placed a checkmark at "This is a custom Makefile." I then went to the Debugger tab, as shown in the video. Under "Select target" I selected "all" and in the "Remote Connection" sub-tab (located within the "Debugger" tab) I set the IP address to 127.0.0.1 (the loopback address) and port 3333. (Remember earlier, when OpenOCD said it was listening on port 3333 for gdb connections? That's why.) Then, in the Additional GDB commands sub-tab, I entered slightly different commands than shown in the video for "After connection," namely:
    • On the first line: "monitor reset init"
    • On the second line: "load nuttx"
    • On the third line, here is where we diverge from the video, I entered "b nx_start" instead of what the video shows. (The video shows "b os_start".) This command puts a breakpoint at the nx_start() function and causes the board to run to that breakpoint. It didn't work for me with os_start because, as I understood from scouring various places, the function was renamed sometime between when the video was made and now.
    I exited this dialog with OK.
  5. The video shows nuttx being configured on the command line using the tools/configure.sh script and make menuconfig. I didn't need to do this because my nuttx was already configured. Caveat: I think I did do make menuconfig to turn on debugging information and to suppress optimization. You always want to suppress optimization when single-step debugging; otherwise the debugger seems to jump all over the place for no rhyme or reason, because actually the compiler reorders instructions for best performance and/or smallest code when you optimize.
  6. The video also shows editing the linker script (in the video's case under configs/stm32f103-minimum/scripts/ld.script, but I'm using a TI TM4C129ENCPDT). If I understand correctly, the purpose of this edit was to lie to the linker about the processor's flash storage capacity. Otherwise the video maker reported that the linker was failing, presumably because debugging information made the code too big. I didn't do this and my code did link successfully without it. Of course, depending on your MCU and its size, your mileage may vary.
  7. Back in Code::Blocks, the video shows right-clicking the nuttx project in the Projects view, selecting "Add files recursively," choosing the nuttx directory, using Select All to select all the files and directories therein, and adding them to the project. This worked for me, but after doing it, the IDE started going haywire, locking up, crashing, windows not sizing correctly... I don't know why. So after several attempts, I decided to skip this step and not add any files to the IDE project. They'll still build correctly (because building is done by the makefile) and single-stepping still worked correctly, though I'll talk more about that in a moment.
  8. At this point, I built the project by going to "Build" → "Build" in the menu. NuttX built. The Code::Blocks "Build log" tab showed the same kind of output I had come to expect from building NuttX on the command line previously.
  9. Back on the command line, I started OpenOCD. This time, I used a script that comes with NuttX:
    $ $TOPDIR/configs/tm4c1294-launchpad/tools/oocd.sh $HOME/NuttX/nuttx
    
  10. Back in Code::Blocks, I went to "Debug" → "Start / Continue." This opened some kind of blank Xterm window, FLASH-programmed the nuttx executable to the board, and started the debugger, placing the cursor at nx_start().

The above worked, but I had a couple of problems.

First of all, single-stepping was rather slow. Specifically, single-stepping through C came with a frustrating and very noticeable delay between each step. Single-stepping through assembly was reasonably quick.

Secondly, I like how other IDEs show an easy-to-interpret gauge that tells me how much of Flash and RAM I'm using as a percentage of my MCU's Flash and RAM capacity. I couldn't figure out how to do this with Code::Blocks.

So, even though everything technically worked, I decided to try TI's Code Composer Studio (CCS). That's a job for next time.

I do like Code::Blocks and have worked with it (and still work with it) pretty extensively, so if you know of a way to speed up single-step debugging or what to do about the IDE going haywire and crashing when I added all the NuttX files to the project, please drop me a line!

July 22, 2019: Using TI's CCSv9

Previously, I had set up Code::Blocks IDE to work on NuttX and my programs for it, but I ran into an issue where single-stepping was slow and there was no memory usage gauge. So I decided to try TI's Code Composer Studio (CCS). Recently they released CCS version 9 (which I'll call CCSv9).

I started by installing CCS in my Linux machine. I went to ti.com and searched for "CCS" in the website's Search bar. Then, I selected the first search result, "Code Composer Studio (CCS) Integrated Development Environment (IDE) CCSTUDIO (ACTIVE)." From here, there was a download link. Clicking on that link took me to another page, where I could download actual files as well as read the Linux Installation Instructions. At the time of this writing, the latest version of CCS is version 9.1.0.00010. According to TI, they test CCS on Ubuntu LTS distributions and one CentOS distribution. All other installation instructions are provided for reference (and are sometimes contributed by community members). Despite this notice, I found that CCS installed perfectly on my Debian "Stretch" machine. Note: As far as I know, Ubuntu is based on Debian, so I think they're close cousins. I didn't have any of the potential issues mentioned on that page. Back at the download page, I downloaded the latest available Linux off-line installer, which came out to some 850 MB. I untarred this and ran the installer. I followed the screens in the graphical installers and everything went smoothly.

I opened CCS and began to setup a project to build, load, and run NuttX as follows:

In the command line, I created a directory at $HOME/NuttX/NuttxCCS to hold the TI Code Composer Studio 9 (CCSv9) project, adjacent to the nuttx and apps directories.

In CCSv9, I created a new CCS project by going to "Project" → "New CCS Project." In the dialog that appeared:

In the "Project Explorer" (by default this view appears along the left side of the CCS window), I right-clicked the NuttxCCS project and opened Properties (located all the way at the bottom of the context menu). In the Project Properties dialog that appeared (while Debug build configuration is selected), I made the following changes. Note that I've experienced CCS "forgetting" some changes when I make too many to a project, so I recommend changing a few settings, applying and closing the dialog, and then reopening it to make more changes.

Note: The following is a bit messy because I wanted to document it all as quickly as possible, before I forget the steps. At some point I plan to come back, clean this up, and improve the instructions.

Project properties dialog:

  1. Show advanced settings (link at bottom)
  2. CCS Build:
    • No checkmark on "Use default build command"
    • No checkmark on "Generate Makefiles automatically"
    • Set "Build location" → "Build directory" to "${PROJECT_LOC}/../nuttx"
    • No checkmark on "Enable parallel build"
    • No checkmark on "Build on resource save (Auto build)
    • Checkmark on Build (Incremental build) and "all" in text field.
    • Checkmark on Clean and "clean" in text field.
  3. GNU Compiler, GNU Linker, GNU Objcopy Utility: These settings have no effect on the build because it is controlled by the NuttX makefile. However, to avoid displaying misleading information, you can remove any include paths from CCS Build → GNU Compiler → Directories and any predefined preprocessor symbols from CCS Build → GNU Compiler → Preprocessor.
  4. C/C++ Build:
    • Builder type: External builder
    • Build command: make -k
    • No checkmark on "Generate Makefiles automatically"
    • Set "Build location" → "Build directory" to "${PROJECT_LOC}/../nuttx"
    • C/C++ Build → Environment: Prepend PATH with: "${ccs_install_root}/tools/compiler/gcc-arm-none-eabi-7-2017-q4-major/bin:" using that last colon as the delimiter between that and the rest of the path.
    • Settings: Binary Parsers: Check mark on Elf Parser only.
    • Settings: Error Parsers: Check marks on GNU gmake Error Parser 7.0, GNU Assembler Error Parser, GNU Linker Error Parser, and GNU gcc/g++ Error Parser.
  5. Debug:
    • Device: Stellaris In-Circuit Debug Interface_0/CORTEX_M4_0
    • Auto Run and Launch Options:
      Auto Run Options:
      • Run to symbol: nx_start
      • Check mark on "On a program load or restart"
      • Check mark on "On a reset"
  6. Run/Debug Settings:
    • Launch configurations: Select the launch configuration and Edit.
    • Program tab:
      • Device: Stellaris In-Circuit Debug Interface_0/CORTEX_M4_0
      • Project: NuttxCCS (or the project name)
      • Program: Path to the nuttx binary (e.g., $HOME/NuttX/nuttx/nuttx)
      • Loading options: Check mark on "Load program"
    • Source tab:
      • Add source lookup path, being the nuttx directory (e.g., $HOME/NuttX/nuttx)
      • Put that directory at the top of the list with the Up button.

In command line, go to nuttx $TOPDIR and:

$ make clean
$ make menuconfig

In menu config:

In CCS, Project → Clean (and perform build). If everything is configured correctly above, the project will build.

Debug: If all is configured correctly above, the project will load and run.

To get the Memory Allocation view to work, the linker needs to generate a "map" file usable by CCS. The NuttX build system produces a file called System.map but CCS cannot parse it. Therefore it is necessary to add a custom linker option. According to patacongo, "Make.defs is a part of your board and you are free to modify it as you like." The Make.defs actually used during the build process is in $TOPDIR, but it gets there by being copied when $TOPDIR/tools/configure.sh is run to select a board and configuration. So it is best to make the edit in our board's config directory (in our case that's $TOPDIR/configs/tm4c1294-launchpad/Make.defs), and then copy that over the one in $TOPDIR. Edit Make.defs and add the following at or near the bottom of the file:

LDFLAGS += -Map=$(TOPDIR)/nuttx.map

According to Chester Gillon in a post on TI's e2e forum, the CCS Memory Allocation view is hard-coded to parse a .map file located at ${BuildDirectory}/${ProjName}.map. In our case, that would be $HOME/NuttX/NuttxCCS/Debug/NuttxCCS.map. This appears to be true as of this writing with CCS Version: 9.1.0.00010. Since we do not know of a user-accessible setting to change it, we work around this by creating a symbolic link:

$ cd $HOME/NuttX/NuttxCCS/Debug
$ ln -s ../../nuttx/nuttx.map NuttxCCS.map

Alternately, if you don't want to create the symbolic link, you can open any (properly formatted) .map file in the Memory Allocation view: Go to that view's menu (small down-pointing triangle) and select "Open TI link-info or GNU linker-map file..." and choose the nuttx.map file, at $TOPDIR/nuttx.map (or any other .map file you wish to examine).

With CCS, I got both of the things that I found lacking in yesterday's Code::Blocks setup, namely that single-step debugging through C code was sped up considerably and I got a working Memory Allocation view that shows Flash and RAM usage as a percentage of total available on the microcontroller. Once again, I do like Code::Blocks so if you know how to speed up single-step debugging there, please let me know!

July 30, 2019: More on Using TI's CCSv9 with NuttX

Increasing Scroll Back Buffer for the CDT Build Console

CCS is based on Eclipse and uses a part of Eclipse called CDT (C Development Tools). When building, the build output (all that text from make that scrolls up the screen) is displayed in a view called Console, which shows the CDT Build Console.

I noticed that with the default settings, the NuttX build generated too much output for the CDT Build Console, so if I wanted to look near the beginning of the build output for something that might cause an error, I couldn't because it had been lost. To fix this:

  1. In the menu, open Window → Preferences.
  2. In the dialog that appears, make sure that advanced settings are displayed. If there is a link at the bottom of the dialog labeled "Show advanced settings" click it. This will show additional settings in the left sidebar of the dialog box.
  3. In the sidebar, find and expand "C/C++" → "Build" → "Console"
  4. Find the item "Limit console output (number of lines)" and set it to something larger. Mine was initially set to 500. I increased it to 20000. This setting seemed to work for me.
  5. Apply and close the dialog.

Since we are using CCS slightly differently than TI expected, it seems necessary to show advanced settings in multiple places. So far I've done that in Project Properties (described last time) and in the Preferences dialog as I just explained above. Initially, I hadn't noticed that some preferences were hidden, so when I tried to find and enlarge the console scrollback I ended up doing it for the Run/Debug console, which is something else, and I saw no improvement. Showing advanced settings and updating the setting for the C/C++ Build Console made all the difference.

Showing source files in the Project Explorer

The other improvement I made is for the project itself.

Normally, if there is a build error, it should be possible to double-click the error either in the CDT Build Console or the Problems view and CCS should open the offending source file and place the cursor on the offending line. This wasn't happening. I thought that was a bit strange because source-level debugging worked (when I built with debug information and optimizations suppressed) but it didn't work for build errors. Nor was I able to use the indexer to navigate (e.g., by right-clicking an identifier and choosing "Open Declaration").

I fixed this by adding the "nuttx" and "apps" folders to the project as Linked Folders. The way to do this is not entirely intuitive because you might be tempted to right-click the project in the Project Explorer and choose "Add Files." But apparently that's not the right way.

Instead:

  1. Right-click the project in the Project Explorer and choose "New" → "Folder."
  2. Make sure the project is selected in the list (in my case it's called NuttxCCS), not "RemoteSystemsTempFiles."
  3. Click "Advanced" (notice a theme for today?)
  4. Select the radio button for "Link to alternate location (Linked Folder)"
  5. In my case, I placed the NuttxCCS directory containing the CCS project adjacent to the nuttx and apps directories. Therefore the path to nuttx is "../nuttx" relative to the project. So in the text field below "Link to alternate location" I entered:
    ${PROJECT_LOC}/../nuttx
    as the path.
  6. Make sure "Choose file system" is set to "default"
  7. Click Finish to add the linked folder.
  8. It might ask a bunch of times (once for each .cfg file it finds) if you want to enable XDCtools. Select "No" each time and be careful because the order of the No and Yes buttons are reversed! (At least on my system!)
  9. Wait for it to build its index, or whatever it's doing.
  10. Repeat the above process to add the apps directory, using
    ${PROJECT_LOC}/../apps
    as the path.

Now, if all went well, build errors can be double-clicked to jump straight to the offending file and line.

That's all for today! See you soon.

August 1, 2019: Even more on Using TI's CCSv9 with NuttX

Stop lengthy "Searching for Binaries"

As mentioned before, CCS is based on Eclipse.

Each time I built the project, I noticed a lengthy Eclipse task called "Searching for Binaries" running for quite some time. I wanted to stop this from bogging down my system. After a quick search, I found the answer to this one here: According to Alex Mueller:

Eclipse searches for the binaries to fill the virtual folder "Binaries" in your project (see Project Explorer). These binaries are also used when you create a Launch Configuration.

If you are using an external Makefile Eclipse does not which binaries were created by the build step. Therefore, after every build it searches the complete project for changes.

Mueller writes that you can limit the search scope. That's exactly what I want, to limit the search scope to the one file I know matters, nuttx. So I followed Mueller's instructions to go to "Project Properties" → "C/C++ General" → "Paths and Symbols" → the "Output location" tab. There is a tree view titled "Output folders on build path" containing search locations. There was only one item in the list: "NuttxCCS/nuttx" with an arrow indicating the item can be expanded. Expanding this item reveals a filter, which was initially empty. I highlighted it, clicked "Edit Filter..." and added multiple items: Everything in the nuttx directory except the nuttx binary itself.

Having made this change, I built the project and there was no lengthy "Searching for Binaries"—in fact the search was pretty much instantaneous! When it comes to computers, I like speed!

Stay tuned for more!

September 3, 2019: Seeing how make invokes the compiler

It happened a few times that I needed to see exactly how make was invoking the compiler.

Normally, only something like this is printed to the console:

CC:  name_of_file.c

But I need to see how the compiler was actually invoked, as in what command line arguments it received.

Googling around, I found all sorts of advice, such as passing --debug=j to make, etc., but it didn't work in this case.

After some experimentation and more searching, I figured out that what I wanted could be achieved by passing a V=1 argument to make:

$ make V=1

Now it prints all kinds of details, like this:

CC:  name_of_file.c
arm-none-eabi-gcc -c -fno-builtin -funwind-tables -Wall -Wstrict-prototypes -Wshadow -Wundef -g -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=hard -I. -isystem /home/builder/NuttX/nuttx/include  -D__KERNEL__ -ffunction-sections -fdata-sections -pipe -fdebug-prefix-map=..= -I/home/builder/NuttX/nuttx/sched -I/home/builder/NuttX/nuttx/arch/arm/src/chip -I/home/builder/NuttX/nuttx/arch/arm/src/common -I/home/builder/NuttX/nuttx/arch/arm/src/armv7-m  name_of_file.c -o  name_of_file.o

December 10, 2019: NuttX to become an Apache Software Foundation (ASF) Project

This isn't so much a technical update as a bit of news. Until the present time, NuttX has been a project run almost exclusively by one person, Gregory Nutt. With support for myriad processor architecture and microcontroller variants, the codebase has grown so large that Mr. Nutt decided it would be best to continue its development as an Apache.org project.

The way Apache.org works is that projects that want to become part of ASF must first become a "podling" in the ASF Incubator. During "incubation" the project undergoes a transition period until all its processes are operating according to the "Apache Way" at which time the project can graduate to become an Apache "top-level project."

At the time of this writing, only the very first parts of this process have taken place, namely the proposal was made, a vote took place (which passed unanimously), and the project is now beginning its first step as an ASF podling.

Stay tuned while this story develops!

Update (October 26, 2022): The Apache NuttX (Incubating) community is apparently beginning the process of graduating the Apache Incubator and becoming an Apache Software Foundation Top Level Project (TLP). See NuttX community discussing graduation from the Incubator below.

March 30, 2020: Updated various links on this page

Since NuttX joined the Apache Software Foundation by becoming an Apache.org Incubator Podling, the NuttX website and documentation have moved from their former web addresses to Apache.org servers. Also, some 3rd party NuttX sites, such as the former nuttx2019.org, have been moved to new locations, such as nuttx.events.

The ongoing changes will ultimately be good for the future of NuttX, but they resulted in various broken links in the sections above. So I went ahead and tracked down all their new locations and updated the links.

If you do find any more broken links, please let me know and I'll go hunting for their new locations.

Thanks for reading and come back soon!

August 15-16, 2020: The NuttX Online Workshop (N.O.W.)

This section last updated August 20th, 2020.

A NuttX 2020 event was planned to take place in Tokyo. However, because of the pandemic, the event was held online instead. The NuttX Online Workshop (N.O.W.) was held online August 15-16, 2020. The video footage and presentations can be seen on YouTube by following the links below:

Note: While the primary place to communicate with the NuttX developers and users is at the NuttX mailing lists, some questions and answers can be found in the forums that were set up for the event, also listed below. Links to other articles about some of these projects are included below as well.

March 31, 2021: An Update...

Many things have happened since my last significant update here, but I hope to get back into regularly documenting my adventures here.

Until now, I've described in (excruciating?!) detail how I've gotten NuttX to build and run on the TI TM4C129x microcontroller but at the outset I mentioned that my reason to dive headlong into NuttX is that I work with many different microcontroller architectures and the programming is very different when jumping from one family to another.

Oh, all the various microcontroller vendors support programming in C, but that's basically where the similarities end. From there, you have three options: you could write bare-metal firmware and operate the chip's basic peripherals by stuffing values into registers; or you could write bare-metal firmware and use a library of hardware abstraction function provided by the chip vendor to encapsulate some of the details of the peripherals; or you could go the RTOS route, and some chip vendors have one or more favorite RTOSes that you could choose from.

The biggest problem with all of those approaches is that, again, they're not portable. Even if you use a hardware abstraction library such as TI's TivaWare for the TM4C129x or STmicro's HAL for the STM32 families, your software is still stuck on that vendor's chips, and sometimes, on a particular model of chip. When your customer needs next-generation electronics with added new features that require a different microcontroller, you often end up having to rework much of the code to fit the new chip, starting back at square one for the most low-level details. At least that has been my experience.

So when I discovered NuttX, its long list of supported microcontroller architectures, its goal of sticking as much as possible to POSIX or POSIX-like standards, and its vibrant developer community, I found a viable and smarter way to write quality firmware with mobility between different microcontroller families.

I have several updates to this Adventure series in the works, which I hope to post soon, and in which I hop over to the STM32 family for the latest project I'm working on. Stay tuned for topics including:

August 21-22, 2021: The NuttX International Workshop

This section last updated February 22nd, 2022.

The 2021 NuttX event was held online like its counterpart of the prior year. A recording of the entire two-day event and all its presentations can be seen on YouTube by following the links below.

Note: The primary place to communicate with the NuttX developer and user community is at its mailing lists.

May 15, 2022: Porting Low-Level Code From TivaWare to NuttX

The following tables show the correspondence between TivaWare identifiers and their NuttX Tiva counterparts, to assist developers in porting low-level code written for TivaWare to NuttX.

This section is a work in progress. I will try to add additional tables as I need them.

Section Contents

Memory Map

TivaWare NuttX Value Description
WATCHDOG0_BASE TIVA_WDOG0_BASE 0x40000000 Watchdog0
WATCHDOG1_BASE TIVA_WDOG1_BASE 0x40001000 Watchdog1
GPIO_PORTA_BASE TIVA_GPIOA_BASE 0x40004000 GPIO Port A
GPIO_PORTB_BASE TIVA_GPIOB_BASE 0x40005000 GPIO Port B
GPIO_PORTC_BASE TIVA_GPIOC_BASE 0x40006000 GPIO Port C
GPIO_PORTD_BASE TIVA_GPIOD_BASE 0x40007000 GPIO Port D
SSI0_BASE TIVA_SSI0_BASE 0x40008000 SSI0
SSI1_BASE TIVA_SSI1_BASE 0x40009000 SSI1
SSI2_BASE TIVA_SSI2_BASE 0x4000a000 SSI2
SSI3_BASE TIVA_SSI3_BASE 0x4000b000 SSI3
UART0_BASE TIVA_UART0_BASE 0x4000c000 UART0
UART1_BASE TIVA_UART1_BASE 0x4000d000 UART1
UART2_BASE TIVA_UART2_BASE 0x4000e000 UART2
UART3_BASE TIVA_UART3_BASE 0x4000f000 UART3
UART4_BASE TIVA_UART4_BASE 0x40010000 UART4
UART5_BASE TIVA_UART5_BASE 0x40011000 UART5
UART6_BASE TIVA_UART6_BASE 0x40012000 UART6
UART7_BASE TIVA_UART7_BASE 0x40013000 UART7
I2C0_BASE TIVA_I2C0_BASE 0x40020000 I2C0
I2C1_BASE TIVA_I2C1_BASE 0x40021000 I2C1
I2C2_BASE TIVA_I2C2_BASE 0x40022000 I2C2
I2C3_BASE TIVA_I2C3_BASE 0x40023000 I2C3
GPIO_PORTE_BASE TIVA_GPIOE_BASE 0x40024000 GPIO Port E
GPIO_PORTF_BASE TIVA_GPIOF_BASE 0x40025000 GPIO Port F
GPIO_PORTG_BASE TIVA_GPIOG_BASE 0x40026000 GPIO Port G
GPIO_PORTH_BASE TIVA_GPIOH_BASE 0x40027000 GPIO Port H
PWM0_BASE TIVA_PWM0_BASE 0x40028000 Pulse Width Modulator (PWM)
PWM1_BASE TIVA_PWM1_BASE 0x40029000 Pulse Width Modulator (PWM)
QEI0_BASE TIVA_QEI0_BASE 0x4002c000 QEI0
QEI1_BASE TIVA_QEI1_BASE 0x4002d000 QEI1
TIMER0_BASE TIVA_TIMER0_BASE 0x40030000 Timer0
TIMER1_BASE TIVA_TIMER1_BASE 0x40031000 Timer1
TIMER2_BASE TIVA_TIMER2_BASE 0x40032000 Timer2
TIMER3_BASE TIVA_TIMER3_BASE 0x40033000 Timer3
TIMER4_BASE TIVA_TIMER4_BASE 0x40034000 Timer4
TIMER5_BASE TIVA_TIMER5_BASE 0x40035000 Timer5
WTIMER0_BASE TIVA_WTIMER0_BASE 0x40036000 Wide Timer0
WTIMER1_BASE TIVA_WTIMER1_BASE 0x40037000 Wide Timer1
ADC0_BASE TIVA_ADC0_BASE 0x40038000 ADC0
ADC1_BASE TIVA_ADC1_BASE 0x40039000 ADC1
COMP_BASE TIVA_CMP_BASE 0x4003c000 Analog comparators
GPIO_PORTJ_BASE TIVA_GPIOJ_BASE 0x4003d000 GPIO Port J
CAN0_BASE TIVA_CAN0_BASE 0x40040000 CAN0
CAN1_BASE TIVA_CAN1_BASE 0x40041000 CAN1
WTIMER2_BASE TIVA_WTIMER2_BASE 0x4004c000 Wide Timer2
WTIMER3_BASE TIVA_WTIMER3_BASE 0x4004d000 Wide Timer3
WTIMER4_BASE TIVA_WTIMER4_BASE 0x4004e000 Wide Timer4
WTIMER5_BASE TIVA_WTIMER5_BASE 0x4004f000 Wide Timer5
USB0_BASE TIVA_USB_BASE 0x40050000 USB 0 Controller
GPIO_PORTA_AHB_BASETIVA_GPIOAAHB_BASE 0x40058000 GPIO Port A (high speed)
GPIO_PORTB_AHB_BASETIVA_GPIOBAHB_BASE 0x40059000 GPIO Port B (high speed)
GPIO_PORTC_AHB_BASETIVA_GPIOCAHB_BASE 0x4005a000 GPIO Port C (high speed)
GPIO_PORTD_AHB_BASETIVA_GPIODAHB_BASE 0x4005b000 GPIO Port D (high speed)
GPIO_PORTE_AHB_BASETIVA_GPIOEAHB_BASE 0x4005c000 GPIO Port E (high speed)
GPIO_PORTF_AHB_BASETIVA_GPIOFAHB_BASE 0x4005d000 GPIO Port F (high speed)
GPIO_PORTG_AHB_BASETIVA_GPIOGAHB_BASE 0x4005e000 GPIO Port G (high speed)
GPIO_PORTH_AHB_BASETIVA_GPIOHAHB_BASE 0x4005f000 GPIO Port H (high speed)
GPIO_PORTJ_AHB_BASETIVA_GPIOJAHB_BASE 0x40060000 GPIO Port J (high speed)
GPIO_PORTK_BASE TIVA_GPIOKAHB_BASE 0x40061000 GPIO Port K
GPIO_PORTL_BASE TIVA_GPIOLAHB_BASE 0x40062000 GPIO Port L
GPIO_PORTM_BASE TIVA_GPIOMAHB_BASE 0x40063000 GPIO Port M
GPIO_PORTN_BASE TIVA_GPIONAHB_BASE 0x40064000 GPIO Port N
GPIO_PORTP_BASE TIVA_GPIOPAHB_BASE 0x40065000 GPIO Port P
GPIO_PORTQ_BASE TIVA_GPIOQAHB_BASE 0x40066000 GPIO Port Q
GPIO_PORTR_BASE TIVA_GPIORAHB_BASE 0x40067000 General-Purpose Input/Outputs (GPIOs)
GPIO_PORTS_BASE TIVA_GPIOSAHB_BASE 0x40068000 General-Purpose Input/Outputs (GPIOs)
GPIO_PORTT_BASE TIVA_GPIOTAHB_BASE 0x40069000 General-Purpose Input/Outputs (GPIOs)
EEPROM_BASE TIVA_EEPROM_BASE 0x400af000 EEPROM memory
ONEWIRE0_BASE TIVA_1WIRE_BASE 0x400b6000 1-Wire Master Module
I2C8_BASE TIVA_I2C8_BASE 0x400b8000 I2C8
I2C9_BASE TIVA_I2C9_BASE 0x400b9000 I2C9
I2C4_BASE TIVA_I2C4_BASE 0x400c0000 I2C4
I2C5_BASE TIVA_I2C5_BASE 0x400c1000 I2C5
I2C6_BASE TIVA_I2C6_BASE 0x400c2000 I2C6
I2C7_BASE TIVA_I2C7_BASE 0x400c3000 I2C7
EPI0_BASE TIVA_EPI0_BASE 0x400d0000 EPI0
TIMER6_BASE TIVA_TIMER6_BASE 0x400e0000 General-Purpose Timers
TIMER7_BASE TIVA_TIMER7_BASE 0x400e1000 General-Purpose Timers
EMAC0_BASE TIVA_ETHCON_BASE 0x400ec000 Ethernet Controller
SYSEXC_BASE TIVA_SYSEXC_BASE 0x400f9000 System Exception Module
HIB_BASE TIVA_HIBERNATE_BASE0x400fc000 Hibernation Module
FLASH_CTRL_BASE TIVA_FLASHCON_BASE 0x400fd000 FLASH Controller
SYSCTL_BASE TIVA_SYSCON_BASE 0x400fe000 System Control
UDMA_BASE TIVA_UDMA_BASE 0x400ff000 uDMA Controller
CCM0_BASE TIVA_CCM_BASE 0x44030000 Cyclical Redundancy Check (CRC)
SHAMD5_BASE TIVA_SHAMD5_BASE 0x44034000 SHA/MD5 Accelerator
AES_BASE TIVA_AES_BASE 0x44036000 Advance Encryption Hardware-Accelerator (AES)
DES_BASE TIVA_DES_BASE 0x44038000 Data Encryption Standard Accelerator (DES)
LCD0_BASE TIVA_LCD_BASE 0x44050000 LCD Controller
??? TIVA_EPHY_BASE 0x44054000
ITM_BASE ??? 0xe0000000 Instrumentation Trace Macrocell
DWT_BASE ??? 0xe0001000 Data Watchpoint and Trace
FPB_BASE ??? 0xe0002000 FLASH Patch and Breakpoint
NVIC_BASE ??? 0xe000e000 Nested Vectored Interrupt Ctrl
TPIU_BASE ??? 0xe0040000 Trace Port Interface Unit

GPIO

TivaWare NuttX Memory MapNuttX tiva_configgpio()
GPIO_PORTA_BASETIVA_GPIOA_BASE GPIO_PORTA
GPIO_PORTB_BASETIVA_GPIOB_BASE GPIO_PORTB
GPIO_PORTC_BASETIVA_GPIOC_BASE GPIO_PORTC
GPIO_PORTD_BASETIVA_GPIOD_BASE GPIO_PORTD
GPIO_PORTE_BASETIVA_GPIOE_BASE GPIO_PORTE
GPIO_PORTF_BASETIVA_GPIOF_BASE GPIO_PORTF
GPIO_PORTG_BASETIVA_GPIOG_BASE GPIO_PORTG
GPIO_PORTH_BASETIVA_GPIOH_BASE GPIO_PORTH
GPIO_PORTJ_BASETIVA_GPIOJ_BASE GPIO_PORTJ
GPIO_PORTK_BASETIVA_GPIOK_BASE GPIO_PORTK
GPIO_PORTL_BASETIVA_GPIOL_BASE GPIO_PORTL
GPIO_PORTM_BASETIVA_GPIOM_BASE GPIO_PORTM
GPIO_PORTN_BASETIVA_GPION_BASE GPIO_PORTN
GPIO_PORTP_BASETIVA_GPIOP_BASE GPIO_PORTP
GPIO_PORTQ_BASETIVA_GPIOQ_BASE GPIO_PORTQ
GPIO_PORTR_BASETIVA_GPIOR_BASE GPIO_PORTR
GPIO_PORTS_BASETIVA_GPIOS_BASE GPIO_PORTS
GPIO_PORTT_BASETIVA_GPIOT_BASE GPIO_PORTT
TivaWare NuttX
GPIO_PIN_0(1 << (GPIO_PIN_0 >> GPIO_PIN_SHIFT))
GPIO_PIN_1(1 << (GPIO_PIN_1 >> GPIO_PIN_SHIFT))
GPIO_PIN_2(1 << (GPIO_PIN_2 >> GPIO_PIN_SHIFT))
GPIO_PIN_3(1 << (GPIO_PIN_3 >> GPIO_PIN_SHIFT))
GPIO_PIN_4(1 << (GPIO_PIN_4 >> GPIO_PIN_SHIFT))
GPIO_PIN_5(1 << (GPIO_PIN_5 >> GPIO_PIN_SHIFT))
GPIO_PIN_6(1 << (GPIO_PIN_6 >> GPIO_PIN_SHIFT))
GPIO_PIN_7(1 << (GPIO_PIN_7 >> GPIO_PIN_SHIFT))
TivaWare NuttX Description
GPIO_O_DATA TIVA_GPIO_DATA_OFFSET GPIO Data
GPIO_O_DIR TIVA_GPIO_DIR_OFFSET GPIO Direction
GPIO_O_IS TIVA_GPIO_IS_OFFSET GPIO Interrupt Sense
GPIO_O_IBE TIVA_GPIO_IBE_OFFSET GPIO Interrupt Both Edges
GPIO_O_IEV TIVA_GPIO_IEV_OFFSET GPIO Interrupt Event
GPIO_O_IM TIVA_GPIO_IM_OFFSET GPIO Interrupt Mask
GPIO_O_RIS TIVA_GPIO_RIS_OFFSET GPIO Raw Interrupt Status
GPIO_O_MIS TIVA_GPIO_MIS_OFFSET GPIO Masked Interrupt Status
GPIO_O_ICR TIVA_GPIO_ICR_OFFSET GPIO Interrupt Clear
GPIO_O_AFSEL TIVA_GPIO_AFSEL_OFFSET GPIO Alternate Function
GPIO_O_DR2R TIVA_GPIO_DR2R_OFFSET Select GPIO 2-mA Drive Select
GPIO_O_DR4R TIVA_GPIO_DR4R_OFFSET GPIO 4-mA Drive Select
GPIO_O_DR8R TIVA_GPIO_DR8R_OFFSET GPIO 8-mA Drive Select
GPIO_O_ODR TIVA_GPIO_ODR_OFFSET GPIO Open Drain Select
GPIO_O_PUR TIVA_GPIO_PUR_OFFSET GPIO Pull-Up Select
GPIO_O_PDR TIVA_GPIO_PDR_OFFSET GPIO Pull-Down Select
GPIO_O_SLR TIVA_GPIO_SLR_OFFSET GPIO Slew Rate Control Select
GPIO_O_DEN TIVA_GPIO_DEN_OFFSET GPIO Digital Enable
GPIO_O_LOCK TIVA_GPIO_LOCK_OFFSET GPIO Lock
GPIO_O_CR TIVA_GPIO_CR_OFFSET GPIO Commit
GPIO_O_AMSEL TIVA_GPIO_AMSEL_OFFSET GPIO Analog Mode Select
GPIO_O_PCTL TIVA_GPIO_PCTL_OFFSET GPIO Port Control
GPIO_O_ADCCTL TIVA_GPIO_ADCCTL_OFFSET GPIO ADC Control
GPIO_O_DMACTL TIVA_GPIO_DMACTL_OFFSET GPIO DMA Control
GPIO_O_SI TIVA_GPIO_SI_OFFSET GPIO Select Interrupt
GPIO_O_DR12R TIVA_GPIO_DR12R_OFFSET GPIO 12-mA Drive Select
GPIO_O_WAKEPEN TIVA_GPIO_WAKEPEN_OFFSET GPIO Wake Pin Enable
GPIO_O_WAKELVL TIVA_GPIO_WAKELVL_OFFSET GPIO Wake Level
GPIO_O_WAKESTATTIVA_GPIO_WAKESTAT_OFFSET GPIO Wake Status
GPIO_O_PP TIVA_GPIO_PP_OFFSET GPIO Peripheral Property
GPIO_O_PC TIVA_GPIO_PC_OFFSET GPIO Peripheral Configuration
??? TIVA_GPIO_PERIPHID4_OFFSETGPIO Peripheral Identification 4
??? TIVA_GPIO_PERIPHID5_OFFSETGPIO Peripheral Identification 5
??? TIVA_GPIO_PERIPHID6_OFFSETGPIO Peripheral Identification 6
??? TIVA_GPIO_PERIPHID7_OFFSETGPIO Peripheral Identification 7
??? TIVA_GPIO_PERIPHID0_OFFSETGPIO Peripheral Identification 0
??? TIVA_GPIO_PERIPHID1_OFFSETGPIO Peripheral Identification 1
??? TIVA_GPIO_PERIPHID2_OFFSETGPIO Peripheral Identification 2
??? TIVA_GPIO_PERIPHID3_OFFSETGPIO Peripheral Identification 3
??? TIVA_GPIO_PCELLID0_OFFSET GPIO PrimeCell Identification 0
??? TIVA_GPIO_PCELLID1_OFFSET GPIO PrimeCell Identification 1
??? TIVA_GPIO_PCELLID2_OFFSET GPIO PrimeCell Identification 2
??? TIVA_GPIO_PCELLID3_OFFSET GPIO PrimeCell Identification 3
TivaWare NuttX Description
GPIO_PIN_TYPE_STD GPIO_PADTYPE_STD Push-pull
GPIO_PIN_TYPE_STD_WPU GPIO_PADTYPE_STDWPU Push-pull with weak pull-up
GPIO_PIN_TYPE_STD_WPD GPIO_PADTYPE_STDWPD Push-pull with weak pull-down
GPIO_PIN_TYPE_OD GPIO_PADTYPE_OD Open-drain
??? GPIO_PADTYPE_ODWPU Open-drain with weak pull-up
??? GPIO_PADTYPE_ODWPD Open-drain with weak pull-down
GPIO_PIN_TYPE_ANALOG GPIO_PADTYPE_ANALOG Analog comparator
GPIO_PIN_TYPE_WAKE_HIGH ??? Hibernate wake, high
GPIO_PIN_TYPE_WAKE_LOW ??? Hibernate wake, low
TivaWare NuttX Description
GPIO_FALLING_EDGE GPIO_INT_FALLINGEDGEInterrupt on falling edge
GPIO_RISING_EDGE GPIO_INT_RISINGEDGE Interrupt on rising edge
GPIO_BOTH_EDGES GPIO_INT_BOTHEDGES Interrupt on both edges
GPIO_LOW_LEVEL GPIO_INT_LOWLEVEL Interrupt on low level
GPIO_HIGH_LEVEL GPIO_INT_HIGHLEVEL Interrupt on high level
GPIO_DISCRETE_INT ??? Interrupt for individual pins
TivaWare NuttX
GPIODirModeSet(GPIO_DIR_MODE_IN) tiva_configgpio(GPIO_FUNC_INPUT | other settings)
GPIOPadConfigSet(GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD) tiva_configgpio(GPIO_STRENGTH_2MA | GPIO_PADTYPE_STD | other settings)
See: tiva_gpiopadstrength(), tiva_gpiopadtype()
GPIOIntEnable() tiva_gpioirqenable()
See: arch/arm/src/tiva/common/lmxx_tm4c_gpioirq.c
GPIOIntDisable() tiva_gpioirqdisable()
See: arch/arm/src/tiva/common/lmxx_tm4c_gpioirq.c
GPIOIntClear() tiva_gpioirqclear()
See: arch/arm/src/tiva/common/lmxx_tm4c_gpioirq.c

Interrupts

TivaWare NuttX IntNumDescription
INT_GPIOA TIVA_IRQ_GPIOA 16 GPIO Port A
INT_GPIOB TIVA_IRQ_GPIOB 17 GPIO Port B
INT_GPIOC TIVA_IRQ_GPIOC 18 GPIO Port C
INT_GPIOD TIVA_IRQ_GPIOD 19 GPIO Port D
INT_GPIOE TIVA_IRQ_GPIOE 20 GPIO Port E
INT_UART0 TIVA_IRQ_UART0 21 UART0
INT_UART1 TIVA_IRQ_UART1 22 UART1
INT_SSI0 TIVA_IRQ_SSI0 23 SSI0
INT_I2C0 TIVA_IRQ_I2C0 24 I2C0
INT_PWM0_FAULTTIVA_IRQ_PWM0_FAULT25 PWM Fault
INT_PWM0_0 TIVA_IRQ_PWM0_GEN0 26 PWM Generator 0
INT_PWM0_1 TIVA_IRQ_PWM0_GEN1 27 PWM Generator 1
INT_PWM0_2 TIVA_IRQ_PWM0_GEN2 28 PWM Generator 2
INT_QEI0 TIVA_IRQ_QEI0 29 QEI0
INT_ADC0SS0 TIVA_IRQ_ADC0 30 ADC0 Sequence 0
INT_ADC0SS1 TIVA_IRQ_ADC1 31 ADC0 Sequence 1
INT_ADC0SS2 TIVA_IRQ_ADC2 32 ADC0 Sequence 2
INT_ADC0SS3 TIVA_IRQ_ADC3 33 ADC0 Sequence 3
INT_WATCHDOG TIVA_IRQ_WDOG 34 Watchdog Timers 0 and 1
INT_TIMER0A TIVA_IRQ_TIMER0A 35 16/32-Bit Timer 0A
INT_TIMER0B TIVA_IRQ_TIMER0B 36 16/32-Bit Timer 0B
INT_TIMER1A TIVA_IRQ_TIMER1A 37 16/32-Bit Timer 1A
INT_TIMER1B TIVA_IRQ_TIMER1B 38 16/32-Bit Timer 1B
INT_TIMER2A TIVA_IRQ_TIMER2A 39 16/32-Bit Timer 2A
INT_TIMER2B TIVA_IRQ_TIMER2B 40 16/32-Bit Timer 2B
INT_COMP0 TIVA_IRQ_COMPARE0 41 Analog Comparator 0
INT_COMP1 TIVA_IRQ_COMPARE1 42 Analog Comparator 1
INT_COMP2 TIVA_IRQ_COMPARE2 43 Analog Comparator 2
INT_SYSCTL TIVA_IRQ_SYSCON 44 System Control
INT_FLASH TIVA_IRQ_FLASHCON 45 Flash Memory Control
INT_GPIOF TIVA_IRQ_GPIOF 46 GPIO Port F
INT_GPIOG TIVA_IRQ_GPIOG 47 GPIO Port G
INT_GPIOH TIVA_IRQ_GPIOH 48 GPIO Port H
INT_UART2 TIVA_IRQ_UART2 49 UART2
INT_SSI1 TIVA_IRQ_SSI1 50 SSI1
INT_TIMER3A TIVA_IRQ_TIMER3A 51 16/32-Bit Timer 3A
INT_TIMER3B TIVA_IRQ_TIMER3B 52 16/32-Bit Timer 3B
INT_I2C1 TIVA_IRQ_I2C1 53 I2C1
INT_CAN0 TIVA_IRQ_CAN0 54 CAN 0
INT_CAN1 TIVA_IRQ_CAN1 55 CAN1
INT_EMAC0 TIVA_IRQ_ETHCON 56 Ethernet MAC
INT_HIBERNATE TIVA_IRQ_HIBERNATE 57 HIB
INT_USB0 TIVA_IRQ_USB 58 USB MAC
INT_PWM0_3 TIVA_IRQ_PWM0_GEN3 59 PWM Generator 3
INT_UDMA TIVA_IRQ_UDMASOFT 60 uDMA 0 Software
INT_UDMAERR TIVA_IRQ_UDMAERROR 61 uDMA 0 Error
INT_ADC1SS0 TIVA_IRQ_ADC1_0 62 ADC1 Sequence 0
INT_ADC1SS1 TIVA_IRQ_ADC1_1 63 ADC1 Sequence 1
INT_ADC1SS2 TIVA_IRQ_ADC1_2 64 ADC1 Sequence 2
INT_ADC1SS3 TIVA_IRQ_ADC1_3 65 ADC1 Sequence 3
INT_EPI0 TIVA_IRQ_EPI0 66 EPI 0
INT_GPIOJ TIVA_IRQ_GPIOJ 67 GPIO Port J
INT_GPIOK TIVA_IRQ_GPIOK 68 GPIO Port K
INT_GPIOL TIVA_IRQ_GPIOL 69 GPIO Port L
INT_SSI2 TIVA_IRQ_SSI2 70 SSI 2
INT_SSI3 TIVA_IRQ_SSI3 71 SSI 3
INT_UART3 TIVA_IRQ_UART3 72 UART 3
INT_UART4 TIVA_IRQ_UART4 73 UART 4
INT_UART5 TIVA_IRQ_UART5 74 UART 5
INT_UART6 TIVA_IRQ_UART6 75 UART 6
INT_UART7 TIVA_IRQ_UART7 76 UART 7
INT_I2C2 TIVA_IRQ_I2C2 77 I2C 2
INT_I2C3 TIVA_IRQ_I2C3 78 I2C 3
INT_TIMER4A TIVA_IRQ_TIMER4A 79 Timer 4A
INT_TIMER4B TIVA_IRQ_TIMER4B 80 Timer 4B
INT_TIMER5A TIVA_IRQ_TIMER5A 81 Timer 5A
INT_TIMER5B TIVA_IRQ_TIMER5B 82 Timer 5B
INT_SYSEXC TIVA_IRQ_FLOAT 83 Floating-Point Exception (imprecise)
??? TIVA_RESERVED_84
??? TIVA_RESERVED_85
INT_I2C4 TIVA_IRQ_I2C4 86 I2C 4
INT_I2C5 TIVA_IRQ_I2C5 87 I2C 5
INT_GPIOM TIVA_IRQ_GPIOM 88 GPIO Port M
INT_GPION TIVA_IRQ_GPION 89 GPIO Port N
??? TIVA_RESERVED_90
INT_TAMPER0 TIVA_IRQ_TAMPER 91 Tamper
INT_GPIOP0 TIVA_IRQ_GPIOP 92 GPIO Port P (Summary or P0)
INT_GPIOP1 TIVA_IRQ_GPIOP1 93 GPIO Port P1
INT_GPIOP2 TIVA_IRQ_GPIOP2 94 GPIO Port P2
INT_GPIOP3 TIVA_IRQ_GPIOP3 95 GPIO Port P3
INT_GPIOP4 TIVA_IRQ_GPIOP4 96 GPIO Port P4
INT_GPIOP5 TIVA_IRQ_GPIOP5 97 GPIO Port P5
INT_GPIOP6 TIVA_IRQ_GPIOP6 98 GPIO Port P6
INT_GPIOP7 TIVA_IRQ_GPIOP7 99 GPIO Port P7
INT_GPIOQ0 TIVA_IRQ_GPIOQ 100 GPIO Port Q (Summary or Q0)
INT_GPIOQ1 TIVA_IRQ_GPIOQ1 101 GPIO Port Q1
INT_GPIOQ2 TIVA_IRQ_GPIOQ2 102 GPIO Port Q2
INT_GPIOQ3 TIVA_IRQ_GPIOQ3 103 GPIO Port Q3
INT_GPIOQ4 TIVA_IRQ_GPIOQ4 104 GPIO Port Q4
INT_GPIOQ5 TIVA_IRQ_GPIOQ5 105 GPIO Port Q5
INT_GPIOQ6 TIVA_IRQ_GPIOQ6 106 GPIO Port Q6
INT_GPIOQ7 TIVA_IRQ_GPIOQ7 107 GPIO Port Q7
??? TIVA_RESERVED_108
??? TIVA_RESERVED_109
INT_SHA0 TIVA_RESERVED_110 110 SHA/MD5
INT_AES0 TIVA_RESERVED_111 111 AES
INT_DES0 TIVA_RESERVED_112 112 DES
??? TIVA_RESERVED_113
INT_TIMER6A TIVA_IRQ_TIMER6A 114 16/32-Bit Timer 6A
INT_TIMER6B TIVA_IRQ_TIMER6B 115 16/32-Bit Timer 6B
INT_TIMER7A TIVA_IRQ_TIMER7A 116 16/32-Bit Timer 7A
INT_TIMER7B TIVA_IRQ_TIMER7B 117 16/32-Bit Timer 7B
INT_I2C6 TIVA_IRQ_I2C6 118 I2C 6
INT_I2C7 TIVA_IRQ_I2C7 119 I2C 7
??? TIVA_RESERVED_120
??? TIVA_RESERVED_121
??? TIVA_RESERVED_122
??? TIVA_RESERVED_123
??? TIVA_RESERVED_124
INT_I2C8 TIVA_IRQ_I2C8 125 I2C 8
INT_I2C9 TIVA_IRQ_I2C9 126 I2C 9
??? TIVA_RESERVED_127
??? TIVA_RESERVED_128
??? TIVA_RESERVED_129

QEI

QEI Register Offsets

TivaWare NuttX Description
QEI_O_CTL TIVA_QEI_CTL_OFFSET QEI Control
QEI_O_STAT TIVA_QEI_STAT_OFFSET QEI Status
QEI_O_POS TIVA_QEI_POS_OFFSET QEI Position
QEI_O_MAXPOS TIVA_QEI_MAXPOS_OFFSET QEI Maximum Position
QEI_O_LOAD TIVA_QEI_LOAD_OFFSET QEI Timer Load
QEI_O_TIME TIVA_QEI_TIME_OFFSET QEI Timer
QEI_O_COUNT TIVA_QEI_COUNT_OFFSET QEI Velocity Counter
QEI_O_SPEED TIVA_QEI_SPEED_OFFSET QEI Velocity
QEI_O_INTEN TIVA_QEI_INTEN_OFFSET QEI Interrupt Enable
QEI_O_RIS TIVA_QEI_RIS_OFFSET QEI Raw Interrupt Status
QEI_O_ISC TIVA_QEI_ISC_OFFSET QEI Interrupt Status and Clear

UART

UART register offsets

TivaWare NuttX Description
UART_O_DR TIVA_UART_DR_OFFSET UART Data
UART_O_RSR TIVA_UART_RSR_OFFSET UART Receive Status
UART_O_ECR TIVA_UART_ECR_OFFSET UART Error Clear
UART_O_FR TIVA_UART_FR_OFFSET UART Flag
UART_O_ILPR TIVA_UART_ILPR_OFFSET UART IrDA Low-Power Register
UART_O_IBRD TIVA_UART_IBRD_OFFSET UART Integer Baud-Rate Divisor
UART_O_FBRD TIVA_UART_FBRD_OFFSET UART Fractional Baud-Rate Divisor
UART_O_LCRH TIVA_UART_LCRH_OFFSET UART Line Control
UART_O_CTL TIVA_UART_CTL_OFFSET UART Control
UART_O_IFLS TIVA_UART_IFLS_OFFSET UART Interrupt FIFO Level Select
UART_O_IM TIVA_UART_IM_OFFSET UART Interrupt Mask
UART_O_RIS TIVA_UART_RIS_OFFSET UART Raw Interrupt Status
UART_O_MIS TIVA_UART_MIS_OFFSET UART Masked Interrupt Status
UART_O_ICR TIVA_UART_ICR_OFFSET UART Interrupt Clear
UART_O_DMACTL TIVA_UART_DMACTL_OFFSET UART DMA Control
UART_O_9BITADDR TIVA_UART_9BITADDR_OFFSET UART 9-Bit Self Address
UART_O_9BITAMASKTIVA_UART_9BITAMASK_OFFSETUART 9-Bit Self Address Mask
UART_O_PP TIVA_UART_PP_OFFSET UART Peripheral Properties
UART_O_CC TIVA_UART_CC_OFFSET UART Clock Configuration
??? TIVA_UART_PERIPHID4_OFFSETUART Peripheral Identification 4
??? TIVA_UART_PERIPHID5_OFFSETUART Peripheral Identification 5
??? TIVA_UART_PERIPHID6_OFFSETUART Peripheral Identification 6
??? TIVA_UART_PERIPHID7_OFFSETUART Peripheral Identification 7
??? TIVA_UART_PERIPHID0_OFFSETUART Peripheral Identification 0
??? TIVA_UART_PERIPHID1_OFFSETUART Peripheral Identification 1
??? TIVA_UART_PERIPHID2_OFFSETUART Peripheral Identification 2
??? TIVA_UART_PERIPHID3_OFFSETUART Peripheral Identification 3
??? TIVA_UART_PCELLID0_OFFSET UART PrimeCell Identification 0
??? TIVA_UART_PCELLID1_OFFSET UART PrimeCell Identification 1
??? TIVA_UART_PCELLID2_OFFSET UART PrimeCell Identification 2
??? TIVA_UART_PCELLID3_OFFSET UART PrimeCell Identification 3

UART Interrupt Mask (IM) Register

These values can be passed to UARTIntEnable(), UARTIntDisable(), and UARTIntClear() as the ui32IntFlags parameter, and are returned from UARTIntStatus():

See arch/arm/src/tiva/hardware/tm4c/tm4c_uart.h.

TivaWare NuttX BitTM4C123TM4C129Description
UART_INT_DMATXUART_IM_DMATXIM17 Yes Transmit DMA Interrupt Mask
UART_INT_DMARXUART_IM_DMARXIM16 Yes Receive DMA Interrupt Mask
UART_INT_9BIT UART_IM_9BITIM 12 Yes Yes 9-Bit Mode Interrupt Mask
??? UART_IM_EOTIM 11 Yes End of Transmission Interrupt Mask
UART_INT_OE UART_IM_OEIM 10 Yes Yes UART Overrun Error Interrupt Mask
UART_INT_BE UART_IM_BEIM 9 Yes Yes UART Break Error Interrupt Mask
UART_INT_PE UART_IM_PEIM 8 Yes Yes UART Parity Error Interrupt Mask
UART_INT_FE UART_IM_FEIM 7 Yes Yes UART Framing Error Interrupt Mask
UART_INT_RT UART_IM_RTIM 6 Yes Yes UART Receive Time-Out Interrupt Mask
UART_INT_TX UART_IM_TXIM 5 Yes Yes UART Transmit Interrupt Mask
UART_INT_RX UART_IM_RXIM 4 Yes Yes UART Receive Interrupt Mask
UART_INT_DSR UART_IM_DSRIM 3 Yes UART Data Set Ready Modem Interrupt Mask
UART_INT_DCD UART_IM_DCDIM 2 Yes UART Data Carrier Detect Modem Interrupt Mask
UART_INT_CTS UART_IM_CTSIM 1 Yes Yes UART Clear to Send Modem Interrupt Mask
UART_INT_RI UART_IM_RIIM 0 Yes Yes UART Ring Indicator Modem Interrupt Mask

UART Interrupt FIFO Level Select (IFLS)

Values that can be passed to UARTFIFOLevelSet() as the ui32TxLevel parameter and returned by UARTFIFOLevelGet() in the pui32TxLevel:

TivaWare NuttX Description
UART_FIFO_TX1_8 UART_IFLS_TXIFLSEL_18thTransmit interrupt at 1/8 Full
UART_FIFO_TX2_8 UART_IFLS_TXIFLSEL_14thTransmit interrupt at 1/4 Full
UART_FIFO_TX4_8 UART_IFLS_TXIFLSEL_halfTransmit interrupt at 1/2 Full
UART_FIFO_TX6_8 UART_IFLS_TXIFLSEL_34thTransmit interrupt at 3/4 Full
UART_FIFO_TX7_8 UART_IFLS_TXIFLSEL_78thTransmit interrupt at 7/8 Full

Values that can be passed to UARTFIFOLevelSet() as the ui32RxLevel parameter and returned by UARTFIFOLevelGet() in the pui32RxLevel:

TivaWare NuttX Description
UART_FIFO_RX1_8UART_IFLS_RXIFLSEL_18thReceive interrupt at 1/8 Full
UART_FIFO_RX2_8UART_IFLS_RXIFLSEL_14thReceive interrupt at 1/4 Full
UART_FIFO_RX4_8UART_IFLS_RXIFLSEL_halfReceive interrupt at 1/2 Full
UART_FIFO_RX6_8UART_IFLS_RXIFLSEL_34thReceive interrupt at 3/4 Full
UART_FIFO_RX7_8UART_IFLS_RXIFLSEL_78thReceive interrupt at 7/8 Full

UART DMA Control (DMACTL) Register

Values that can be passed to UARTDMAEnable() and UARTDMADisable():

TivaWare NuttX Description
UART_DMA_RX UART_DMACTL_RXDMAEReceive DMA Enable
UART_DMA_TX UART_DMACTL_TXDMAETransmit DMA Enable
UART_DMA_ERR_RXSTOPUART_DMACTL_DMAERRStop DMA receive if UART error

September 24-25, 2022: The NuttX International Workshop

This section last updated September 25th, 2022.

As in the previous two years, the 2022 NuttX International Workshop event was held online. A recording of the entire two-day event and all its presentations can be seen on YouTube by following the links below.

Note: The primary place to communicate with the NuttX developer and user community is at its mailing lists.

October 26, 2022: NuttX community discussing graduation from the Incubator

Back in December 2019, I wrote that NuttX, which was until then driven almost exclusively by one person, Gregory Nutt, became accepted into the Apache Incubator at the Apache Software Foundation (ASF).

This move was motivated by a desire to shift from a Benevolent Dictator For Life (BDFL) model to a community-driven model.

The ASF has hundreds of different software projects driven by equally many different communities. Some of these are termed Top-Level Projects (TLP) while others are subprojects of a TLP.

The way projects become part of the ASF is that they first must be accepted as a "podling" within the Apache Incubator. During the "incubation" process, the project organizes (or re-organizes), builds and expands its community, migrates its source code licenses to the Apache 2.0 License, and learns "The Apache Way" which is how project governance works at the ASF. When the community feels it is ready, it votes to graduate, then has the Incubator vote to recommend its graduation to the ASF board of directors, and if these votes pass, a resolution is brought before the board for an approval vote and formation of the Top Level Project.

All of the above is related to governance and may seem unrelated to the technical aspects of using NuttX as your embedded RTOS, but there is a significant benefit to graduating and becoming a Top-Level Project as opposed to staying in the Incubator, namely more frequent releases. Back in NuttX's BDFL days, Gregory Nutt released a new version of NuttX every other month like clockwork. While in the Incubator, the frequency of releases slowed down from six releases per year to about three, due in part to the requirement for podlings to undergo two rounds of voting for each release: first the podling must vote successfully, and then the Incubator's mentors must vote to approve the release. In some cases, it takes weeks for enough Incubator mentors, who are volunteers, to vote on a release, so the releases end up delayed.

Though the two rounds of voting and the reduced frequency of releases may be seen as disadvantages, I think it is significant to note that the number of improvements, new microcontroller architectures, new board support, and bug fixes, have skyrocketed in the three years since NuttX joined the Apache.org Incubator. I think this is due in large part to the fact that the work previously done by an overworked BDFL is now shared among more than a dozen skilled developers who have been involved with NuttX for many years. I'd say that's a definite advantage.

The recent news (only a few days old at this writing) is that after roughly three years in the Incubator, the following mailing list posts appeared on the NuttX developer's mailing list:

Round one of voting at the NuttX podling level:

Seems there are exciting times ahead for Apache NuttX! Stay tuned while this story develops!

November 17, 2022: Happy Graduation, Apache NuttX Top-Level-Project!

I've written several times about the journey of NuttX from one-man-project to BDFL-driven community to merit-driven community at the Apache Incubator.

Today, NuttX has graduated the Apache Incubator and is officially Apache NuttX, a Top-Level-Project of the Apache Software Foundation!

The high12noon blog is pleased to say "Congratulations!" to the Apache NuttX community, who work tirelessly to bring this fantastic RTOS to the world.

Round two of voting at the Apache Incubator level:

Graduation announcement:

November 25, 2022: NuttX runs on the PINE64 PinePhone!

LEE Lup Yuen, an IoT educator, CTO, consultant, blogger, and NuttX developer, has written a series of articles about grokking the PINE64 PinePhone (PinePhone official site, PinePhone on Wikipedia). This is a 64-bit ARM Cortex-A53-based smartphone that normally runs Linux. And Lup Yuen has gotten NuttX to boot and run on it! The step-by-step process is documented in a series on articles on Lup Yuen's personal blog.

Today's exciting news is that PinePhone support has landed in NuttX! PR-7692, which was merged just a few short hours ago, upstreams the culmination of Lup Yuen's work thus far on the NuttX port to the PinePhone. These are exciting times indeed for NuttX on some seriously powerful hardware.

If you'd like to run NuttX on a PinePhone, see the documentation at Documentation/platforms/arm/a64/boards/pinephone/index.rst in the NuttX tree. In particular, Lup Yuen points out that a serial debug cable is needed.

Lup Yuen's educator background really shows as the blog articles are well-written with clear explanations, photographs, and beautiful illustrations. If you'd like to follow along on Lup Yuen's journey to bring NuttX to the PinePhone, the articles on Lup Yuen's blog, in chronological order through today, are:

Hopefully many more helpful articles will follow on Lup Yuen's blog, so I recommend to set a bookmark and keep an eye on it!

References:

January 16, 2023: NuttX 12.0 released!

This section last updated January 20th, 2023. (Added link to release announcement.)

The title says it all: Apache NuttX 12.0 has just been released!

There are a couple of firsts in this release:

I've written about the new PinePhone support previously. Development of that support seems to be ongoing and improving with a continuing stream of PinePhone-related PRs at the NuttX GitHub.

The PinePhone is only one out of about 250 boards (I don't know the exact count) that currently are supported in the official NuttX tree. There is always the possibility to port NuttX to new boards and either upstream that support (propose it for inclusion in the official NuttX sources) or maintain it as an in-house "out-of-tree" board.

Upstreaming makes sense for commonly available off-the-shelf boards and hackable products. Upstreaming the support benefits the community as a whole because it allows others to use existing support as a starting point for their own projects. It also benefits the developer who upstreamed the support because they'll get improvements and bug fixes proposed by others "for free."

Maintaining a port as an in-house "out-of-tree" board makes sense in other contexts, such as for proprietary commercial products that use NuttX as the RTOS running in their boards.

NuttX is under the Apache 2.0 license, which makes both of the above scenarios possible.

References:

September 28-29, 2023: The NuttX International Workshop in Campinas, Brazil

This section last updated October 6th, 2023.

For the first time in three years, the 2023 NuttX International Workshop event was a physical event held at The School of Electrical and Computer Engineering (FEEC/Unicamp) in Campinas, Brazil. In addition to the physical event, it was made possible to attend virtually, and the proceedings have been placed online for later viewing. The recordings of the entire two-day event and all its presentations can be seen on YouTube by following the links below.

Note: The primary place to communicate with the NuttX developer and user community is at its mailing lists.

NuttX International Workshop Day 1

Day 1 - September 28, 2023

Full video

Day 2 - September 29, 2023

Full video

December 5, 2024: A Worldwide Distributed Embedded Build Farm? (Part 1)

How does one test a system as vast and complex as NuttX?

Currently, NuttX has two tiers, or at least what I'll call tiers, of testing.

These are:

  1. First tier: Compilation smoke test.
  2. Second tier: ostest, found in the nuttx-apps repository (GitHub).

Today, we'll discuss the first tier, which is the compilation smoke test. In part 2 (coming soon), we'll cover the ostest.

First Tier: Compilation Smoke Test

Simply stated, NuttX is compiled to see whether the build succeeds or is broken.

What can we possibly learn from that? After all, as anyone who has written code should know, code can compile just fine but not work correctly. While that's true, it is still important to perform this test. Here's why:

NuttX is a very complex codebase with an equally complex set of build requirements.

To handle all of the above, a NuttX build is configured with myriad tuning knobs called Kconfig options. These control which files are compiled, how they are compiled, and sometimes exert fine grained control over details within the files. Given that there are countless combinations of Kconfig settings, it is combinatorially impossible to test every possible build of NuttX.

Yet, when editing code, it is very easy for a developer to make a build-breaking mistake that will not manifest on that developer's machine, because the particular Kconfig options in use will mask the mistake. However, if this code makes it into a Pull Request (PR) and is merged into the NuttX mainline, the build may suddenly start breaking for many other developers whose Kconfig settings do not mask the mistake.

If that were to happen frequently, with different people accidentally breaking different parts of the build unbeknownst to themselves, the community as a whole would start losing a lot of time, and gaining a lot of frustration, to broken builds that were working fine a moment ago, and now aren't.

How can we test every build if we just established that it is combinatorially impossible to do so? The answer is that while we cannot test every single possible build, we can at least compile all of the stock board configurations that NuttX comes with. If all of those build successfully, it gives us adequate confidence that the changes shouldn't break the build for most people, most of the time.

But there's a logistical problem. There are nearly 1,600 board configurations at this writing, and the number is always growing. Compiling nearly 1,600 builds on your own development machine, just to see if you've broken anything, will take much too long. It could be a significant number of hours!

The NuttX project tried to solve this by using GitHub Actions, which is GitHub's Continuous Integration (CI) system. This system has the computing power to perform these builds much faster than most developer machines. But there's a catch. It costs real money to use GitHub Actions, and with 1,600 builds happening for every PR and for every force-push in every PR, the costs were piling up fast.

Lup Yuen LEE, an educator and NuttX developer, explores this issue in several recent blog articles (external links):

Based on those articles, it sounds like a temporary workaround has been put into place to reduce cost, but the work hasn't ended. The NuttX developers are apparently trying to come up with a way for volunteers around the world to somehow hook into a distributed system and participate in build testing without using an unreasonable amount of computing power from any individual volunteer.

This reminds me of earlier efforts at distributed computing, such as SETI@home (Wikipedia) or the Great Internet Mersenne Prime Search (Wikipedia). It should be interesting to keep an eye on this.

Do you have an idea how the NuttX developers can build a worldwide distributed build farm? I'm sure they'd like to hear about it at the NuttX developer mailing list! And, if it works for NuttX, it possibly could work for many other projects faced with similar challenges.

Check back soon for the second tier of testing, ostest.

NuttX Articles On Other Blogs

This section lists articles on other blogs that are related to NuttX and that I found interesting, helpful, or unique in some way.

This section last updated January 25th, 2022.

References and External Resources

This section last updated January 16, 2023.

NuttX journey to Apache Top-Level-Project:

As always, stay tuned for more Adventures with NuttX!


Back to main page

Send feedback to: the name of this blog at mail dot com.