// RAMの状態出力のデモ(SSD1306仕様の0.96インチOLEDを使用) // checkMem();RAMの使用状況チェック, printMem(); チェック結果をシリアルに表示 // coreDump();RAMの内容をダンプ // 2019/5/15 ラジオペンチ #include #include // adafruitのライブラリを使用 #include #define SCREEN_WIDTH 128 // OLED display width, in pixels #define SCREEN_HEIGHT 64 // OLED display height, in pixels // Declaration for an SSD1306 display connected to I2C (SDA, SCL pins) #define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin) Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); // メモリチェック用変数(ここから) int aRamStart = 0x0100; // RAM先頭アドレス(固定値) int aGvalEnd; // グローバル変数領域末尾アドレス int aHeapEnd; // ヒープ領域末尾アドレス int aSp; // スタックポインタアドレス char aBuff[6]; // 表示フォーマット操作バッファ char ascii[16]; // ascii文字列記録バッファ(コア) void setup() { Serial.begin(115200); if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3C for 128x64 Serial.println(F("SSD1306 allocation failed")); for (;;); // Don't proceed, loop forever } display.clearDisplay(); // 画面消去(これをやらないとadafluitロゴが出る) display.drawRect(0, 0, 128, 64, 1); // 画面最外周に線を引く(138x64の長方形) display.fillRect(0, 0, 32, 16, 1); // 画面左上に32x16画素の長方形を書く for (int x = 0; x < 127; x += 10) { display.drawFastVLine(x, 0, 64, 1 ); // 10画素間隔で縦線 } for (int y = 0; y < 63; y += 10) { display.drawFastHLine(0, y, 128, 1 ); // 10画素間隔で横線 } display.display(); // 実際に表示 checkMem(); // メモリーの使用状況をチェック printMem(); // チェック結果をシリアルに表示 coreDump(); // コアダンプ(RAM領域の内容を表示) } void loop() { // checkMem(); // メモリーの使用状況をチェック // printMem(); // チェック結果をシリアルに表示 // coreDump(); // コアダンプ(RAM領域の内容を表示) while (1) {} } //-------メモリ使用状況チェック、表示、ダンプの関数---------------------------------------- // ここから↓ void printMem() { // RAM使用状況を表示 Serial.println(); Serial.println(F("RAM allocation table")); Serial.println(F("usage start end size")); Serial.print(F("groval: ")); // 固定アドレス printHexDecimal(aRamStart); // 開始 Serial.print(F(" - ")); printHexDecimal(aGvalEnd); // 終了 Serial.print(" "); printHexDecimal(aGvalEnd - aRamStart + 1); // サイズ Serial.println(); Serial.print(F("heap : ")); // ヒープ printHexDecimal(aGvalEnd + 1); // 開始 Serial.print(F(" - ")); printHexDecimal(aHeapEnd - 1); // 終了(aHeapEndは次のヒープ用のアドレスなので-1) Serial.print(F(" ")); printHexDecimal(aHeapEnd - 1 - (aGvalEnd + 1) + 1); // サイズ Serial.println(); Serial.print(F("free : ")); // Free領域 printHexDecimal(aHeapEnd); // 開始 Serial.print(F(" - ")); printHexDecimal(aSp); // 終了 Serial.print(F(" ")); printHexDecimal(aSp - (aHeapEnd) + 1); // サイズ Serial.println(); Serial.print(F("stack : ")); // スタック領域 printHexDecimal(aSp + 1); // 開始(aSpは次のスタック用アドレスなので+1) Serial.print(F(" - ")); printHexDecimal(RAMEND); // 終了(RAMENDは0x8fffでシステム側で定義) Serial.print(F(" ")); printHexDecimal(RAMEND - (aSp + 1) + 1); // サイズ Serial.println(); Serial.println(); } void checkMem() { // RAM使用状況を記録 // 意味不明なところもあるけどそのまま使用 uint8_t *heapptr, *stackptr; stackptr = (uint8_t *)malloc(4); // use stackptr temporarily heapptr = stackptr; // save value of heap pointer free(stackptr); // free up the memory again (sets stackptr to 0) stackptr = (uint8_t *)(SP); // save value of stack pointer aSp = (int)stackptr; // スタックポインタの値を記録 aHeapEnd = (int)heapptr; // ヒープポインタの値を記録 aGvalEnd = (int)__malloc_heap_start - 1; // グローバル変数領域の末尾アドレス } void printHexDecimal(int x) { // 引数を16進と10進で表示 0xXXXX(dddd) sprintf(aBuff, "%04X", x); Serial.print(F("0x")); Serial.print(aBuff); Serial.print(F("(")); sprintf(aBuff, "%4d", x); Serial.print(aBuff); Serial.print(F(")")); } // ここまでコピペ //--------------------------------------------------------------------------- // コアダンプする時は更にここから最後までをコピペ void coreDump() { // コアダンプ (RAM領域ダンプ) unsigned int fromAdr = 0x0000; // 開始アドレス unsigned int toAdr = 0x08FF; // 終了アドレス int p = 0; unsigned int i; byte data; Serial.println(F("Core dump")); // タイトル表示 for (i = fromAdr; i <= toAdr; i++) { // 指定アドレス範囲を、 if ((i & 0xFF) == 0x00) { // アドレスの末尾が0x00だったら Serial.println(F("addr 0 1 2 3 4 5 6 7 8 9 A B C D E F <- ascii char ->")); } if (( i & 0x0F) == 0) { // 行の先頭なら printHex4chr(i); // アドレス表示 Serial.print(F(":")); clrAscii(15); // 表示に備えバッファを16文字分クリア(スペースコードで埋める) p = 0; } Serial.print(F(" ")); // データ間にスペース入れる data = _SFR_MEM8(i); // データメモリ読み出し printHex2chr(data); // 16進2文字で表示 addAscii(data, p); // 文字コードなら記録 p++; if ((i & 0x0F) == 0x0F) { // 行末だったら、 Serial.print(F(" ")); printAscii(15); // 該当文字列を表示して Serial.println(); // 改行 } if ((i & 0xFF) == 0xFF) { // 末尾がFFだったら1行開ける Serial.println(); } } Serial.println(); } void clrAscii(int n) { // 文字バッファを指定数クリア for (int x = 0; x <= n; x++) { ascii[x] = ' '; } } void addAscii(byte d, int p) { // 文字コードだったら指定位置に記録 if ((d > 0x20) & (d < 0x7F)) { // キャラクタコードの範囲だったら ascii[p] = d; // バッファの指定位置に記録 } } void printAscii(int n) { // 文字バッファの内容を指定数表示 for (int x = 0; x <= n; x++) { Serial.print(ascii[x]); // バッファの文字を表示 } } void printHex2chr(byte x) { // 16進2桁で出力 sprintf(aBuff, "%02X", x); Serial.print(aBuff); } void printHex4chr(unsigned int x) { // 16進4桁で出力 sprintf(aBuff, "%04X", x); Serial.print(aBuff); }