Friday, July 26, 2013

Notes on tackling an Open Source Beaglebone Black Project, Part 1

The Project

In summer of 2013 while looking for the next work challenge, I grabbed the opportunity to use my 'spare' time to further my knowledge, buy some more test equipment and the new Beaglebone Black I'd been dreaming about, and joined an open-source Google Summer of Code project PRU/JTAG to help out.

The things I liked about the project were:

  • it involved the Beaglebone Black (BBB) which has 1 GHz TI Sitara AM335X ARM Cortex A8 SoC (System on Chip) processor, SD card, Ethernet, USB host and slave interfaces, HDMI, programmable I/O pins - the works - for $45!
  • it involved developing a useful and inexpensive device (BBB-based high-speed JTAG debugger) that could be really helpful to others developing their projects
  • it would use the PRUSS (Programmable Real-time Unit Subsystem) which is two 200 MHz independent co-processors included on the Sitara chip, to provide real-time signalling capability on external pins
  • it involved an external plug-in board ('cape') with a CPLD (Complex Programming Logic Device) that would provide *really* high-speed signalling capability (MHz)
  • learning more about JTAG (I'd used JTAG debuggers and emulators in the past - a godsend to improving software development productivity - but had no real idea how the signalling worked)
  • the latest version of Linux, including possible work on the kernel itself
  • the opportunity to get a crash skills upgrade course - learning from experts who have long been involved in the open-source Linux community
  • the opportunity to help mentor students who are getting involved

It's been only a couple of weeks, and my expectations have already been wildly exceeded!


Project Members

Besides the student, there were already two project mentors who I'll refer to by their nicknames on the #beagle-gsoc IRC channel.  KA6SOX is experienced with FPGA and CPLD devices and is the designer of the cape board.  PANTO is very experienced in the Linux kernel and embedded development and, critically for this project, had just finished developing a driver model for Linux that communicated with code running in the PRU processors.  KA6SOX imagined a JTAG debugger running at 5 MHz or higher, given all the hardware assist devices involved.

I came onto the project very shortly after it began.  The engineering student (JJ2BAILE) was already familiar with JTAG standards and had developed a PRU program in assembly language, configured the Device Tree (a new hardware pin-configuration utility built into Linux 3.8 for ARM devices), and the PRU program toggled some pins on the BBB header to emulate the JTAG signals (TCK, TMS, TDI, TDO).

As it evolved, my job became to guide development of the OpenOCD component - OpenOCD is an open-source on-chip-debugger software that runs on Linux and Windows, and is used with gdb (gnu debugger) as glue to load firmware onto, and debug, an external target board - the team had already chosen the TI Stellaris Launchpad evaluation board ($12).

I wanted to get more hands-on with board-level work, possibly to make a board myself in the future.  And I wanted to learn about CPLD and PRU, to control hardware at very high speeds - to learn how to program them.

But the last decade of working years has been primarily in the Microsoft Windows world developing .NET and C# applications, and some firmware development - I wanted to do more of that.  I've worked with Arduino's, Microchip PIC, and ARM7 devices - a little FPGA with Verilog.  I had never used the BBB before, and only knew vaguely what the PRU was all about.  

On the plus side - I had used Unix extensively in the past, Ubuntu Linux, OpenWRT Linux for wireless routers, and written and debugged firmware in C for various targets and with various tools.  I was familiar with command-line development (gcc compiler) and IDE (Eclipse), cross-development toolchains such as gcc, TI Code Composer Studio, Freescale Code Warrior, and Microchip MPLAB.  And oscilloscopes, logic analyzers, microcontroller emulators, software-level debuggers, etc.

So I had no doubt I could make a positive contribution, but could I do it fast enough to make a difference to the project?


What Needed to be Done?

  • Linux familiarity
  • development tools
  • research

From experience I knew it was critical to get familiar with running Linux on the BBB, and compiling software on it or for it.  You can't develop software without the right computing environment and a toolchain (or several of them) in place.

But beyond that ... the project was about the communication between gdb and a JTAG target, and the details of EVERYTHING in the middle (OpenOCD, Angstrom Linux, PRU, CPLD, JTAG signalling) were new to me.  A lot more unknowns were, at that point, unknown to me - although (like Donald Rumsfeld) I assumed they were there!

So I made an initial list of what to research first:

  • OpenOCD, plug-ins, configuration and gdb server interface
  • similar open-source projects
  • JTAG
  • PRU
  • vrings


Research Phase 1

OpenOCD: Looking at the OpenOCD source code, I found the 'hooks' needed to communicate with various JTAG debugging devices - some used serial communication, others bit-bashing of I/O pins.  Many JTAG debuggers supported by OpenOCD use the popular FTDI USB serial device interface for the communication connection.  None use an ARM PRU for the communication channel.  OpenOCD implements a gdb server (which can be TCP/IP socket based) which is how gdb communicates with it.

BlackMagic:  The open-source BlackMagic project provides a small on-target debugger that implements a gdb server, and illustrates most of what OpenOCD is doing without the complexity of the OpenOCD 'Jim' scripts - which are a major part of configuring OpenOCD.  It helped to clarify by presenting simpler picture of the concepts required.

OpenJTAG:  The OpenJTAG project, not only provided an extension to OpenOCD (thus an example of how to do it), but also - like this project - used an intermediate CPLD as part of the communication link to the JTAG pins.  Interestingly, OpenJTAG makes use of command bytes rather than bitstreams, and the CPLD converted each command into appropriate JTAG pin-signalling sequences.  That approach seemed to have great potential to speed up communication for our project - critical, because to achieve MHz-scale speeds would require as little communication overhead as possible.

goJTAG:  JTAG also is about Boundary Scan, not just debugging - scanning a JTAG-equipped board to see what JTAG-compliant devices are on it, and then sending them JTAG commands to check pin input and output states - it is for board testing.  Some boards have multiple JTAG connectors.  Asking the team, I found they did plan to perform Boundary Scans as part of their testing.  OpenOCD did not seem to perform Boundary Scan (although it can be done using scripts) - but I found the goJTAG project that did.

Each of these open-source projects provided a slightly different view, on how to potentially implement a JTAG solution.

JTAG: Joint Test Action Group, also standing for IEEE 1149.1 Standard Test Access Port and Boundary-Scan Architecture.  A very hardware-level view - impenetrable to me at this point.  Fortunately the open-source projects would help in the understanding of the pin signalling needed, and how a JTAG-equipped board would respond.  Besides talking to devices to control / monitor pin states, JTAG is also used for debugging (breakpoints, single-step), downloading firmware to a target board (the faster, the better), and logging execution sequences of the target for timing analysis.

PRU:  Information on the TI websites and others describing what it is.  How to program it (in assembler), how to load programs into the PRUs on the BBB, how to communicate between the PRUs and ARM processes?  JJ2BAILE had a working demo including Device Tree overlays - a means of mapping hardware resources (pins) to SoC chip functions (registers).  I had to learn a bit about DTs and how to use them on the BBB properly.

vrings:  KA6SOX and PANTO talked about 'vrings' (virtual I/O) for the communication - I could find very little about that online, except in connection with Virtual Machines and that didn't quite fit how they were talking about vrings.  It soon became clear that vrings were an in-memory FIFO list of memory buffers, written by one program and read by another - obviously it would be very fast to exchange information between processes that way.  To communication bi-directionally would need two vrings.  On the Sitara, each of the PRU processors had their own data and instruction memory, some memory shared between the two of them, and they could access the DRAM memory used by the ARM processor.  So one end of the vring would be written by ARM Linux-side code, the other end read by PRU code.

I imagined two serial channels, one in each direction (ARM->PRU, PRU->ARM) and the need to have some kind of structure - rules for communicating, also known as a protocol - for the communications on them.  The first to come to mind was a raw bitstream - a succession of bytes corresponding directly to JTAG pin settings.  Each byte (presumably originated from OpenOCD) would be ultimately copied to the JTAG pins as it arrived.  Any responses received from the target as a result of the pins changing state could be similar transferred (also as a bitstream) back to OpenOCD.  There are lots of problems with this approach, topmost among them how to control timing - almost always a critical factor when communication with electronic devices.  Another - how to identify (on the incoming bitstream) which responses corresponded with which of the commands on the output bitstream)?

So I'd learned something about OpenOCD, and had to figure out how to write software that would interact with 'vrings'.  Were they Linux devices, or what?  How to use them?

The answers would have to wait until getting the Linux and development tools going on the BBB, when I knew more to ask intelligent questions.


Linux and the BeagleBone Black

I set up a spare computer with the latest Ubuntu as a host development system, and used it and a Windows computer and the tutorials on the BeagleBone Black website to:

  • boot the saved Angstrom Linux on the BBB
  • on Windows - learned how to connect to BBB terminal windows using serial USB (with putty) and the RNDIS network connection (with putty ssh), it was trivially easy as the USB device drivers were automatically installed when the BBB starts, and power to the BBB came from the USB connection itself
  • on Linux - well, hard to find out how to do what - on Windows - was trivially easy.  That would come later
  • no SD card came with my BBB and I knew if the saved image got corrupted - the BBB would be dead to me!  So I got a few 8 Gb micro-SD memory cards and, using Windows, learned how to use the Image Writer utility to format an SD card properly and copy an Angstrom distribution onto it.
  • now I could boot from two Linux devices on the BBB - the eMMC (Flash Memory) device, and the SD card.
  • I tried using bonescript and the gpiodemo suggested on the tutorials, and did get some pins toggling as a binary counter - and could see them on my new OpenBench Logic Sniffer and Windows OpenBench Logic Sniffer software - success!
But after booting the BBB a few times from the SD card, I could not connect anymore - there was no more RNDIS network driver connected.  The RNDIS network driver failed to recognize the BBB when I booted it from the SD card image.  Did I corrupt the kernel, a driver, the file system?

I would have to monitor the boot process with a serial terminal - but the putty connection to the USB serial device to the BBB showed nothing because it didn't start working until the boot was complete.  Unless booting from the eMMC flash memory, but that was no help to debug the other problem.

So I ordered an FTDI USB serial 3.3v cable from Digikey (768-1015-ND, it took a few days to arrive) and connected it to the J1 header on the BBB.  Now I had a reliable way to monitor the real serial console, to see the u-boot output and everything.  And, it became easier to use Linux to interact with the BBB.

So what had happened?  I think, nothing.  It was just that, somehow with the SD card as boot device, Windows XP, the BBB drivers, and BBB were - unreliable.  Out of 10 times booting the BBB, the RNDIS driver appeared in Hardware Manager only a few times.  Booting from the eMMC boot device always worked.

I had learned what I could on Windows, now it was mandatory to switch to Linux development on Ubuntu - because I had learned from KA6SOX and PANTO that a special Linux kernel would have to be built from source code.


   COMING SOON
   Next article:  Notes on tackling an Open Source Beaglebone Black Project, Part 2


Links

BeagleBone Black
TI PRUSS - Programmable Realtime Unit Subsystem
TI AM33XX PRUSSv2
TI Programmable Real-time Unit - Extending Functionality of Existing SoCs
CPLD - Complex programmable logic device
JTAG IEEE 1149.1 Standard Test Access Port and Boundary-Scan Architecture
OpenOCD Project
BlackMagic JTAG Probe Project
OpenJTAG Project
 goJTAG
TI Stellaris Launchpad EK-LM4F120XL
Arduino Open-Source Hardware Platform

Tuesday, November 10, 2009

Simple Localization in SQL Server with a Formula field

This little trick works for an application supporting a few languages (English, Spanish, French), although it won't scale much further.

A SQL Server database table MyTable requires a Description field, but an English, Spanish, and French translation need to be stored in the record and (hopefully) retrieved transparently.  Three fields are created: EN_Description, SP_Description, FR_Description.  A fourth field Language holds one of three values ('EN','SP','FR').

A user-defined function is created:

CREATE FUNCTION dbo.udf_LanguageDependantValue
    (
    @language varchar(2),
             @EN_value varchar(100),
             @SP_value varchar(100),
             @FR_value varchar(100)
    )
RETURNS varchar(100)
AS
BEGIN
    DECLARE @result varchar(100)

    SET @result = 'Unassigned'
   
    IF @language = 'EN'
        SET @result = @EN_value
    IF @language = 'SP'
        SET @result = @SP_value
    IF @language = 'FR'
        SET @result = @FR_value

    RETURN @result
END

Back in the table definition, a final field Description is created, with the Formula:

([dbo].[udf_LanguageDependantValue]([Language], [EN_Description], [SP_Description], [FR_Description]))

Now use a standard SELECT statement and SQL Server automatically retrieves the correct language field:

SELECT Description FROM MyTable

Thursday, November 5, 2009

ASP.NET runtime error: ambiguous match found

The solution to this turned out to be far from obvious, and once again posts by other bloggers came to the rescue.

(If you want the executive summary: it was due to variables defined with different cases.)

I just converted a .NET web project to a VS2008 web application, also changing the .NET Framework used (both in the Project, and the IIS website) from 1.1 to 2.0. The conversion went quite smoothly using the VS Convert To Web Application wizard, but one page had the problem below. Other pages using the exact same control and TagPrefix line compiled and worked without complaint.

Parser Error

Description: An error occurred during the parsing of a resource required to service this request. Please review the following specific parse error details and modify your source file appropriately.

Parser Error Message: Ambiguous match found.

Source Error:



Line 1:  <%@ Register TagPrefix="axp" Namespace="Axezz.WebControls" Assembly="AxpDBNet" %>
Line 2:  <%@ Register TagPrefix="cr" Namespace="CrystalDecisions.Web" Assembly="CrystalDecisions.Web, Version=11.0.3300.0, Culture=neutral, PublicKeyToken=692fbea5521e1304" %>
Line 3:  <%@ Page language="c#" Codebehind="UpdateEventQueue.aspx.cs" AutoEventWireup="false" Inherits="CANBTV.UpdateEventQueue" %>

Source File: /CANBTV_3_0_0/UpdateEventQueue.aspx    Line: 1



Version Information: Microsoft .NET Framework Version:2.0.50727.3603; ASP.NET Version:2.0.50727.3082

There were no errors reported by Visual Studio.

Not finding anything wrong in the code, I exchanged the positions of Line 1 and Line 2 ... the warning remained on Line 1, it did not follow the Axezz.WebControls line. So it isn't about the TagPrefix lines themselves, but something else.

Due to changes in customer requirements, some lines had been removed from the .aspx and the aspx.cs source files, but those did not seem to be implicated and the HTML tags were still balanced and well-formed.

I did have some trouble with the Designer ("Error creating control: Unknown server tag 'axp:AxpDataGrid'). Removing the TagPrefix line completely changed the error message shown where the control should be ("This control cannot be displayed because its tag prefix is not registered in this web form") - makes sense - so I put back the TagPrefix line, the error message returned to the "unknown server tag" one.

What? Is this a problem with the TagPrefix line, third party controls, or as Peter Johnson's Blog implies, variable naming problems - use of inconsistent case? I started looking at the latter, but there were so many ... the first dozen or so variables were okay, I got tired of looking at more ...

Curious about the difference between a functioning page and this one, I right-clicked on the .aspx in VS and chose View in Component Designer almost at random ... it wouldn't open, a half dozen messages errors were listed of the type: The variable 'x' is either undeclared or was never assigned. Hmm.

Then in File Explorer, I noticed there was no .designer.cs file for this .aspx. The original pre-conversion website didn't have any .designer.cs files at all, I guess VS.NET didn't use them (used .aspx.resx files instead?)

I found this post by Jan Schrueder (Create a missing designer.cs file) - open the .ASPX in HTML mode, CTRL+A, CTRL+K, CTRL+F (select all and format), then it said to right-click the Project and then Convert to Web Application. I had already done that, so I just selected the offending .aspx file only and ran Convert to Web Application.

Voila! a message box reported that, indeed, one of my variables had a different case in the .aspx vs the .aspx.cs. It wasn't one of the ones reported, in the Component Designer error messages either.

It transpired that there were three such variable conflicts in the .aspx.cs file, like this:

        protected System.Web.UI.WebControls.DropDownList Dropdownlist_ProgramTypes;
        protected System.Web.UI.WebControls.DropDownList DropDownList_ProgramTypes;

the .aspx controls used the capitalized names DropDownList_... so I removed the Dropdownlist_ protected variables until the Convert to Web Application succeeded.

There was still no .designer.cs file, but I built and ran the web app anyway ... now it worked like a charm.

By the way, the VS Designer still showed the error messages Error creating control: Unknown server tag 'axp:AxpDataGrid' over the control until I closed that file and re-opened it in the Designer ... then the controls looked correct.

And the .designer.cs file never did show up, that .aspx still uses a .aspx.resx file instead.


I just came across Hariman Haghighi's blog where he points out how to configure a custom task to add to your project, to catch .Ambiguous problems at compile time.  I don't know if it would have helped me - but it might help you!

Mike