why this blog

I’m not a ‘web person’ by nature.  I’m technical in nature, but with regards to the past 20 years of WWW stuff, I’m really a bit of a luddite.

Anyway, after many attempts to learn to enjoy doing www stuff, I have realized that I will probably always consider it more of a chore than a pleasure, so I am going to switch to ‘user mode’ and capitalize on the myriad of canned, hosted solutions for things like publishing a journal.

I still don’t really know what I’m doing with it, but maybe at least I’ll be more productive, and be able to focus on what it is I’m journaling about…

NuttX on a Netduino Plus 2; setup Ethernet, verified

I awoke this morning to discover that I had turned into a giant cockroach.  Oh, and also that my NP2 was still running.  So, I replied to the group with the results, and created a patchfile, which has been incorporated into head and should come out in NuttX 6.29.

It’s interesting that I should have a part that is so susceptible to this erratum, but I am glad — otherwise it would have been harder to detect, far harder to have confidence that maybe it is hardware related, and also harder to verify the fix.  Sometimes when you fail, you actually succeed!

Now that I am done with external hardware, I need to get all the internal (on-chip) hardware working.  This includes all gpios, in and out and open-drain and pullup, interrupts with the gpios, I2C, SPI, A/D, PWM, and serial.  Lot of work….

NuttX on a Netduino Plus 2; setup Ethernet, pt 2

Checking back with the forum, I see some advice that the ENC28J60 is returning wildly invalid data (I added low level logging of device register actions).  The thing is, sometimes it works fine, and stays working fine.  So I grope forward with some greybox tests:

  1. reproducibility:  when it fails, it fails on the first packet.  when it doesn’t fail, it can go on indefinitely (which here means about 2 hrs before I give up waiting).
  2. frequency:  given the failure happens on the first packet, I can boot and see if the first packet passes or fails.  I do about 40 boots, and get 45% failure.
  3. since that seems to suggest something setup-y, I add code to dump all the ENC28J60 registers right after init, and right before pulling the first packet, looking for discrepancies and correllations.

The last test showed that all the registers were fine, but there is a slight complication.  One of the registers (well at least one), is a shadow register, and you don’t get the real value during initialization.  The real value is obtained after some activity.  This is the ERXWRPT register, which is the receive buffer write pointer, i.e. where incoming network data is written.  In the failure cases, I noticed that pointer was not pointing within the receive buffer, but was pointing into the transmit buffer.  That makes no sense, and should not be possible because the hardware constrains that to be between start and end.

While reading the datasheet to figure out how the chip works, I did notice in the intro section (who reads those, right?) that you should consult errata for post-ship bug notices.  Why not?  I went into it thinking that maybe I didn’t wait long enough after flicking on the powerctl before writing config, because that is something specific to this board, but noticed instead that there is an Errata 5 related to spurious reset of the ERXWRPT to 0, instead of to the receive buffer start.  The workaround being that you should align your receive FIFO to address 0 to mask the problem.  I did this and the problem went away.  I left the board running overnight with continual network traffic.


NuttX on a Netduino Plus 2; setup Ethernet

OK, after the trouble with the SD card, which I thought would be a drop-kick, I’m a little daunted going into this one.  We’ll see!  But I definitely know more starting out.

So, first thing is code, and I found a project with an enc28j60 in it, and there is a up_enc28j60.c module in it, so I copy it over and commence to modifying.

Now I need clock.  On this board, the Ethernet controller chip (a Microchip ENCJ28J60) is clocked from A8 using a thing called MCO1 on the HSE.  Blablablah.  This actually was straightforward to setup, and I remembered my power control line this time.  I bind the driver to the spi in a manner similar to how it’s done with the SD card.  No kooky status to convey.

Now I need to build.  How?!  I have a devil of a time trying to figure out how to select ‘Network Devices’.  Its supposed to become available once you select networking support but I’ll be damned but that did not do it.  I crowbarred it open by setting the parameter in defconfig.  Then I was able to get to the to the ENC28J60 settings, which I setup.

Build fails.  There actually is a web of options that all need to be set correctly to get a build to go through to completion.  Things like ‘enable the worker thread’ and ‘enable socket options’ and ‘do not disable clock interfaces’ and ‘do not enable SLIP support’.  Eventually I get a build.  (I punted on a couple that were NSH related by disabling get, put, wget commands, but eventually I figured them out also and enabled them).

Now I can build, and it kinda works.  But often I get an assertion:

Assertion failed at file:net/enc28j60.c line: 1433

(sigh).  OK that has to do with packet pointers being wildly wrong (way overflowing buffers, etc.).  So back to the groups I go asking if anyone has seen this, and simultaneously I read source.  But first, I sleep….


NuttX on a Netduino Plus 2; setup SD card support, pt 3

The breakage of my other board has me obsessed — how could it be?  Well, it could be for a simple reason:  I had rebrained that board, and I had a bad solder joint on my replaced chip.  That board had a damaged processor and I had decided to try my hand at replacing the CPU (and with a tastier one, the 415), which I did successfully much to my amazement. But I failed to consider that little fact about it’s history when I started this project, and also that I had not done a full test of it’s functionality.  My fear was that I had broken a trace under the CPU but at length it simply turned out to be a bad solder joint, which was easily remedied with a smidge of molten lead, and the world seems sane once again.  Anyway, lesson learned, and that board will not be used for further work on this project.

Eventually, I also discovered that I had a typo in the pin defs for the SPI ports in board.h.  It was a cut-and-paste error, and I had copied the SPI1 text down into SPI2 and SPI3.  I correctly modified the pin variant, but not the port number.  I changed that and…  it works!  Or at least I can mount, and I can do a directory listing.  Haven’t tried anything fancier, but that satisfies me at this phase.

NuttX on a Netduino Plus 2; setup SD card support, pt 2

I rummage through the source for ENODEV and find that this is returned almost as a generic error message, so I add debug messages as breadcrumbs along the path of execution.  But where is the debug output going?  Well, I lost that when I went to the USB console.  It was suggested that I try the ‘ramlog’ device, which will then give me a ‘dmesg’ command.  I try, but this makes things much worse (board fails to boot), so in desperation I try re-enabling syslog and directing to USART2.  Now I have debug on on that port, and interactive console on the USB.

I discover that NuttX SPI has a notion of ‘status’.  This is not an intrinsic SPI concept, but something NuttX straps on to give some info about the device attached to that SPI port, and in fact it conveys things like ‘card inserted’, and ‘write protected’.  In fact the only statuses defined are SD-related.  So I modify up_spi.c stm32_spi3status() to indicate that.

Along the way I remembered that there are also power control lines for the SD and Ethernet controllers.  I add code to flick the power on, but no avail.

I break down and pull out the oscilloscope, and see no SPI clock.  In desperation I try flashing back the original Netduino firmware and see that SD doesn’t work there either!  What?  I try a different board, and it does work!  So I wasted a lot of time with a somehow defective board, I think, so I flashed NuttX on the known good board and it still doesn’t work.

I break out the oscilloscope and see no SPI clock, which I know has to be there sometime!  And of course I verify that with the original firmware (and discovered some interesting behaviour that explains some problems there, BTW, but that’s a separate topic).

And so I slunk away defeated.  For today.

NuttX on a Netduino Plus 2; setup SD card support

Having mapped out all my IO pins, I decided to attempt support for the SD card first.  It’s ostensibly a simpler device than the Ethernet controller, and the hardware assignment is fixed, so I should be able to do all my setup statically during boot.

Along the way, though, I noticed that there is another app configuration ‘usbnsh’.  It does a CDC serial emulation over the usb, so I could use this instead of USART2 on PA2/PA3.  I need to do something like this eventually anyway, since those pins must be available to user applications, so I give it a whirl.  Much to my delight it works as expected, so I switch now to further development work from within the ‘usbnsh’ project.

Also, I grow weary of reconfiguring menuconfig options each time I do a distclean build.  At length, I figure out that ‘defconfig’ in the various app directory supplies those options, so the first one that changes is the host build system and the toolchain selection.  This works as expected.  The file has a warning that it is a generated file, but I think that means generated by the author.  Its certainly not generated from with the build system, so I don’t feel bad about accumulating my selections in this file as I go and as they are validated.  My hope is that an end user will be able to simply deploy the code base, execute ‘make’, and have a correct and functional firmware, without having to make any configuration choices at all.

I removed ‘syslog’ to liberate USART2, this seemed to work.  Oddity:  ‘syslog’ is located under ‘File Systems’.  There are many such placements that run counter to at least my intuition, so get used to it.  There’s a lot of grepping in my future.

I also noticed and altered the JTAG options to be the NOJNTRST variant, because I believe that is what is correct for the netduino.  I make the preceding changes the defaults in my defconfig.

OK, getting back to MMC, this is on SPI3, so I mapped all the SPI pins board.h, I mapped CS’s in netduinoplus2_internal.h, I modded up_spi.c to do CS stuff, and up_nsh.c to up_spiinitialize() and also mmcsd_spislotinitialize().

I build, and, why not try to mount?

nsh> mount -t vfat /dev/mmcsd0 /mnt/fs
 nsh: mount: mount failed: 19

fail.  I have no idea what 19 means, and if there is a better way to test, so I ask the group.  They tell me its erno, ‘ENODEV’.

I put this aside for the day.

NuttX on a Netduino Plus 2; mapping pins

Today consists of mundane chores.  I notice a new release just came out, 6.28, so I pull that and merge in my changes.  Fortunately, everything I have done is in an added directory, and also fortunate is that it builds and works.  This took a couple hours for me, because I am fastidious about testing the buildability at each step.  But what really took up the day was mapping out the IO for the peripherals.

This mapping step is necessary because the board setup code has to specify how the on-chip peripherals connect to the pins — there’s several choices.  Also, the task is made worse from nomenclature clash — from the user’s perspective they are named one way (e.g. D0-D7, COM4, A0, etc), and the pins have different names in the CPU.  Moreover, abstract peripherals like ‘the sd card’, ‘the ethernet controller’, ‘the COM1 port’, need to be translated to what CPU resource they are using, like ‘spi3’, ‘spi1’, or ‘usart6’.

So, I sit down with schematic, datasheet, and ‘arch/arm/src/stm32/chip/stm32f40xxx_pinmap.h’, and correlate all the things.

Another concern I have looking forward is that most of the pins on the netduino header serve alternate functions, depending on the user application deployed.  For example D3 could be any of: a digital IO, TX of COM2, or a PWM output.  On the other hand, most embedded systems are single-function, and a board initialization routine will set those choices once and for all.  So I don’t know if I will later run into challenges whereby I need to change the IO functionality later, on-the-fly.  We’ll see.  For my first step, I will try to get drivers working for the dedicated off-chip hardware, namely:  the SD card, the ENC38J60 Ethernet controller.

NuttX on a Netduino Plus 2; making board configs

Naturally, manually editing .config was just a temporary workaround.  I prefer my projects to build correctly straight out of source control.  The configuration system is a bit much to reverse-engineer, so I just ask the group how to configure a board.  I get advice, and also the maintainer updates project’s wiki/docs with the instructions since were not already there.

I also switch back to building the ‘nsh’ application (from ‘ostest’) since I am beyond testing the os and want to get interactive.

I also edit board.h, up, autoleds.c, netduinoplus2-internal.h to adapt for the on-board LED.  The LED is my first peripheral ported, haha.

NuttX on a Netduino Plus 2; attempting the port…

OK, now that the build system is validated, it’s time to start the real work at hand.

Before starting, I reached out to the online group to ask if anyone had attempted this, if there was an existing project, and if there was any general advice.  This seemed to be new ground so off I went.

Since the Netduino Plus 2 (henceforth ‘NP2’) uses an STM32F405, it seemed reasonable to use an existing project for that same processor as a base, and so I chose the STM32F4Discovery project.  I copied all the stuff in configs/stm32f4discovery into configs/netduinoplus2, then I grepped for ‘stm32f4discovery’ in those files an manually changed all such instances to ‘netduinoplus2’.  Lastly, I renamed a file ‘src/stm32f4discovery-internal.h’ to ‘src/netduinoplus2-internal.h’, and adjusted the #includes that referred to that file.

Then I did

./configure.sh netduinoplus2/nsh
cd ..
. ./setenv.sh
make menuconfig

and changed the ‘build setup, host platform’ and ‘system type, toolchain selection’, and performed trial build.  Surprisingly, it went through.  No expectation that it would work, so I started to mess with things in menuconfig.

For fun, I tried ‘system type, fpu support’.  That didn’t work; but not critical now, I’ll come back to it later.  Also changing STM32 Chip Selection to a ‘405 (which is what my board actually uses) failed miserably.  So badly I had to do a ‘make distclean’ and start from the beginning!  Thats a bug in the menuconfig system (or some other part of the configuration process, regardless) in my eye, but I’ll just continue with the ‘407 for now.

There is a ‘dfu bootloader’ option.  I asked the group about this, but it turns out it is not meaningful for this chip — its used for arranging the image to not overwrite a bootloader.  However, these newer chips have the bootloader embedded in ROM in a special place where it can’t be overwritten.

The first thing I critically need to do is set up the clock frequency that reflects the board’s hardware design (25MHz).  ‘Custom clock configuration’ got me nowhere good, so I rummaged and found that it seems to be in ‘include/board.h’.  I ask the group and got confirmation that this is the one and only place to set it up.  I also got advice that perhaps my first configuration should be for ‘ostest’, rather than ‘nsh’, so I go to that henceforth. I recompute the needed values.

I also happily noticed that console output is configured for USART2 mapping to PA2/PA3, at 38400,N81.  This is good news because coincidentally that is COM2 on the NP2, and those lines are brought out to the header.  So my next sanity check should just reflect the clock change I made.  I do a build:

./configure.sh netduinoplus2/ostest
cd ..
. ./setenv.sh
make menuconfig

built and burned.  Connect my trusty FTDI, and… no output.  (sigh).  Casually inspecting, I notice symbolic links in arch/arm/src, one called ‘board’ and one called ‘chip’.  ‘board’ is pointing into the stm32fdiscovery tree.  That can’t be right; at least it won’t be picking any of my clock param changes.

I traverse a path paved by grep and at length discover that link is setup from a parameter stored in .config (which is generated from menuconfig) named ‘CONFIG_ARCH_BOARD’.  I distclean, reconfigure it all, and just before running make, I manually change it to “netduinoplus2”.

I built, and diffed the .hex file from this run with the one from before and discovered a one byte difference, the values of which did indeed reflect the clock divisor change I had made.  (Thank god for deterministic builds).

I burned, and ran, and… success!  Tons of console output from the ostest app looking like, well, OS tests.  Which appear to be passing!