HomePACESearch
ProjectsForumsSite Map

Current:
Level Down:

Notes on using your BX24


READ THIS
If you have a new BX24, BEFORE you load any programs to it, be sure to connect it to a serial port and power it up. There is a small diagnostics program on the chip, and you should make sure it runs successfully (it dumps a lot of stuff to the serial port) before you overwrite it. If your BX24 doesn't work and you overwrite this program, Netmedia's Tech Support won't be able to help you much.

There are several features the BX24 has that most or all of the other microcontrollers do not that make it an interesting and worthwhile choice. They include:

Multitasking Operating System

The BX24 is based on a small RISC processor made by Atmel. This processor has its own assembly language (as all processors do), and Netmedia has written a small operating system for it to schedule all the tasks such as the Basic Interpreter engine, and on other models, the network. When you use the multitasking, you have to remember that you are still running on a single CPU, so you tasks aren't actually running concurrently, but since most of your operations will likely involve waiting for some sort of input or event, you can do other things while you wait.

Some knowledge of operating systems will be helpful if you want to fully understand how this stuff works, but I'll try to give a Cliff's-Notes approach here. There are some things that you will probably need to know first.

The task switching is interrupt driven. I don't think you can intercept these interrupt signals, which happen every 1/512th seconds, but you can disable them (or at least lock a task on the CPU, which is the same thing).

If you have one or more tasks waiting on data from another task, locking one of the tasks is a good way to cause a deadlock and grind your processor to a halt. You have to be careful how you use this.

The BX operating system provides you deadlock free (or at least deadlock reduced) methods to share data between tasks, but again, you can still cause a deadlock if you don't know what you are doing.

You have to explicitly declare the stack for each task. The stack is used for things like return addresses after function calls, and local variables in those functions, so you have to guess about how big these stacks will need to be. The point of this is you can't make heavily recurssive tasks. Also, the RAM on the chip is only 400 bytes, so you can't make too many tasks either, unless some or all of them don't need a stack. Netmedia claims to have written code with over 1000 tasks, but they also said it was extremely slow.

For more information, see the Operating System Reference in the Documents section.

Defining your stack

You declare a stack just like you declare an array of verables in ram. A good practice to name the variable Stack<ProcessName>.

Like this:

Dim StackDoSometing(1 To 32) as Byte
Dim StackDoSometingElse(1 To 16) as Byte

Note: These have to be declared at the module level, and not as local variables in the function that spawns the task.

Spawning Tasks

Using the stacks above, and assuming you have two functions declared called DoSomething and DoSomethingElse, in any function, you can spawn the tasks using the CallTask function.

Here's an example:

'-----------Stacks---------------
Dim StackDoSometing(1 To 32) as Byte
Dim StackDoSometingElse(1 To 16) as Byte


'-----------Main----------------- 
Sub Main()

	' Spawn The Tasks
	CallTask "DoSomething", StackDoSomething
	CallTask "DoSomethingElse", StackDoSomethingElse

	' Give all other processor time
	' to the tasks 
	Do
		Call Sleep(60.0)
	Loop
End Sub


'-----------DoSomething--------- 
Sub DoSomething()

	' Do Something Here

End Sub

'------------DoSomethingElse------
Sub DoSomethingElse()

	' Do Somehting Else Here

End Sub


Yeilding Before Interrupt

The Call Sleep() statement is still fairly accurate when running multiple tasks, and the operating system won't wake your task up until all of the wait time has expired. A neat little hack you can use when a task doesn't need to execute any more, but wants to be woken back up on the next round is Call Sleep(0.0).

Locking a Task on the CPU

If you want to lock a task on the CPU for a while, you can just say Call LockTask(), and your task will stay on the cpu until either the Sleep, Delay, or UnlockTask functions are called.

Be sure you understand the difference between Sleep and Delay if you have some time critical task that is running.

Sharing Data Between Tasks

It is my understanding that the Atmel uses an RPN type arithmetic unit, so there are some problems with two tasks using the same global variables. One way to beat this is to use Semaphores, if your tasks need to share the same value. If you need to pass data between tasks, Queues are a little more appropriate. There are a few pages in the Operating System reference that do about the best job of explaining this, so I'll leave the explanation up to them. Go check out pages 20 to 26 of the Operating System reference if you need tasks to share data.
Persistent Variables

One of the neat things the BasicX has is Persistent Variables. These are variables that will stay set after a reset or power-failure. You can use them for all sorts of things, but these variables CANNOT be used for something that changes frequently. They are implemented in Flash memory, which you will wear out after 100,000 writes. This is an eternity for variables that only change every couple of hours or days, but if your program screws up, you can horse up your BX chip in a matter of seconds.

First, all persistent variables must be module-level (global) variables, and the best practice is to get your program working first with RAM variables. After you know it works correctly, you can change the code to make it a persistent variable very easily.

An example of a good use for a persistent variable is a tempurature controller, where your Heater/Cooler set-points need to remain set after a power-failure. First start be defining your variables in RAM:

Dim HeaterOnAt as Byte ' 0 to 255 is probably a wide enough range
Dim CoolerOnAt as Byte
After you know your program works and won't screw up your Flash ram, change your declerations to:

Dim HeaterOnAt as new PersistentByte ' 0 to 255 is probably a wide enough range
Dim CoolerOnAt as new PersistentByte

Be sure to read the Persistent Variables section of the Operating System reference for some more info before you use these. Also, there is a little blurb in the Language Reference that gives you a few more limitations--namely that you should declare them in the order they are first accessed at Run Time.
Function Library
We probably won't have time to document each and every function that this chip has in ROM, so you should checkout the System Library document in the
Documents. There's a LOT of stuff, so you should at least skim the entire document.

While you're at it, hit the Operating System Reference and read up on what the BX operating system can do to make your life easier.

This document created by: CJ Oster and Joe Ngai

Last Modified: April 22, 2003
Please contact Professor Gary Swenson (swenson1@uiuc.edu) to learn more about the course, or contact the webmaster (wiegert@uiuc.edu) with questions or comments about the web site.  Web Site designed by Purvesh Thakker.