A great WordPress.com site

Tag Archives: netduino

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….

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:

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).

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.

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.

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….

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.

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).

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’.

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.