SSブログ
English Version

GreenPAKで遊ぶ(その2)書き込み環境完成 [GreenPAK]

 前回の記事の最後に書いたように PIC を使った自作の汎用制御基板の Pic24ジェネラルボックス(以降、GenBox と記す)を使った SLG46826 の書き込み環境が完成したので開発する上で調査した内容等をまとめてメモしておきます。
 久しぶりに自作のセルフコンパイラである独自言語の picle を使いました。全てを自分のコードで構築していく作業はある意味世界を一から創造していくようでもあり、独特な趣きがあります。
 尚、今回開発した書き込み環境を Grenwriter と命名しました。



■書き込み処理での確認事項
 主に下記の2つの資料を参考にしましたが今回のソフトを開発する上での重要事項について確認結果も含めて書いてみます。
  • 資料1:In-System Programming Guide SLG46824/6/7-A
  • 資料2:SLG46826 Datasheet


①NVMメモリの消去方法
 設計情報を保存している NVM は Pic24 等のようなフラッシュメモリを実装している一般的なマイコンの場合と同様にメモリ内容を消去してから書き込む必要があります(消去で'0'の状態になり、書き込みで'1'に変更できる)。消去と書き込みの最小単位(ページ
)は 16 バイトです。
 上記の資料1には書き込み方法として下図のフローチャートが記載されています。

書き込みフローチャート


 無料の資料なので言い辛いのですが、'Data'の初期値が未記載ですし'Yes'が変な位置にあります。メモリマップは下図のようになっていて、先頭がコンフィグ情報等が設定されるレジスタで 200H からがコンフィグ情報を保持する不揮発メモリ、300H からが EEPROM 用の不揮発メモリの領域です。

SLG46826 メモリマップ


 消去用のレジスタの構造は下図のようになっていて、NVM は 16 バイト(=1ページ)x16 の構成で最後のページはチップ情報なので書き込み禁止であることから上記のフローチャートでの'Data'の初期値は 80H であることが判りました。

消去レジスタの構造


 消去レジスタの説明には I2C でレジスタ内容を受け取った後に I2C 規格に準拠した ACK を返さず、詳細は SLG46824/6/7-A errata document (revision XC)を参照するように書かれています。

 下図は実機で確認した消去時の動作で、消去開始時のロジアナ波形です。ACK が無いだけでなく、微妙なタイミングでセッション終了(最初の橙色の四角)が発生しています。消去中はバスマスター等の動作は停止すると書いてあるので消去動作の完了は ACK 応答がある(I2C 通信では無反応の場合は NAK と見なされる)ことで確認する処理にしました。消去は最大 20ms と書いてあるのでタイマウェイトでもいいのですが ACK 方式の方が速いと思います。消去試験をしていたため、下図では I2C アドレスが 00H になっています。
 尚、前回記事では I2C のクロックが 100kHz でしたが今回から 400kHz に変更しています。

消去開始時のロジアナ波形例


 下図は ACK 応答を受け取り、消去処理の完了を確認しているタイミングのロジアナ波形です。ACK 応答に続くリードデータに対してはセッションを終了するために NAK 応答するようにしています。最終的な消去処理の実装はライトコマンドでポーリングし、ACK 応答が来た時は即座にセッションを終了するようにしました。この ACK ポーリング方式は NVM の書き込み時の書き込み処理終了の判断でも使いました。

消去完了時のロジアナ波形例


 消去処理全体の波形が下図になります。この時は 9ms 程度で消去処理が完了しています。

消去時全体のロジアナ波形例


②ソフトリセット時の待ち時間
 コンフィグデータを NVM に書き込んだ後に動作に反映させるためには電源を再投入するかソフトウェアでのリセット処理を行うことで NVM のコンフィグデータをコンフィグ用のレジスタにコピーする必要があります。今回は I2C でレジスタを設定することで実行されるソフトリセット方式を採用します。

 ソフトリセットは C8H レジスタに 02H を書き込むことで実行されます(下図参照)。

ソフトリセット関連レジスタ


 リセットコマンドを受信すると I2C のセッション終了をトリガにしてPOR(パワーオンリセット)と同じ処理が実行されるとのことです(下図参照)。

リセットコマンドタイミング


 リセット処理の時間が資料に見当たらないので上記の ACK ポーリング方式でリセット処理の完了を判断することにしました。
 下図はリセットコマンド発行時の波形です。書き込みデータに対してもきちんと ACK が返ってきてますね。セッション終了(橙色の四角)でリセット処理が開始されるので直後の ACK ポーリングに対しては NAK 状態になっています。

ソフトリセット開始時のロジアナ波形例


 下図は ACK を受信でき、 ACK ポーリング処理を終了した部分の波形です。

ソフトリセット終了時のロジアナ波形例


 下図はソフトリセット実行時の全体の波形です。リセット処理には 1.2ms 程度の時間がかかっているようです。この時間は電源電圧や設計した回路内容等にも依存するかもしれません。

ソフトリセット実行中のロジアナ波形例


③ I2C アドレスの設定方法
 SLG46826 は設定により I2C のアドレスを変更できますし、IO ピンで設定するようにもできます。
 下図がアドレス設定用レジスタの構成です。上位4ビットでレジスタ設定か外部ピン設定かを指定します。レジスタ設定の場合は下位4ビットの値になります。従って CAH レジスタに1が設定(これはディフォルト値)されるとアドレスの上位4ビット(GrrenPAK の資料では Control Code と記載)が 0001B になります。

I2C アドレス設定レジスタ


 このように I2C のアドレス設定は柔軟性があるので今回開発した書き込みソフト Grenwriter では後述するように I2C スキャン機能やアドレス設定機能を付けました。



■Grenwriter に実装した機能
 下図のメニュー画面で表示されている機能を実装しました。I2C によるレジスタの書き込み機能も実装するか迷いましたが、NVM から レジスタへの転送時はほぼすべての機能を停止して実行しているようなのでレジスタの詳細を理解せずに下手に動かしながら変更した場合、問題が発生する可能性があること、及び NVM の書き込みは 1000 回程度は可能なようなのでレジスタ書き込みは実装しないことにしました。

メニュー画面

 個々の機能に関して以降に記載します。
  1. I2C スキャン
     I2C のアドレス空間をスキャンする機能です。現在のアドレス設定値に加え、見つかったアドレス候補の値も表示するようにしました。複数の SLG46826 が接続されているケースも考慮して、現在のアドレス設定値は自動変更されません。

    スキャン画面

  2. I2C アドレス設定
     SLG46826 と I2C 通信するためのアドレスを設定します。

  3. コンフィグ用 I2C アドレス設定
     本設定をした場合、NVM 書き込み時にコンフィグ内の I2C アドレスが設定値に置き換えられます。I2C 通信用のアドレスも自動で変更されるので NVM 書き込み後も継続して通信できます。

  4. ヘキサファイルロード
     GreenPAK Designer で作成したヘキサファイルを TeraTerm の画面にドラッグ&ドロップすることで読み込み、読み込んだデータの内容を画面に表示します。Grenwriter には内部に256バイトのバッファがあり、ヘキサファイルの内容はこのバッファに読み込まれます。以降に記載しているダンプ系コマンドを実行した際もバッファ内データがダンプ内容に置き換えられます。

    ヘキサファイルロード画面

  5. NVM 書き込み
     バッファ内容を NVM へ書き込みます。コンフィグ用 I2C アドレスが設定済みの場合はバッファ内のアドレス値を設定値に変更してから NVM へ書き込みます。書き込みにより I2C アドレスが変更される場合でもその後の操作が継続できるようにアドレスの設定値が自動的に追従します。

    NVM 書き込み画面

  6. EEP 書き込み
     バッファ内容を EEP に書き込みます。後述の EEP 読み込み後にバッファにパッチを当て EEP 書き込みを行うことでチップ内のデータへのパッチが可能となります。

    EEP 書き込み画面

  7. NVM ダンプ
     NVM の内容を SLG46826 から読み込みます。内部バッファの内容も読み込んだものに置き換えられます。

    NVM ダンプ画面

  8. EEP ダンプ
     EEP の内容を SLG46826 から読み込みます。内部バッファの内容も読み込んだものに置き換えられます。画面構成は NVM ダンプと同様です。

    EEP ダンプ画面

  9. レジスタダンプ
     レジスタの内容を SLG46826 から読み込みます。内部バッファの内容も読み込んだものに置き換えられます。

    REG ダンプ画面

  10. バッファデータパッチ
     バッファ内の内容を変更します。

    バッファパッチ画面





■Grenwriterソフトウェア
 ソースを以下に貼っておきます。picle言語はC言語に近いのでC言語が使えるなら処理内容を確認するのは容易だと思います。

メイン処理(picle言語)
# GreenPAK writer Ver 0.01 2024/05/26 by skyriver # Grenwriter written with picle language use LibGreen; # serial reset proc SeriReset() { var dmy; if (I2CAdr(Padr,I2C_WR) = 0) { if (I2CSnd($c8) = 0) { dmy = I2CSnd( 2 ); # reset } I2CStop(); } } # erase NVM proc EraNvm() { PrnStr_( "Erase NVM :" ); EraRom(0,14); } # erase EEPROM proc EraEep() { PrnStr_( "Erase EEP :" ); EraRom(16,31); } # write NVM func WriteNvm() { PrnStr_( "¥nWrite NVM :" ); return = WritePages( 2, 14 ); PrnStr_( "¥n" ); } # write EEPROM func WriteEep() { PrnStr_( "¥nWrite EEP :" ); return = WritePages( 3, 15 ); PrnStr_( "¥n" ); } # input I2C adr func InpAdr( now ) { PrnStr_( "¥ninput I2C adr(0..F) " ); if ( now >= 0 ) { PrnHexB_( now / 8 ); } else { PrnStr_( "xx" ); } PrnStr_( " -> " ); return = GetHex(); } # patch buffer data proc Patch() { var adr,dat,c; PrnStr_( "¥n input adr:" ); adr = GetHexByte(); if ( (adr>=0) & (adr<=$FF) ) { PrnHexB_( adr ); PrnStr_( " data " ); PrnHexB_( _Buf[ adr ] ); PrnStr_( " -> " ); dat = GetHexByte(); PrnHexB_( dat ); PrnStr_( " sure?(Y/N) : " ); c = InpChar_(); PrnChar_( c ); if ( ToUpper(c) = 'Y' ) { _Buf[ adr ] = dat; } PrnStr_( "¥n" ); } } proc PrnErr() { PrnStr_( " .. Error !!¥n" ); } proc Help() { PrnStr_("¥n<<<< Grenwriter for Green PAK SLG46826 >>>>¥n"); PrnStr_(" S:scan I2C A:set I2C current adr¥n"); PrnStr_(" L:load HexFile B:set I2C adr(NVM)¥n"); PrnStr_(" W:write NVM E:write EEP¥n"); PrnStr_(" D:dump NVM F:dump EEP¥n"); PrnStr_(" R:dump REG P:patch buffer data¥n"); PrnStr_(" Q:quit¥n"); PrnStr_(" V0.01 2024/05/26 by skyriver¥n¥n"); } proc main() { var c,adr,nadr,flg; Init(); Padr = $08; # I2C addr nadr = -1; while (1) { Help(); PrnChar_( ']' ); c = ToUpper(InpChar_()); PrnChar_( c ); if ( c = 'S' ) { PrnStr_( "¥nscan I2C adr" ); adr = Scan(); PrnStr_( "¥n now adr:" ); PrnHexB_( Padr / 8 ); if ( adr >= 0 ) { PrnStr_( " estimate adr:" ); PrnHexB_( adr / 8 ); } PrnStr_( "¥n" ); } else if ( c = 'A' ) { adr = InpAdr( Padr ); if ( (adr>=0)&(adr<16) ) { PrnHexB_( adr ); Padr = adr * 8; } PrnStr_( "¥n" ); } else if ( c = 'L' ) { PrnStr_( "¥nDrag HexFile" ); if ( LoadHex() = 0 ) { DumpBuf(); } } else if ( c = 'B' ) { adr = InpAdr( nadr ); if ( (adr >=0)&(adr<16) ) { PrnHexB_( adr ); nadr = adr * 8; } PrnStr_( "¥n" ); } else if ( c = 'W' ) { if ( nadr >= 0 ) { _Buf[ $CA ] = nadr / 8; } PrnStr_( "¥nErase NVM :" ); flg = 1; EraRom( 0, 14 ); if ( WriteNvm() = 0 ) { DumpBuf(); flg = 0; } SeriReset(); Padr = _Buf[ $CA ] * 8; WaitAck(); if ( flg ) { PrnErr(); } } else if ( c = 'E' ) { PrnStr_( "¥nErase EEP :" ); flg = 1; EraRom( 16, 31 ); if ( WriteEep() = ) { DumpBuf(); flg = 0; } if ( flg ) { PrnErr(); } } else if ( c = 'D' ) { PrnStr_( "¥n dump NVM" ); if ( ReadMem( 2 ) = 0 ) { DumpBuf(); } } else if ( c = 'F' ) { PrnStr_( "¥n dump EEP" ); if ( ReadMem( 3 ) = 0 ) { DumpBuf(); } } else if ( c = 'R' ) { PrnStr_( "¥n dump REG" ); if ( ReadMem( 0 ) = 0 ) { DumpBuf(); } } else if ( c = 'P' ) { Patch(); } else if ( c = 'Q' ) { break; } } PrnStr_( "¥nSee you again!" ); }



LibGreen ライブラリ(picle言語)
#LibGreen GreenPAK writer libraly Ver 0.01 2024/05/26 by skyriver # written with picle language use LibPic; use LibI2C; use LibGreen1; # load Hex into buffer # return -> 0:ok func LoadHex() { var i,c,cnt,adr,type,dmy; for ( i = 0; i < 256; i=i+1 ) { _Buf[ i ] = 0; } do { do { c = InpChar_(); if ( c = $1B ) { # ESC return = -1; break; # $__$ } } while ( c <> ':' ); Sum = 0; cnt = GetHexByte(); if ( (cnt>$20) | (cnt<0) ) { return = 1; } else { adr = GetHexByte() * 256 + GetHexByte(); if ( adr >$F0 ) { return = -2; } else { type = GetHexByte(); for ( i = 0; i < cnt; i=i+1 ) { _Buf[ adr + i ] = GetHexByte(); } dmy = GetHexByte(); if ( Sum & $FF ) { return = 3; # SUM err } } } } while ( (return=0) & (type=0) ); } # write ROM 1 page # badr <- block adr 00:RAM,02:NVM,03:EEP # page <- write page num # return -> 0:ok func WrRom( badr, page ) { var i,cbyte,tmp; cbyte = Padr | badr; page = page * 16; return = I2CAdr( cbyte, I2C_WR ); if ( return = 0 ) { return = I2CSnd( page ); if ( return = 0 ) { for ( i = 0; (i < 16) & (return = 0); i=i+1 ) { return = I2CSnd( _Buf[ page + i ] ); } I2CStop(); WaitAck(); if ( return = 0 ) { return = 1; if ( I2CAdr( cbyte, I2C_WR ) = 0 ) { if ( I2CSnd( page ) = 0 ) { if ( I2CAdr( cbyte, I2C_RD ) = 0 ) { for ( i = 0; i < 16; i=i+1 ) { return = I2CRcv(1); if ( return = 0 ) { if ( I2CRcv <> _Buf[ page + i ] ) { PrnStr_( " missmatch at " ); PrnHex_( page + i ); PrnChar_( ' ' ); PrnHexB_( _Buf[ page + i ] ); PrnStr_( "->" ); PrnHexB_( I2CRcv ); return = 2; # miss match break; # $__$ } } } tmp = I2CRcv(0); } } } I2CStop(); } } } } # write pages in ROM # basr <- block adr 00:RAM,02:NVM,03:EEP # until <- last page num func WritePages( badr, until ) { var i; for ( i = 0; (i<=until) & (return=0); i=i+1 ) { PrnChar_( ' ' ); PrnHexB_( i ); return = WrRom( badr, i ); } } proc Init() { var i; InitReg(); InitI2C( $0210 ); # I2C 2ch:$0210 LATA[0] = 0; LATB[0] = 0; LATA[-2] = $0000; LATB[-2] = $0b0c; I2C_RD = 1; I2C_WR = 0; _Buf = Alloc( 256 ); for ( i = 0; i < 256; i=i+1 ) { _Buf[ i ] = 0; } } proc main() { var est; Init(); Padr = $08; # I2C addr PrnStr_( "¥nread RAM" ); if ( ReadMem( 0 ) = 0 ) { DumpBuf(); } PrnStr_( "¥nread NVM" ); if ( ReadMem( 2 ) = 0 ) { DumpBuf(); } PrnStr_( "¥nread EEP" ); if ( ReadMem( 3 ) = 0 ) { DumpBuf(); } est = Scan(); if ( est >= 0 ) { PrnStr_( "¥n estimate:" ); PrnHexB_( est ); } PrnStr_( "¥nDrag Hex file" ); if ( LoadHex() = 0 ) { DumpBuf(); } }



LibGreen1ライブラリ(picle言語)
#LibGreen1 GreenPAK writer libraly Ver 0.01 2024/05/26 by skyriver # written with picle language var I2C_RD, I2C_WR, Padr, _Buf, Sum; func ToUpper( c ) { if ( (c >= 'a') & (c <='z' ) ) { c = c - ('a' - 'A'); } return = c; } # scan I2C # return -> estimate adr func Scan() { var i,j,adr,cnt,est; cnt = 0; return = -1; est = -1; adr = 0; for ( i = 0; i < 8; i=i+1 ) { PrnStr_( "¥n " ); PrnHexB_( adr ); PrnStr_( " :" ); for ( j = 0; j < 16; j=j+1 ) { PrnChar_( ' ' ); if ( I2CAdr(adr,I2C_WR) ) { PrnStr_( "--" ); if ( cnt = 4 ) { return = est; } cnt = 0; } else { PrnHexB_( adr ); cnt = cnt + 1; if ( cnt = 1 ) { est = adr; } } I2CStop(); adr = adr + 1; } } PrnStr_( "¥n" ); } # wait until ack proc WaitAck() { var dat; do { dat = I2CAdr(Padr,I2C_WR); I2CStop(); } while (dat); } # erase ROM # st <- start block # en <- end block proc EraRom( st, en ) { var i,dmy; if ( st <= en ) { for ( i=st; i<=en; i=i+1 ) { PrnChar_(' '); if (I2CAdr(Padr,I2C_WR) = 0) { if (I2CSnd($E3) = 0) { # ERSR dmy = I2CSnd(i | $80); } } I2CStop(); WaitAck(); PrnHexB_(i); } } } # dump buffer proc DumpBuf() { var adr,i,j; adr = 0; for ( j=0; j<16; j=j+1 ) { PrnStr_( "¥n " ); PrnHexB_( adr ); PrnStr_( " :" ); for ( i=0; i< 16; i=i+1 ) { PrnChar_( ' ' ); if ( i = 8 ) { PrnStr_( "- " ); } PrnHexB_( _Buf[adr] ); adr = adr +1 ; } } PrnStr_( "¥n" ); } # read memory # badr <- block adr 00:RAM,02:NVM,03:EEP # return -> 0:no error func ReadMem( badr ){ var i, cbyte; cbyte = Padr | badr; return = I2CAdr( cbyte, I2C_WR ); if ( return = 0 ) { return = I2CSnd( 0 ); if ( return = 0 ) { return = I2CAdr( cbyte, I2C_RD ); if ( return = 0 ) { for ( i = 0; i < 256; i=i+1 ) { return = I2CRcv( 1 ); if ( return ) { break; # $__$ } _Buf[ i ] = I2CRcv; } cbyte = I2CRcv( 0 ); # dummy read(nack) I2CStop(); } } } } # get hex data from input # GetHex() { func GetHex() { var c; c = InpChar_(); c = ToUpper( c ); if ( (c >= '0') & (c <= '9') ) { return = c - '0'; } else if ( (c >= 'A') & (c <= 'F') ) { return = c + ( 10 - 'A' ); } else { return = -1; } } # get hex byte data func GetHexByte() { return = GetHex(); if ( return >= 0 ) { return = return * 16 + GetHex(); Sum = Sum + return; } }



LibI2C ライブラリ(picle言語)
#LibI2C I2C libraly v0.02 2024/05/25 # written with picle language by skyriver var RegRcv,RegTrn,RegBrg; var RegCon,RegStat; var I2CRcv; # send data to slave # data <- send data # return -> 0:no error func I2CSnd( data ) { while ( RegCon[0] & $1f ) {} RegTrn[0] = data; while ( RegStat[0] & $4000 ) {} return = RegStat[0] & $8000; # check nack } # receive data form slave # ack <- 0:nak, else:ack # I2CRcv -> receive data # return -> 0:no error func I2CRcv( ack ) { while ( RegCon[0] & $1f ) {} RegCon[0] = RegCon[0] | $0008; # enable receive while ( RegCon[0] & $0008 ) {} if ( ack ) { RegCon[0] = RegCon[0] & ~$0020; # set ack } else { RegCon[0] = RegCon[0] | $0020; # set nack } RegCon[0] = RegCon[0] | $0010; # send ack/nack while ( RegCon[0] & $0010 ) {} I2CRcv = RegRcv[0]; return = RegStat[0] & $0040; # check overflow } # start seqence and send salave adrs # adr <- slave_adrs # rd <- 1:rd,0:wr # return -> 0:no error func I2CAdr( adr, rd ) { RegCon[0] = RegCon[0] | 3; # repeated start return = I2CSnd( (adr+adr)|rd ); } # stop I2C sequence proc I2CStop() { RegCon[0] = RegCon[0] | $0004; # set PEN(stop) while ( RegCon[0] & $0004 ) {} } proc InitI2C( base ) { RegRcv = base; RegTrn = base + 2; RegBrg = base + 4; RegCon = base + 6; RegStat = base + 8; RegBrg[0] = 37; # Fcy:16MHz -> 157:100kHz 37:400kHz RegCon[0] = $8000; # enable I2C } proc main() { var adr,err,i,j; InitI2C( $0210 ); # I2C 2ch:$0210 adr = 0; for ( j = 0; j < 8; j=j+1 ) { PrnHexB_( adr ); PrnStr_( " :" ); for ( i = 0; i < 16; i=i+1 ) { PrnChar_( ' ' ); if ( I2CAdr( adr, 0 ) ) { PrnStr_( "--" ); } else { PrnHexB_( adr ); } I2CStop(); adr = adr + 1; } PrnStr_( "¥n" ); } }



LibPic ライブラリ(picle言語)
#LibPic major registance v0.01 2018/08/20 var _REG,LATA,LATB,LATC; var ArIdx,Word,_Byte; func Alloc( size ) { return = Array_(ArIdx); ArIdx=ArIdx+size; } proc InitReg() { var Ad1pcfg; Ad1pcfg = $032c; Ad1pcfg[0] = $ffff; # set digital mode LATA=$02c4; LATB=$02cc; LATC=$02d4; Word = Alloc(1); _Byte = Word; } func GetHigh( dat ) { Word[0] = dat; return = _Byte[1]; } func GetLow( dat ) { return = dat & $ff; }



★追記 2024/05/28
 X(旧Twitter)に投稿したメッセージに添付した操作例の動画を貼っておきます。




[TOP] [ 前へ ] 連載記事一覧 [ 次へ ]

nice!(0)  コメント(0) 
共通テーマ:趣味・カルチャー

GreenPAKで遊ぶ(その1) [GreenPAK]

 プログラマブルデバイスは GAL をよく使っていますが消費電流が大きいことから割合新しいデバイスである GreenPAK を秋月さんで購入してみました。
 購入したのは
  • GreenPAK SLG46826G
  • SSOP20ピン(0.65mm)/SOP20ピン(1.27mm)DIP変換基板
です。手持ちの細ピンヘッダを使って DIP 変換したものが下の写真です。

DIP 変換した SLG46826G


■GreenPAKの概要
 はじめに GreenPAK とは何かを説明すべきでしょうが手を抜いて Gemini の回答を貼っておきます(初の試みでAI利用ですw)
 下記の AI の意見に追記すると GreenPAK シリーズ中 SLG46826 は I2C により NVM(コンフィグレーション用の不揮発メモリ)や NVM の内容がコピーされるメモリに対して書き込みができるので基板に組み込んで運用中にリコンフィグレーションするような使い方もできそうです。

GreenPAKは、ルネサス エレクトロニクスが提供する混合信号集積回路 (IC)と開発ツールのファミリです。従来のICとは異なり、GreenPAKはプログラム可能な不揮発性メモリを使って構成することができ、アナログ回路デジタル回路を自由に組み合わせることができます。 GreenPAKの主な利点は以下の通りです。
  • 柔軟性: 用途に合わせて回路を自由に設計できるため、プロトタイピング小規模な生産に最適です。
  • 短納期: 設計から製造までを短期間で行うことができ、迅速な製品化を実現できます。
  • 低コスト: 従来のASICに比べて安価で、コストを抑えることができます。
  • 省電力: 低消費電力の設計が可能なため、バッテリ駆動機器などに最適です。
GreenPAKは、以下のような様々な用途に使用されています。
  • ウェアラブルデバイス
  • IoT機器
  • 医療機器
  • 産業機器
  • オーディオ機器
GreenPAKの詳細については、ルネサス エレクトロニクスのWebサイトをご覧ください。 以下は、GreenPAKに関する参考情報です。


■開発用ソフトウェア
 ルネサスさんが無償で提供(ダウンロードには登録が必要)している Go Configure Software HUB(以降、Go Hubと記す)を使用して開発できます(デバイス選択後 GreenPAK Designer が起動される)。
※追記 2024/05/30 ルネサスさんの教育資料ではGreenPAK DesignerGo Hubの別名とのこと

 GAL での開発で使用する Wincupl は論理式での記述でしたが Go Hub ではサイプレスの PSOC のように回路図チックな図を描いて開発します。個人的には論理式やプログラム記述方式の方が好きですが部品のプロパティがたくさんある場合には今回の様なお絵描き式の方が適しているのかもしれません。

 下図はテスト用としてオシレータ(OSC0)を使った間欠的な矩形波を出力する回路を入力した画面です。外部ピン(PIN5)からオシレータの on/off 制御を可能なようにしています。シミュレートするための外部ピン入力信号として V3 を追加しました。V3 はプロパティ設定によって回路シミュレータ(LTspice)のように矩形波出力等の色々な出力が可能です。

テスト用回路


 下の画面がシミュレーション結果です。PIN 16 には想定通り、間欠的な矩形波が出力されました。

シミュレート結果画面


■実機で動かした
 SLG46826 対応のライターを購入していませんが、ArduinoM5StickC を使った書込み環境が公開されているようです。これらの手持ちは殆ど無いのですが「最近遊んだMPU」の記事に書いたようにルネサスさんから頂いた Arduino UNO R4 MINIMA がありました。
 ところが・・ですよ、MININA では書き込みがうまくできず、ネット情報によると I2C ライブラリ関連で問題があるとのことですorz
 MINIMA のライブラリを調査する気にはなれず、書き込みに必要なのは I2C インターフェースということで「Pic24ジェネラルボックスの作成(その2)」の記事等で書いた自作の Pic24ジェネラルボックス(以降、GenBoxと記す)を使うことにしました。
 GenBox では自作の JIT 方式のセルフコンパイラである picle が動くので今回の様な試行錯誤する作業では(私にとっては)作業効率がいいのです。

 下図に GenBox の回路図を示します。

Pic24GenBoxの回路図


 SLG46826GenBox は下表のように接続しました。

SLG46826GenBox
10:GND1:GND
20:VDD, 7:VDD25:3.3V
12:SDA6:RB2
13:SCL8:RB3


 参考として SGL46826 の各ピンの信号を下図に示します。

SGL46826 のピンアサイン


 下の写真は GenBox を接続した状態のものです。左端の USB ケーブルでパソコンに接続され、TeraTerm とつながっています。右上からの3本線はロジアナに接続しています。

SGL46826 と GenBox の接続状態


 試しに I2C のアドレス空間をスキャンしてみた結果が下の画面です。

I2C スキャン結果


 初めにシーケンシャルリードを行ってみることにしました。
 下図が SLG46826In-System Programming Guide に記載されているシーケンシャルリードのコマンドです。

SLG46826 のシーケンシャルリード


 最初は最後のリードデータに対しても ACK 応答した為、ロック状態になってしまいましたが上図を参照して ACK/NAK を無くしたところ、うまく動きました(I2Cのハードウェアを直に制御しているのでこんなこともできます)
 しかし、腑に落ちなかったので I2C の開発元である NXP 社(当時のフィリップス社)が提供する I2C 仕様も確認してみました。抜粋を下図に示します。

I2C の仕様(シーケンシャルリード)


 これを見るとシーケンシャルリード時に SLG46826 からの最後のデータに対しては NAK 応答するように書いてあります。上図の 「SLG46826 のシーケンシャルリード」の図に書いてあった最後のデータに対する No Ack bit は NAK のことだったんですね。

 0x74 と 0x75 のメモリデータを正常に読み込めた際のロジアナ波形も貼っておきます。NAK 応答を追加しても正常に動作しました。上記の「SLG46826 のシーケンシャルリード」と全く同じですね。

シーケンシャルリード時のロジアナ波形例


 この時の画面は下図になります。

シーケンシャルリード時の画面例


 最後にソースも貼っておきます。

シーケンシャルリード処理(picle言語)
# SLG46826 input data read Ver 0.01 20240523 by skyriver # I2C addr 0x08 # Din 0x74 8543210_ # 0x75 __EDCBA9 var RegRcv,RegTrn,RegBrg; var RegCon,RegStat,RegAdd,RegMsk; # send data to slave # data <- send data # return -> 0:no error func I2CSnd( data ) { while ( RegCon[0] & $1f ) {} RegTrn[0] = data; while ( RegStat[0] & $4000 ) {} return = RegStat[0] & $8000; # check nack } # receive data form slave # ack <- 0:NAC,else:ACK # RegRcv -> receive data # return -> 0:no error func I2CrRcv( ack) { while ( RegCon[0] & $1f ) {} RegCon[0] = RegCon[0] | $0008; # enable receive while ( RegCon[0] & $0008 ) {} if ( ack ) { RegCon[0] = RegCon[0] & ~$0020; # set ack } else { RegCon[0] = RegCon[0] | $0020; # set nack } RegCon[0] = RegCon[0] | $0010; # send ack while ( RegCon[0] & $0010 ) {} return = RegStat[0] & $0040; # check overflow } # start seqence and send salave adrs # adr_cmd <- sla_adrs << 1 | RD:1 # return -> 0:no error func I2CAdr( adr_cmd ) { RegCon[0] = RegCon[0] | 1; # start return = I2CSnd( adr_cmd ); } # stop I2C sequence proc I2CStop() { RegCon[0] = RegCon[0] | $0004; # set PEN(stop) while ( RegCon[0] & $0004 ) {} } proc Init( base ) { var Ad1pcfg,TrisB; Ad1pcfg = $032c; Ad1pcfg[0] = $ffff; # set digital mode RegRcv = base; RegTrn = base + 2; RegBrg = base + 4; RegCon = base + 6; RegStat = base + 8; RegAdd = base + 10; RegMsk = base + 12; RegBrg[0] = 157; # Fcy:16MHz -> 100kHz RegCon[0] = $8000; # enable I2C } proc main() { var adr,res0,res1; Init( $0210 ); # I2C 2ch:$0210 adr = $08 * 2; res0 = $ff; res1 = res0; if ( I2CAdr( adr ) ) { PrnStr_("--"); } else { if ( I2CSnd( $74 ) = 0 ) { if ( I2CAdr( adr | 1 ) = 0 ) { # read if ( I2CrRcv( 1 ) = 0 ) { res0 = RegRcv[0]; } if ( I2CrRcv( 0 ) = 0 ) { res1 = RegRcv[0]; } } } } I2CStop(); PrnHexB_( res0 ); PrnHexB_( res1 ); }


 SLG46826 の I2C は本家の I2C 仕様と比較してアドレスが11ビット(本家は拡張アドレスは10ビット)だったり、Conrol Code が設定できたり(本家仕様では 1111固定)と独自拡張がされているようですが、今回はこれで筆を置きたいと思います。上記のソースは I2C のハード制御も全て含む完結したソースになっていますが、次回は I2C 関連処理をライブラリ化し、Go Hub で作成したコンフィグレーションデータの書き込みも行ってみたいと思います。


■参考にさせて頂いた情報
 下記の情報を参考にさせて頂きました。ありがとうございます。



[TOP] [ 前へ ] 連載記事一覧 [ 次へ ]

nice!(0)  コメント(0) 
共通テーマ:趣味・カルチャー

久々のばら苑 [日記]

 少し時間が経ってしまいましたが、2024年5月15日の夕方に久々に生田緑地ばら苑に行って来たので記録しておきたいと思います。

 このばら苑は旧向ケ丘遊園にあったばら苑を遊園地の閉園後、存続を求める市民の要望に応じて2002年に川崎市が引き継いだものです。

 今回もいつものように生田緑地の入口の方から木段を登ってばら苑の裏門からの入苑です。

ばら苑の裏門に続く木段


 ばら苑ののぼりが見えてきましたね^^

ばら苑ののぼり


 ばら苑裏門手前の広場に辿り着きました。

ばら苑裏門手前の広場


 上の写真の左端奥に存在感のある木が静かに佇んでいました。

存在感のある木


 開苑時間は16時半までで入苑が16時まででしたが16時ジャストに入苑しました^^;
 赤いばらの色が目に沁みます。この感覚を写真に残すのは難しそうでしたが背景の黒に浮かぶ鮮やかなばらの写真が撮れました。

赤いばら


 青空を背景に佇む淡いピンクのバラには何かしら高貴な雰囲気を感じますね。

淡い色のばら


 風に揺られて戯れているばらたちがなんだか楽しそう。

戯れるばらたち


 バックに椅子を添えるとなにかしらメルヘンな物語が浮かんできそうです。

メルヘンチックなばら


 定番の背景をぼかしたアップを一枚。中心から少しずらしたことで安定感が増しますね。

黄色いばら


 閉苑(16時半)5分前に裏門から退苑してそのまま生田緑地の奥の池まで足を延ばしてみました。
 地面からニョキニョキ伸びているメタセコイヤが素晴らしいですね。

メタセコイア


 見上げるとメタセコイアに覆われた空が見えました。

空を覆うメタセコイア


nice!(0)  コメント(0) 
共通テーマ:趣味・カルチャー

ドローンのケース作成 [3D_printer]

 ハンドル用のアイコンにも使っているように趣味の一つがラジコンなのですが空物のラジコンは国土交通省により2022年6月から登録制度が導入されました。これにより機体重量が 100g 以上のものは登録無しでは飛ばせなくなってしまいました。

 しかし、機体重量が 100g 未満であれば航空法による規制対象外になることから許可無しで飛行させることが可能です。また、小型であれば室内でも飛ばせるので雨や風の日でも楽しめます。ということで機体重量が 100g 未満の 4K カメラ付きのドローンを購入してみました。バッテリを3個付けて ¥4,270 でした。

 下の写真が購入したドローンです。写真には写っていませんがコントローラ用のスマホ固定部品と充電用の USB ケーブルも付属していました。
 今、気が付きましたがドローンの右上の方のカードが1ヵ所破損していますね^^; 欠損した破片は失くしてしまったので ABS フィラメントで出力して接着剤を使って修理する予定です。

購入したドローン


 機体が軽くて華奢なのでカバンで持ち運べるようにケースを作成してみました。CADでの設計画面が下図になります。ドローン本体の上面の曲線に合わせた形状にしました。

ドローンケース1(CAD画面)


 下図は下側から見た図(左側)とキャップを開けた状態の図(右側)になります。ドローンの下面も少し曲率があるのですがとりあえず平らにしています。

ドローンケース2(CAD画面) ドローンケース3(CAD画面)


 3Dプリンタで出力したパーツが下の写真です。PETG フィラメントを使いましたが、左側の透明の方は右側の緑色よりも粘りが小さく、下図のパーツにはありませんがサポートを外すのも大変で PLA フィラメントに近い性質でした。

出力したケース部品


 ケースにドローンを入れる際の写真が下の写真です。

ケースに入りかけのドローン


 このケースに入れた状態であればカバンの中に入れても壊れないと思います。夕方の散歩の際にドローンをカバンに忍ばせて近くの人の居ない広場で飛ばしてみようと思います。

nice!(0)  コメント(0) 
共通テーマ:趣味・カルチャー