FWアップデート用のROMのアドレス配置に関して

お世話になっております。

カイロスです。

現在、以下の環境でファームウエアアップデートを実行しようとしている過程で、サンプルプログラムの処理で気になったところがあったので質問させてください。

(FW情報)
CPU:63T
ROM配置:更新用ROMと運用ROMを分ける
方法:シリアルを通じて、外部フラッシュメモリに更新プログラムを保存し、そこから随時プログラムを読み込んでROMを更新
参考サンプルプログラム:USBマスストレージ経由内蔵FlashROM書き換えプログラム(R01AN3503JJ0105)

内部のRAMが足りないので、サンプルプログラムを読み解いて、必要部分のみで実装できないか試行錯誤しているのですが、以下が気になったところです。

(質問内容)
・サンプルプログラムは、ROM配置が連続していることを前提としている?

サンプルプログラムで、128byteを切り出す処理にて、途中で書き出す長さがオーバーフローしそうになったら、
・128byteを埋める
・あふれた分を予備バッファに保存
・ROMに書き出す
・予備バッファの値を、次回のバッファに持ち越す

という流れになっているなと思いまして、そうなると、途中で書き出すROMのアドレスが大きく飛んだ場合、書き出したい箇所に書き出せないのでは?と思いました。
(すみません。サンプルプログラムをある程度読んだことがある人前提の説明になっていますが、ご容赦ください)

この私の認識があっているのか、それとも、実は私が読み解けていないのかあれば教えていただきたいです。


ちなみに、最終的な実装としては連続したアドレスになるので、上記の処理でも問題ないと思います。

以上、よろしくお願いいたします。

  • カイロスです。

    自己解決しました。

    サンプルプログラムでの下記の部分の解読が甘く、アドレスが離れていると、次回のバッファに持ち越されることを理解できました。

    ありがとうございます。

    /******************************************************************************
    * Function Name     : fu_create_writedata
    * Description       : Creates data divided into 1 times write-byte units.
    *                   : If a checksum error occurs, calls the error function.
    * Argument          : void
    * Return value      : FLASH_API_OK : Complete to prepare 1 times write byte data
    *                   : FLAHS_API_NG : Not complete write data
    ******************************************************************************/
    static fl_rtn_t fu_create_writedata(void)
    {
        fl_rtn_t ret_code = FLASH_API_OK;
        uint32_t tmp_addr_cnt;
        uint32_t read_cnt;
        uint32_t cnt;

        /* **** If there is not surplus data, set next data */
        if (0 == g_fl_write_data.addr)
        {
        /* ==== If there is no base address, set base address ==== */
            g_fl_write_data.addr = g_fu_mot_s_bin.addr & (0xFFFFFFFF - (ROM_WRITE_SIZE - 1)) - USB_WRITE_OFFSET;
        }
        /*option byte check*/
        if ((g_fu_mot_s_bin.addr >= FU_ROM_OPTION_BYTE_ADDRESS) && (g_fu_mot_s_bin.addr < FU_ROM_VECTOR_ADDRESS))
        {
            fu_error(ERROR_OPTION_BYTE);
        }

        if (g_fu_mot_s_bin.addr >= (uint32_t)FU_ROM_VECTOR_ADDRESS)
        {
            /*write ignore*/
            return FLASH_API_OK;
        }

        tmp_addr_cnt = (g_fu_mot_s_bin.addr - g_fl_write_data.addr - USB_WRITE_OFFSET);
       
        if ((tmp_addr_cnt + g_fu_mot_s_bin.len) > ROM_WRITE_SIZE)
        {
            /* ==== If receive data more than blank size ==== */
            /* Copy data until write buffer is full */
            for (cnt = 0; tmp_addr_cnt < ROM_WRITE_SIZE; cnt++)
            {
                g_fl_write_data.data[tmp_addr_cnt++] = g_fu_mot_s_bin.data[cnt];
            }
            read_cnt = cnt;

            /* Store the surplus data ==== */
            g_fu_mot_s_bin_reserve.addr = g_fu_mot_s_bin.addr + read_cnt - USB_WRITE_OFFSET;
            g_fu_mot_s_bin_reserve.len = g_fu_mot_s_bin.len - read_cnt;
            memcpy(g_fu_mot_s_bin_reserve.data,
                    &g_fu_mot_s_bin.data[read_cnt],
                    g_fu_mot_s_bin_reserve.len);
        }
        else
        {   /* ==== If receive data less than blank size ==== */
            /* Store all data */
            memcpy(&g_fl_write_data.data[tmp_addr_cnt],
                    g_fu_mot_s_bin.data,
                    g_fu_mot_s_bin.len);
        }

        if (ROM_WRITE_SIZE > tmp_addr_cnt)
        {
            ret_code = FLASH_API_NG;      /* **** If writing data buffer is not full, return NG **** */
        }
        return ret_code;
    }
  • ウチではその辺のサンプル一切読まずに全部自力で実装していますので話がずれているかもしれませんが...

    RX 系で CodeFlash 領域 (FFFx0000-FFFFFFFF) を更新しようとすると内蔵 CodeFlash を P/E モードにしなければならないです。 P/E モードにすると CodeFlash 領域を Read/Fetch できなくなる仕様。なので RX63T では書き込みプログラムを内蔵 RAM に転送して RAM 上から CodeFlash 書き込みを行わなければなりません。その辺は理解されていることとして

    RX63T ハードウエア仕様として CodeFlash へのプログラムは 128 バイト単位で行う義務がプログラマ側にあります。もしデータが 128 バイトに足らないまま次のアドレスが飛んでいる場合

    1. 前ブロックは後ろの足らない部分に FF を埋めて 128 バイトにしてから書く

    2.後ブロックは前の足らない部分に FF を埋めて 128 バイトにしてから書く

    ということになります。足らない部分に埋めると考えるとめんどくさいですが、実際の処理はバッファの初期値として全バイト FF を埋めておき、データがあればバッファを上書きするだけですので悩むところはないと思います。そもそも外付け SPI-Flash からマイコンプログラムを読み込むのならすべて FF な領域もお構いなしに書いちゃえばよいので何も考える必要はありません。

    ちなみにウチでも外付け SPI-Flash からマイコン CodeFlash を更新することはやっていますが SPI-Flash 読み込み+CodeFlash 更新だけなら 3KiB 程度で済んでいます (USB Mass Storage Device に構成していません)独自 USB ファンクションなプログラムを実装しても 6.4KiB ってとこで RAM が足らないってのはなさそうな気がしますが・・・