旧文备份:怎样利用好单片机上的存储器资源来实现OD的存储与访问
我们知道OD(对象字典)是CANopen的核心,所有功能都是围绕它开展的,是协议栈的数据中心,良好的OD实现是协议栈高效稳定运行的基础,而OD的实现最基本的一点就是怎么去保存它。因为OD的内容比较杂,读写属性上,有只读数据、只写数据、可读写数据;保存要求上有非易失和掉电丢失两种类型;数据类型上有字符型、整型、长整型等等;存储格式上有8位、16位、32位等。其它的不管,本文现只讨论怎么利用单片机的资源去尽量满足OD的存储需求。
有人会以为这还要讨论么?只读的就放在只读存储器中,可写的就放在RAM中,需要掉电保存的就放在非易失可读写存储器中。话是这么说,但实际上问题很多,罗列如下:
1. 对协议栈只读并不表示对应用程序只读。
2. 可读写而又掉电保存的数据不能放在RAM里。
3. 频繁读写的数据不能放在非易失存储器中,因为非易失存储器往往速度慢,有写次数限制。
4. 单片机资源有限,存取方式和读写速度有限值,因此得合理利用。
既然有这些问题,我们先对OD的数据进行分析分类:
1. 系统只读参数。自节点出厂就无需更改,例如,节点硬件序列号、软硬件版本等。
2. 过程数据对象。频繁读写,掉电无需保存。例如,采集的模拟量、待输出的开关量。
3. 系统配置参数。可读写,偶尔配置,大部分时间只读。
基本上所有的OD对象都可以归到这三类中去。下面再以AVR单片机为例说说单片机的几类存储资源以及其特点:
|
类型 |
运行中读写属性 |
访问速度 |
容量 |
特点 |
|
|
FLASH |
程序存储器 |
只读 |
一般 |
较大 |
操作方便但只能放程序和初始化只读数据,掉电不丢失 |
|
SRAM |
数据存储器 |
读写 |
最快 |
小 |
操作方便,速度快,掉电数据丢失 |
|
EEPROM |
数据存储器 |
读写 |
读一般,写很慢 |
小 |
操作复杂,写速度极慢 |
看到上面这个表,你会马上把OD的三类数据存放位置定下来吧,系统只读参数放在FLASH中;过程数据对象放在SRAM中;系统配置参数放在EEPROM中。
实际上确实该如此安排,但是所有问题的解决了?NO,NO,NO!OD中的数据对象是怎么安排进存储器的?系统启动怎么初始化?怎么去访问?下面提供一种方案:
出厂设置随程序一起写入FLASH,然后系统重器开始运行,在软件初始化过程中,程序将出厂默认的整个OD对象从FLASH 载入到RAM中去,不论是OD的那种分类的数据;之后如果判断是第一次运行,将用RAM中属于的统配置参数的那一类数据去初始化EEPROM,否则用EEPROM中的系统配置参数去重新覆盖对应的RAM映像。好了初始化完成,开始运行,因为所有OD数据都load到RAM中,因此OD对外可以提供统一快速的数据服务接口,外部的读操作就是直接读RAM,写则是先写RAM映像,然后再判断如果是OD的系统配置参数那一类则同时更新EEPROM。最后要注意一点就是OD的对象属性等信息一定要放在FLASH中,否则将是一个极大的RAM开销。
上面方案优点是在满足OD需求的前提下能够提供统一快速的OD访问接口;能够及时存储非易失性数据;并能在软件上实现恢复出厂设置的操作而不增加额外的出厂设置备份空间(在EEPROM中置一标志就行了,自己去想)。明显的优点也意味着明显的缺点,就是占用较多RAM空间,只读数据和非易失性数据都要映射到RAM中,浪费了一部分RAM,这将使得本来就紧张的RAM资源更加紧张,好在一般节点上的OD内容一般不多,而且现在RAM非常便宜。
上面的方案同样适用于其他单片机,基本上现在的单片机上都有FLASH和RAM,而即使有的单片机没有EEPROM,但是本身FLASH区是可以运行中在线写入的,也可以当EEPROM用(但此时最好就不要来一个写一个了,因为FLASH是页擦除的,比较耗时间,因此建议做成批量写入方式,OD的0x1010和0x1011对象有涉及),实在不行还可以外扩。
(于2007.11.08)
旧文备份:怎样利用好单片机上的存储器资源来实现OD的存储与访问的更多相关文章
- 怎样利用好单片机上的存储器资源来实现OD的存储与访问
转自:http://www.cnblogs.com/winshton/p/4897789.html 我们知道OD(对象字典)是CANopen的核心,所有功能都是围绕它开展的,是协议栈的数据中心,良好的 ...
- 旧文备份:简单CANOpen 协议说明
(十年前的旧文,不舍等扔) 创建日期:2005-11-17 修改日期:2005-11-17 文件名称:简单CANOpen 协议说明.doc 作者:winshton 版本:V1.0 (注:本文以24in ...
- 旧文备份:FFTW介绍
1. FFTW介绍 FFTW由麻省理工学院计算机科学实验室超级计算技术组开发的一套离散傅立叶变换(DFT)的计算库,开源.高效和标准C语言编写的代码使其得到了非常广泛的应用,Intel的数学库和Sci ...
- 旧文备份:rtlinux安装手册
前段时间接触了几天RTLinux,折腾了好几天才总算把它安装上,得益于Prof. Chang-Gun Lee的安装建议,觉得该文档可能会对准备尝试安装RTLinux的朋友们有帮助,本人英语很烂,也比较 ...
- 旧文备份: 怎样实现SDO服务
SDO是CANopen协议中最复杂的一部分,带有应答机制,有多种传输方式,并且完整的SDO功能节点需提供1个SDO server和多个SDO client,因此SDO的实现异常困难,协议多种传输方式的 ...
- 旧文备份:在CANopen网络中通过LSS服务设置节点地址和网络波特率
CANopen专有个子协议用来描述怎样去通过网络设置节点地址和波特率,就是CiA DSP-305,大伙都叫LSS协议,是Layer Setting Services的缩写,不太好翻译,可以叫底层设置服 ...
- 旧文备份:CANopen协议PDO的几种传输方式
(于2007.1.22) 由于PDO所传输的数据内容是无协议的且分配的标识符范围较SDO靠前,因此,其效率和优先级都是较高的,通常用于实时过程数据的传输. PDO是生产/消费类型的通讯方式,数据只有一 ...
- 旧文备份:CANopen协议中SDO服务
SDO是服务数据对象接口(Service Data Obiect)的缩写,顾名思义提供服务数据的访问接口,服务数据就是一些实时性要求不高的数据,一般是指节点配置参数,因此,SDO一般用来配置和获得节点 ...
- 旧文备份:CANopen中SYNC的功能和使用
SYNC是CANopen管理各节点同步数据收发的一种方法,相当于网络节拍,基于同步的PDO按照这个网络节拍来执行实时数据的收发.SYNC属于生产/消费型通讯方式,网络中有且只有一个SYNC生产者,一般 ...
随机推荐
- Dropping Balls UVA - 679(二叉树的遍历)
题目链接:https://vjudge.net/problem/UVA-679 题目大意:t组样例,每组包括D M 层数是D 问第M个小球落在哪个叶子节点? 每个节点有开关 刚开始全都 ...
- Unity Animation.CrossFade Animation.Play
using System.Collections; using System.Collections.Generic; using UnityEngine; public class PlayerCo ...
- MongoDB数据库常用操作
推荐文章 --- 一天精通MongoDB数据库 注意: monogdb数据在使用之后必须及时 mongodb.close()否则后台崩溃. 1. 删除文档中的一个字段 db.<集合名>.u ...
- 模拟登陆并爬取Github
因为崔前辈给出的代码运行有误,略作修改和简化了. 书上例题,不做介绍. import requests from lxml import etree class Login(object): def ...
- DP:凑零钱问题/最长非降子序列(C++)
你给出一定数额的钱 i 元给我,我利用手中的硬币(m元, j元, k元...)兑换等值的钱给你,要求硬币数最少. 举例:给出1-11的钱,手中硬币有1元,3元,5元. 重点是找到状态和状态转移方程. ...
- HDU 4336——Card Collector——————【概率dp】
Card Collector Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)To ...
- MyEclipse 比较常用的快捷键
Ctrl+D: 删除当前行 Alt+↓ 当前行和下面一行交互位置(特别实用,可以省去先剪切,再粘贴了) Alt+↑ 当前行和上面一行交互位置(同上) Alt+← 前一个编辑的页面 Alt+→ 下一个编 ...
- 简简单单谈WCF
另一个系统去访问另一个系统,就是需要使用到分布式通讯咯.. 1. webService .netfromwork3.5中存在 2. webapi 3. Wcf scop通讯协议 以上三种都是 ...
- one + two = 3
读入两个小于100的正整数A和B,计算A+B.需要注意的是:A和B的每一位数字由对应的英文单词给出. 输入 测试输入包含若干测试用例,每个测试用例占一行,格式为"A + B =", ...
- pymongo模块
import pymongo # 创建与MongoDB服务器的连接 mongoclient = pymongo.MongoClient(host='127.0.0.1', port=27017) # ...