HOME
  Security
   Software
    Hardware
  
FPGA
  CPU
   Android
    Raspberry Pi
  
nLite
  Xcode
   etc.
    ALL
  
LINK
BACK
 

2021/11/07

QMK firmwareでプログラムのサイズを小さくするテクニック、ケチケチ プログラミングの方法 QMK firmwareでプログラムのサイズを小さくするテクニック、ケチケチ プログラミングの方法

(QMK firmware How to Reduce Program Size、Reducing QMK firmware size)

Tags: [電子工作], [QMK]




● QMK firmwareの関連記事


2021/08/23
QMK firmwareの開発環境を ラズパイや Windows WSLにセットアップする方法
QMK firmwareの開発環境を ラズパイや Windows WSLにセットアップする方法

  ラズパイや Windows WSL環境でカスタマイズ キーボードのファームウェア QMK firmwareの開発環境を構築

2022/01/09
BUFFALOの USB テンキーを Pro Microと QMKを使って VIAカスタマイズ キーボードに改造する方法
BUFFALOの USB テンキーを Pro Microと QMKを使って VIAカスタマイズ キーボードに改造する方法

  BUFFALO USB 10-Key keyboard BSTK100 modification by Pro Micro and QMK firmware VIA

2021/08/11
社畜のキーボード「新入社員の同期」を購入してみた!! VIA、QMK、Remapでのカスタマイズに対応
社畜のキーボード「新入社員の同期」を購入してみた!! VIA、QMK、Remapでのカスタマイズに対応

  キー内容が Remap等でカスタマイズ可能な社畜のキーボード「新入社員の同期」を 3500円で購入


● QMK firmwareでプログラムのサイズを小さくするテクニック、ケチケチ プログラミングの方法

 QMK firmware How to Reduce Program Size、Reducing QMK firmware size

 QMKで良く使われる Pro Micro基板の ATmega32U4はプログラム領域が 32Kbyteです。

 そして QMK firmwareで複数の機能を有効にすると、すぐに 32KBを超えてしまいます。

 ※ ブートローダー領域が 4KB有るので、実際には 28KB(28672bytes)が使用可能な上限値です。

Checking file size of handwired_freewing_test_qmk_default.hex
 * The firmware is too large! 29202/28672 (530 bytes over)
 [ERRORS]

 そこで、少しでも QMKのファームウェアのプログラム サイズを少なくするケチケチ プログラミング テクニックを紹介します。

How to Reduce Program Size Reducing QMK firmware size with Pro Micro



● Audio機能を使う時 NO_MUSIC_MODE 2532バイトの得

 Reduce about 2000 byte
 22542 - 20010 = Reduce 2532 byte

config.h
#ifdef AUDIO_ENABLE
   #define AUDIO_PIN C6
#endif
Checking file size of handwired_freewing_test_audio_default.hex [OK]
 * The firmware size is fine - 22542/28672 (78%, 6130 bytes free)

config.h
#ifdef AUDIO_ENABLE
   #define AUDIO_PIN C6
   #define NO_MUSIC_MODE // Save 2000 bytes
#endif
Checking file size of handwired_freewing_test_audio_default.hex [OK]
 * The firmware size is fine - 20010/28672 (69%, 8662 bytes free)


●ポインタを使う 6バイトの得

 21406 - 21400 = Reduce 6 byte

// MATRIX_ROWS = 18
// MATRIX_COLS = 8
// matrix_row_t = uint8_t
bool matrix_scan_custom(matrix_row_t current_matrix[]) {
    bool matrix_has_changed = false;

    for (uint8_t row = 0; row < MATRIX_ROWS; ++row) {
        matrix_row_t now_rows = read_rows(row);
        if (current_matrix[row] != now_rows) {
            current_matrix[row] = now_rows;
            matrix_has_changed = true;
        }
    }

    return matrix_has_changed;
}
Checking file size of handwired_freewing_fcm084_default.hex      [OK]
 * The firmware size is fine - 21406/28672 (74%, 7266 bytes free)
// MATRIX_ROWS = 18
// MATRIX_COLS = 8
// matrix_row_t = uint8_t
bool matrix_scan_custom(matrix_row_t current_matrix[]) {
    bool matrix_has_changed = false;

    matrix_row_t* p = current_matrix;

    for (uint8_t row = 0; row < MATRIX_ROWS; ++row) {
        matrix_row_t now_rows = read_rows(row);
        if (*p != now_rows) {
            *p = now_rows;
            matrix_has_changed = true;
        }
        ++p;
    }

    return matrix_has_changed;
}
Checking file size of handwired_freewing_fcm084_default.hex      [OK]
 * The firmware size is fine - 21400/28672 (74%, 7272 bytes free)


●三項演算子を使う 12バイトの得

 21328 - 21316 = Reduce 12 byte

        if (readPin(inputPin)) {
            rows |= 1;
        }
Checking file size of handwired_freewing_fcm084_default.hex    [OK]
 * The firmware size is fine - 21328/28672 (74%, 7344 bytes free)
        rows |= (readPin(inputPin) ? 0 : 1);
Checking file size of handwired_freewing_fcm084_default.hex    [OK]
 * The firmware size is fine - 21316/28672 (74%, 7356 bytes free)


● LTO_ENABLE = yes 3120バイトの得

 24564 - 21444 = Reduce 3120 byte

rules.mk
# LINK_TIME_OPTIMIZATION_ENABLE = no
# LTO_ENABLE = no # Config Option Link Time Optimization

Checking file size of handwired_freewing_fcm084_default.hex   [OK]
 * The firmware size is fine - 24564/28672 (85%, 4108 bytes free)

rules.mk
# LINK_TIME_OPTIMIZATION_ENABLE = yes
LTO_ENABLE = yes # Config Option Link Time Optimization

Checking file size of handwired_freewing_fcm084_default.hex   [OK]
 * The firmware size is fine - 21444/28672 (74%, 7228 bytes free)


●変数の外出し 2バイトの得

 25904 - 25902 = Reduce 2 byte

 and_rowの所。

    matrix_row_t* p = current_matrix;
    for (uint8_t row = 0; row < MATRIX_ROWS; ++row) {

        matrix_row_t now_rows = 0;
        for (uint8_t col = 0; col < MATRIX_COLS; ++col) {
            now_rows <<= 1;
            now_rows |= ((tmp[MATRIX_COLS - col - 1] & (1<<row)) ? 0 : 1);
        }
Checking file size of handwired_freewing_test_expand_io_i2c_default.hex   [OK]
 * The firmware size is fine - 25904/28672 (90%, 2768 bytes free)
    matrix_row_t* p = current_matrix;
    for (uint8_t row = 0; row < MATRIX_ROWS; ++row) {

        matrix_row_t and_row = (1<<row);
        matrix_row_t now_rows = 0;
        for (uint8_t col = 0; col < MATRIX_COLS; ++col) {
            now_rows <<= 1;
            now_rows |= ((tmp[MATRIX_COLS - col - 1] & and_row) ? 0 : 1);
        }
Checking file size of handwired_freewing_test_expand_io_i2c_default.hex   [OK]
 * The firmware size is fine - 25902/28672 (90%, 2770 bytes free)


●定数に 1を使う 2バイトの得

 25904 - 25902 = Reduce 2 byte

 三項演算子の ? 0 : 1の所。

        matrix_row_t and_row = (1<<row);
        matrix_row_t now_rows = 0;
        for (uint8_t col = 0; col < MATRIX_COLS; ++col) {
            now_rows >>= 1;
            now_rows |= ((tmp[col] & and_row) ? 0 : 0x80);
        }
Checking file size of handwired_freewing_test_expand_io_i2c_default.hex   [OK]
 * The firmware size is fine - 25904/28672 (90%, 2768 bytes free)
        matrix_row_t and_row = (1<<row);
        matrix_row_t now_rows = 0;
        for (uint8_t col = 0; col < MATRIX_COLS; ++col) {
            now_rows <<= 1;
            now_rows |= ((tmp[MATRIX_COLS - col - 1] & and_row) ? 0 : 1);
        }
Checking file size of handwired_freewing_test_expand_io_i2c_default.hex   [OK]
 * The firmware size is fine - 25902/28672 (90%, 2770 bytes free)


●二重ループ側の for文の数値を変更する 4バイトの得

 26004 - 26000 = Reduce 4 byte

    for (uint8_t col = 0; col < MATRIX_COLS - 1; ++col) {
        ...
        for (uint8_t col2 = col + 1; col2 < MATRIX_COLS; ++col2) {
Checking file size of handwired_freewing_test_expand_io_i2c_default.hex   [OK]
 * The firmware size is fine - 26004/28672 (90%, 2668 bytes free)
    for (uint8_t col = 0; col < MATRIX_COLS - 1; ++col) {
        ...
        for (uint8_t col2 = MATRIX_COLS - 1; col2 > col; --col2) {
Checking file size of handwired_freewing_test_expand_io_i2c_default.hex   [OK]
 * The firmware size is fine - 26000/28672 (90%, 2672 bytes free)


● forループ側の数値を最適化する 216バイトの得

 25902 - 25686 = Reduce 216 byte

 但し、ビルドしたものが動かない。
 原因: unsigned charなのでマイナス値にならないから!

        for (uint8_t col = 0; col < MATRIX_COLS; ++col) {
            now_rows <<= 1;
            now_rows |= ((tmp[MATRIX_COLS - col - 1] & and_row) ? 0 : 1);
        }
Checking file size of handwired_freewing_test_expand_io_i2c_default.hex   [OK]
 * The firmware size is fine - 25902/28672 (90%, 2770 bytes free)
        for (uint8_t col = MATRIX_COLS - 1; col >= 0; --col) {
            now_rows <<= 1;
            now_rows |= ((tmp[col] & and_row) ? 0 : 1);
        }
Checking file size of handwired_freewing_test_expand_io_i2c_default.hex   [OK]
 * The firmware size is fine - 25686/28672 (89%, 2986 bytes free)


● forループ側の数値を最適化する 変化無し(上記の修正版)

 25902 - 25902 = Reduce 0 byte

 上記の修正版

        for (uint8_t col = 0; col < MATRIX_COLS; ++col) {
            now_rows <<= 1;
            now_rows |= ((tmp[MATRIX_COLS - col - 1] & and_row) ? 0 : 1);
        }
Checking file size of handwired_freewing_test_expand_io_i2c_default.hex   [OK]
 * The firmware size is fine - 25902/28672 (90%, 2770 bytes free)
        for (uint8_t col = MATRIX_COLS - 1; col >= MATRIX_COLS; --col) {
            now_rows <<= 1;
            now_rows |= ((tmp[col] & and_row) ? 0 : 1);
        }
Checking file size of handwired_freewing_test_expand_io_i2c_default.hex   [OK]
 * The firmware size is fine - 25902/28672 (90%, 2770 bytes free)
        for (int8_t col = MATRIX_COLS - 1; col >= 0; --col) {
            now_rows <<= 1;
            now_rows |= ((tmp[col] & and_row) ? 0 : 1);
        }
Checking file size of handwired_freewing_test_expand_io_i2c_default.hex   [OK]
 * The firmware size is fine - 25902/28672 (90%, 2770 bytes free)


● forループを whileで置き換える 変化無し

 25902 - 25902 = Reduce 0 byte

        for (uint8_t col = 0; col < MATRIX_COLS; ++col) {
            now_rows <<= 1;
            now_rows |= ((tmp[MATRIX_COLS - col - 1] & and_row) ? 0 : 1);
        }
Checking file size of handwired_freewing_test_expand_io_i2c_default.hex   [OK]
 * The firmware size is fine - 25902/28672 (90%, 2770 bytes free)
        uint8_t col = 0;
        while (col < MATRIX_COLS) {
            now_rows <<= 1;
            now_rows |= ((tmp[MATRIX_COLS - col++ - 1] & and_row) ? 0 : 1);
        }
Checking file size of handwired_freewing_test_expand_io_i2c_default.hex   [OK]
 * The firmware size is fine - 25902/28672 (90%, 2770 bytes free)
        int8_t col = -1;
        while (++col  < MATRIX_COLS) {
            now_rows <<= 1;
            now_rows |= ((tmp[MATRIX_COLS - col - 1] & and_row) ? 0 : 1);
        }
Checking file size of handwired_freewing_test_expand_io_i2c_default.hex   [OK]
 * The firmware size is fine - 25904/28672 (90%, 2768 bytes free)


● forループを whileで置き換える 変化無し

 25902 - 25902 = Reduce 0 byte

    for (uint8_t row = 0; row < MATRIX_ROWS; ++row) {
Checking file size of handwired_freewing_test_expand_io_i2c_default.hex   [OK]
 * The firmware size is fine - 25902/28672 (90%, 2770 bytes free)
    uint8_t row = -1;
    while (++row < MATRIX_ROWS) {
Checking file size of handwired_freewing_test_expand_io_i2c_default.hex   [OK]
 * The firmware size is fine - 25902/28672 (90%, 2770 bytes free)


● forループの記述を逆にする 駄目

 25880 - 25888 = Reduce -8 byte

        for (uint8_t col = 0; col < MATRIX_COLS; ++col) {
            now_rows <<= 1;
            now_rows |= ((tmp[MATRIX_COLS - col - 1] & and_row) ? 0 : 1);
        }
Checking file size of handwired_freewing_test_expand_io_i2c_default.hex   [OK]
 * The firmware size is fine - 25880/28672 (90%, 2792 bytes free)
        for (uint8_t col = MATRIX_COLS - 1; col < MATRIX_COLS; --col) {
            now_rows <<= 1;
            now_rows |= ((tmp[col] & and_row) ? 0 : 1);
        }
Checking file size of handwired_freewing_test_expand_io_i2c_default.hex   [OK]
 * The firmware size is fine - 25888/28672 (90%, 2784 bytes free)


● forループを whileで置き換えて数値を最適化する 駄目

 25880 - 25882 = Reduce -2 byte

        for (uint8_t col = 0; col < MATRIX_COLS; ++col) {
            now_rows <<= 1;
            now_rows |= ((tmp[MATRIX_COLS - col - 1] & and_row) ? 0 : 1);
        }
Checking file size of handwired_freewing_test_expand_io_i2c_default.hex   [OK]
 * The firmware size is fine - 25880/28672 (90%, 2792 bytes free)
        uint8_t col = MATRIX_COLS;
        while (--col < MATRIX_COLS) {
            now_rows <<= 1;
            now_rows |= ((tmp[col] & and_row) ? 0 : 1);
        }
Checking file size of handwired_freewing_test_expand_io_i2c_default.hex   [OK]
 * The firmware size is fine - 25890/28672 (90%, 2782 bytes free)
        int8_t col = MATRIX_COLS;
        while (--col >= 0) {
            now_rows <<= 1;
            now_rows |= ((tmp[col] & and_row) ? 0 : 1);
        }
Checking file size of handwired_freewing_test_expand_io_i2c_default.hex   [OK]
 * The firmware size is fine - 25882/28672 (90%, 2790 bytes free)


●三項演算子を置き換える 変化無し

 25902 - 25902 = Reduce 0 byte

        matrix_row_t and_row = (1<<row);
        while (--col < 0) {
            now_rows <<= 1;
            now_rows |= ((tmp[col] & and_row) ? 0 : 1);
        }
Checking file size of handwired_freewing_test_expand_io_i2c_default.hex   [OK]
 * The firmware size is fine - 25902/28672 (90%, 2770 bytes free)
        matrix_row_t and_row = (1<<row);
        while (--col < 0) {
            now_rows <<= 1;
            now_rows |= ((tmp[col] & and_row)>>row);
        }
Checking file size of handwired_freewing_test_expand_io_i2c_default.hex   [OK]
 * The firmware size is fine - 25902/28672 (90%, 2770 bytes free)


● QMK公式 AVRを最大限に活用する

Squeezing the most out of AVR

 AVRはリソースに深刻な制約があり、QMKが成長し続けるにつれて、新しい開発がこれらの制約に適合できないため、AVRのサポートをレガシーステータスに移行する必要があるかもしれないポイントに近づいています。

 ただし、ファームウェアのコンパイル済みサイズを減らす必要がある場合は、それを行うためのいくつかのオプションがあります。

● rules.mk Settings
LTO_ENABLE = yes

CONSOLE_ENABLE = no
COMMAND_ENABLE = no
MOUSEKEY_ENABLE = no
EXTRAKEY_ENABLE = no

SPACE_CADET_ENABLE = no
GRAVE_ESC_ENABLE = no
MAGIC_ENABLE = no

MUSIC_ENABLE = no

● config.h Settings
#undef LOCKING_SUPPORT_ENABLE
#undef LOCKING_RESYNC_ENABLE

#define NO_ACTION_ONESHOT

#define NO_ACTION_TAPPING

#define NO_MUSIC_MODE

#define LAYER_STATE_8BIT
#define LAYER_STATE_16BIT
#define NO_ACTION_LAYER

● sprintf or snprintfを別の関数で置き換え
    // OLD CODE
    char wpm_str[4] = {0};
    sprintf(wpm_str, "WPM: %03d", get_current_wpm());
    oled_write(wpm_str, ' '), false);
to
    // NEW CODE
    oled_write_P(PSTR("WPM: "), false);
    oled_write(get_u8_str(get_current_wpm(), ' '), false);
or
    // NEW CODE
    oled_write_P(PSTR("WPM: "), false);
    oled_write(get_u8_str(get_current_wpm(), '0'), false);



Tags: [電子工作], [QMK]

●関連するコンテンツ(この記事を読んだ人は、次の記事も読んでいます)

【自由工作】市販のキーボードを無改造で VIA QMK化する Keyboard Quantizerを自作する【夏休み】
【自由工作】市販のキーボードを無改造で VIA QMK化する Keyboard Quantizerを自作する【夏休み】

  夏休みが明けたら 僕のキーボードが最強になって クラスのみんなから MMK 大作戦

BUFFALOの USB テンキーを Pro Microと QMKを使って VIAカスタマイズ キーボードに改造する方法
BUFFALOの USB テンキーを Pro Microと QMKを使って VIAカスタマイズ キーボードに改造する方法

  BUFFALO USB 10-Key keyboard BSTK100 modification by Pro Micro and QMK firmware VIA

QMK firmwareの開発環境を ラズパイや Windows WSLにセットアップする方法
QMK firmwareの開発環境を ラズパイや Windows WSLにセットアップする方法

  ラズパイや Windows WSL環境でカスタマイズ キーボードのファームウェア QMK firmwareの開発環境を構築

QMK firmwareで I/Oピンが足りない場合にデコーダ、デマルチプレクサを使用して IOを拡張する解決方法
QMK firmwareで I/Oピンが足りない場合にデコーダ、デマルチプレクサを使用して IOを拡張する解決方法

  QMK firmware expand I/O for many matrix keyboard、How to use IO Expander Multiplexer / Demultiplexer / Decoder

QMK firmwareで I/Oピンが足りない場合に I2Cの GPIOエキスパンダを使用して IOを拡張する解決方法
QMK firmwareで I/Oピンが足りない場合に I2Cの GPIOエキスパンダを使用して IOを拡張する解決方法

  QMK firmware expand I/O for many matrix keyboard、How to use I2C GPIO Expander PCF8574 and PCF8575

QMK firmwareで Audio機能を試してみる
QMK firmwareで Audio機能を試してみる

  QMK firmware test Audio function with Piezo buzzer

QMK firmwareで OLED機能で SSD1306を試してみる
QMK firmwareで OLED機能で SSD1306を試してみる

  QMK firmware test OLED Driver with SSD1306

QMK firmwareで Analog Stick機能で PSP2000用アナログ ジョイスティックを試してみる
QMK firmwareで Analog Stick機能で PSP2000用アナログ ジョイスティックを試してみる

  QMK firmware test Analog Joystick function with PSP2000 Analog Stick

最新の QMK firmwareで new_keyboard.shのコマンドが動かなくなったのを修正する方法
最新の QMK firmwareで new_keyboard.shのコマンドが動かなくなったのを修正する方法

  QMK Bugfix Create New Keyboard new_keyboard.sh command No such file or directory Error

QMK firmwareの Githubを forkした自分のリモートに pushすると怒られて pushできない場合の対応方法
QMK firmwareの Githubを forkした自分のリモートに pushすると怒られて pushできない場合の対応方法

  refusing to allow an OAuth App to create or update workflow `.github/workflows/api.yml` without `workflow` scope

中華製の格安なプログラマブル USBキーボードを買ってみた QMK VIAとは別物
中華製の格安なプログラマブル USBキーボードを買ってみた QMK VIAとは別物

  中華製のプログラマブル USBキーボード KeyboardSetter.exe

社畜のキーボード「新入社員の同期」を購入してみた!! VIA、QMK、Remapでのカスタマイズに対応
社畜のキーボード「新入社員の同期」を購入してみた!! VIA、QMK、Remapでのカスタマイズに対応

  キー内容が Remap等でカスタマイズ可能な社畜のキーボード「新入社員の同期」を 3500円で購入




[HOME] | [BACK]
リンクフリー(連絡不要、ただしトップページ以外は Web構成の変更で移動する場合があります)
Copyright (c) 2021 FREE WING,Y.Sakamoto
Powered by 猫屋敷工房 & HTML Generator

http://www.neko.ne.jp/~freewing/hardware/qmk_firmware_reduce_program_size/