Author Topic: Porting UTasker to the Rabbit Processor  (Read 13478 times)

Offline mhoneywill

  • Full Member
  • ***
  • Posts: 173
    • View Profile
Porting UTasker to the Rabbit Processor
« on: May 21, 2008, 02:10:13 PM »
Hi Mark,

Partly in an exercise to understand utasker in more depth I would like to look at the possibility of Porting uTasker to the Rabbit Processor. Specifically the Rabbit 3000 processor on the RCM3200 board, which uses an ASIX chip for Ethernet access.

We currently use these RCM3200 modules in some of our products, see www.rabbitsemiconductor.com

We use the Softools C compiler www.softools.com which is an ANSI C compiler so that part should be OK. Much better that the Dynamic C compiler supplied by Rabbit / DIGI.

The Rabbit is basically an 8bit device which uses paged memory to access up to 1M of memory. The RCM3200 module has 512K Flash and 512K Ram. The fact that the rabbit is limited to 64K memory, without paging and that uTasker supports small memory sizes looks like it might be a good fit.

My first question is do you mind if I have a play with this, I am currently evaluating the LPC23xx and LM3Sxxxx versions of uTasker and have merged the two stacks. Would one of these make a good basis to start from or would you look at something like the N64 version as a starting point, I presume the stacks are the same and just the hardware specific files are different.

Cheers

Martin Honeywill

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3236
    • View Profile
    • uTasker
Re: Porting UTasker to the Rabbit Processor
« Reply #1 on: May 21, 2008, 03:16:13 PM »
Hi Martin

You are right that the majority of the project is identical, just the HW releated interfaces are modified for different processors. Sometimes this is quite easy (eg. TICK timer and ports) and sometimes a bit more difficult (eg. FLASH architectures, Ethernet interfaces, etc.).

When I port to a new chip I start with the package which matches closest (generally an ARM based package for another ARM chip). Not due to the CPU core itself but rather due to the fact that the peripherals tend to be quite similar. I don't know details about the Rabbit modules but I expect that you could take any of the packages you have as a base.

You are welcome to try this out. The first things to be done are to ensure that the startup and heap set up are correct (uTasker needs to know where the last variable is - see
        extern unsigned char __heap_end__;
        #define HEAP_START_ADDRESS &__heap_end__                         // GNU last location of static variables

in LPC23XX.c

Then you need to get the TICK timer and its interrupt operating, and configure a port for monitoring the watchdog operation (usually in fnInitialisePorts() in debug.c).

This will allow the board to flash an LED to show that the OS is operating and that the TICK has the correct configuration.

Then you need to adapt the Ethernet interface (a bit more work is involved here) and the FLASH routines (assuming you want to use the file system), followed by any peripheral drivers required.

Note that I generally don't do all of this work on the target but prefer to adapt the uTasker simulator to simulate the new CPU (actually its peripherals). This involves more work at the beginning but improves efficiency over time since even new HW drivers can be added and tested in the simulator [in addition it forces you to understand the peripherals in more detail] - although there are usually a few points that need to be corrected before the HW works, afterwards this usually involves one 'short' debug session at the end rather than working the whole time with the embedded debugger.

It is exiting getting a new device up and runnning and 'can' also be fun. However it does sometimes take a bit longer than expected and so can also involve some frustrating moments!

What are the advantages of the Rabbit processors? What advantage does it offer over, for example, the LPC23XX? This has big memory, good peripherals, is fast (and 32 bit) and quite cheap. The Rabbit modules seem to be quite costly for an 8-bit solution (?).

Regards

Mark

Offline mhoneywill

  • Full Member
  • ***
  • Posts: 173
    • View Profile
Re: Porting UTasker to the Rabbit Processor
« Reply #2 on: May 21, 2008, 05:26:49 PM »
Hi Mark,

Thanks for your quick response, you ask what are the advantages of the Rabbit Processors.

Well the simple answer is for a new product NONE in my opinion.

For a slightly longer answer, we currently have products that use the Rabbit processor, so it would be nice to have a unified environment across processors. Also the Rabbit processors are available in Core modules which allow users to have a fast time to market for products. You can get a TCP IP stack for this processor but it is quite bloated and is based around the Dynamic C compiler that the chip supplier produces. This is a NON ANSI C compliant complier that is quite buggy. The TCP IP stack has been ported to Softools by Softools but it doesn't have all the bells and whistles that uTasker has, also it will not run in the simulator.

I admit that this may be more of an academic exercise that anything but, it might give you another market for uTasker. !000's of rabbit modules are sold and the yahoo groups for Rabbit and Softools are quite active with users. If nothing else it might raise the profile of uTasker if it is known that there is another Stack option available for it. I can see a number of current Rabbit users migrating to Chips like the LPC23xx and the Luminary parts, and giving them an upgrade path could be interesting. The one advantage of the rabbit modules 4 or 5 years ago was that they provided a quick and easy way to add TCP IP connectivity, and they came with loads of software examples.

I also think your concept of a Simulator is a very powerful one and is something that would appeal to Rabbit users. Especially as new peripherals could be added and simulated, like Graphics LCD displays and Keypads etc. I think the whole methodology of writing a program from the ground up that will run in both the simulator and  the target device introduces practices that make the resulting code inherently more portable. i.e. storing all hardware specific code in separate modules.

One thing I would do also is to simplify some of the uTasker examples, rather that have one huge application.c file with loads of #ifDefs I would have lots of little examples that showed one aspect of uTasker. Like a UDP example or a simple single page WEB server, with no file system. This is what was so appealing about the Rabbit, you had a simple example of say a WEB server and it was easy to understand what was happening.

Below is an example of their Static Web Page Demo

Code: [Select]
/*******************************************************************************
        static.c
        Z-World, 2000

        A very basic example using the HTTP library. This program
        completely intilizes the library, outputing a basic static
        web page.
*******************************************************************************/


/***********************************
 * Configuration                   *
 * -------------                   *
 * All fields in this section must *
 * be altered to match your local  *
 * network settings.               *
 ***********************************/

/*
 *  The TIMEZONE compiler setting gives the number of hours from
 *  local time to Greenwich Mean Time (GMT).  For pacific standard
 *  time this is -8.  Note:  for the time to be correct it must be set
 *  with tm_rd which is documented in the Dynamic C user manual.
 *
 */

const int TIMEZONE = -8;

/********************************
 * End of configuration section *
 ********************************/

#include "stcpip.h"

/*
 *  #pragma init_file is a WinIDE SC2000 feature that takes the binary image
 *  of a file, places it in extended memory on the controller, and
 *  associates a symbol with the physical address on the controller of
 *  the image.
 *
 */

extern char const far index_html[];
#pragma init_file( index_html, "pages/static.html" )
extern const char far rabbit1_gif[];
#pragma init_file( rabbit1_gif, "pages/rabbit1.gif" )

const char MAX_TCP_SOCKET_BUFFERS = 1;

/*
 *  http_types gives the HTTP server hints about handling incoming
 *  requests.  The server compares the extension of the incoming
 *  request with the http_types list and returns the second field
 *  as the Content-Type field.  The third field defines a custom
 *  function to handle that mime type.
 *
 *  You can get a list of mime types from Netscape's browser in:
 *
 *  Edit->Preferences->Navigator->Applications
 *
 */

/* the default mime type for '/' must be first */
SSPEC_MIMETABLE_START
SSPEC_MIME( ".html", "text/html" ),
SSPEC_MIME( ".gif", "image/gif" ),
SSPEC_MIMETABLE_END

/*
 *  http_flashspec assocates the file image we brought in with ximport
 *  and associates it with its name on the webserver.  In this example
 *  the file "samples/http/pages/static.html" will be sent to the
 *  client when they request either "http://yoururl.com/" or
 *  "http://yoururl.com/index.html"
 *
 */

SSPEC_RESOURCETABLE_START
SSPEC_RESOURCE_XMEMFILE( "/", index_html ),
SSPEC_RESOURCE_XMEMFILE( "/index.shtml", index_html ),
SSPEC_RESOURCE_XMEMFILE( "/rabbit1.gif", rabbit1_gif ),
SSPEC_RESOURCETABLE_END

void main()
{
    longword _IP;
char buffer[ 20 ];

WDT_DISABLE();
if( xavail() < 0x10000UL )
{
printf( "This demo requires 256k or more of RAM" );
return;
}
startTimer( 100, 0, 1 ); // Timer must be at IP=1
ipset0();

/*
*  sock_init initializes the TCP/IP stack.
*  http_init initializes the web server.
*/

// Select ethernet hardware: usingAsix, usingDevKit, usingRealtek, usingSMSC
usingAll();
sock_init();
http_init();

// Wait for DHCP server to send an IP address.
// ifconfig( IF_ETH0, IFS_DHCP, 1, IFS_UP, IFS_END );
if( ifconfig(IF_ETH0, IFS_DOWN, IFS_IPADDR, aton("192.168.18.1"), IFS_NETMASK, aton("255.255.255.0"), IFS_UP, IFS_END) ) printf("ifconfig failed!\n");
while( ifpending(IF_ETH0) == IF_COMING_UP )
tcp_tick(NULL);
ifconfig( IF_ETH0, IFG_IPADDR, &_IP, IFS_END );
    printf("My IP address: %s.\n", inet_ntoa( buffer, _IP));

/*
*  tcp_reserveport causes the web server to ignore requests when there
*  isn't an available socket (HTTP_MAXSERVERS are all serving index_html
*  or rabbit1.gif).  This saves some memory, but can cause the client
*  delays when retrieving pages.
*/

tcp_reserveport(80);

/*
*  http_handler needs to be called to handle the active http servers.
*/

while (1) {
http_handler();
   }
}

I hope this explains my thoughts.

Cheers

Martin

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3236
    • View Profile
    • uTasker
Re: Porting UTasker to the Rabbit Processor
« Reply #3 on: May 21, 2008, 08:36:30 PM »
Hi Martin

Thanks for the explanation. I must admit that I was amazed at the Rabbit following - the Yahoo group is huge.
Also I have to admit that I have never used it, although I did read up on its Ethernet capabilities and looked at examples in the book "Embedded Ethernet and Ethernet Complete" by Axelson.

I have heard that it is somewhat unconventional (a bit bound to the tools it comes with) and I understand that one either loves it or it drives one mad...

So are you going to give it a shot? ;-)

Regards

Mark

Offline mhoneywill

  • Full Member
  • ***
  • Posts: 173
    • View Profile
Re: Porting UTasker to the Rabbit Processor
« Reply #4 on: May 21, 2008, 10:30:26 PM »
Hi Mark,

Well in for a penny in for a pound, I'll give it a shot I think. I'll have to do it in my own time at least initially. (read evenings and not work time). And I might need a bit of hand holding  ;-).

The rabbit does have a massive following and I think that is basically down to its Ethernet support. If you use the softools compiler that I mentioned then you get away from the reliance on the tools it comes with. And yes Dynamic C can drive you mad.

If you want I can ship you an eval board with a Rabbit RCM3200 module, the demo version of the softools compiler available from their website will compile to RAM, it just will not program the Flash. This is fine for development as you debug in ram anyway.

Cheers

Martin

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3236
    • View Profile
    • uTasker
Re: Porting UTasker to the Rabbit Processor
« Reply #5 on: May 21, 2008, 11:40:41 PM »
Hi Martin

If you would like to send me a module I will install the the demo version of the softools compiler. This will allow me to hopefully be able to identify any initial problems (I know the ropes there...). However I think that it would be great to have a go at the simulator at the same time - it is not that difficult and of course I can give you all details you need.

I won't have a great amount of time so I don't plan on any coding - this will be your baby - but I should be able to guide you if you need any support.

Good luck!

Regards

Mark

Offline mhoneywill

  • Full Member
  • ***
  • Posts: 173
    • View Profile
Re: Porting UTasker to the Rabbit Processor
« Reply #6 on: May 22, 2008, 12:03:51 PM »
Hi Mark,

Where should I send the module? I couldn't find an address on your web site.

Shall I keep the discussions about progress etc in this forum post? Might be useful for other users to see my trials and tribulations.

I will take your suggestion and try an look at the simulator first, these are the procedures that I think I should follow.

1. Turn off Ethernet using, #define DEVICE_WITHOUT_ETHERNET this should remove a chunk of code.

2. Define the end of the Heap, I presume __heap_end__ is a compiler/linker variable that contains this value. I'll see what Softools has.

3. Rename LPC23xx.c etc. to R3000.c (for the rabbit 3000) I presume I need to work my way through this file producing rabbit versions of all the functions. Starting with IO functions. Do you have a minimal version of this file that you use for initial development?

4. The Softools setup, contains drivers for the Ethernet, and Serial Ports, also flash programming is also supported (but it does inhibit interupts)  so I think these could be used rather then re-inventing the wheel.

5. Softools has a Tick Timer so I could hook into this for the tasker. Where should I look in the code to set this up? What Tick time base do you normally use

6. Ethernet, Serial and Flash will follow later.

It would also be nice to create a Debug output channel that will act as a debug printf output, in the simulator it will route to a  text box that can just stream output. On the target this would either route nowhere or in the case of the Softools compiler, route to a printf terminal interface that it supports whist in debug mode. This concept would be easy to extend to other targets that supported some form of simple debug channel.

Cheers

Martin


Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3236
    • View Profile
    • uTasker
Re: Porting UTasker to the Rabbit Processor
« Reply #7 on: May 22, 2008, 02:46:31 PM »
Martin

I think that we can try to use this thread - it will force us to keep 'to-the-point'.
I will send you a postal address by mail.

As you will start with the simulator, I'll just remark on the first point for the moment.

I suggest not changing anything in the project set up but 'migrate' from an existing chip to the new chip as follows:
1. Copy an existing hardware directory (eg. Hardware\LPC23XX to Hardware\Rabbit)
2. Rename the relevant file in that directory to the new chip (eg. LPC23XX.c to Rabbit.c, LPC23XXSim.c to RabbitSim.c)
3. In the VS project add new project directories for the new chip (at the bottom is a screen shot of my project with all supported chips in it as reference - the new chip should have its own hardware and WinSim (virtual) project directory, although all files are actually in the single new folder.
4. In the application directory make a copy of app_hw_lpc23xx.h and rename it to something like app_hw_rabbit.h
5. In VS add a build configuration for the new chip (again basically a copy of existing build), declaring a project define like _RABBIT rather than _LPC23XX
6. In all your new files replace the define _LPC23XX by _RABBIT. In config.h add a new block for the rabbit (containing heap size, TICK resolution and processor/board details - mainly the name for the simulator)*1

Now you should be able to build and run the project. This is using the new files but the original (LPC) content.
The idea is now to replace parts of the new code, step-by-step, with code for the new chip. Parts which have not yet been 'migrated' will run and simulate with the old chip code so the complete project should in fact always run in the simulator. To run on the target you can strip out some defines as you suggested and also reduce the task table to simply the watchdog task - linking some driver code from the other chip should not harm since it will not actually be executed.

7. The first goal is to get the TICK operating. If you start the simulator and step through the code you will see what happens, what is performed with the previous hardware and so what is required from the new hardware (this assumes that you have and assembler startup code for the new chip which will at least jump to the first C-code, since this is not simulated).
The sequence is (based on LPC23XX)
- fnInitHW(), which configures the PLL, MAM, ports, default vector table, (initialises RAM variables if GNU), and conditionally the Watchdog operation.
- fnInitialiseHeap() is a tricky one which is compiler dependent due to the ram location as discussed previously. Note that it fills all RAM from the top of heap to the top of stack with a pattern which is later used to measure the stack use.
- uTaskerStart(). This is hardware-independent code but does call fnStartTick() at the end, which is where the ticker needs to be confured. You will find that this jumps into your new rabbit.c HW code and you need to configure the- Rabbit HW to generate the TICK (including setting up interrupts).

8. The simulator (and target) will now simply execute a loop and requires the TICK interrupt to do anything useful. The TICK interrupt was set up in fnStartTick() and the interrupt is RealTimeInterrupt() [also in Rabbit.c]. This calls the uTasker TICK handler and resets and interrupt flags necessary.

9. To get the simulator to do this it must simulate the TICK timer. I suggest using the LM3S project as reference since its simulator does this in fnSimTimers() - the LPC project uses an older method which is not as accurate (it will still be called even if the timer is actually disabled...this will be improved). You will see that the simulation part attempts to check that the peripherals are correctly configured, that their interrupst are really enabled and also uses the real vector table to jump to the interrupt routine.

How this is done on the rabbit depends on its hardware and this is what needs to be understood and then simulated.

10. Now it is time to 'migrate' LPC code to Rabbit code. To do this you need to do 4 things.
- add the register and register content defines to rabbit.h (this is all based on a struct of the internal peripheral registers: ucLPC23xx in the LPC)
- add the internal peripheral register struct in RabbitSim.c and its definition in simRabbit.h
- add the specific peripheral to the register struct (eg. LPC23XX_TIMER)
- exchange the simulation code in RabbitSim.c (eg. in fnSimTimers() to check the present timer configuration, incriment its count value and execute the timer interrupt on timer match).

To get the first TICK operating you may find that you need to add PLL peripherals, Timer peripheral and Interrupt controller peripheral before it will all work (if you are impatient to see it running for the first time this extra work is a bit frustrating). However, once you are sure that it is doing this properly you will understand these modules well enough to not have any problems on the target. If you are convinced enought that the target will operate with the code that you have simulated it probably will do and so it is then time to verify this on the HW. Usually there will be a flag somewhere which you didn't understand correctly but this is mostly a small itteration. [I have created complete drivers in the simulator for chips which I had never used before and sometimes they do run first time on the hardware - when they don't I usually find that the correction is restricted to maybe a register flag which has the wrong polarity or at the wrong location but usually nothing which takes more that a short time to solve. The message is simply that the work invested in the simulator, although quite intensive at first, usually results in a good pay back later].

11. Some chip customisation.
You will certainly want to do some customisation to the simulator so that it displays the Rabbit chip/module. This requires a simple BMP of the chip to be put in the Rabbit\GUI directory - it is conditionally loaded in WinSimMain.cpp. Also the port simulation can be modified to suit the rabbit processor/module, but this can be the subject of future development steps.

Good luck

Regards

Mark

*1 - modified

« Last Edit: May 22, 2008, 08:06:41 PM by mark »