UMEHOSHI ITA TOP PAGE COMPUTER SHIEN LAB
#ifndef _MY_UTIL_H /* Guard against multiple inclusion */ #define _MY_UTIL_H // 【2023-4】でファイルを追加 // EEPROM 制御関数 unsigned int NVM_unlock (unsigned int nvmop);//ロック解除,NVMCON設定シーケンス unsigned int NVM_erase_page(unsigned int address);// address指定で1ページ(1024バイト)を0xffに消去 unsigned int NVM_write_word (unsigned int address, unsigned int data);//addressの位置にdataワードを書き込む int get_version(); // バージョンを返す。 void power_on_start(); #endif /* _MY_UTIL_H */
#include <xc.h> #include <proc/p32mx270f256b.h> #include <stdlib.h> #include "my_util.h" #include "common.h" // 参考: 60001121G_JP.pdf の不揮発性メモリ ( NonVolatile Memory )CONTROL unsigned int NVM_unlock (unsigned int nvmop)//ロック解除,NVMCON 設定シーケンス { unsigned int status; asm volatile ("di %0" : "=r" (status));// Disable all Interrupts NVMCON = nvmop; // NVM(SFR)Flashプログラミング制御レジスタ設定 NVMKEY = 0xAA996655;//EEPROMの意図しない書き込みなどを防ぐ指定シーケンス1 NVMKEY = 0x556699AA;//EEPROMの意図しない書き込みなどを防ぐ指定シーケンス2 NVMCONSET = 0x8000;// Start the operation using the Set Register while (NVMCONbits.WR){ ;// Wait for operation to complete } if (status & 0x00000001){ asm volatile ("ei");// Restore Interrupts } else { asm volatile ("di"); } NVMCONCLR = 0x0004000; // Disable NVM write enable return (NVMCON & 0x3000);// Return WRERR and LVDERR Error Status Bits // bit13:WRERRのbitが1の時、プログラミングまたは消去シーケンスは正常に完了しなかった // bit12:LVDERRのbitが1の時、WRERRがセットされた場合、データは破損した可能性がある } // UMEHOSHI_ITAで使っているのはPIC32MX270F256Bでプログラムフラシュの // kseg0_program_memは、0x9D000000より0x9D03F000の範囲 // 0x9D020000?をこの引数にして消去可能(ページ消去で消せるのは1024バイト) // 0x9D03F000-0x9D020000=126976が一般ユーザが書き込める範囲となる // 次の消去アドレスは0x9D020200、次が0x9D020400で、0x9d03ee00まで指定可 unsigned int NVM_erase_page(unsigned int address) { unsigned int res; if( address < 0xB0000000U) address += +0x20000000U; NVMADDR = (unsigned int) address; // 書き込みアドレス(書き込み位置) // 書き込みモードの指定 // 0001 - 4バイト単位で書き込む // 0011 - 512バイト単位で書き込む(指定アドレスは512の倍数) // 0100 - 512バイト消去ページ消去動作: NVMADDRで選択したページを消去する // 0101 - プログラム領域をすべて消去(ブート領域でのみ実行可) //NVMCONbits.NVMOP = 0b0001; // WordWrite //NVMCONbits.WREN = 1;// 書き込みの許可(bit 14 WREN: 書き込みイネーブルビット) //0x4001;// NVM(SFR)Flashプログラミング制御レジスタ設定 res = NVM_unlock (0x4000);//WRERR: 書き込みエラービットをクリア res |= NVM_unlock (0x4004);// メモリ初期化のページ消去動作 return res;// Return Result(ゼロが戻れば成功) } // PIC32MX270F256Bでプログラムフラシュの kseg0_program_memは、0x9D000000より // 0x9D03F000の範囲で、dataの1ワード(32bit)を、addressの位置に書き込む。 unsigned int NVM_write_word (unsigned int address, unsigned int data) { unsigned int res; NVMDATA = data; // 書き込みデータ asm("nop"); if( address < 0xB0000000U) address += +0x20000000U; NVMADDR = address; // 書き込みアドレス(書き込み位置) // 書き込みモードの指定 // 0001 - 4バイト単位で書き込む // 0011 - 512バイト単位で書き込む(指定アドレスは512の倍数) // 0100 - 4KB単位で消去 // 0101 - プログラム領域をすべて消去(ブート領域でのみ実行可) //NVMCONbits.NVMOP = 0b0001; // WordWrite //NVMCONbits.WREN = 1;// 書き込みの許可(bit 14 WREN: 書き込みイネーブルビット) //0x4001;// NVM(SFR)Flashプログラミング制御レジスタ設定 res = NVM_unlock (0x4001); return res;// Return Result } // パワーオン時のEEPROM内容で指示する起動関数を呼び出す処理(init_interrupt内で呼ぶ) // パワーオン時でSW2が押さない時、EEPROM内の0x9D03fff0番地内容が示す関数を実行。 // パワーオン時でSW2が押した時、EEPROM内の0x9D03fff4番地内容が示す関数を実行。 // W2が押した時の起動関数の処理を:202503 で追加 void power_on_start(){ if ((PORTB & 0x80) == 0) {// SW2が押されいる unsigned *flag = (unsigned *) 0x9D03fff4; if( *flag != 0xffffffff) { void (* func)(void) = (void *) *flag; func(); // EEPROM内の0x9D03fff4番地の関数を呼び出す } } else {// SW2が押されていない場合の起動 unsigned *flag = (unsigned *) 0x9D03fff0; if( *flag != 0xffffffff) { void (* func)(void) = (void *) *flag; func(); // EEPROM内の0x9D03fff番地の関数を呼び出す } } } // :202503 で下記power_on_startを上記に変更 //void power_on_start(){ // if ((PORTB & 0x80) == 0) return; // SW2が押されてれば、リターン // unsigned *flag = (unsigned *) 0x9D03fff0; // if( *flag == 0xffffffff) return; // void (* func)(void) = (void *) *flag; // func(); // EEPROM内の0x9D03fff番地の関数を呼び出す } // 通常モードと、UARTコマンドモードを、My_APP_Tasks()関数内で切り替える関数 ;202504追加 int uart_command_mode = 1; // これが1の場合UARTコマンドモードで、0なら通常モード int mode_change_request = 0;// これを1にすると、上記モードに切り替わって0に戻る // 上記mode_change_requestを1にセットすると、uart_command_modeの設定に変更する。 // (_UME_THROUGH_MODE のスルーモードが1であれば、それが優先されます。) int change_mode(){// 上記2つの変数に基づいて、モードを変更する extern void recive_and_send_uart_with_polling();// my_uart.c extern void uart_cmd_mode_polling();// my_uart.c extern int core_once_count2_val; if(mode_change_request == 0) return 0;// 切り替わらない if(core_once_count2_val > 0) return 0;// 起動後の2秒間は実行しない。 mode_change_request = 0;//処理終了の変更 if( _HANDLES[_IDX_DEF_POLLS_UART] != (void *)recive_and_send_uart_with_polling && uart_command_mode == 0){ // 通常モードに変更 APP_State_Reset(); init_outBuffers(); //USB出力用リングバッファ関連変数 の初期化 _HANDLES[_IDX_DEF_POLLS_UART] = (void *)recive_and_send_uart_with_polling; return 1; } if( _HANDLES[_IDX_DEF_POLLS_UART] != (void *)uart_cmd_mode_polling && uart_command_mode == 1){// UARTコマンドモードに強制変更 APP_State_Reset(); init_outBuffers(); //USB出力用リングバッファ関連変数 の初期化 _HANDLES[_IDX_DEF_POLLS_UART] = (void *)uart_cmd_mode_polling; return 1; } return 0; } // 指定された int 変数を V に設定します。以下のコメントで示す変数を設定;202504追加 // specified_idがIDでなくポインタの場合は、その指し示す先のint変数を設定 void set_int_var(int specified_id, int value){ if(specified_id == _SPECIFIED_flagEcho){ // エコーモード変更用 extern int flagEcho; flagEcho = value; } else if(specified_id == _SPECIFIED_mode_change_request){ mode_change_request = value; // 通常モードとUARTコマンドの変更指示 } else if(specified_id == _SPECIFIED_uart_command_mode){ uart_command_mode = value; // 通常モードとUARTコマンドの変更指示 } else { int *ptr = (int *)specified_id; *ptr = value;// 識別子がポインタの場合は、そのポインタが示す変数を変更 } }