页次: 1
我想在RTT中,通过RTT提供的API,分配一片内存,这片内存不在cache的控制范围,这样使用这片内存就没有cache一致性的问题,我想问在RTT中有无这样的API?
你的需求似乎Cortex-M架构上的MPU模块能满足,通过定义一个连续的地址片为MPU_ACCESS_NOT_CACHEABLE来实现。
一旦定义后,也无需OS进行什么特殊操作,普通malloc即可。
但至于F1C100s的ARM926EJ-S内核,应该只有MMU可用,好像没有类似的功能。
还是要在驱动里手动调用诸如:mmu_invalidate_dcache()、mmu_clean_dcache()等函数来操作cache。
总之,上述功能应该不是OS的API范畴,与CPU架构关系很大。具体可以参考RTT的libcpu/arm/arm926里的相关实现。
1、在稳定良好的电磁环境下测试,先排除硬件干扰。
2、关狗,再一点点使用各种输出手段增加运行状态的输出,同时保证稳定复现故障。
输出手段可以是串口打印、LED或IO特定频率的翻转;
通过输出,至少应该能明确识别几个状态:复位、运行到业务逻辑的某个循环阶段。
printf()有时候还真是万能的调试手段。
3、不要改变之前故障时的任何软件配置,保证故障复现率。接下去,就靠观察,看规律。
就算有野指针,也一定会在特定逻辑阶段后才出现,起码让你有个大致审核代码的范围。
特别注意下栈、堆的空间是否分配足够,不论是否用了RTOS,栈或堆的溢出故障导致的现象,有时候看起来会有点随机,尤其是程序需要与外部互动的时候。
上述操作的唯一目的,就是缩小排查范围,如果是软问题,知道了大致代码范围,仔细读几遍代码后,就等着拍大腿吧。
lvgl在x86平台上用SDL库来实现的跨平台兼容,能接受的输入包括键盘、鼠标和鼠标滚轮,在例程里的main.c里就有,打开相应的条件编译开关就行了。
具体的处理逻辑在indev/keyboard.c里面实现,用keyboard_read()来提取键值。
main.c
while(1) {
/* Periodically call the lv_task handler.
* It could be done in a timer interrupt or an OS task too.*/
lv_task_handler();
usleep(5 * 1000); /*Just to let the system breath*/
#ifdef SDL_APPLE
SDL_Event event;
while(SDL_PollEvent(&event)) {
#if USE_MOUSE != 0
mouse_handler(&event);
#endif
#if USE_KEYBOARD
keyboard_handler(&event);
#endif
#if USE_MOUSEWHEEL != 0
mousewheel_handler(&event);
#endif
}
#endif
}
keyboard.c
bool keyboard_read(lv_indev_data_t * data)
{
data->state = state;
data->key = keycode_to_ascii(last_key);
return false; /*No more data to read so return false*/
}
void keyboard_handler(SDL_Event * event)
{
/* We only care about SDL_KEYDOWN and SDL_KEYUP events */
switch(event->type) {
case SDL_KEYDOWN: /*Button press*/
last_key = event->key.keysym.sym; /*Save the pressed key*/
state = LV_INDEV_STATE_PR; /*Save the key is pressed now*/
break;
case SDL_KEYUP: /*Button release*/
state = LV_INDEV_STATE_REL; /*Save the key is released but keep the last key*/
break;
default:
break;
}
}
static uint32_t keycode_to_ascii(uint32_t sdl_key)
{
/*Remap some key to LV_GROUP_KEY_... to manage groups*/
switch(sdl_key) {
case SDLK_RIGHT:
case SDLK_KP_PLUS:
return LV_GROUP_KEY_RIGHT;
case SDLK_LEFT:
case SDLK_KP_MINUS:
return LV_GROUP_KEY_LEFT;
case SDLK_UP:
return LV_GROUP_KEY_UP;
case SDLK_DOWN:
return LV_GROUP_KEY_DOWN;
case SDLK_ESCAPE:
return LV_GROUP_KEY_ESC;
#ifdef LV_GROUP_KEY_BACKSPACE /*For backward compatibility*/
case SDLK_BACKSPACE:
return LV_GROUP_KEY_BACKSPACE;
#endif
#ifdef LV_GROUP_KEY_DEL /*For backward compatibility*/
case SDLK_DELETE:
return LV_GROUP_KEY_DEL;
#endif
case SDLK_KP_ENTER:
case '\r':
return LV_GROUP_KEY_ENTER;
default:
return sdl_key;
}
}
Zodiac 说:建议看下Android源码里的,hardware/ril/reference-ril,很有参考价值。
是这个吗? https://github.com/mozilla-b2g/android-hardware-ril/tree/master/reference-ril
是的。建议直接去同步最新版看看,跟踪下变化:
Zodiac 说:既然都是基于gnu工具链,试试Clion也可以啊。JetBrains家的IDE,素质都不错的。原生支持CMake构建,整合的GDB调试器,随意连Jlink,用着很舒服。
Clion要钱啊(
要钱也比MDK/IAR便宜啊。就算买JetBrains全家桶,用最高企业类授权,一年是649美刀一个工位,还不算每年的优惠活动和续订第三年及后续的直接对折。创业公司可申请5年对折优惠,对开源项目和教育机构直接免费。
MDK Pro现在是3800美刀一年一工位,还不算国内代理捆绑式销售按公司规模给你来个最低消费一次性买N个工位的这种手段。
IAR这位抢钱专业户就不说了。
这两平台要不是靠着自家的优化编译器撑台面,哪家公司还愿意每年大把大把的买授权啊。更不用说,他们这整整落后一代的编辑器,不怎么好用的构建系统,和对Win平台的绑定。
对绝大多数的嵌入式应用,GCC还真够用了。
配个顺手的跨平台IDE,用自己熟悉的构建系统(CMake或SCons,甚至是做成泛用模版的makefile),调试靠GDB,仿真跑QEMU,整体体验比MDK/IAR好。
现在MDK也像Altium一样,开始挨家挨户发律师函了,何不乘此机会换个更自由的开发环境?
况且,MDK平台的适用场景仅限RTOS,而基于GCC工具链的环境,换个编译器就能上Linux,无缝衔接。
超级萌新 说:兆易厚积薄发,前期要忍受没有MDK/IAR JLINK的阵痛.
不过有网友说eclipse + openocd 更好用
不知道为何都用eclipse? 为何不在vscode下搞一套呢?打开速度比eclipse快。
vscode 的定制比eclipse麻烦(或者说,没eclipse下面来得自由)。
没有原生的构建系统,都是用插件搭的(或者说贴膏药凑的)。
C/C++的支持也是各种拼,搞得这工具定位很尴尬,上不上下不下的。
轻量不及Sublime Text,专业不及MDK/IAR。
既然都是基于gnu工具链,试试Clion也可以啊。JetBrains家的IDE,素质都不错的。原生支持CMake构建,整合的GDB调试器,随意连Jlink,用着很舒服。
宋宝华老师的书不推荐,不过他早期参与翻译的《精通Linux设备驱动程序开发》值得一读。
嵌入式linux这块,核心技术没怎么变,但新工具和内核驱动开发的新东西还是不少,主要侧重方法和实践,变化很快的东西没必要去啃过时的书。
618要囤的书,建议收《UNIX环境高级编程》之类的不容易过时的大部头。
比较推荐一些培训机构的讲义,https://bootlin.com/docs/
https://bootlin.com/doc/training/embedded-linux/
https://bootlin.com/doc/training/linux-kernel/
https://bootlin.com/doc/training/yocto/
https://bootlin.com/doc/training/buildroot/
配合动手实验,很快能入门。再要深入,内核源码会是更好的资源。
https://www.sunrom.com/p/m62429-digital-pot
可以参考下应用电路和代码。两线控制,用起来蛮方便。
这似乎不关“驱动是否要放用户态”的事吧?
BSP包完全可以独立出来开发的:device tree能单独编译,自定义的驱动能编译成内核模块,只在编译的时候借助下内核的构建系统。
楼主的需求是否只是想 “分清内核、驱动、应用之间的开发界限,降低互相间的耦合” ?
其实,内核对设备的抽象做了不少工作了,很大程度降低了应用层使用具体设备的复杂度。
应用通过统一的devfs、sysfs或者proc来与驱动进行交互。从结果来看,就是降低了应用与驱动之间的耦合。
楼主所提的 “提供一个统一、固定的平台给产品开发人员” 需求 ,只要保证 “同类设备,保持统一规范的devfs、sysfs、procfs的访问接口” ,即可满足。
楼主又提到 “应用启动时自己控制外设驱动的加载和on-chip驱动的加载,以及外设驱动和on-chip驱动的交互”,这只能是基于内核托管的情况下才能部分实现,还是以内核模块为单位的简单管理。更细粒度的管理,应用层 ‘不应’ 也不能直接去触碰。驱动涉及到的资源协调和配置都应该是OS一级去处理的事,而不是一个以进程为单位的APP该操心的事。
linux 把驱动拉到内核态,是为了最大化运行效率。qnx 为代表的微内核把驱动之类的做到用户态,是为了运行时的稳定而牺牲了运行效率。
这是个不同场景利弊取舍的事,也不能一下子分清哪种做法就一定是好的。
但不论驱动放在何处,其与应用层之间的接口保持统一和固定了,就能给开发人员提供一个稳定的开发环境。
原作者已有相关的移植工作,详见:
文档: https://blog.littlevgl.com/2018-01-03/linux_fb
源码: https://github.com/littlevgl/lv_projects
在matplotlib-3.0.2版的代码里发现如下内容:
该库会自行搜索OS上可用的agg后端,次序为,
for candidate in ["macosx", "qt5agg", "qt4agg", "gtk3agg", "gtk3cairo", "tkagg", "wxagg", "agg", "cairo"]:。
那么,只要ubuntu 14 安装了可用的UIagg的库,似乎就能解决问题。
源码位于:https://pypi.org/project/matplotlib/#files
# Line892 @matplotlib/_init_.py
class RcParams(MutableMapping, dict):
...
def __getitem__(self, key):
...
elif key == "backend":
val = dict.__getitem__(self, key)
if val is rcsetup._auto_backend_sentinel:
from matplotlib import pyplot as plt
plt.switch_backend(rcsetup._auto_backend_sentinel)
# Line177 @matplotlib/pyplot.py
def switch_backend(newbackend):
"""
Close all open figures and set the Matplotlib backend.
The argument is case-insensitive. Switching to an interactive backend is
possible only if no event loop for another interactive backend has started.
Switching to and from non-interactive backends is always possible.
Parameters
----------
newbackend : str
The name of the backend to use.
"""
close("all")
if newbackend is rcsetup._auto_backend_sentinel:
for candidate in ["macosx", "qt5agg", "qt4agg", "gtk3agg", "gtk3cairo",
"tkagg", "wxagg", "agg", "cairo"]:
try:
switch_backend(candidate)
except ImportError:
continue
else:
rcParamsOrig['backend'] = candidate
return
....
一套py代码在不同OS版本上表现不同,多数是OS环境差异引起的。
从问题log来看,已经提示ubuntu 14的环境上,导入的matplotlib用了agg才出的问题。然而,该后端的确只支持写入文件,不支持屏幕绘制。
由此,估计问题是出在OS上,没有可用UI版本的agg。例如:Qt5Agg Qt4Agg Gtk3Agg GTK3Cairo TkAgg WxAgg。
或者是,部署matplotlib时默认为agg;需要导入后手动由代码指定一个可用UI的agg(前提:OS环境必须有相关lib)。
相关py调用,例如:matplotlib.use('GTK')
参考:
https://matplotlib.org/faq/usage_faq.html#what-is-a-backend
https://stackoverflow.com/questions/4930524/how-can-i-set-the-backend-in-matplotlib-in-python
https://github.com/rreilink/pylvgl
又一个lvgl的python绑定,只可惜目前仅支持到 v5.1.1 版。与最新版相比,少了一些绘图模块。
可以拿来作为熟悉API和快速设计界面的一个工具。
使用效果与mpy版相同。
使用步骤:
1、下载
git clone --recurse-submodules https://github.com/rreilink/pylvgl.git
2、按需修改分辨率
lv_conf.h:LV_HOR_RES,LV_VER_RES
3、生成扩展模块
$ python3 ./setup.py
4、安装PyQt5
$ pip3 install PyQt5
5、进入python交互界面,导入模块,开始体验。
$ python3
Python 3.6.5 (default, May 9 2018, 10:02:20)
[GCC 4.2.1 Compatible Apple LLVM 9.1.0 (clang-902.0.39.1)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>>
>>> from pylvgl import Demo, lvgl
>>> d = Demo()
>>>
>>> b1 = lvgl.Btn(lvgl.scr_act())
>>> b1.set_size(200,50)
>>> b1.align(b1.get_parent(), lvgl.ALIGN_IN_LEFT_MID, 0, 0)
>>>
>>> l1 = lvgl.Label(b1)
>>> l1.set_text('LittlevGL')
>>>
>>> lm = lvgl.Lmeter(lvgl.scr_act())
>>> lm.align(cal.get_parent(), lvgl.ALIGN_IN_LEFT_MID, 300, 0)
>>> lm.set_range(0,100)
>>> lm.set_value(10)
>>>
>>> style_lm1.line_width = 4
>>> style_lm1.body_main_color = 0x2200
>>> style_lm1.body_grad_color = 0x0022
>>> lm.set_style(style_lm1)
>>>
>>> lb2 = lvgl.Label(lm)
>>> lb2.set_text('10%')
>>> lb2.align(lm, lvgl.ALIGN_CENTER, 0, 0)
附:
步骤5中所导入的辅助模版,另存为pylvgl.py,放在工程目录。
import lvgl
from PyQt5 import QtGui, QtWidgets, QtCore
class LvglWindow(QtWidgets.QLabel):
def __init__(self):
super().__init__()
self.setMinimumSize(lvgl.HOR_RES, lvgl.VER_RES)
self.setMaximumSize(lvgl.HOR_RES, lvgl.VER_RES)
self.timer = QtCore.QTimer()
self.timer.timeout.connect(self.update)
self.timer.start(10)
def mousePressEvent(self, evt):
self.mouseMoveEvent(evt)
def mouseReleaseEvent(self, evt):
self.mouseMoveEvent(evt)
def mouseMoveEvent(self, evt):
pos = evt.pos()
lvgl.send_mouse_event(pos.x(), pos.y(), evt.buttons() & QtCore.Qt.LeftButton)
def update(self):
# Poll lvgl and display the framebuffer
for i in range(10):
lvgl.poll()
data = bytes(lvgl.framebuffer)
img = QtGui.QImage(data, lvgl.HOR_RES, lvgl.VER_RES, QtGui.QImage.Format_RGB16)
pm = QtGui.QPixmap.fromImage(img)
self.setPixmap(pm)
class Demo():
def __init__(self):
self.app = QtWidgets.QApplication([])
self.window = LvglWindow();
self.window.show()
def run(self):
self.app.exec_()
补充:
该工程使用bindingsgen.py和sourceparser.py两个自定义工具,及lvglmodule_template.c模版,自动解析lvgl源码并生成编译扩展模块所需的接口代码,即lvglmodule.c。
上述工具基于pycparser模块,且根据lvgl定制,与API版本关联,目前支持到v5.1.1。
有兴趣的朋友,可以尝试自行编译。
$ pip3 install pycparser
$ python3 ./bindingsgen.py
SSH X11 Forwarding了解一下。
https://itekblog.com/ssh-x11-forwarding-display-using-mobaxterm/
关注GUI开发。个人认为win32 api式的GUI开发模式太老了。现在硬件越来越强大,趋势是CSS/XML/JSON+JS/LUA/PYTHON/HTML5开发模式
http://blog.qt.io/cn/2018/08/15/qt_on_microcontrollers_mcu/
QT已经开始尝试向低端平台拓展了,其中就包括QML模块。不知道是否会做进一步的优化,对于Cortex-M4/7平台来说,还是有点臃肿。还是很期待啊,QT生态圈的诱惑力还是很大的。
页次: 1