原创 关于 FREESCALE 的 DEMO 中 PSOR与PCOR 操作的常见错误

2013-8-13 17:09 1864 20 20 分类: 消费电子

关于 FREESCALE 的 DEMO 中 PSOR与PCOR 操作的常见错误

 

[引文]

在 freescale kinetis 提供的 sample code 中, 以及遍及各种论坛中, 常见对 GPIO register 中的 PSOR 与 PCOR 操作, 存在着 |= 的操作错误.

考虑到 toggle 一个 led 灯, 几乎是每一位入门选手的第一课. 遇到这种甚至是 Freescale 官方发布的代码错误(它并非致命, 逻辑上也有效), 想必对相关寄存器的理解, 会产生相当的困扰.

在 Allen 的 Coding 过程中, 这个 bug 也被 Allen 注意到, 并随手校正, 但是我们发现, 在 Freescale 的官方论坛中, 这个错误被工程师仔细提出, 并认为无法容忍.

参考: https://community.freescale.com/thread/309384

我们惊讶于国外 Engineer 是如此较真的同时, 也陷入一种思索中``` 工程世界, 要求明确清晰, 不容含糊过关.  这就是一个工程师对人对己的一份专业执着吗?

 

[详述]

1. 在 Freescale 提供的 sample 中, 我们常常见到这样的例子(来自于最基础的 blinky sample),

    /*
     * Initialize the Red LED (PTB18)
     */
    {
        /* Turn on clock to PortB module */
        SIM_SCGC5 |= SIM_SCGC5_PORTB_MASK;

        /* Set the PTB18 pin multiplexer to GPIO mode */
        PORTB_PCR18 = PORT_PCR_MUX(1);

        /* Set the initial output state to high */
        GPIOB_PSOR |= RED_SHIFT;

        /* Set the pins direction to output */
        GPIOB_PDDR |= RED_SHIFT;
    }

    /*
     * Initialize the Green LED (PTB19)
     */
    {
        /* Turn on clock to PortB module */
        SIM_SCGC5 |= SIM_SCGC5_PORTB_MASK;

        /* Set the PTB19 pin multiplexer to GPIO mode */
        PORTB_PCR19 = PORT_PCR_MUX(1);

        /* Set the initial output state to high */
        GPIOB_PSOR |= GREEN_SHIFT;

        /* Set the pins direction to output */
        GPIOB_PDDR |= GREEN_SHIFT;
    }

请注意被我们用粗体标记的代码, 这里是设置相应 RED LED, 以及 GREEN LED 输出高电平, 也就是熄灭 LED 的动作.

我们假设(如果有错误请告诉我), 这里的 |= 的用法是错误的, 尽管它逻辑上不影响熄灭 LED 的效果, 我们这里应该改为 = 表达方式:

 GPIOB_PSOR = RED_SHIFT;

其理由来自于"开发者圣经"( Reference Manual), 请看 PSOR与PCOR 的解释:

1.jpg
明确的, 对于 PSOR 与 PCOR register, 只有相关bit 为逻辑1时, 相关bit 有效, 分别执行为 1, 0(对于上述两个 register). 而任何为 0 的 bit, 都不会产生任何改变.
 
这意味着, 无关原始 PSOR 与 PCOR 的初始值为何, 使用 =, 当无关bit 为0时, 将不会造成在 out 状态上的任何变化, 或者最终影响到 PDOR 相关 IO 输出值的任何变化.
 
也就是说, 尽管 |= 执行了我们需求的逻辑操作, 但是 |= 浪费了 "codeword" 与 "machine cycle", 并可能带来不可预知的 "side effects".
 
故我们编程时, 对待 PSOR, PCOR register, 应使用 = 操作.
 
我们相信, 这种 |= 的误用, 是否深层次反应 Coder 并未曾仔细阅读 RM, 甚至尽管代码片段来自于 Freescale sample code 发布的官方团队.
 
对我们可能出现的理解错误, 如经发现请立即纠正我.
 
 
[PS]
事实上, 对于 ARM7 如 NXP LPC serial, 我们可以观察到同样功能的 register , IOSET 与 IOCLR, 我们的印象中, 未曾在 nxp 的代码中, 读到这种 |= 的错误用法.
 
Allen Zhan
于深圳福田
发表于 EETC

 

文章评论0条评论)

登录后参与讨论
我要评论
0
20
关闭 站长推荐上一条 /2 下一条