This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] MSP430FR58471:自更新机制、此机制使用运行在 RAM 之外的 I2C

Guru**** 1099700 points
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/668367/msp430fr58471-self-update-mechanism-using-i2c-running-out-of-ram

器件型号:MSP430FR58471

您好!

我在论坛上找不到有关此主题的其他主题、因此我想制作一个主题。 我目前正在使用 RAM 外的 I2C 开发一种自更新机制。 我需要从 RAM 运行此代码、以便在正在运行的目标上接收并刷写完整的 TI-TXT 固件映像。 作为参考、我将使用 MSP430-GCC 编译器。

到目前为止、我已经能够将此代码下载到器件上、将其自身加载到 RAM 中并开始从 RAM 中执行。 但是、当我尝试向器件发送 I2C 时、会出现问题。 由于某种原因、我的 I2C ISR 未被正确调用。 我已经介绍了用户指南的许多章节、我发现一件有趣的事情是通过 SYSRIVECT 使用基于 RAM 的中断矢量。  也许这是在 RAM 之外运行 ISR 所必需的? 如果能帮助您了解为何 ISR 未被正确调用、将会很好、总之、我们也欢迎您提出建议。

我已经包含了我要跳转到的代码。 在执行此操作之前、我将此"更新程序"代码编程到主闪存的某个部分、然后将 SP 和 PC 设置为跳转。

#include 

define str (s)#s
#define ENQUOTE (s) str
(s)#define DO_pragma (x)_Pragma (#x)
#define location (var_name、address) DO_pragma (location (var_name、address)
)#define attribute_section (x)__attribute ((((((section (x)))))

)#define RAM_base 0x1c00
#define RAM_END 0x1ffe
#define BEGIN_RAM_execution()\
asm ("mov #"ENQUOTE (RAM_END)"、R1");\
asm ("br #"ENQUOTE (RAM_base))
#define CODE_BASE 0x8000
#define MAIN_CODE_OFFSET 0x0400
#define BEGIN_ROM_execution () asm ("br #0x8400")
#define I2C_INT_vector 0xxee

#define SCL (1 << 7)
#define SDA (1 << 6)
#define MCU_IRQ (1 << 4)

#define XT1_LF_MODE (LFXTDRIVE_0 + 0x0100)

#endif //defined (__MSP430FR58471__)

寄存器 unsigned int i2c_byte asm ("R4");
寄存器 unsigned int i2c_temp asm ("R5")
;

*在 main 中定义 unsigned intrasc / unsigned inu_mspu 地址("r10)*需要检查#gmspc / unsigned inu_entr/ unsigned inu_mspu
0x1
#define GSC_stage2_ADDR 0x2
#define GSC_stage2_erase 0x3
#define GSC_stage2_word 0x4
#define GSC_stage2_PROG 0x5

void attribute_section (".text")__attribute__((优化("OS"))) main (void){

//*将您的自身从主 ROM 复制到 RAM */
asm ("mov #2、R5"); //存储编号2
asm ("mov #main_entry, r7"); //存储 main_entrance 位置
asm ("mov #the_end、R8"); //存储 the_end 位置
asm ("mov #"ENQUOTE (RAM_base)"、R9");//存储 RAM_base 位置
asm ("memcpy:"); // memcpy 标签(复制循环从此处开始)
asm ("mov @r7、0 (R9)"); //将闪存内容移动到 RAM
asm ("add r5、r7"); //将闪存指针递增2
asm ("添加 R5、R9"); //将 RAM 指针递增2

asm ("cmp r7、r8"); //检查我们是否已到达_end 位置
asm ("jne memcpy"); //如果不是,重复循环

//将 I2C 中断矢量地址写出到矢量表(0xcee)*/
asm ("mov #main_entry, r7"); //存储 main_entrance 位置
asm ("mov #i2c_isr、R8"); //存储 i2c_ISR 位置
asm ("subr7、r8"); //从 i2c_isr addr 中减去 main_entrance addr、R8具有偏移
asm ("添加#"ENQUOTE (RAM_base)"、R8"); //添加 RAM_base 的值以获取 i2c_ISR
asm 的新位置("mov #"ENQUOTE (I2C_INT_vector)"、R9");//存储 i2c 中断矢量
asm 的位置("mov R8、0 (R9)"); //将 I2C ISR 地址写出到矢量表

//跳转到 RAM 并执行*/
begin_RAM_execution();

asm ("main_entration:");
while (1);//循环此处,以便 I2C ISR 具有返回
到}

void attribute_section (".text")__attribute__(优化("O0");//循环,这样 I2C ISR (void
= 021E_)(void _switch)(void = 0x1e_)、iv_i_range (in)(void 0c)(void _isr_)(void 0c)(in_isr
情况0x06: //向量6:STTIFG (启动条件)
(笑声) //此处的其余 UCB0IFG 案例
默认值:
break;
}
}

void attribute_section(".text") the _end(){
}

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好、Robert、

    感谢您发布问题。
    我正在为您研究这个问题、并将尽快返回给您。

    此致、
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    感谢您的回答 Ling、如果您想了解更多详细信息、请告诉我。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好、Robert、

    您在哪里设置了 SYSRIVECT? 代码中没有看到它。

    另一个选项是使用 I2C 轮询而不是使用中断。
    www.ti.com/.../slaa600d.pdf

    此致
    Kc
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    实际上、我切换到了 I2C 轮询方法、并成功完成了更新。
    *对于尝试执行此操作的任何人、请确保您的 DCO /时钟分频器设置为您提供足够快的时钟、否则您将会错过计时。

    我现在遇到的唯一问题是为了计算 CRC 而擦除主存储器。 我的目的是擦除0x8000-0xF7FF 之间的存储器部分。 但是、无论我使用哪种方法、将这些存储器地址设置为0x00都将失败。 在可能由于复位而无法响应后续 I2C 调用之前、它会成功获取前0xa00字节左右的数据。 我尚未启用 MPU、这些地址不在空存储器中、并且我已将12MHz 时钟的 FRAM 等待状态设置为1、因此我不确定导致此情况的原因。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    我通过写入0xff 而不是0x00来成功地"擦除"闪存、并且只需更改我的 CRC 函数来解决这个问题。
    我知道非 FRAM MCU 使用0xff 擦除、这导致我尝试擦除、但我无法解释为什么 FRAM 器件需要这么做。