PFS173-S16 Padauk是一家台湾超低成本微控制器供应商,因“3 美分 MCU”而臭名昭著。
该供应商本身仅提供带有专有 C 语言的封闭工具链。与此同时,部分基于逆向工程的开源独立工具链已面世。 仍有一些领域尚未完全理解。其中一个主题是 I/O 寄存器的初始状态。实际设备的行为与数据表有些不一致,这可能是由于勘误表或专有和开放工具链的不同行为造成的。
为了详细研究 Padauk PFS173-S16 上的这种行为,我们使用一个小程序在启动后直接将整个 I/O 空间复制到 RAM。由于无法对 I/O 寄存器进行索引访问,因此必须生成单独的指令来复制每个地址。 在对 MCU 外围设备进行正确初始化后,通过串行端口转储 I/O 区域备份。
上图显示了重置后整个 I/O 区域的转储。有 128 个可能的寄存器,但只有一些被使用和记录 - 只有少数寄存器实际上显示非零值。
一个有趣的方面是一些值是重复的,例如地址 00 和 01 中的 0xF0。这尤其引人注目,因为 0x01 处的寄存器实际上未使用。更多的实验表明,最后访问的寄存器的内容实际上是重复的。
这种行为看起来非常像浮动内部总线 - 如果访问的寄存器不存在,则不会将新信息写入总线;由于寄生电容,上次访问的逻辑电平被存储。如果这是一个安全关键设备,这当然会是一个很好的侧通道。但我们仍然可以利用这种效果来识别哪些 I/O 地址实际被使用,哪些没有被使用。
为了探测未使用的寄存器,我只需在 I/O 读取之前直接将 0x55 写入已知寄存器。如果下一次读访问是针对未使用的 I/O 位置,它将被读为 0x55 并且可以轻松识别。如上图所示,许多 I/O 地址现在读取为 0x55,因此未使用或只写。
大多数使用的寄存器可以轻松地与文档进行交叉检查。但是,有几个寄存器无法分配。第一个用红色标记为 0x23,还有一组用绿色标记为 0x2d、0x2e、02f。进一步探究发现,0x2d 显然是一个控制寄存器。复位状态为 0xE0。位 7-5、3、1、2 为 R/W,位 4 和 2 为 RO 或 WO。0x2e 和 0x2f 似乎是只读的。
JS 在 EEVBlog-Forum 上的出色侦查为绿色寄存器提供了非常有趣的解释:似乎早期的 padauk 微控制器包含一个称为电阻频率转换器 (RFC) 的外设,在经销商的旧数据表版本中仍可找到。这些寄存器的位配置与调查结果完全一致,因此很有可能匹配。目前尚不清楚为什么这个外设没有记录。
它仍然在 Padauk 的目录中提到,但没有列出具有此功能集的单个设备。未记录的寄存器 0x23(红色)的用途很容易识别:它实际上包含 ADC 的额外 LSB。似乎 Padauk 有一个用于 11 位 ADC 的标准 IP 块,该 IP 块也用于 PFS173。由于某种原因,它被声明为 8 位 ADC,而低三位未记录。可能存在噪音问题?
调查 RFC
JS之前找到的文档提供了基本的功能说明,并列出了寄存器,但细节有些少。没有什么是不能研究的……
上图显示了我对 RFC 的“C 型”操作的理解。它基本上由一个施密特触发器和一个接地开关组成。如果在 IO 引脚和正电源之间连接一个 RC 耦合器(如图所示),则输入电压将根据 RC 时间常数缓慢增加。如果达到某个触发电压,接地开关将使输入短路至地,直到达到较低的触发电压。每次发生这种情况时,计数器都会增加一。实际上,该电路形成了一个张弛振荡器。
通过评估固定间隔内的计数次数,可以测量电容或电阻的变化。
上表显示了寄存器映射。控制寄存器允许选择特定引脚。需要写入位 4 才能启动和停止计数器。
__sfr __at( 0x2d ) _rfcc;
__sfr __at( 0x2e ) _rfccrh;
__sfr __at( 0x2f ) _rfccrl;
#定义RFCC _rfcc
#定义RFCCRH _rfccrh
#定义RFCCRL _rfccrl
寄存器映射如上所示。使用 RFC 相当简单,如下所示:
RFCC = 0xc0 | 0x08 | 0x02 ; // 选择 PB6,设置为 C 模式,启用输出
uint16_t结果;
RFCC | = 1 << 4;// 启动 RFC
_delay_ms( 50 );
RFCC&=~( 1 << 4 );// 停止 RFC
结果=(RFCCRH<< 8 )|RFCCRL;
示波器图片显示了操作期间 RFC 引脚上的电压。在这种情况下,100nF 电容和 10 kOhm 电阻并联连接到 VDD。
可以清楚地看到,RC 元件的充电遵循指数规律。上触发电压为 4V,下触发电压约为 700 mV。我不清楚较低电压下振铃的来源,它似乎是 RFC 外围设备的产物。
接地开关的阻抗似乎相对较高。在这种情况下,使用 100nF 电容,大约需要 11 µs 才能放电。
当使用较低的电容值时,计数频率会相应增加。最小放电时间似乎是 1 个 IHRC 周期(此设备中的 IHRC 为 16 MHz = 62.5 ns)。在这种情况下,观察到电压下冲至 0V。很明显,当复位电压未正确定义时,RC 振荡器的运行将不稳定。似乎建议调整电容值,以便复位时间低于一个 IHRC 周期(复位电压为 0V),或明显高于(复位电压为 700 mV)。
另一个值得关注的参数是振荡器频率如何随电源电压的变化而变化。
我测量了 R=10 kOhm 和 C=100nF 的振荡器在不同 VDD 值下的频率。
可以看出,频率有一致的变化。这是因为触发电压根据电源电压而变化。较低的触发电压似乎由 0.2 * VDD 定义,而较高的触发电压则定义为约 0.8 * VDD。电压很可能直接来自带有电阻分压器的电源。
真正的对称松弛振荡器不会显示这种电压依赖性,但由于放电由接地开关定义,因此引入了对开关电压的依赖性。不过,1.5 V 电源差中约 10% 的变化对于许多应用来说应该足够了。
太棒了,看起来 RFC 确实像宣传的那样好用。我们可以用它做什么?