UMEHOSHI ITA TOP PAGE    COMPUTER SHIEN LAB

UMEHOSHI IT (my_util.c と my_util.h)

my_util.hのソース

#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 */

my_util.cのソース

#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;// 識別子がポインタの場合は、そのポインタが示す変数を変更
    }
}