ArduSat XRAMFS Prototyping

It is not every day that I get to tell the family I’m doing “rocket science”, but I hope over the past few days, it can be an exception. Space, the final frontier. In this case, it was a lack of space and the frontier it creates, that got me thinking.

At the recent Linux Conf AU Jon Oxer spoke about Freetronics’ efforts in designing the payload for the upcoming NanoSatisfi ArduSat1 launch (pictured below). Jon mentioned in the presentation that the AVR freeRTOS code compilation that I’ve been supporting is being used in the Supervisor node of that platform.

Ardusat_payload_freetronics

I immediately thought that it would be great to build a distributed cache RAM system to support each of the ATmega328p “Arduino” Client nodes, using the XRAM capabilities of the ATmega2561 Supervisor node. So, I did.

P1030071
P1030068

Using this prototype system, each Arduino Client node now has sole access to 32kByte of XRAMFS in addition to their 2kByte of internal RAM.

Initial performance measured is 422kByte/s throughput for the swap function. In other words, half of the entire Arduino RAM can be swapped with the contents of XRAMFS in just 4.74ms.

I’ve also the code for supporting a centralised SD Card on this platform to Sourceforge AVRfreeRTOS, and written about it at ArduSat SD Card Prototyping.

Background

In working with the Arduino hardware I’ve found that the severe limitation in RAM space causes constraints on what can be done. For example, Ethernet, USB and other modern applications need kBytes of buffer to be used effectively, and the ATmega328p used as the Arduino Uno platform supports a total of only 2kB RAM.

Using the Arduino Mega (or Android ADK hardware) has been the saviour of that situation for me, offering an identical environment, but 8kByte of RAM as a playground. And, most importantly, the ability to directly connect 0 wait-state external SRAM.

This XRAM capability of the ATmega2560 and ATmega2561 has been exploited by Rugged Circuits in their QuadRam module, which offers 512kByte of SRAM in one small package.

P1030069

Therefore, using common off the shelf technology, I had the materials available to test the theory that building a XRAMFS system, to support the ArduSat platform, would work.

This allows each ArduSat Client to store 16 TIMES more data than it can currently access, and have access to that data at a relatively high speed from a medium not subject to wear (such as for example an SD card).

Ingredients & Build

This section looks at the ingredients and how to construct the prototype.

Supervisor Node – Arduino Mega / Freetronics EtherMega / Android ADK

The ArduSat Supervisor node is based on the ATmega2561 MCU, because it is significantly smaller than the ATmega2560 MCU used in the Arduino Mega platform. The only difference between the two chips is that the ATmega2561 doesn’t provide as many Ports, and has only 64 Pins versus 100 Pins on the ATmega2560.

P1030070

For this prototyping, the ATmega2560 is necessary, because I elected to use pin change interrupts as part of the bus protocol. Also, the Arduino Mega platform is readily available. I don’t even know where I’d go to get a ATmega2561 board…

The use of rainbow hook-up wire was essential for the success of the prototype.

Client Node – Arduino Uno / Freetronics Eleven

The ArduSat Client node is designed to be identical to the Arduino Uno platform, to ensure that it is absolutely easy for people to test code they intend to run in space. Therefore a variety of Arduino Uno devices are being used (basically, whatever I had around).

XRAM Module – Rugged Circuits QuadRAM

I’ve implemented using the Rugged Circuits QuadRAM and the MegaRAM previously. These modules slip over the end of the Arduino Mega platform, instantly enabling either 512kByte or 128kByte of zero wait state SRAM, mapped to the system address space. They also conveniently bring out the SPI interface onto through-hole for pins.

Ad200

Something about the ability to create 16x 32kByte XRAM pages, linked with 16x Client nodes, seemed like synchronicity.

Layout

The prototype platform is designed to be the classic multi-slave SPI bus layout. This design is demonstrated in the AVR151 document and, in excerpt, is produced below.

Spi_wiring

Because of my decision to use the Pin Change Interrupts as part of the bus protocol, The Supervisor node (SPI Master) would use the Port K and Port J pins to fill the role of individual Slave Select (SS) pins. The Client nodes would each use their normal SS pin (PB2) to connect to the Supervisor.

In designing for 16x Client nodes, there is a limitation on Port J in that the good folks at Arduino determined not to break out all of the pins which, together with sharing PCINT8 with the Rx0 pin, significantly limits the number of Clients feasible on the prototype platform.

In practice, 8 Client nodes attached to all the pins on Pork K is the simple alternative. As luck (or good planning) would have it, those pins are all brought out onto one connector on the Arduino Mega platform, as evidenced by these pictures.

Amongst friends, a direct connection of the SPI SCK, MISO, and MOSI lines to all Clients is optimal. But in a shared environment, it would make sense to use FET bus isolation to keep Clients from physically attaching to the SPI bus until their SS line is held low by the Supervisor. A gram of hardware prevention can cure a tonne of software ill, as a “rogue” Client could otherwise potentially lock up the SPI bus for all, and the guys in the ISS won’t be happy if asked to hit the reset button.

Bus Protocol

Hey! – Yeah What? – This! – OK

That’s the protocol. Works in the home. Works in the office. Works the world over.

Read_overviewRead_middleviewRead_detail

Information to this Saleae Logic chart below in Client Implementation section.

Hey!

The Supervisor node holds all the PCINT pins high. If a Client wants to initiate a Read/Write/Swap transaction, it will pull its SS line low for 30µs. This needs to be long enough for the Supervisor to register an interrupt and process it. If multiple Clients call out simultaneously, no problem, the Supervisor will grab all of the requests and push them onto a queue of requests to serve.

Yeah What?

At the next opportunity, the Supervisor serving task will pop a request off the queue, and identify which Client made the request. It will also check if there were other simultaneous requests, and push them back to the front of the queue.

The Supervisor then pulls the relevant Client SS line low. The Client has been listening for this, and at this point it enables its Slave interface to the SPI bus, and the two swap acknowledgements. When the Supervisor receives the ACK code, it knows the Client is ready, so it requests a command.

This!

When the Client (SPI Slave) has received the Supervisor ACK code, it prepares a command, and is prepared to either read, write or swap XRAMFS data under the command of the Supervisor (SPI Master).

The command set implemented by this protocol can be easily extended to include accessing other shared resources connected to the Supervisor node. This could include analogue sensors, SDCARD mass storage (though using the SPI bus would offer a degree of complexity), or serial interfaced devices.

OK

At the end of one command, with the data transaction complete, a final byte is exchanged to ensure that the Client has remained in sync with the Supervisor, and the SPI bus is released by the Client. It is important the Client stays off the SPI bus. The Supervisor then processes the next Yeah What? request.

Supervisor Implementation – freeRTOS

The Supervisor is implemented as a freeRTOS task, using standard SPI bus libraries contained in my code base. These libraries (now that this project has worked them over) are about as optimised as is possible to write in C, and achieve a good throughput over the SPI bus.

There are two (or one) PCINT based Interrupt that reads the PCINT pins and pushes the raw pin state onto a queue. This process traps multiple simultaneous requests, overcoming any interrupt masking or race conditions. Currently 30µs are allowed for the interrupts to execute. 10µs has been tested, but depending on how long the Supervisor stays in “Critical” state (interrupts off) processing other (non XRAMFS) tasks this time can be adjusted.

From idle, the Supervisor takes only 90µs to 0.1ms to pop a request from the queue and action it. Under load, it could take as long as 64ms to action a request. As soon as the pin state is collected it is processed to identify which SS line triggered the call, and therefore which bank of XRAM should be enabled. Also, at this time I check that no additional requests are pending from the same pin state. If so, the remaining pin state is pushed back on the queue to get next time round.

The exchange of acknowledgements ensures that both sides are speaking SPI, and are set to proceed.

The command contains the action (read / write / swap / test), the address of the XRAMFS block, the size of the XRAMFS block, and a CRC byte.

The bus transaction speed is dependent on the SPI Master SCK clock divisor. Optimally, a SPI Slave can receive data at 1/4th of its system clock. Currently, it is set to one 1/8th, therefore theoretical performance is double that of the logic capture above.

Initially, I determined to calculate a CRC byte to store along with the data, but the calculation time is large compared to the transaction time, and therefore too costly to implement at the protocol level. The application should utilise the CRC when it recovers data to confirm that the data is intact, and not irradiated.

Also, error checking following the transfer could be implemented. But at this stage I think it is better to have the Client do all sanity and error checking of its own data.

Client Implementation – freeRTOS or Arduino IDE

The Client is implemented in freeRTOS as a simple library function, that is passed a command structure, and a pointer to local RAM to be Read/Write/Swap. Some details below.

typedef enum { Huh        = 0, // Client didn't issue us a command, so just break.
               Read       = 1, // read from XRAMFS
               Write      = 2, // write to XRAMFS
               Swap       = 3, // read from both XRAMFS & local RAM, and swap
               Test       = 4  // do something else, to be determined
} RAMFSCommand; // from point of view of the client (Arduino 328p)

typedef struct        /* structure to hold the RAMFS info */
{ RAMFSCommand       ram_cmd;        // Read / Write / Swap / Test
  size_t             ram_addr;       // Address of first byte of RAM in a RAMFS (greater than RAM_START_ADDR)
  uint16_t           ram_size;       // Size of RAM block in RAMFS (less than RAM_COUNT or 32kByte)
  uint8_t            ram_crc8;       // Calculated CRC of stored data
} xRAMFSarray, * pRAMFSarray;

uint8_t ramfs_transfer_block( pRAMFSarray pRAMFS_block, uint8_t *data );

I used C and the freeRTOS platform because it is easiest for my environment, and I know it best. But, I’ll re-write it as a library in the Arduino IDE environment as needed. It won’t be too hard.

The client can use the XRAMFS malloc function to manage RAM allocation. A very simple malloc has been built, which can’t free XRAMFS. But, it can be simply ignored if desired and the command structure can be filled manually.

Initially, I implemented an interrupt driven semaphore system to manage the Yeah What? part of the bus protocol, but typically the Supervisor responds so quickly that the time to do several context swaps generated by the interrupt exceeded the time the Supervisor was prepared to wait. A simple wait loop keeps the Client on ready standby for 90µs so it can complete the transaction in the shortest time.

The Client code has no knowledge of where its XRAM is located on the Supervisor. Therefore the code is orthogonal and constant, irrespective which Client being used. This is a very useful feature where the author may not know in advance which ArduSat Client his code will be running upon.

Client application code should be written to make use of the Swap XRAMFS <-> RAM capability. This makes best use of the SPI bus features to combine Read and Write into one transaction, effectively doubling throughput over the Write plus Read combination.

The user interface (monitor) is just for initial testing. I’ll have to write a load generation rig to find out what this baby can do, but that can wait for the next post. The logic analyser has captured the result of the > r (read) command in the below command line sequence. We can see the 20µs (now 30µs) Hey! on the Slave Select, 90µs pass before the acknowledgement bytes are swapped (only one cycle needed), 6 bytes of command structure are passed (Read command is 0x01), and then the data is read out of XRAMFS to the Client.

Terminal

Design Notes

The basis of every design: detailed functional specifications, hardware design, and user interface documentation. Oh, and scribbles much.

P1030072

Updates

I’ve updated the code on 22 February to remove some oversights in the Client main program, and added the OK check byte to the protocol. Code as usual on AVRfreeRTOS on Sourceforge.

Updated on 23 February to include some error checking on Supervisor side (preventing malicious Client requests), and on Client side preventing hang if the Supervisor is AWOL. Also removed the aggressive SPI timing utilising receive double buffering, as it often caused errors, and had no performance effect.

Initial performance measured is about 422kByte/s throughput for the swap function. Specifically 4.73825ms is needed for a complete 2048Byte data payload transaction (including sync, command, & OK timing). This also includes freeRTOS task swapping, as the Supervisor task is run with interrupts enabled in normal mode.

Have fixed some code issues on 4 March, mainly around a few µs delays required to let things run their course.

Now the platform is running stable with 4x Clients. A video is here

And here is a screenshot of the 4x terminals.

4xXRAMFS Client Monitors Screenshot

April 27th – I’ve uploaded the code for supporting a centralised SD Card on this platform to Sourceforge AVRfreeRTOS, and written about it at ArduSat SD Card Prototyping.

Melding freeRTOS with ChaN’s FatF & HD44780 LCD on Freetronics EtherMega

This post is a bit of a mixed bag, describing some software and hardware integration, together with some raving about a great tool I’ve been using. So, let’s get started.

Platform

Some time ago I got a Freetronics EtherMega, which is essentially an Arduino Mega2560 with an integrated Wiznet W5100 Ethernet interface, and a MicroSD card cage. I’ve introduced this product and the use of freeRTOS here.

EtherMega (Arduino Mega 2560) and freeRTOS

One great thing about the ATmega2560 used in the EtherMega, and the Arduino Mega2560, is the availability of an external memory bus. I’ve been using a Rugged Circuits QuadRAM, and now have ordered three more of their MegaRAM devices, and intend to make the ATmega2560 my standard platform. Why three? Well everyone knows that good things come in threes.

QuadRAM (512kByte) on Freetronics EtherMega (Arduino) ATmega2560 with freeRTOS

I’m actually preferring the Rugged Circuits MegaRAM which has only 128kBytes of RAM, so it won’t be as flexible for bank switching as its big brother. Also its chip select line is reversed (note to self to fix this in the driver). But, simply having 64kBytes of normal extended RAM plus another 56kBytes of special purpose (bank switched) RAM seems like it wil be sufficient for the duration. I’ve bought a couple to go on some Android ADK devices, that I’ll write about soon.

Recently, I also acquired a Freetronics 16×2 LCD-keypad-shield to use as a drop-on display for debugging and status, and anything really. It works really nicely and with its single pin switch analogue interface (which will be useful for navigation). Unfortunately there is a conflict between the SD Card device select pin on the EtherMega (Arduino pin D4) and one of the data pins on the 16×2 LCD.

My rectification of this pin usage conflict can be seen on the pictures below, where the yellow wire joins Pin D4 to Pin D2. What can’t be seen is that the leg of Pin D4 has been cut off, so it doesn’t insert into the EtherMega, so there is no elecrical connection between the D4 pin on the 16×2 LCD, and the D4 Pin used on the EtherMega.

P1010882P1010884P1010883P1010886

Tools

Recently I purchased a Saleae Logic to use in developing. I have got to say that this is probably the best $149 that I have spent on any tool, ever. Having the ability to capture long periods (minutes) of data, with 24MHz resolution, and zoom, shrink, drag, flick around in it, and also compare many windows of alternative samples is just so great. It saves so much time being able to simply “see” what the device is actually doing on the SPI, I2C and serial ports, simultaneously, is well great. But I already said that.

P1010781

Software – FatF File System

As usual, the code is on AVRfreeRTOS on Sourceforge.

My main work was to put the existing ChaN’s FatFs Generic FAT File System Module v0.9 into my existing ATmega2560 freeRTOS system, using my existing libraries, and generally being fully integrated into the system, as a plaform for some further work.

This was fairly time consuming (until I got my Saleae Logic), because the SPI bus transfers required to initiate and drive a SD card are complex, and depend on which version of SD card (MMC, SD, HDSD) is being used.

Now that everything is working, I’ve also done some SPI optimisation, to speed up multi-byte SPI bus transfers used for reading and writing to the SD card.

In testing with a Freetronics EtherMega driving an 4GByte HDSD card the system achieved the following results.

  • Byte transfer cycle time: MOSI 3.750us, MISO 3.6250us
  • Multibyte transfer cycle time: MOSI 1.3333us, MISO 1.3750us
  • Gross Performance increase: MOSI 2.8x, MISO 2.64x

Measured performance for a multi-MegaByte file copy is about 140kBytes/s which includes both read and write operations to the same SD card.

Software – HD44780 LCD

As usual, the code is on AVRfreeRTOS on Sourceforge.

Also, as I had purchased a 16×2 LCD display and I wanted to implement a flexible solution for display, I also ported the Control Module for HD44780 Character LCD into my system.

This was pretty straightforward, once I’d recognised the pin confict issue between the two Freetronics devices, and perhaps the most interesting things to say are:

  • Using a macro to control the pin assignment means that it is very easy to change the pins used for any display type. Simply renumber them in the macro and it is done.
  • Also, using the standard avr-libc stdio utility vsprintf formatting allows me to choose how much library I want to bring in. The standard library doesn’t support float formatting, but with a simple link switch either a simpler (smaller) or more fully featured (larger) standard library can be included. I also use the standard avr-libc tools for the serial port, so there is no additional overhead specifically for the LCD.

Wiznet W5100

Now I’ve finished the W5100 drivers from Wiznet, incorporating their new v1.6 changes (because they screwed up the silicon ARP state machine). And also, a fix for a subtle bug caused
by writing to the W5100 Tx buffer before it was finished with a previous transmission. This was fixed by checking the Tx read pointer and comparing it with the Tx write pointer. When the chip is idle, they are the same. That took me 3 weeks to isolate.

Now the fun part starts, which will be to re-learn the IP protocol suites, through re-implementing some of the standard network tools, like HTTP, FTP, NTP, DHCP, DNS, that we just take for granted. DHCP is done. Ping is done. HTTP is done.

Here is a web server running on this platform.

EtherMega server

QuadRAM (512kByte) on Freetronics EtherMega (Arduino) ATmega2560 with freeRTOS

I’ve been spending some time integrating the Rugged Circuits QuadRAM extension for the Arduino Mega (or Freetronics EtherMega) into the freeRTOS environment. And, it is now my standard environment. Actually, the MegaRAM, a slightly cheaper 128kByte version is my standard, as I’ve not found an application yet that needs more than 64kBytes total RAM. But, that will happen.

QuadRAM is available from Rugged Circuits again, after a long intermission.

Without adding any complexity into the environment, I can address up to 56kBytes of heap variables, effectively leaving the entire 8kbyte of internal RAM for the stack. With no complexity or overhead.

In addition, with some simple commands within a task can implement bank switching to access up to 7 additional banks of RAM, each up to 56kBytes.

A further degree of integration into freeRTOS is to completely automate memory bank switching, to give each of either 7 or 15 tasks a bank of RAM for its exclusive use. But this is a goal for the next few months.

Here are some pictures.

P1010781P1010782P1010783

And here are the links to the products described.

Rugged Circuits QuadRAM

amzn_assoc_ad_type = “smart”;
amzn_assoc_ad_mode = “search”;
amzn_assoc_tracking_id = “feilipu04-20”;
amzn_assoc_title = “Shop Related Products”;
amzn_assoc_default_category = “All”;
amzn_assoc_search_bar = “true”;
amzn_assoc_search_bar_position = “bottom”;
amzn_assoc_default_search_phrase = “arduino”;
amzn_assoc_marketplace = “amazon”;
amzn_assoc_placement = “adunit0”;
amzn_assoc_region = “US”;

//ws-na.amazon-adsystem.com/widgets/onejs?acw=true&MarketPlace=US

I’m very happy with my Saleae Logic too. Must write a review on this, one day. Great tool, more useful every day.

The described code is all available on Sourceforge, if you’re intending to try this at home.

The only finished example using the memory routines is the MegaSD project. Take a look at it on Sourceforge to see how to use the extra RAM.

HOW TO

What do we have to do to get this build working? Well it is pretty simple really, once everything is figured out. It is really only three steps.

  1. Initialise the RAM, and tell the AVR that it should enable its extended RAM bus.
  2. Tell the compiler that you’re moving the heap into the new extended RAM address space.
  3. Tell freeRTOS to move its heap to the new extended RAM address space.

Initialise the RAM

The RAM should be initialised prior to building the standard C environment that comes along for the ride. It can be done in the .init1 (using assembler) or in .init3 in C. I built both methods, but elected to just use the C method, as it is more maintainable (legible).

There are a number of references for this code. Some of the older ones refer incorrectly to a MCUCR register. That is not correct for the ATmega2560.

This example covers what Rugged Circuits suggest for their testing of the QuadRAM, but it doesn’t put the initialisation into .init3, which is needed to make the initialisation before heap is assigned. It makes the initialisation carefree.

// put this C code into .init3 (assembler could go into .init1)
void extRAMinit (void) __attribute__ ((used, naked, section (".init3")));
void extRAMinit (void)
{
// Bits PL7, PL6, PL5 select the bank
// We're assuming with this initialisation we want to have 8 banks of 56kByte (+ 8kByte inbuilt unbanked)
DDRL  |= 0xE0;
PORTL &= ~0xE0;  // Select bank 0
// PD7 is RAM chip enable, active low. Enable it now.
DDRD |= _BV(PD7);
PORTD &= ~_BV(PD7);
// Enable XMEM interface
XMCRA = _BV(SRE); // Set the SRE bit, to enable the interface
XMCRB = 0x00;

To ensure that this .init3 function, that I’ve put into lib_ext_ram, is included in your linked code, we need to call something from the lib_ext_ram library. If you’re planning to use the banks of RAM, then this is easy as you’ll naturally be calling the bank switching functions.

However, if you only want to use the extra 56kByte of RAM for simplicity (it is after all 7x more than you have available with just the internal RAM), then just call this function once from somewhere, possibly main(). I have added it to the freeRTOS stack initialisation function in port.c, so I don’t need to see it ever again.

extRAMcheck();

It returns the XMCRA value, that can be tested if you desire. But there’s no need as things will anyway have gone badly pear shaped if the RAM is not properly enabled. Calling this once is all that is needed to ensure that the .init3 code is properly inserted into the linked code.

Note: that the above code is specific to the QuadRAM device. The MegaRAM device has different IO in use, and the differences are noted in my code on Sourceforge.

Move the heap

The standard C heap has to be moved to the new location above the stack. There are other memory allocation options, but in my opinion this is the most sensible one and the only one I’m planning to implement.

The __heap_start and __heap_end symbols describe the addresses occupied by the extended RAM, and inform malloc() of the location of the heap. This is described in more detail here http://www.nongnu.org/avr-libc/user-manual/malloc.html. This is a great diagram showing the situation.

Malloc-x2
avr-gcc -Wl,-Map,MegaSDTest.map -Wl,--gc-sections -Wl,--section-start=.ext_ram_heap=0x802200  -Wl,--defsym=__heap_start=0x802200,--defsym=__heap_end=0x80ffff -mmcu=atmega2560 -o "MegaSDTest.elf" $(OBJS) $(USER_OBJS) $(LIBS)

Tell freeRTOS

Now freeRTOS has to be made aware of these changes to the heap location. There are three heap management options available for the AVR port. The two most memory economical options use a fixed array of memory defined in the .data section on initialisation. Clearly, this is not going to be useful. For the third option heap_3.c, which uses malloc(), we have nothing more to do.

However, getting heap_1.c and/or heap_2.c to work is not that complicated either. There are three parts to this. Firstly, creating a new section name, and locating it at the start of the desired heap space. We’ve already done that, above, with the –section-start command. The forth option heap_4.c has also been implemented.

Secondly, we have to make a small modification to both heap_1.c heap_2.c and heap_4.c to inform the compiler that the freeRTOS heap will be located at this .ext_ram_heap location. That is done in this manner (heap_2.c shown).

static union xRTOS_HEAP
{
//... edited ...
unsigned char ucHeap[ configTOTAL_HEAP_SIZE ];
//... edited ...
#if defined(portEXT_RAM)
} xHeap  __attribute__((section(".ext_ram_heap"))); // Added this section to get heap to go to the ext memory.
#else
} xHeap;
#endif

And finally, now we’ve (probably, just because we can) allocated a large (up to 32kByte maximum) freeRTOS heap, we need to ensure that the loader omits this section from its preparations for writing the .hex file to flash (in a similar manner to the way the .eeprom section is removed).

avr-objcopy --remove-section=.eeprom --remove-section=.ext_ram_heap -O ihex MegaSDTest.elf  "MegaSDTest.hex"

Something to watch for is that none of your other code is calling malloc(), because if it does its memory allocations will collide with the freeRTOS heap. Either check that malloc() is not being linked in or, for the paranoid, just assign the heap_1.c heap_2.c or heap_4.c heap to a region separate to your new malloc() heap addresses.

And that’s all there is to getting an easy 512kByte of fast no-wait-state RAM on your Freetronics EtherMega or Arduino Mega2560. Enjoy!

EtherMega (Arduino Mega 2560) and freeRTOS

This is an unboxing and porting review of the Freetronics EtherMega.

Ethermega-production-sample-2_large

It is an Arduino Mega 2560 compatible product, with the added goodness of a Wiznet W5100 Ethernet module and a MicroSD card cage on board.

http://www.freetronics.com/products/ethermega-arduino-mega-2560-compatible-with-onboard-ethernet

Obviously, my first job is to port the freeRTOS code to run on the EtherMega ATmega2560 microcontroller. There are some things about the ATmega2560 that are different from other ATmega devices, making it necessary to modify the standard freeRTOS code for it to work correctly. But the main difference is that because of the size of its flash memory, it has a 3 byte program counter (rather than 2 byte in every other ATmega device).

There are only a few references to making the ATmega2560 work. This reference is the most compelling guide.

http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=70387

Stu_San has proposed a port, and I have used it as an accurate guide to getting things running. There are some changes. freeRTOS has changed significantly with regard to how the port.c file is built. Also, I’ve already implemented options for Timer selection. So the resultant code on the Sourceforge AVRfreeRTOS Project is slightly different to what Stu_San proposed.

https://sourceforge.net/projects/avrfreertos/

The avr-linker script needs to have a small addition to support Stu_San’s suggestions. For the purposes of simplicity (only change a little as possible, to get things working), I’ve only included the .task tag into the avr6.x file, that will replace the normal avr-binutils file in /usr/lib/ldscripts

UPDATE: as of avrlibc 1.8.0 there is a .lowtext section in avr6.x included at the bottom of flash, which is exactly what we need for this outcome. Hence, in the port for freeRTOS800 I’ve converted from .task to use .lowtext, which means there is no need to change or modify the avr6.x file. It will just work automagically.

At this stage the EtherMega is nicely flashing its LED at me, which means that the scheduler and IO addressing using my digitalAnalogue tools are working correctly. But, I’m sure there are many things still to improve over the coming days and weeks.

Update – 25 January 2012

Corrected an error calculating the serial port baud rate. The (all) AVR data sheet has an error in it, that only exhibits at certain CPU frequencies. Unfortunately, I’ve normally only used Arduino and Freetronics kit over-clocked to 22.1184MHz, which provides perfect baud rates with no error. This CPU frequency does not exercise the faulty data sheet calculation, to generate errors.

WormFood’s AVR Baud Rate Calculator

The standard Arduino CPU frequency of 16MHz causes the serial port to run too slow by 3.7% at 115200 baud (well outside the recommended range of 2%), and more importantly the data sheet calculation chooses the wrong set up value for the UBRR value driving the baud clock, causing the serial port to become unworkable. The calculation method has been improved in the AVR <util/setbaud.h> file, and that calculation method is now used in my serial library. New code uploaded.

Update – 8 March 2012

Completed the ChaN FatF library port to freeRTOS for driving the microSD card. Supports both SD and HCSD. Code in usual place.

Update – 5 April 2012

Completed the Ethernet library port to freeRTOS for driving the Wiznet W5100. Supports TCP, UDP and Raw IP modes. Code in usual place.

The standard Arduino Mega stk500v2 bootloader used by default in the Freetronics EtherMega does not work when loading more than 64kB into flash. I’ve found a modified version by msproul that works, or at least does now that I’ve changed it a little more, to be found here.

freeRTOS and libraries for AVR ATmega with Eclipse IDE

I’ve created a Sourceforge project as a place to host all my current tools and working environment. The Sourceforge site is now 4 years old, and there’s a GitHub site too, which is now the most up to date repository

Preferred: Github freeRTOS & libraries for AVR ATMEGA

Secondary: Sourceforge freeRTOS & libraries for AVR ATMEGA

The Sourceforge repository has become so complex, with so many libraries, I thought that it was about time to make a simple version, which has the minimum implementation to get started. No additional libraries included. One timer option, using the watchdog timer. One heap option, using avr-libc malloc. One example application, just a blink with two tasks, for Uno, Mega, and Goldilocks boards.

Github minimum AVRfreeRTOS

The thing about open source. Sometime you have to give back.

Things I’m really happy about:

  • Arduino Uno family ATmega328p, Freetronics EtherMega (Arduino Mega2560), and Goldilocks ATmega1284p, scheduling and IO works.
  • Being able to use any Timer on the AVR as the system Tick. In practice this means Timer0 on 328p (Arduino Uno), Timer3 on 2560 (Arduino Mega) and 1284p (Pololu SVP) and Timer2 on 1284p with 32.768kHz watch crystal (Freetronics Goldilocks). The watchdog timer has also been implemented, and if there is no critical need for accurate timing, this is the lowest resource impact system tick.
  • Converting all of the relevant libraries to be friendly to a RTOS system. No delay busy-wait loops etc. Everything defers to (is interruptible by) the scheduler when waiting, or is driven from interrupts.
  • Having many finished projects, that are good demonstrations of lots of AVR and freeRTOS capabilities.
  • Having the Sparkfun LCD Shield working properly, with printf string formatting.
  • Having the Rugged Circuits QuadRAM 512kByte and MegaRAM 128kByte RAM extensions working on ATmega2560.
  • Porting ChaN FatF microSD card support for a variety of uSD shield cages.
  • Porting Wiznet W5100, W5200, and W5500 drivers for Arduino Ethernet shields.
  • Porting Wiznet and uIP DHCP and HTTP applications, creating options for implementing a basic web server.
  • Properly implementing semaphores for access to resources (ports, interfaces, ADC, LCD).
  • Properly implementing queues for transferring data between tasks (threads).

The repository of files on Sourceforge freeRTOS & libraries for AVR ATMEGA is a working collection for a freeRTOS based platform using the AVR-GCC and AVRDUDE platform. The development environment used was Eclipse IDE.

With the Eclipse IDE the C Development Environment (CDE), and the AVR plug-in are both needed. It is assumed that the AVR avr-libc libraries are installed.

The freeRTOS folder contains the most recent version 8.2.3 of freeRTOS, but it has been abridged down to only those files relevant for AVR GCC. The port.c file has been extensively modified to allow the use of either of the 328p Timer0 or Timer1 timers. And, the use of Timer3 on the Pololu SVP which has uses a 1284p. Timer 3 for Arduino Mega using a 2560 also works. Timer2 support has been added for the Freetronics Goldilocks and its 32,768kHz crystal. A Real Time system_tick is added using time.h functionality added to the system libraries described below.

The freeRTOSBoardDefs.h file contains most of the variables that you’ll need to change regularly.

There are some relevant and often used libraries added to the basic freeRTOS capabilities.

  • lib_io: contains often used I/O digital and ADC routines borrowed from Pololu.
  • lib_io: contains the tools to use the TWI (non-trademarked I2C) bus. It contains integrated interrupt driven master and slave routines
  • lib_io: contains the tools to use the SPI bus.
  • lib_io: contains routines to drive the serial interface. there are three versions; avrSerial for use before the freeRTOS scheduler has been enabled, and xSerial for use during normal operations. xSerial is interrupt driven and uses an optimised ring buffer. xSerialN is further generalised to allow multiple simultaneous serial ports.
  • lib_ext_ram: contains routines to drive the Rugged Circuits QuadRam on Arduino Mega2560, or Freetronics EtherMega.
  • lib_util: Optimised CRC calculations.
  • lib_util: Extended alpha (string) to integer (binary, octal, decimal, hexdecimal) conversion.
  • lib_time: Real time calculations, from avr-libc upstream, providing esoteric time and date calculations.
  • lib_rtc: drivers for the DS1307 RTC using I2C.
  • lib_fatf: contains ChaN’s FatF FAT32 libraries for driving the microSD card.
  • lib_iinchip: contains the W5100 drivers and the W5200 drivers from Wiznet.
  • lib_inet: contains a DHCP, and HTTP implementation.
  • lib-uIP: contains the uIP implementation derived from Contiki2.7, implemented on MACRAW mode of W5100/W5200, and extensible.
  • lib_ft800: contains optimised drivers for the Gameduino2, a FTDI FT800 implementation, with LCD and touch screen support.

Some more recent posts are here:

Arduino AVRfreeRTOS

Goldilocks Analogue Synthesiser

Goldilocks Analogue Prototyping 4

Melding freeRTOS with ChaN’s FatF & HD44780 LCD on Freetronics EtherMega

Rugged Circuits QuadRAM on Freetronics EtherMega

Quick review of Freetronics EtherMega

Description of the AVR Pong multi-processor game.

Additional steps to use the Mega2560

EtherMega (Arduino Mega2560) and FreeRTOS

I sell on Tindie

Step-by-step Instructions

Our Destination:

On completing these instructions you should have an Eclipse IDE (Integrated Development Environment) installed with all relevant libraries installed, to use the freeRTOS, and the libraries I’ve modified, to build projects (Eclipse term for a set of code) of your own.

We’re Assuming:

These instructions are based on an Ubuntu LTS install, but the path to the destination is not complex, and can be roughly followed for any installation platform.

Step 0. As usual on an Ubuntu (Debian) system, refresh the software sources.

sudo apt-get update

Step 1. Install the AVR Libraries.

Together, avr-binutils, avr-gcc, and avr-libc form the heart of the Free Software toolchain for the Atmel AVR microcontrollers. They are further accompanied by projects for in-system programming software (uisp, avrdude), simulation (simulavr) and debugging (avr-gdb, AVaRICE).
sudo aptitude install avr-libc avrdude binutils-avr gcc-avr gdb-avr

Step 2. Install the Arduino environment.

Doesn’t hurt to have the Arduino environment available. It can be used for programming boot-loaders (using AVR-ISP code), and generally for checking health of equipment, using known good example code.

This will pull in some extra libraries that the Arduino platform needs.

sudo aptitude install arduino

 

Step 3. Install the Eclipse IDE.

It is not necessary to use or install an IDE to develop with freeRTOS, or with any other system. It is easy to use makefiles and the command line with avr-gcc and avrdude. In fact, I didn’t use Eclipse for a long time. And, when I first started to use it, it felt very unnatural and clumsy.

However, now I’ve been using it for some time I highly recommend it, for the ability to see deeper into the code (definitions are detailed on mouse over), and to compare (live differences) and roll-back code to any step of your editing process.

Again, installation is easy with Ubuntu (Debian), but it can take a while. Lots of things get installed along with it.

sudo aptitude install eclipse

Step 4. Select the C & C++ development tools within Eclipse.

Eclipse is a Java based platform, but it works just as well with C, and C++, as it does with a wide variety of languages. Getting the C Development Tools (CDT) is the first step to a C environment that we’ll be using.

Open Eclipse, and lock it to your launcher. You’ll be using it frequently.

Using the Menus, click:

Help>>Install New Software…>>Add…

CDT Indigo http://download.eclipse.org/tools/cdt/releases/indigo

Select only “CDT Main Features”, and install these plugin development tools.

Step 5. Select the AVR development environment within Eclipse.

The AVR environment includes direct access to the avrdude downloading tool for one-click programming of your AVR devices.

Using the Menus, click:

Help>>Install New Software…>>Add…

AVR Plugin http://avr-eclipse.sourceforge.net/updatesite/

Select “CDT Optional Features”, and install these plugin development tools.

Step 5c. Select C/C++ Perspective

First you need to select the right perspective, being C/C++. Top right there is a button showing “Java”. Just to the left is a button (like a window) for selecting perspective. Select

Other…>>C/C++

When that is finished, you should have Eclipse menu button containing a AVR* with a green down arrow. That is the button used to program the device.

Step 6. Define a freeRTOS static library project.

There are lots of short cuts, and alternative ways to achieve things using context sensitive menus in Eclipse. I’ll concentrate on the top menu bar options, though you can get most things from a context menu click in the right window.

File>>New>>C Project: AVR Cross Target Static Library: Empty Project

A static library project is never run by itself. It is always linked to by other projects, called AVR Cross Target Applications.

Give the project a name (perhaps freeRTOS82x).

Now a project will apear in the “Project Explorer” window. Select it. We are going to set some options relating to this project.

Project>>Build Configurations>>Set Active>>Release

Project>>Properties

AVR:Target Hardware: MCU Type: ATmega328p (or other depending on hardware)

AVR:Target Hardware: MCU Clock Frequency: 16000000 (for Arduino hardware or other depending on your hardware)

C/C++ Build: Configuration: [All Configurations] (make sure this is set for all following configurations)

C/C++ Build: Environment: AVRTARGETFCPU: 16000000

C/C++ Build: Environment: AVRTARGETMCU: atmega328p

C/C++ Build: Settings: AVR Compiler: Optimisation: Other Optimisation Flags: -ffunction-sections -fdata-sections -mcall-prologues -mrelax (and use -Os or -O2)

Now we are going to add just the freeRTOS files, from the subdirectory within the freeRTOS82x_All_Files.zip file that you have downloaded from Sourceforge, and extracted somewhere sensible.

File>>Import…>>General:File System

Select the “into folder” as the project name you just created, and “Select All” for the import on the freeRTOS subdirectory. That should import the entire freeRTOS system. Spend some time browsing, if you like.

NOTE. Do NOT import the entire contents of the freeRTOS82x_All_Files.zip file. At this stage just import contents of the freeRTOS subdirectory.

Now we define the include library for the build. Remember to select [All Configurations] first.

Project>>Properties>>C/C++ Build>>Settings: AVR Compiler: Directories 

Add the from the “Workspace…”: freeRTOS82x/include

“${workspace_loc:/${ProjName}/include}”

Now there are fouralternative memory management routines, explained in the freeRTOS documentation. We are going to use the heap_2.c version, so we need to exclude the other three files from the build. In the project explorer RIGHT CLICK (context menu) each one then exclude them.

./MemMang/heap_1.c

./MemMang/heap_3.c

./MemMang/heap_4.c

Resource Configurations>>Exclude from Build…: Select All

Following this step, it should be possible to compile the library.

Project>>Build All

If there are any ERRORS, then go back and check the configurations for the project. Sometimes they may be changed, forgotten, or otherwise different from what you expected.

There will be some WARNINGS, relating to the usage of different Timers. I added these warnings to keep these things front of mind, as depending on which hardware I’m using the ./include/FreeRTOSBoardDefs.h file needs to be managed to suit.

Step 7. Define an Application Project.

An Application will generate the final hex code that you upload to the AVR with avrdude. This final code is created from the freeRTOS static library code generated above, together with code contained in the avr-libc, and any other linked projects.

We are going to import the UnoBlink or MegaBlink project as it makes a good example. Without a display, or real-time-clock module, it will only flash a LED. But, least we know it is alive.

To get started create a new project as below.

 File>>New>>C Project: AVR Cross Target Application: Empty Project

Give the project a name (perhaps MegaBlink or retrograde).

Now a project will appear in the “Project Explorer” window. Select it. We are going to set some options relating to this project.

Project>>Build Configurations>>Set Active>>Release

Project>>Properties

AVR:AVRDUDE:Programmer:New…

Configuration name: Arduino or Freetronics 2010

Programmer Hardware: Atmel STK500 Version 1.x firmware

Override default port: /dev/ttyUSB0 (FTDI USB) OR /dev/ttyACM0 (AVR USB)

Override default baudrate: as or if required.

AVR:Target Hardware: MCU Type: ATmega328p (or other depending on hardware)

AVR:Target Hardware: MCU Clock Frequency: 16000000 (or other depending on hardware)

C/C++ Build: Configuration: [All Configurations] (make sure this is set for all following configurations)

C/C++ Build: Environment: AVRTARGETFCPU: 16000000

C/C++ Build: Environment: AVRTARGETMCU: atmega328p

C/C++ Build: Settings: AVR Compiler: Directories: “${workspace_loc:/freeRTOS82x/include}”

C/C++ Build: Settings: AVR Compiler: Optimisation: Other Optimisation Flags: -mcall-prologues -mrelax (and use -Os or -O2)

C/C++ Build: Settings: AVR C Linker: General: Other Arguments -Wl,–gc-sections

C/C++ Build: Settings: AVR C Linker: Libraries: Add “m” without quotes. m is the standard math library, which should be included in most projects.

C/C++ Build: Settings: AVR C Linker: Objects: Other Objects Here you need to add the compiled freeRTOS library. And this is the only place where the Debug and Release builds are different.

With Release Build selected, paste “${workspace_loc:/freeRTOS82x/Release/libfreeRTOS82x.a}”

With Debug Build selected, paste “${workspace_loc:/freeRTOS82x/Debug/libfreeRTOS82x.a}”

Or select the Workspace option to navigate to the actual assembler files to be linked into the project.

Project References: freeRTOS82x ticked.

Now we are going to add the MegaBlink (or retrograde) files, from the MegaBlink.zip (or retrograde.zip) file that you have downloaded from sourceforge, and extracted somewhere sensible. If you downloaded the freeRTOSxxx_All_Files.zip, you have all the sources.

File>>Import…>>General:File System

Select the “into folder” as the project name you just created, and “Select All” for the import. That should import the 2 files shown inro the project file system. Spend some time browsing, if you like.

Following this step, it should be possible to compile and link the project.

Project>>Build All

If this step completes successfully, with no additional ERRORS, then the final step is to upload the new application into your Arduino or Freetronics device.

Make sure that you have your device plugged into the USB port, then simply hit the AVR* button in the row of buttons. You will see some green text showing the status of the upload, finishing with the words

avrdude done. Thank you.

Now, you should have a flashing LED.

Now you can import any additional projects, in the same way.

Step 8. Things to watch.

Turn on the serial port by removing the comments around the serial port definitions, and watch to see aspects of the program in action.

Expect to manage the amount of heap allocated in the ./include/FreeRTOSBoardDefs.h file, to ensure that the total SRAM utilised (as noted in the final linker stage when using heap_1.c, heap_2.c or heap_4.c) remains less than 100% or for ATmega328p 2048 bytes.

Expect to manage the amount of stack space allocated to each task during the set up, to ensure you’re not wasting space, nor (worse) you’re over writing another task’s stack.

For the Arduino Uno, keep the total number of tasks to below 4, otherwise too much SRAM is consumed in stack allocations.

Freetronics freeRTOS Retrograde Real Time Clock (DS1307) – Part 3 Final

In Part 2  I promised to build a very stylish finished product, that could be displayed with pride. Well, I don’t think I’ve quite achieved that. But, at least now I consider the project finished, and now have the confidence to get on with other projects.

I have mounted some tiny servos, the funky white on blue LCD display, and the Freetronics 2010 board on some Craftwood. Cutting the hole for the LCD was a bit hit & miss, using a carving knife to shape the hole, and managing not to loose any fingers in the process.

Dsc04060Dsc02851

The hour servo is mounted at the bottom of the board, and travels clockwise from midnight, with noon vertical, until it re-tours to 0 on the stroke of midnight. The hour hand travels clockwise from 0 minutes at the bottom, over 30 minutes horizontal, to 59 minutes at the top of the stroke. At 0 minutes, the minute hand re-tours to 0 at the bottom. I find the movement of the servos on the stroke of the hour somewhat like a chime. Not too oppressive, but enough to draw my attention to the passing of another hour.

As the 4 line LCD has so much screen real estate, I have added the maximum and minimum temperature display, with hour, day and month when each extreme was reached.

Adding the LM335Z Temperature IC was discussed in Part 2. I found that the accuracy of the LM335Z IC could be improved by firstly knowing exactly what the Vcc was for operating the AVR device. Measuring this, and putting it in the calculation enabled enough accuracy to be found. Using the 5V regulator on the Freetronics 2010 delivered 4.97V for me, and this value is hard coded into the code. I have several LM335Z devices and they have different offsets, which is adjusted by modifying the subtraction in the Kelvin to Celsius calculation. As the LM335Z is accurate once the offset is established, there is no need to operate it in the “accurate” mode, IMHO, given we have software to make the adjustments it needs.

Dsc02855Dsc02852Dsc02854

The instability in the temperature readings discussed in Part 2 was caused by the long wires to the sensor. Once the device was fixed into the prototyping area on the 2010, together with bypass capacitor, the stability of readings improved greatly. However, during testing, I noted that the maximum values were reading very high. These false high maximum values were caused because the ADC process was sampling during a servo move. The servos consume a lot of power, and this causes voltage drop on Vcc. Hence the reference voltage for the ADC is no longer accurate.

Dsc02845Dsc02847

To prevent the ADC from operating during the servo moves, I simply used one of the freeRTOS semaphores I established previously. I use semaphores to control access to the LCD, the I2C and to the ADC. Use of a semaphore enables independent processes to share a single hardware resource without conflicts developing. The fix for the erroneous high maximums was done simply by taking the ADC semaphore (to prevent the ADC reading process from starting) during times when the servos are being instructed to move. Simple, with freeRTOS to manage the process interaction for me.

ERRATA

The code included in the updated source does not properly fix the issue of false maximum temperatures. It incorrectly releases the ADC semaphore immediately following resetting the PWM values. This means that the hands can still be moving when the ADC process gets unblocked which causes false maximums, because of voltage droop in Vcc, typically at midnight when both hands are in motion.

The fix is to move the vTaskDelay call between the set_PWM_hardware and xSemaphoreGive calls. I also increased it to 2000 milli Seconds too, to ensure the hands are really stopped before the ADC process gets unblocked.

set_PWM_hardware( servoHours_uS, servoMinutes_uS );

vTaskDelay( 2000 / portTICK_RATE_MS ); // a 2 second delay to ensure the hands have properly stopped.

xSemaphoreGive( xADCSemaphore );

 

END ERRATA

Another piece of code added since Part 2 is to write the maximum and minimum temperatures and the times the extremes occurred into the EEPROM available on the 2010. The functions to use the EEPROM are available in the AVR library and are very straightforward to use. Having a permanent record of temperature extremes is perhaps one thing this clock does, that other clocks in my house can’t do.

There are a lot of comments in the updated freeRTOS Retrograde Clock code, now hosted at Practical Arduino. As a reminder the code uses the AVR and Pololu Libraries, so these both need to be installed before you compile.

 

Freetronics freeRTOS Retrograde Real Time Clock on PS3 – Part 2a

Just for interest, I decided to see how the support for AVR or Arduino was on the PS3.

Using the standard tools on Ubuntu Lucid 10.4 from my OtherOS installation. A quick search for AVR on synaptic got the avr-lib, avr-gcc, and avrdude tools needed. No special versions, just straight off the repository.

Then, I followed the link to the Pololu Libraries in my Part 2 post, made the changes to OrangutanLCD.h as noted, hit make, and crossed my fingers. No issue. It all worked. sudo make install to put the files in right place.

OK. does the PS3 USB platform recognise the FTDI 232RL USB chip on the Freetronics 2010? Yes. Another hurdle cleared, with no issues.

With that step done, it was simple to download the retrograde files from Practical Arduino as noted in Post 2, extract them. Hit make program and off we go. avrdude works as expected, and the new code is loaded as normal.

I’d say the whole test was over faster than it has taken to type this note.

I should be over this, but I get so happy when technology just works… particularly when it is all free. Got to love your FOSS.

One small issue. There doesn’t seem to be a release of Arduino tools for PS3 (PowerPC). Pity about that. Perhaps in another repository…