CQ-FRK-FM3 基板用FM音源プログラム -- TGFM3 (8)

gcc の「-mstructure-size-boudary=」オプションの指定による違いについて、ハードウェア・ウォッチドッグ・タイマにアクセスする部分を具体例として示します。
まず、「mb9b610t.h」中のハードウェア・ウォッチドッグ・タイマの union / struct 定義部分を下に示します。

/* HWWDT_MODULE register bit fields */
typedef struct stc_hwwdt_wdg_ctl_field
{
  __IO uint8_t INTEN : 1;
  __IO uint8_t RESEN : 1;
} stc_hwwdt_wdg_ctl_field_t;

typedef struct stc_hwwdt_wdg_ris_field
{
  __IO uint8_t RIS : 1;
} stc_hwwdt_wdg_ris_field_t;

/* Hardware watchdog registers */
typedef struct
{
  __IO uint32_t WDG_LDR;
  __IO uint32_t WDG_VLR;
       union {
         __IO uint8_t                   WDG_CTL;
              stc_hwwdt_wdg_ctl_field_t WDG_CTL_f;
        };
       uint8_t  RESERVED0[3];
  __IO uint8_t  WDG_ICL;
       uint8_t  RESERVED1[3];
       union {
         __IO uint8_t                   WDG_RIS;
              stc_hwwdt_wdg_ris_field_t WDG_RIS_f;
       };
       uint8_t  RESERVED2[3055];
  __IO uint32_t WDG_LCK;
}FM3_HWWDT_TypeDef;

この定義が正しくコンパイルされた場合の、アドレス・オフセットの割り付けは下の図のようになります。

この状態で、「system_mb9bf61xt.c」 ファイル中の SystemInit() 関数の始めの部分でハードウェア・ウォッチドッグ・タイマを停止している記述、

  FM3_HWWDT->WDG_LCK = 0x1ACCE551; /* HW Watchdog Unlock */
  FM3_HWWDT->WDG_LCK = 0xE5331AAE;
  FM3_HWWDT->WDG_CTL = 0;          /* HW Watchdog stop */

は、次のようにコンパイルされます。 
最適化オプションは「-Os」、つまりサイズを優先する指定にしています。

00000240 <SystemInit>:
 240:  4b28       ldr     r3, [pc, #160]   ; (2e4)
 242:  4a29       ldr     r2, [pc, #164]   ; (2e8)
 244:  2101       movs    r1, #1
 246:  f8c3 2c00  str.w   r2, [r3, #3072]  ; 0xc00
 24a:  4a28       ldr     r2, [pc, #160]   ; (2ec)
 24c:  f8c3 2c00  str.w   r2, [r3, #3072]  ; 0xc00
 250:  2200       movs    r2, #0
 252:  721a       strb    r2, [r3, #8]

          . . . < 中略 > . . ..

 2e4:  40011000   .word   0x40011000
 2e8:  1acce551   .word   0x1acce551
 2ec:  e5331aae   .word   0xe5331aae

アドレス 0x246、0x24C の「str.w」命令でロック・レジスタ (WDG_LCK) にロック解除の固定パターンを書き込んでおり、そのオフセットは正しく 0xC00 になっています。
gcc 自体のデフォルトでは、「-mstructure-size-boundary=32」(長いので以降は 「-ms-s-b=」と略記)ですが、ARM 用 gcc としては -ms-s-b=8 とするのが通例のようです。
したがって、普通は特に -ms-s-b= のオプションを指定しなくても正しくコンパイルされます。
しかし、なぜか PizzaFactry8 (CQ 版) 付属の gcc ツールチェインでは、-ms-s-b=8 の設定になっていないようで、-ms-s-b=8 オプションを明示しないと正しくコンパイルされません。
一般の ARM 用 gcc で -ms-s-b=32 オプションを指定した場合、および、PizzaFactory8 (CQ 版) のデフォルト状態では、下の図のように、アドレス・オフセットが正しくなりません。

図の緑色のドットの部分は、-ms-s-b=32 のオプション指定により、ビット・フィールド換算で 32 ビットに満たない数のビットをパッキングする際に付加されるパディング部分を示しています。
この「余計」な部分は合計で 8 バイトあり、WDG_LCK へのオフセットが正しくは 0x0C00 なのに、0x0C08 となっています。
この状態でコンパイルした結果を下に示します。

00000240 <SystemInit>:
 240:  4b2a       ldr     r3, [pc, #168]   ; (2ec)
 242:  4a2b       ldr     r2, [pc, #172]   ; (2f0)
 244:  2101       movs    r1, #1
 246:  f8c3 2c08  str.w   r2, [r3, #3080]  ; 0xc08
 24a:  4a2a       ldr     r2, [pc, #168]   ; (2f4)
 24c:  f8c3 2c08  str.w   r2, [r3, #3080]  ; 0xc08
 250:  2200       movs    r2, #0
 252:  721a       strb    r2, [r3, #8]

          . . . < 中略 > . . ..

 2ec:  40011000   .word   0x40011000
 2f0:  1acce551   .word   0x1acce551
 2f4:  e5331aae   .word   0xe5331aae

アドレス 0x246、0x24C の「str.w」命令のオフセットは 0xC08 であり、正しくない値になっています。
コントロールレジスタ (WDG_CTL) のオフセットは 0x08 で正しいのですが、ロック・レジスタに正しくアクセスできていないのでロックが外れず、ハードウェア・ウォッチドッグは解除されないままとなります。
1 バイト単位でのパッキングを指定する方法には、-mstructure-size-boundary= オプションのほかに、-fpack-struct オプションを使う方法もあります。
しかし、-fpack-struct オプションには、著しい「副作用」があります。
「-fpack-struct」オプションを付けてコンパイルした結果を示します。

00000240 <SystemInit>:
 240:  b530       push    {r4, r5, lr}
 242:  4b4e       ldr     r3, [pc, #312]   ; (37c)
 244:  2151       movs    r1, #81          ; 0x51
 246:  f893 2c00  ldrb.w  r2, [r3, #3072]  ; 0xc00
 24a:  f883 1c00  strb.w  r1, [r3, #3072]  ; 0xc00
 24e:  f893 1c01  ldrb.w  r1, [r3, #3073]  ; 0xc01
 252:  f06f 011a  mvn.w   r1, #26
 256:  f883 1c01  strb.w  r1, [r3, #3073]  ; 0xc01
 25a:  f893 0c02  ldrb.w  r0, [r3, #3074]  ; 0xc02
 25e:  f06f 0033  mvn.w   r0, #51          ; 0x33
 262:  f883 0c02  strb.w  r0, [r3, #3074]  ; 0xc02
 266:  f893 0c03  ldrb.w  r0, [r3, #3075]  ; 0xc03
 26a:  201a       movs    r0, #26
 26c:  f883 0c03  strb.w  r0, [r3, #3075]  ; 0xc03
 270:  f893 4c00  ldrb.w  r4, [r3, #3072]  ; 0xc00
 274:  f06f 0451  mvn.w   r4, #81          ; 0x51
 278:  f883 4c00  strb.w  r4, [r3, #3072]  ; 0xc00
 27c:  f893 4c01  ldrb.w  r4, [r3, #3073]  ; 0xc01
 280:  f883 0c01  strb.w  r0, [r3, #3073]  ; 0xc01
 284:  f893 0c02  ldrb.w  r0, [r3, #3074]  ; 0xc02
 288:  2033       movs    r0, #51          ; 0x33
 28a:  f883 0c02  strb.w  r0, [r3, #3074]  ; 0xc02
 28e:  2200       movs    r2, #0
 290:  f893 0c03  ldrb.w  r0, [r3, #3075]  ; 0xc03
 294:  f883 1c03  strb.w  r1, [r3, #3075]  ; 0xc03
 298:  721a       strb    r2, [r3, #8]

          . . . < 中略 > . . ..

 37c:  40011000   .word   0x40011000

異様に長いですが、何をやっているのかと言えば、32 ビット・レジスタである WDG_LCK を 8 ビット単位でアクセスするコードになっています。
レジスタに対するオフセットは 0xC00 〜 0xC03 で、正しい値であり、メモリ上の変数に対するアクセスであれば「遅い」だけで正常な動作となるのですが、WDG_LCK レジスタは 32 ビット幅でアクセスする必要があり、8 ビット幅のアクセスでは正しく機能しません。