Embedded programming using Powerbasic with RTOS-32 (Part 1)

This will be a short introduction to using the Powerbasic 6.0 console compiler with the Ontime RTOS-32 embedded operating system. Hopefully future articles will go into more depth into the subject.

What version of RTOS-32 ?

The first thing is that you must have version 6.09 of RTOS-32. Why ?  Simply put, Powerbasic handles strings quite differently than most programming languages, such as C, with its use of the WIN32 OLE API’s for handling variable length strings. Ontime only added support for this in version 6.09 (very current). As far as I can tell, I am the first developer to attempt to use Powerbasic with RTOS-32 and Ontime was very helpful in getting us started. In my development I will be using other Modules in RTOS-32 for things like Internet communications, files, etc. so the list below may be more than the bare minimum required.

New Win32 API Functions supported:

  • SysAllocStringByteLen
  • SysAllocStringLen
  • SysStringLen
  • SysFreeString

Plus some other WIN32 API’s must have dummy wrappers (a few require some code) defined in a supporting C source file (ie. MyWin32API.c) such as:

  • CoInitialize
  • CoUninitialize
  • ScrollConsoleScreenBufferW  (requires your own calls to RTDisplayScroll API in RTTarget)
  • PeekConsoleInputW   (requires being passed on to PeekConsoleInputA)
  • ClearCommError
  • EscapeCommFunction
  • GetCommModemStatus
  • GetCommProperties
  • GetCommState
  • SetCommState
  • SetCommTimeouts
  • SetupComm
  • MessageBeep (requires a call to Beep)
  • closesocket
  • WSACleanup

The key to using RTOS-32 with Powerbasic is that you will require at least one C source code file to generate a DLL (Dynamic Link Library) which has the RTOS-32 runtime modules Library (LIB) files compiled into it. In my case I generate a DLL called:  Rttdll.dll

You can customize this DLL to include what ever features Powerbasic lacks and any initialization code you desire for RTOS-32 into it. Ontime’s tech support should be able to provide you with a simple Powerbasic example, since they used the one we started with to provide us with the minimal code to make it work.

Using Powerbasic Console compiler

Now once you have the rttdll.dll compiled you can then declare any calls in the RTOS-32 library functions (or any custom ones you write in C) using the standard Powerbasic Declare command. RTOS-32 provides a very limited WIN32 API emulation layer, along with the few wrappers mentioned above which you add and now the Powerbasic compiler has enough to work with RTOS-32. It is best to test Powerbasic commands to see if they are supported by RTOS before you use them, since some commands may not be supported by RTOS-32 and the Powerbasic compiler adds more and more of its own runtime code for certain command sets used, which could use WIN32 API’s not yet supported by RTOS-32. But much of the basic command set will work with RTOS-32. I am not a C programmer, but I was able to tweak the C initialization source code file they provided me and to compile it (using the free Community version of Visual Studio) and to run the Make file via the command line compiler, to compile the runtime DLL I required.

This is where it gets fun!

Once you have the basics setup to compile a minimal Powerbasic console application, this is where things start to get fun. So how should one write an RTOS-32 application using Powerbasic ?

I found that the best way was to use conditional compiler directives so I can write a single User Interface library which supports both Windows and RTOS-32. In Windows, Powerbasic has a rich command set for displaying a console (text based) application. In RTOS-32, I simply use the RTOS-32 API instead to do many things or call to the Video card directly. Text base screens on VGA adapters are easily accessed directly using memory addresses. So by simply changing the value of one constant used by the compiler directives I can compile the app to run fully in Windows or to run fully in RTOS-32.

' setting compiler directives

%UseRTOS = 1

#IF %UseRTOS
     #COMPILE EXE "pbasicRTOSapp.exe"
#ELSE
     #COMPILE EXE "pbasicWINapp.exe"
#ENDIF

' example dual library compiled using compiler directives

DECLARE SUB RTDisplayString LIB "RTTDLL.DLL" ALIAS "RTDisplayString" (s AS ASCIIZ) CDECL

SUB UI_Print(BYVAL T$)
    #IF %UseRTOS

        RTDisplayString BYVAL STRPTR(T$)
    #ELSE
        PRINT T$;
    #ENDIF
END SUB

Notice in the above example that the RTOS-32 RTtarget API function RTDisplayString uses the CDECL convention for parameter passing, which is how RTOS-32 does it, unlike Windows (WIN32) and Powerbasic natively which use the Standard Call convention for passing parameters.  By using the CDECL directive in the DECLARE call you can all any RTOS-32 library modules functions (which you compiled into your rttdll.dll runtime library) directly.

Powerbasic supports the following parameter passing formats:

  • BDECL  – which is a Pascal calling convention
  • CDECL – which is a C calling convention (used by RTOS-32)
  • SDECL – which is the Standard calling convention used by Windows and also is default to Powerbasic itself.
Now to benefit from writing embedded code using Powerbasic

Why use BASIC rather than C for embedded coding for RTOS-32 ? Because BASIC is much easier to work with than C and Powerbasic is extremely powerful and provides all the raw power of pure C, but with the ease of BASIC.  Powerbasic has one of the most powerful string engines in the software industry and if your app does a lot of string manipulation you will be glad you used Powerbasic. Powerbasic also generates executables with the performance one gets with a native C compiler. The syntax of BASIC is far more readable than is C and maintaining software will be much easier. Now let’s look at some of the features of Powerbasic you will definitely use with an RTOS-32 app.

Low level memory access:

Working with direct memory is easy with Powerbasic. It has commands which are far superior to the old fashioned Peek and Poke of BASIC’s old days. First you can easily move large blocks of memory. You can use pointers for nearly any data type supported by the compiler, even within strings. You can define local arrays using any data type via a pointer to already existing memory blocks (ie. define an array which exists within video ram).

Variety of Compiler Directives:

The use of compiler directives and Macros allows you to easily write one set of routines which can easily switch between native Powerbasic commands and native RTOS-32 API’s.

Inline Assembler:

Yes, Powerbasic provides inline assembler for when you must resort to very low level coding directly to hardware.

Graphics Windows even with a Console application:

This is interesting. The Powerbasic Console compiler can write native Windows Console applications, but then display a popup Graphic window and it provides an extensive Graphic library. While this can not be used with RTOS-32 (it does not emulate Windows graphics), it can be used via conditional compiling so in Windows you can use native graphics and in RTOS-32 you can write your own VGA compatible graphics. Since Powerbasic can easily copy its Graphic window into an 32 bit BGR memory buffer which you can access directly via pointers, you can write a single graphic engine which works in a Windows graphic window (draw into buffer and then copy to screen) or in a memory buffer you define and then copy to the VGA memory. The low resolution VGA graphic modes don’t support 32 bit buffers, but RTOS-32 does allow you to access the VESA BIOS information so you can get a pointer to a VESA 32 bit Graphic mode. The best ones to work with are 640 x 480, 800 x 600 and 1024 x 768. Most Intel integerated (graphics) chips support these VESA graphic modes which can provide you with a Linear Frame buffer which can be directly accessed. Moving memory from your own graphic buffer to video ram buffer is easy once you have the VESA 32 bit pointer to a Linear Frame buffer. By writing the Graphics engine to write to my own Graphic memory buffer (I use Global dynamic strings for defining a memory buffer) it will be the same whether the app runs in Windows or RTOS-32. In Windows the memory buffer is copied to the Powerbasic Graphic Window and in RTOS-32 it is copied directly to the linear frame buffer address.

Extensive Console text commands:

When compiling for Windows Powerbasic provides an extensive Console text window command set. Now when the compiler directive is set for RTOS-32 you will have to resort to standard low level VGA port calls or use some of the RTTarget module API’s. I originally used the RTTarget API’s, but found they were not as fast as I desired (or didn’t do something I required) so I used direct calls into video ram instead. This allowed me to do all sorts of tricks and Powerbasic is well equipped for talking directly to memory.

Why use dual compiling ?

Testing on the embedded target is slow because one has to create a bootdisk (or you can use a debug monitor and pass it via Ethernet connections) first and compile everything for the RTOS-32 system and that takes valuable time. Compiling for Windows and running the app using Powerbasic is lightning fast (compiler was written in assembler and compiles amazingly fast). By testing the code in Windows and when it works as intended then a simple compiler directive change one can compile for RTOS-32. The only extensive testing on RTOS-32 is the UI library you have to build, but once you have it, then much of the testing can be done on Windows.

This should provide enough information for you to get started with RTOS-32 using the Powerbasic 6.0 Console Compiler. The benefits of using Powerbasic are well worth the effort. One can also port old QBasic and Quick Basic code to for use on embedded systems. Non-GUI (no class stuff) classic Visual Basic code might be ported with a little effort. RTOS-32 will run on the most minimal x86 system, such as those which use a Vortex x86 chip rather than an Intel chip. One example is the 86Duino board. There are a number of tiny x86 boards now available which are the size of a Raspberry PI, such as the Lattepanda, Minnowboard Turbot and the UP board. There are plenty of Mini-ITX x86 boards available, though larger, which are still a decently small package.

Yes, Powerbasic is well suited to the embedded world. If you are using Windows Embedded then the Windows (Graphic GUI) version of the compiler may be a better choice. Why not try your hand with Powerbasic with RTOS-32.