问答

汇集网友智慧,解决技术难题

21ic问答首页 - ATMEGA4809的时钟配置疑问?

时钟配置 atmega4809 TE ST define model

ATMEGA4809的时钟配置疑问?

JackTang19942021-09-02
在使用AVR单片机时,发现设置MAIN时钟时需要对CCP寄存器进行解锁操作(4个内指令完成)。在查看了protected_io.S文件后,发现此使用了汇编来解锁以保证能在4个指令周期内完成时钟配置。但是有一个疑问就是,调用protected_write_io函数来操作CCP寄存器时,汇编代码中使用的寄存器为R20和R24为什么不是其他寄存器呢?#include <assembler.h>
        PUBLIC_FUNCTION(protected_write_io)

#if defined(__GNUC__)

#ifdef RAMPZ
        out     _SFR_IO_ADDR(RAMPZ), r1         // Clear bits 23:16 of Z
#endif
//为什么使用R24和R22以及R20,为什么不能是其他寄存器。这些寄存器都是protected_write_io函数的形参
        movw    r30, r24                // Load addr into Z
        out     CCP, r22                // Start CCP handshake
        st      Z, r20                  // Write value to I/O register
        ret                             // Return to caller

#elif defined(__IAR_SYSTEMS_ASM__)

# if !defined(CONFIG_MEMORY_MODEL_TINY) && !defined(CONFIG_MEMORY_MODEL_SMALL) \
                && !defined(CONFIG_MEMORY_MODEL_LARGE)
#  define CONFIG_MEMORY_MODEL_SMALL
# endif
# if defined(CONFIG_MEMORY_MODEL_LARGE)
        ldi     r20, 0
        out     RAMPZ, r20              // Reset bits 23:16 of Z
        movw    r30, r16                // Load addr into Z
# elif defined(CONFIG_MEMORY_MODEL_TINY)
        ldi     r31, 0                  // Reset bits 8:15 of Z
        mov     r30, r16                // Load addr into Z
# else
        movw    r30, r16                // Load addr into Z
# endif
# if defined(CONFIG_MEMORY_MODEL_TINY)
        out     CCP, r17                // Start CCP handshake
        st      Z, r18                  // Write value to I/O register
# elif defined(CONFIG_MEMORY_MODEL_SMALL)
        out     CCP, r18                // Start CCP handshake
        st      Z, r19                  // Write value to I/O register
# elif defined(CONFIG_MEMORY_MODEL_LARGE)
        out     CCP, r19                // Start CCP handshake
        st      Z, r20                  // Write value to I/O register
# else
#  error Unknown memory model in use, no idea how registers should be accessed
# endif
        ret
#else
# error Unknown assembler
#endif

        END_FUNC(protected_write_io)
        END_FILE()



回答 +关注 6
2781人浏览 1人回答问题 分享 举报
1 个回答
  • 查看反汇编代码,在执行protected_write_io函数时,可以看到是使用了R20、R22、R24、R25这几个working寄存器。所以猜想可能是编译器特定的操作。意思就是会将函数的形参用R20、R22、R24这种普通寄存器保存。验证:
    新建一个3个参数的函数,发现在反汇编窗口看到的汇编代码也是使用R20、R22、R24
    结论:
    所以得出函数调用所使用的working寄存器是一样的,不会变。所以在protected_io.S文件中汇编代码中使用的working寄存器固定为R20、R22、R24、R25。再解释下为会汇编文件protected_write_io反汇编后会发现有4个寄存器(R20、R22、R24、R25),这是因为使用了指针的形式,指针在8位单片机中是使用16位来表示的,所以需要2个8位的寄存器来保存。


您需要登录后才可以回复 登录 | 注册