88907
### 経緯

Spresenseで始めるローパワーエッジAI (太田義則 著 オーム社) を参考にしながらArduino IDEでのプログラミングを行っています。  
この本の9章のソースコードを元にソースを作成していましたが、HardFault が出てしまい動作しませんでした。

フォールトが出たプログラムは以下のリンクにあるdisplayUtil.ino、region_detect.ino、semaseg_camera.inoです。

<https://github.com/Ito617/to_question_in_stack_overflow/tree/main/Spresense_semaseg/semaseg_camera>

ここで利用する学習結果は参考にしている本の[著者が公開している物](https://github.com/TE-
YoshinoriOota/Spresense-LowPower-
EdgeAI/tree/main/Chap09/nnc_model)をそのまま利用しており、Spresense拡張ボードに差し込んだmicroSDカードに保存してあります。

Spresense本体には拡張ボード、カメラボードとLCD（KMRTM28028-SPI）がつながっています。セマンティックセグメンテーションをやる前にカメラから取得した画像を液晶ディスプレイにストリーミング再生するプログラムは動いているので、この接続不良の可能性は低いと思っています。

実際にセマンティックセグメンテーションのプログラムを動かした際の挙動について説明します。

semaseg_camera.ino 129行目

```

    display.fillRect(0, 0, 320, 240, ILI9341_BLUE);
    
```

にあるとおり、ディスプレイ前面が青色になり、その後もプログラム通りに次のシリアル通信が送られてきました。

```

    14:57:21.653 -> DNN initialize
    14:57:23.279 -> no detection
    
```

しかし、カメラから取得され、一部のピクセルを書き換えられた画像がディスプレイにストリーミング再生されるはずが、再生されず画面は青色のままであり、シリアルモニタにHardFaultのエラーメッセージが出ました。  
これがそのエラーログのリンクです。  
<https://github.com/Ito617/to_question_in_stack_overflow/blob/main/Spresense_semaseg/ErrorLog0512>

### 動かない問題の部分

どこで動作が止まってしまうのかを調べた結果、semaseg_camera.ino
114行目で呼び出されているdraw_sideband関数で止まっていることまでは分かりました。出力画像の両端に青色の帯を描く部分で、この部分だけを消して動かすと、プログラム全体は動きました。

この部分だけを抜き出したのが次のコードです。一応コンパイルまではできますが、ディスプレイの映像は全面青色のままです。

```

    #include <Camera.h>
    #include "Adafruit_ILI9341.h"
    #define TFT_DC  9
    #define TFT_CS  10
    Adafruit_ILI9341 display = Adafruit_ILI9341(TFT_CS, TFT_DC);
    
    #define OFFSET_X  (48)
    #define OFFSET_Y  (6)
    #define CLIP_WIDTH  (224)
    #define CLIP_HEIGHT  (224)
    #define DNN_WIDTH  (28)
    #define DNN_HEIGHT  (28)
    
    void CamCB(CamImage img) {
      if (!img.isAvailable()){
        return;
      }
    
        goto disp;
    
    disp:
      uint16_t* buf = (uint16_t*)img.getImgBuff(); 
    
      draw_sideband(buf, OFFSET_X, ILI9341_BLUE);
    
      display.drawRGBBitmap(0, 0, buf, 320, 24);
    }
    
    void setup() {
    
      Serial.begin(115200);
      display.begin();
      display.setRotation(3);
      display.fillRect(0, 0, 320, 240, ILI9341_BLUE);
    
      theCamera.begin();
      theCamera.startStreaming(true, CamCB);
    }
    
    void loop() {
      // put your main code here, to run repeatedly:
    
    }
    
```

このプログラムでも同様にHardFaultが出て動きませんでした。  
メインメモリの割り当て方も128kBから1536kBまで、選択できるものは試しましたがダメでした。

```

    13:44:58.757 -> arm_hardfault: PANIC!!! Hard fault: 40000000
    13:44:58.757 -> up_assert: Assertion failed at file:armv7-m/arm_hardfault.c line: 135 task: frame_hdr_thread
    13:44:58.789 -> up_registerdump: R0: 0d160280 00000030 00000000 00000001 0d16027e 0d160002 0d000261 00000000
    13:44:58.789 -> up_registerdump: R8: 00000000 00000000 00000000 00000000 00000000 0d03fe90 0d000279 0d00024e
    13:44:58.789 -> up_registerdump: xPSR: 01000200 BASEPRI: 000000e0 CONTROL: 00000000
    13:44:58.789 -> up_registerdump: EXC_RETURN: ffffffe9
    13:44:58.789 -> up_dumpstate: sp:     0d030680
    13:44:58.789 -> up_dumpstate: IRQ stack:
    13:44:58.789 -> up_dumpstate:   base: 0d02fee0
    13:44:58.822 -> up_dumpstate:   size: 00000800
    13:44:58.822 -> up_dumpstate:   used: 00000198
    13:44:58.822 -> up_stackdump: 0d030680: 00000087 0d037698 00000080 0d03256c 0d03fdbc 00000003 00000000 00000000
    13:44:58.822 -> up_stackdump: 0d0306a0: 00000000 00000000 00000000 0d0061a1 0d007d27 0d004dd7 0d004db5 0d0106ef
    13:44:58.822 -> up_stackdump: 0d0306c0: 000000e0 0d005ddd 000000e0 0d03fdbc 0d160002 0d000261 00000000 0d00521b
    13:44:58.822 -> up_dumpstate: sp:     0d03fe90
    13:44:58.856 -> up_dumpstate: User stack:
    13:44:58.856 -> up_dumpstate:   base: 0d03f6c8
    13:44:58.856 -> up_dumpstate:   size: 00000800
    13:44:58.856 -> up_dumpstate:   used: 0000015c
    13:44:58.856 -> up_stackdump: 0d03fe80: 00000000 00000000 00000000 0d0378c0 0d0378c0 0d03feac 0d02f466 0d000279
    13:44:58.856 -> up_stackdump: 0d03fea0: 0d02f448 0d000bc9 0d0378b0 0d0378c0 00000000 00000000 00000000 0d0061ed
    13:44:58.960 -> up_stackdump: 0d03fec0: 0d0061e5 00000000 00000420 80000820 0d03d490 00000000 00000000 00000000
    13:44:58.960 -> up_taskdump: Idle Task: PID=0 Stack Used=460 of 1000
    13:44:58.960 -> up_registerdump: R0: 00000000 0d0316dc 0d036f44 00000000 00000000 0d031658 0d0325be 00000000
    13:44:58.960 -> up_registerdump: R8: 0d0317b0 07d2402b ec5dfdb1 64615039 00000000 0d033040 0d0105bb 0d015e6e
    13:44:58.960 -> up_registerdump: xPSR: 41000000 BASEPRI: 000000e0 CONTROL: 00000000
    13:44:58.960 -> up_registerdump: EXC_RETURN: ffffffe9
    13:44:58.960 -> up_taskdump: hpwork: PID=1 Stack Used=604 of 2016
    13:44:58.960 -> up_registerdump: R0: 00000002 0d033bc4 0d0316dc 0d033bc4 0d033b40 00000080 0d0325d4 00000000
    13:44:58.960 -> up_registerdump: R8: 0d0325dc 00000000 00000000 00000000 01ff0000 0d0347c0 0d01141f 0d01816c
    13:44:58.960 -> up_registerdump: xPSR: 01000000 BASEPRI: 00000080 CONTROL: 00000000
    13:44:58.960 -> up_registerdump: EXC_RETURN: ffffffe9
    13:44:58.960 -> up_taskdump: lpwork: PID=2 Stack Used=268 of 2016
    13:44:58.960 -> up_registerdump: R0: 00000002 0d034894 0d035564 0d034894 0d034810 00000080 0d0325e0 00000000
    13:44:58.960 -> up_registerdump: R8: 0d0325e8 00000000 00000000 00000000 00000000 0d035490 0d01141f 0d01816c
    13:44:58.960 -> up_registerdump: xPSR: 01000000 BASEPRI: 00000080 CONTROL: 00000000
    13:44:58.960 -> up_registerdump: EXC_RETURN: ffffffe9
    13:44:58.960 -> up_taskdump: lpwork: PID=3 Stack Used=268 of 2016
    13:44:58.960 -> up_registerdump: R0: 00000002 0d035564 0d036234 0d035564 0d0354e0 00000080 0d0325e0 00000000
    13:44:58.988 -> up_registerdump: R8: 0d0325e8 00000000 00000000 00000000 00000000 0d036160 0d01141f 0d01816c
    13:44:58.988 -> up_registerdump: xPSR: 01000000 BASEPRI: 00000080 CONTROL: 00000000
    13:44:58.988 -> up_registerdump: EXC_RETURN: ffffffe9
    13:44:58.988 -> up_taskdump: lpwork: PID=4 Stack Used=268 of 2016
    13:44:59.022 -> up_registerdump: R0: 00000002 0d036234 0d0316dc 0d036234 0d0361b0 00000080 0d0325e0 00000000
    13:44:59.022 -> up_registerdump: R8: 0d0325e8 00000000 00000000 00000000 00000000 0d036e30 0d01141f 0d01816c
    13:44:59.022 -> up_registerdump: xPSR: 01000000 BASEPRI: 00000080 CONTROL: 00000000
    13:44:59.022 -> up_registerdump: EXC_RETURN: ffffffe9
    13:44:59.022 -> up_taskdump: cxd56_pm_task: PID=6 Stack Used=400 of 1000
    13:44:59.022 -> up_registerdump: R0: 00000002 0d037f94 0d0316dc 0d037f94 0d0389f0 0d03874c 0d037f10 00000000
    13:44:59.055 -> up_registerdump: R8: 0d0389f4 0d03258c 00000000 00000000 00000064 0d038728 0d010ac1 0d01816c
    13:44:59.055 -> up_registerdump: xPSR: 01000000 BASEPRI: 00000080 CONTROL: 00000000
    13:44:59.055 -> up_registerdump: EXC_RETURN: ffffffe9
    13:44:59.055 -> up_taskdump: gnss_receiver: PID=7 Stack Used=284 of 1000
    13:44:59.055 -> up_registerdump: R0: 00000002 0d03c664 0d036f44 0d03c664 0d03c5e0 000000e0 0d03ce80 0d03c538
    13:44:59.088 -> up_registerdump: R8: 00000000 00000000 00000000 00000000 00000000 0d03ce50 0d01141f 0d01816c
    13:44:59.088 -> up_registerdump: xPSR: 01000000 BASEPRI: 00000080 CONTROL: 00000000
    13:44:59.088 -> up_registerdump: EXC_RETURN: ffffffe9
    13:44:59.088 -> up_taskdump: init: PID=8 Stack Used=924 of 8176
    13:44:59.088 -> up_registerdump: R0: 00000000 00025800 00007fff 00000001 0d02d450 0d02d450 0d000000 0d02d440
    13:44:59.121 -> up_registerdump: R8: 00000000 00000000 00000000 00000000 00000000 0d03f5e8 0d00258d 0d00258c
    13:44:59.121 -> up_registerdump: xPSR: 61000000 BASEPRI: 000000e0 CONTROL: 00000000
    13:44:59.121 -> up_registerdump: EXC_RETURN: ffffffe9
    13:44:59.121 -> up_taskdump: frame_hdr_thread: PID=9 Stack Used=348 of 2048
    13:44:59.121 -> up_registerdump: R0: 00000002 0d0375c4 0d03d1e4 0d0375c4 0d0374e0 0d03fe64 0d037540 00000000
    13:44:59.121 -> up_registerdump: R8: 0d0374e4 0d03258c 00000000 00000000 00000000 0d03fe40 0d010ac1 0d01816c
    13:44:59.154 -> up_registerdump: xPSR: 01000000 BASEPRI: 00000080 CONTROL: 00000000
    13:44:59.154 -> up_registerdump: EXC_RETURN: ffffffe9
    13:44:59.154 -> up_taskdump: cam_dq_thread: PID=10 Stack Used=564 of 1024
    13:44:59.154 -> up_registerdump: R0: 00000002 0d037774 0d0375c4 0d037774 0d0376f0 000000e0 0d038830 000000e0
    13:44:59.154 -> up_registerdump: R8: 0d038878 0d038840 00000080 00000000 00000000 0d040188 0d01141f 0d01816c
    13:44:59.187 -> up_registerdump: xPSR: 01000000 BASEPRI: 00000080 CONTROL: 00000000
    13:44:59.187 -> up_registerdump: EXC_RETURN: ffffffe9
    
```

このプログラムがなぜHardFaultになるのか、カメラで取得した画像の両サイドに帯を上書きして出力したい場合、どうするべきだったかがわかりません。どなたかご回答お願いします。
CC BY-SA 4.0
2022-05-18T05:21:56.557
88897
2022-05-23T05:47:50.673
2022-05-23T05:47:50.673
52646
52646
question
spresense
カメラ画像を加工してディスプレイにストリーミングすると HardFault が発生する
こんにちは。  
draw_sidebandの返り値に問題があったそうで、少し前に当該サンプルも更新されています。  
最新のコードで試してみてはいかがでしょうか。
CC BY-SA 4.0
2022-05-18T13:03:47.857
88907
2022-05-18T13:03:47.857
34630
88897
answer