mirror of
https://github.com/rvtr/twl_mcu.git
synced 2025-06-18 14:45:41 -04:00
273 lines
6.6 KiB
C
273 lines
6.6 KiB
C
#pragma section @@CODE c_flash
|
|
#pragma section @@BITS c_f_bits AT 0xFE88
|
|
#pragma section @@DATA c_f_data AT 0xFE90
|
|
|
|
#pragma HALT
|
|
#pragma NOP
|
|
|
|
#include "macrodriver.h"
|
|
#include "user_define.h"
|
|
#include "jhl_defs.h"
|
|
#include "I2C_selfprog.h"
|
|
#include "SelfLib.h"
|
|
|
|
#include "user_define.h"
|
|
#include "Timer.h"
|
|
|
|
extern sreg UCHAR EntryRAM[];
|
|
|
|
|
|
bit self_prog_mode;
|
|
|
|
u8 writeBuffer[16];
|
|
struct stWordAddress self_prog_settings;
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
I2Cから自己書き換え
|
|
書き換える範囲は 0x0000 - 0x1FFFまで。
|
|
I2Cをほかで使っているので、フラグなどで飛んできてください。
|
|
書き換え完了後は電源再投入が必要です。
|
|
マイコンは停止します。
|
|
*****************************************************************************/
|
|
void self_programming(){
|
|
u8 status;
|
|
|
|
self_write_init();
|
|
|
|
led_wifi = 1;
|
|
FlashStart();
|
|
FlashEnv( EntryRAM );
|
|
|
|
if( self_write_eraseall() != 0 ){
|
|
led_R_on;
|
|
FlashEnd();
|
|
LREL0 = 1;
|
|
while(1){}
|
|
}
|
|
led_wifi = 0;
|
|
|
|
/// フラッシュの準備 ///
|
|
self_prog_settings.WriteBank = 0;
|
|
|
|
//// 各行の処理 ////
|
|
while( 1 ){
|
|
led_wifi = 1;
|
|
status = i2c_firm_rcv_line();
|
|
if( status != 0 ){
|
|
led_G_on;
|
|
FlashEnd();
|
|
LREL0 = 1;
|
|
LSRSTOP = 0;
|
|
WDTE = 0x4A; // リセット
|
|
while(1){}
|
|
}
|
|
led_wifi = 0;
|
|
|
|
status = write_firm_line();
|
|
if( ( status & 0x80 ) != 0 ){
|
|
// フラッシュ異常中断
|
|
FlashEnd();
|
|
LREL0 = 1;
|
|
while(1){}
|
|
}
|
|
led_wifi = 0;
|
|
}
|
|
FlashEnd();
|
|
WDTE = 0x01; // リセット
|
|
while(1){}
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
下準備
|
|
*****************************************************************************/
|
|
static void self_write_init(){
|
|
// SPIE0 = 1;
|
|
WTIM0 = 1; // ウェイトコンディションをだす。(仮)
|
|
|
|
// B //
|
|
TMHE1 = 0; /* stop TimerH0 */
|
|
TOEN1 = 0; /* disable output */
|
|
led_G_pwm;
|
|
|
|
// R //
|
|
TMHE0 = 0; /* stop TimerH0 */
|
|
TOEN0 = 0; /* disable output */
|
|
led_R_pwm;
|
|
|
|
// Y //
|
|
TCE50 = 0; /* TM50 counter disable */
|
|
TOE50 = 0; /* output disabled */
|
|
// TM50_Stop(); // LED_Wifi これ使っちゃだめ!
|
|
led_wifi = 1;
|
|
|
|
LSRSTOP = 1; // WDT停止
|
|
|
|
DI();
|
|
MK0 = 0xFFFF;
|
|
MK1 = 0xFFFF;
|
|
EI();
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
書き込み対象の部分を消去
|
|
*****************************************************************************/
|
|
static u8 self_write_eraseall(){
|
|
u8 flash_status = 0;
|
|
u8 temp;
|
|
|
|
flash_we = 1;
|
|
if( CheckFLMD() != 0 ){
|
|
return( 128 + 1 );
|
|
}
|
|
|
|
for( temp = 0; temp != (u8)( ( 0x2800 & 0xFC00 ) >> 10 ); temp++ ){
|
|
if( FlashBlockBlankCheck( 0, temp ) == 0x1B ){
|
|
flash_status |= FlashBlockErase( 0, temp );
|
|
}
|
|
}
|
|
if( flash_status != 0 ){
|
|
return( 128 + 2 );
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
一行分受信。データ足りない部分は0xFFでパディングするようになってるけど、
|
|
元データをちゃんとしてあるので本来不要
|
|
*****************************************************************************/
|
|
static u8 i2c_firm_rcv_line(){
|
|
u8 rec_length;
|
|
u8 data_counter;
|
|
u8 temp;
|
|
|
|
// ':' レコードマーク
|
|
do{
|
|
IICIF0 = 0;
|
|
WREL0 = 1;
|
|
while( ( IICIF0 == 0 ) && ( SPD0 == 0 ) ){ ; }
|
|
if( SPD0 == 1 ){
|
|
return( 1 ); // 書き換え終了。
|
|
}
|
|
}while( IIC0 != ':' ); // タイムアウトとかなしで永遠ループ
|
|
|
|
// レコード長
|
|
rec_length = rcvHex2bin();
|
|
|
|
// アドレス
|
|
temp = rcvHex2bin(); // 上位
|
|
self_prog_settings.WriteAddress = (u8*)( ( (u16)temp << 8 ) + rcvHex2bin() ); // 下位
|
|
|
|
// "00" (レコードタイプ)
|
|
if( rcvHex2bin() == 01 ){
|
|
return( 2 ); // 書き換え終了。
|
|
}
|
|
|
|
// ここからデータ
|
|
for( data_counter = 0; data_counter < rec_length; data_counter++){
|
|
writeBuffer[ data_counter ] = rcvHex2bin();
|
|
}
|
|
|
|
// サム(読み捨て)
|
|
rcvHex2bin();
|
|
// 改行コード \r\n はここでは見ないよ
|
|
|
|
// 0xFFで残りをパディング
|
|
while( data_counter < 16 ){
|
|
writeBuffer[ data_counter ] = 0xFF;
|
|
data_counter++;
|
|
}
|
|
return( 0 );
|
|
}
|
|
|
|
|
|
/*****************************************************************************
|
|
実書き込み 4ワード16バイトずつ。
|
|
*****************************************************************************/
|
|
static u8 write_firm_line(){
|
|
// ライターアップデート1は、
|
|
// 0x0000 - 0x1FFF ブート&本体を動かすコード
|
|
// 0x2000 - 0x27FF 自己書き換えコード
|
|
// 0x2800 - 空き。
|
|
//
|
|
// ライターアップデート2`は、
|
|
// 0x0000 - 0x1FFF ブート&本体を動かすコード
|
|
// 0x2000 - 0x27FF (空き)
|
|
// 0x2800 - 自己書き換えコード
|
|
// です
|
|
if( self_prog_settings.WriteAddress >= (u8*)0x2800 ){
|
|
// EEPエミュレーションで書き換えない範囲
|
|
return( 2 );
|
|
}else{
|
|
// 書き換える範囲
|
|
led_R_on;
|
|
if( FlashWordWrite( &self_prog_settings, 4, writeBuffer ) != 0 ){
|
|
return( 128 + 64 + 1 );
|
|
}
|
|
led_G_on;
|
|
if( FlashBlockVerify( 0, (u8)( ( (u16)(self_prog_settings.WriteAddress) & 0xFC00 ) >> 10 ) ) != 0 ){
|
|
// ライト リトライ
|
|
led_R_pwm;
|
|
if( FlashWordWrite( &self_prog_settings, 4, writeBuffer ) != 0 ){
|
|
return( 128 + 64 + 2 );
|
|
}
|
|
if( FlashBlockVerify( 0, (u8)( ( (u16)(self_prog_settings.WriteAddress) & 0xFC000 ) >> 10 ) ) != 0 ){
|
|
// 内部電荷診断エラー
|
|
return( 128 + 64 + 3 );
|
|
}
|
|
}
|
|
// 1行完了しました。
|
|
led_G_pwm;
|
|
led_R_pwm;
|
|
}
|
|
return( 0 );
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
2バイト分のヘキサを受信してバイナリを返す。
|
|
0x31 0x33 → 0x13
|
|
エラー処理とかしてないです。
|
|
ポーリングです。
|
|
*****************************************************************************/
|
|
static u8 rcvHex2bin(){
|
|
u8 dat;
|
|
u8 temp;
|
|
|
|
IICIF0 = 0;
|
|
WREL0 = 1;
|
|
while( IICIF0 == 0 ){ ; }
|
|
temp = IIC0;
|
|
if( ( '0' <= temp ) && ( temp <= '9' ) ){
|
|
dat = ( temp - '0' );
|
|
}else if( ( 'A' <= temp ) && ( temp <= 'Z' ) ){
|
|
dat = ( temp - 'A' + 10 );
|
|
}else if( ( 'a' <= temp ) && ( temp <= 'z' ) ){
|
|
dat = ( temp - 'a' + 10 );
|
|
}
|
|
dat <<= 4;
|
|
|
|
IICIF0 = 0;
|
|
WREL0 = 1;
|
|
while( IICIF0 == 0 ){ ; }
|
|
temp = IIC0;
|
|
if( ( '0' <= temp ) && ( temp <= '9' ) ){
|
|
dat |= ( temp - '0' );
|
|
}else if( ( 'A' <= temp ) && ( temp <= 'Z' ) ){
|
|
dat |= ( temp - 'A' + 10 );
|
|
}else if( ( 'a' <= temp ) && ( temp <= 'z' ) ){
|
|
dat |= ( temp - 'a' + 10 );
|
|
}
|
|
|
|
return( dat );
|
|
}
|
|
|