使用 Powerbasic 进行嵌入式编程(RTOS-32)(第一部分)





5.00/5 (3投票s)
简要介绍如何将 Powerbasic 6.0 控制台编译器与 Ontime RTOS-32 嵌入式操作系统结合使用
本文将简要介绍如何将 Powerbasic 6.0 控制台编译器与 Ontime RTOS-32 嵌入式操作系统结合使用。希望未来的文章能更深入地探讨该主题。
RTOS-32 的哪个版本?
首先,您必须拥有 **RTOS-32 的 6.09 版本**。为什么?简单来说,Powerbasic 处理 string
s 的方式与 C 等大多数编程语言截然不同,它使用 WIN32 OLE API 来处理可变长度的 string
s。Ontime 仅在 6.09 版本(非常新)中增加了对此的支持。据我所知,我是第一个尝试将 Powerbasic 与 RTOS-32 结合使用的开发人员,Ontime 在帮助我们入门方面非常给力。在我的开发中,我将使用 RTOS-32 中的其他模块来实现 Internet 通信、文件等功能,因此下面的列表可能比最低要求要多。
支持新的 Win32 API 函数
SysAllocStringByteLen
SysAllocStringLen
SysStringLen
SysFreeString
此外,一些其他的 WIN32 API 必须在支持的 C 源文件中(例如,MyWin32API.c)定义 **dummy wrappers**(有些需要一些代码),例如:
CoInitialize
CoUninitialize
ScrollConsoleScreenBufferW
(需要您自己调用RTTarget
中的RTDisplayScroll
API)PeekConsoleInputW
(需要转发到PeekConsoleInputA
)ClearCommError
EscapeCommFunction
GetCommModemStatus
GetCommProperties
GetCommState
SetCommState
SetCommTimeouts
SetupComm
MessageBeep
(需要调用 Beep)closesocket
WSACleanup
将 RTOS-32 与 Powerbasic 结合使用的关键在于,您至少需要一个 C 源文件来生成一个 DLL(动态链接库),该 DLL 编译了 RTOS-32 运行时模块库(LIB)文件。在我的例子中,我生成了一个名为 Rttdll.dll 的 DLL。
您可以自定义此 DLL,以包含 Powerbasic 所缺乏的任何功能以及您为 RTOS-32 希望实现的任何初始化代码。Ontime 的技术支持应该能为您提供一个简单的 Powerbasic 示例,因为他们使用了我们开始的那个示例来为我们提供使之工作的最少代码。
使用 Powerbasic 控制台编译器
现在,一旦您编译了 rttdll.dll,您就可以使用标准的 Powerbasic Declare 命令声明 RTOS-32 库函数(或您在 C 中编写的任何自定义函数)中的任何调用。RTOS-32 提供了一个非常有限的 WIN32 API 仿真层,以及上面提到的几个您添加的 wrapper,现在 Powerbasic 编译器足以与 RTOS-32 一起工作。最好在您使用 Powerbasic 命令之前测试它们是否受 RTOS 支持,因为某些命令可能不受 RTOS-32 支持,而 Powerbasic 编译器会为某些命令集添加越来越多的自身运行时代码,这可能会使用 RTOS-32 尚未支持的 WIN32 API。但是,大部分基本命令集都可以与 RTOS-32 一起使用。我不是 C 程序员,但我能够修改他们提供的 C 初始化源文件,并使用免费的 Visual Studio 社区版进行编译,通过命令行编译器运行 Make 文件,从而编译了我所需的运行时 DLL。
有趣的地方来了!
一旦您设置好了编译最小 Powerbasic 控制台应用程序的基础,事情就开始变得有趣了。那么,一个人应该如何使用 Powerbasic 编写 RTOS-32 应用程序呢?
我发现最好的方法是使用条件编译器指令,这样我就可以编写一个支持 Windows 和 RTOS-32 的单一用户界面库。在 Windows 中,Powerbasic 提供了丰富的命令集来显示控制台(基于文本)应用程序。在 RTOS-32 中,我只需使用 RTOS-32 API 来完成许多事情,或者直接调用显卡。VGA 适配器上的文本屏幕可以通过内存地址轻松直接访问。因此,只需更改编译器指令使用的一个常量的值,我就可以将应用程序编译为完全在 Windows 中运行,或者完全在 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
请注意,在上面的示例中,RTOS-32 RTtarget
API 函数 RTDisplayString
使用 CDECL 调用约定进行参数传递,RTOS-32 就是这样做的,这与 Windows (WIN32) 和 Powerbasic 本身使用标准调用约定传递参数不同。通过在 DECLARE
调用中使用 CDECL 指令,您可以直接调用任何 RTOS-32 库模块函数(您已将其编译到 rttdll.dll 运行时库中)。
Powerbasic 支持以下参数传递格式
- BDECL – 这是 Pascal 调用约定
- CDECL – 这是 C 调用约定(RTOS-32 使用)
- SDECL – 这是 Windows 使用的标准调用约定,也是 Powerbasic 本身的默认约定
现在,开始受益于使用 Powerbasic 编写嵌入式代码
为什么在 RTOS-32 的嵌入式编码中使用 BASIC 而不是 C?因为 BASIC 比 C 更容易使用,而 Powerbasic 功能极其强大,提供了纯 C 的所有原始功能,同时又具有 BASIC 的易用性。Powerbasic 拥有软件行业中最强大的 string
处理引擎之一,如果您的应用程序进行了大量 string
操作,您将很高兴使用了 Powerbasic。Powerbasic 生成的可执行文件也具有原生 C 编译器所能达到的性能。BASIC 的语法比 C 更具可读性,维护软件将更加容易。现在,让我们看看 Powerbasic 您一定会用到的 RTOS-32 应用程序的某些功能。
低级别内存访问
使用 Powerbasic 可以轻松地进行直接内存操作。它提供了比 BASIC 早期时代的旧式 Peek 和 Poke 命令更强大的命令。首先,您可以轻松地移动大块内存。您可以使用指针来处理编译器支持的几乎任何数据类型,甚至在 string
s 中。您可以通过指向现有内存块的指针使用任何数据类型来定义局部数组(例如,定义一个存在于视频内存中的数组)。
多种编译器指令
通过使用编译器指令和宏,您可以轻松地编写一组例程,这些例程可以在原生 Powerbasic 命令和原生 RTOS-32 API 之间轻松切换。
内联汇编器
是的,Powerbasic 提供了内联汇编器,以便在必须直接对硬件进行非常低级别的编码时使用。
即使是控制台应用程序,也支持图形窗口
这很有趣。Powerbasic 控制台编译器可以编写原生的 Windows 控制台应用程序,然后显示一个弹出式图形窗口,并提供了一个广泛的图形库。虽然这不能与 RTOS-32 一起使用(它不模拟 Windows 图形),但可以通过条件编译来使用,因此在 Windows 中您可以使用原生图形,而在 RTOS-32 中,您可以编写自己的 VGA 兼容图形。由于 Powerbasic 可以轻松地将其图形窗口复制到 32 位 BGR 内存缓冲区中,您可以通过指针直接访问该缓冲区,因此您可以编写一个单一的图形引擎,该引擎可以在 Windows 图形窗口中运行(绘制到缓冲区然后复制到屏幕),或者在一个您定义的内存缓冲区中运行,然后复制到 VGA 内存。低分辨率 VGA 图形模式不支持 32 位缓冲区,但 RTOS-32 允许您访问 VESA BIOS 信息,因此您可以获取 VESA 32 位图形模式的指针。最好使用 640 x 480、800 x 600 和 1024 x 768 的分辨率。大多数 Intel 集成(图形)芯片支持这些 VESA 图形模式,它们可以提供一个可以直接访问的线性帧缓冲区。一旦有了 VESA 32 位线性帧缓冲区指针,就可以轻松地将内存从您自己的图形缓冲区移动到视频 RAM 缓冲区。通过编写图形引擎来绘制到我自己的图形内存缓冲区(我使用全局动态字符串来定义内存缓冲区),无论应用程序在 Windows 还是 RTOS-32 中运行,它都会是相同的。在 Windows 中,内存缓冲区会被复制到 Powerbasic 图形窗口,在 RTOS-32 中,它会被直接复制到线性帧缓冲区地址。
丰富的控制台文本命令
当为 Windows 编译时,Powerbasic 提供了一个丰富的控制台文本窗口命令集。现在,当编译器指令设置为 RTOS-32 时,您将不得不诉诸标准的低级别 VGA 端口调用或使用一些 RTTarget
模块 API。我最初使用了 RTTarget
API,但发现它们不像我期望的那么快(或者没有实现我需要的功能),所以我改用了直接调用视频内存。这使我能够执行各种技巧,而 Powerbasic 非常适合直接与内存通信。
为何使用双重编译?
在嵌入式目标上进行测试很慢,因为您必须先创建一个引导磁盘(或者您可以使用调试监视器并通过以太网连接传递),然后为 RTOS-32 系统编译所有内容,这会浪费宝贵的时间。在 Windows 上进行编译并使用 Powerbasic 运行应用程序速度极快(编译器是用汇编编写的,编译速度惊人)。通过在 Windows 中测试代码,并在其按预期工作后,只需更改一个编译器指令,就可以为 RTOS-32 编译。唯一需要在 RTOS-32 上进行的大量测试是您必须构建的用户界面库,但一旦构建好,大部分测试就可以在 Windows 上完成。
这些信息应该足以帮助您开始使用 Powerbasic 6.0 控制台编译器进行 RTOS-32 开发。使用 Powerbasic 的好处非常值得付出努力。您还可以将旧的 QBasic 和 Quick Basic 代码移植到嵌入式系统中使用。非 GUI(无类)的经典 Visual Basic 代码可以通过一些努力进行移植。RTOS-32 可以在最基本的 x86 系统上运行,例如那些使用 Vortex x86 芯片而非 Intel 芯片的系统。一个例子是 86Duino 板。现在有许多小型 x86 板,大小与 Raspberry PI 相当,例如 Lattepanda、Minnowboard Turbot 和 UP board。有许多 Mini-ITX x86 板可用,虽然体积更大,但仍然是一个相当小的包装。
是的,Powerbasic 非常适合嵌入式领域。如果您正在使用 Windows Embedded,那么编译器的 Windows(图形 GUI)版本可能是更好的选择。不妨尝试一下用 Powerbasic 进行 RTOS-32 开发。