8 years, 2 months ago.

JCU_HelloWorldの質問(2)

下記で、サンプルを参考に、LCDに表示されてる画像を、JPEGファイルとして保存するようにしたのですが、LCDに表示されているものが保存されず、真っ黒な画像が保存されます。二回目から、異常な画像が保存されます。 LDCモジュールの表示も止めて、エンコードする必要があるのでしょうか?

試行サンプル

            JPEG_Converter  decoder;
            JPEG_Converter::bitmap_buff_info_t  aBitmapData;
            size_t EncodeSize;
           
            //YCbCr setting 
            aBitmapData.width           = LCD_PIXEL_WIDTH;
            aBitmapData.height          = LCD_PIXEL_HEIGHT;
            aBitmapData.format          = JPEG_Converter::WR_RD_YCbCr422;   //YCbCr[0] & ARGB8888[1] is 4byte, not RGB565[2] is 2byte
            aBitmapData.buffer_address  = (void *)user_frame_buffer0;
            pc.printf("File encode start\n");
            // JPEG_Converter

            if (decoder.encode(&aBitmapData, user_frame_buffer1, &EncodeSize) == JPEG_Converter::JPEG_CONV_OK) {
                pc.printf("File encode done %dbyte\n", EncodeSize);
                pc.printf("File write start\n");
                sprintf( fname, "/sd/img_%04d.jpg", imgCnt++ );
                FILE *wr_fp = fopen( fname, "w");
                for( long i=0; i < EncodeSize;i++) {
                    putc( user_frame_buffer1[i], wr_fp );
                }
                fclose(wr_fp);
                pc.printf("File write done\n");
                led1 = 0;
            } else {
                pc.printf("Error:JCU encode error\n");
                led1 = 0;
            }

【正常の場合】

/media/uploads/digiponta/cr-tg56vmaa08m8.jpg_large.jpg

【異常の場合】 LCDでは、普通に見えていました。(デコードエラーは私のコードのバグでした。それは修正済みです)

/media/uploads/digiponta/img_0012.jpg

二回目以降の実行が変になり易いようです。

【対象療法】 とりあえず、エンコードしてファイルに保存したら、NVIC_SystemReset(); を読んで、GR-PEACHをリセットするようにしています。これだと、とりあえず変な画像ほ保存は起きなくなります。 このせいか、不明なのですが、JEPEGを復号するときに、JEPGファイルのサイズ取得のftellから、ゼロしか返らなくなりました。

Question relating to:

Team for GR-PEACH Producer Meeting

1 Answer

8 years, 2 months ago.

LCDは止める必要はありません。JPEG変換用バッファのキャッシュに前回のデータが残ってしまっているのだと思います。
以下の方法でキャッシュインバリデートしてみてください。

// キャッシュインバリデート関数を追加
static void dcache_invalid(void * p_buf, uint32_t size){
    uint32_t start_addr = (uint32_t)p_buf & 0xFFFFFFE0;
    uint32_t end_addr   = (uint32_t)p_buf + size;
    uint32_t addr;
 
    /* Data cache invalid */
    for (addr = start_addr; addr < end_addr; addr += 0x20) {
        __v7_inv_dcache_mva((void *)addr);
    }
}

// エンコードの直前でキャッシュインバリデート
            dcache_invalid(user_frame_buffer1, sizeof(user_frame_buffer1));
            if (decoder.encode(&aBitmapData, user_frame_buffer1, &EncodeSize) == JPEG_Converter::JPEG_CONV_OK) {
                pc.printf("File encode done %dbyte\n", EncodeSize);



バッファのサイズの合計が1MBを超えないのであれば、バッファを非キャッシュメモリに配置する方法もあります。
この場合、dcache_invalid()やdcache_clean()などのキャッシュ制御は不要です。

#if defined(__ICCARM__)
/* 32 bytes aligned */
#pragma data_alignment=32
static uint8_t user_frame_buffer0[FRAME_BUFFER_STRIDE * LCD_PIXEL_HEIGHT];
static uint8_t user_frame_buffer1[FRAME_BUFFER_STRIDE * LCD_PIXEL_HEIGHT] @ ".mirrorram"; //非キャッシュ
#pragma data_alignment=4
#else
/* 32 bytes aligned */
static uint8_t user_frame_buffer0[FRAME_BUFFER_STRIDE * LCD_PIXEL_HEIGHT]__attribute((aligned(32)));
static uint8_t user_frame_buffer1[FRAME_BUFFER_STRIDE * LCD_PIXEL_HEIGHT]__attribute((section("NC_BSS"),aligned(32))); //非キャッシュ
#endif

Accepted Answer

dkato様 レス、有難うございます。うまく画像が保存できるようになったようです。様子を見てみます。 あとは、保存したJPEGファイルの表示がうまくいけば、一通り動作が完成します。なぜか、エラーもでてないのですが、SDメモリからのデータ読み込みに失敗して、デコードエラーになっているようです。

posted by Hirofumi Inomata 13 Sep 2016

SDカードが認識されるまで少し時間がかかるので、認識前にリードしてしまっているのではないでしょうか。P7_8のレベルがLowになっていれば、SDカードへのアクセスが可能です。
こちらの下部にある、SDFileSystem_GR_PEACHを使うと、USBのMSCと同じようなIFでSDの接続を確認できます。(trueが返るまでconnect()関数を実行)

posted by Daiki Kato 14 Sep 2016