本篇主要介绍,通过Jupyter在Microblaze Subsystems上使用C语言编程,实现一些简单的功能。
目录
前言
正文
一、软核PMODA、PMODB、RPI、ARDUINO
二、在软核上编程C程序
(1)加载基础覆盖
(2)定义子函数并调用
(3)数据类型转换
(4)申请指针,申请获取大块的内存空间存放数组数据等。
(5)创建类对象等
(6)注意事项
结尾
关于软核的知识,笔者所知比较少,个人浅显的理解为,软核是一种比较特殊的IP核,是一种微处理器IP核。在由电源、Microblaze以及FPGA构成的主板和内存所组成的最小系统下,我们可以像在PC机上使用C语言一样进行编程,从而对硬件进行操作。
下面是在网上找开源项目时偶然发现的关于软核编程的教程,所以拿来和大家一起分享。
笔者发现,pynq上可以用来编程的软核主要有PMODA、PMODB、RPI、ARDUINO,而这恰恰对应官方手册里的IOPs部分。仔细阅读过文档不难发现,这四个其实是开发板留出来的扩展接口,所以根据推测可知,每个接口对应的软核其实是在接口与扩展设备交互时,用于控制使用的。
我们可以打开开发板的文件base.py,从代码中也可以印证我们的推测。下面以ARDUINO为例,介绍如何在软核上编程。
load an overlay
from pynq.overlays.base import BaseOverlay
base = BaseOverlay('base.bit')
jupyter编程界面(此文件文末给出):
The %%microblaze
magic provides an environment where we can write the code and it takes a single argument - the Microblaze we wish to target this code at. This first example simply adds two numbers together and returns the result.
The functions we defined in the magic are now available for us to interact with in Python as any other function.
%%microblaze base.ARDUINO
#此处可以使用的有: PMODA、PMODB、RPI、ARDUINO
int add(int a, int b) {
return a + b;
}
add(4,6)
The main purpose of the Python bindings it to transfer data between the host and slave processors. For simple cases, any primitive C type can be used as function parameters and return values and Python values will be automatically converted as necessary.
%%microblaze base.ARDUINO
float arg_passing(float a, char b, unsigned int c) {
return a + b + c;
}
arg_passing(1, 2, 3)
Finally we can pass a void
pointer which will allow the Microblaze to directly access the memory of the host processing system for transferring large quantities of data. In Python these blocks of memory should be allocated using the Xlnk.cma_array
function and it is the responsibility of the programmer to make sure that the Python and C code agree on the types used.
%%microblaze base.ARDUINO
long long big_sum(void* data, int len) {
int* int_data = (int*)data;
long long sum = 0;
for (int i = 0; i < len; ++i) {
sum += int_data[i];
}
return sum;
}
from pynq import Xlnk
allocator = Xlnk()
buffer = allocator.cma_array(shape=(1024 * 1024), dtype='i4')
buffer[:] = range(1024*1024)
big_sum(buffer, len(buffer))
In the C code typedef
s can be used to create psuedo classes in Python. If you have a typedef
called my_class
then any functions that being my_class_
are assumed to be associated with it. If one of those functions takes my_class
as the first argument it is taken to be equivalent to self
. Note that the typedef
can only ultimately refer a primitive type. The following example does some basic modular arithmetic base 53 using this idiom.
%%microblaze base.ARDUINO
typedef unsigned int mod_int;
mod_int mod_int_create(int val) { return val % 53; }
mod_int mod_int_add(mod_int lhs, int rhs) { return (lhs + rhs) % 53; }
a = mod_int_create(63)
b = a.add(4)
print(b)
print(b.val)
有些C中的功能是不受支持的
There are some limitations to be aware of in the Jupyter integration with the Microblaze subsystem in particular the following things are unsupported and will result in the function not being available.
struct
s or union
s of any kindAll non void*
parameters are passed on the stack so beware of passing large arrays in this fashion or a stack overflow will result.
目前还不知道在软核中编程C的用途,不过应该是一个比较重要的功能,后续用到会再拿来说的。
代码文件链接:https://pan.baidu.com/s/1lMdQ2_WEfheJIyA7paCr_w
提取码:ambc
文章到这里就结束了,如果这篇文章帮助到了您,请点赞鼓励,谢谢!
技术交流请在下方评论区,笔者会尽快回复的!