Renesas RX631 UART
UARTを用いて、RX631のデバッグをします。
回路はRX631→SCI1→FT231XS→COM(パソコン)となります。
ここでは、printf(IOStream)を使うために、RenesasのSIM I/O(シミュレーション用のデバッグコンソール)を用いて、PCにシリアル転送を行います。
(自身でprintf関数を実装するのもいいかと思います。)
まず、lowsrc.cとlowsrc.hという名前で次のファイルをプロジェクトに追加します。(ソースコードは長いので後述。)(CS+のプロジェクトファイルから転用しました。)
e2 stduio左側プロジェクトエクスプローラのプロジェクトフォルダ内のsrcフォルダを右クリックし,
新規→ソース・ファイルからlowsrc.c
新規→ヘッダ・ファイルからlowsrc.h
を作成します。(ソースコードは長いので後述。)
ソースコードの追加はプロジェクトファイルのsrcフォルダに直接作成することでも可能です。
次に、reset_program.c内の
//#ifdef __cplusplus // Use SIM I/O //extern "C" { //#endif //extern void _INIT_IOLIB(void); //extern void _CLOSEALL(void); //#ifdef __cplusplus //} //#endif
とreset_program.cのPowerON_Reset_PC関数内の
//_INIT_IOLIB(); //_CLOSEALL();
のコメントアウトを外します。
つぎに、SCI1(UART)の設定をします。
ソースコードを追加するために、e2 stduio左側プロジェクトエクスプローラのプロジェクトフォルダ内のsrcフォルダを右クリックし,
新規→ソース・ファイルからSCI.c
新規→ヘッダ・ファイルからSCI.h
を作成します。(ソースコードは長いので後述。)
つぎに、hardware_setup.cにてSCI.hをインクルードし、HardwareSetup関数でSCI.cのSCI1_initialize関数を呼びます。
これで、デバッグの準備は出来ました!
main文にて
#include <stdio.h> #include "iodefine.h" #include "machine.h" void main(void) { unsigned int i; while(1){ printf("Hello RX World!\n"); for(i = 0; i < 65000; i++) nop(); } }
TeraTerm等を開き、COMを接続し、Hello RX World!が表示されれば成功です!連続でprintfをするのは処理が重いため、nop関数を用いてdelayをとっています。
これでターミナル等を用いてデバッグをすることが可能になりました。
COMの設定は
・ボーレート:115200
・データ:8bit
・パリティ:なし
・ストップビット:1bit
と一般的な設定になっています。
大まか設定としては、SCI1を使ってprintfにリダイレクト(charput,charget)しているということになるかとおもいます。
SCIの初期化の手順は
1.消費電力低減機能の解除
2.ピン設定
3.SCIの初期化
4.ユーザー関数の定義
の順でおこいます。
1.消費電力低減機能の解除
RX631シリーズには、RX621シリーズには実装されていなかった、消費電力低減機能が実装されています。
これはレジスタの初期状態ではすべての周辺機能が消費電力低減状態で起動しており、これを解除するまで任意の周辺機能を使用することが出来ません。
なので、まずはじめにSCI1の消費電力低減機能を解除します。
// SCI1 SYSTEM.PRCR.WORD = 0xA502; // Release protect MSTP(SCI1) = 0; // Wake up SCI1 SYSTEM.PRCR.WORD = 0xA500; // Protect
となります。MSTPCRレジスタに各モジュールの消費電力低減機能を解除するビットがあり、このビットがMSTP(***)というふうにiodefine.hでマクロされているので、これを使用します。
しかし、このMSTPCRレジスタにはアクセスロックがかかっているため、PRCRレジスタに0xA502を設定し、ロックを解除し、消費電力低減機能を解除した後は、再度ロックします。
2.ピン設定
// Set MPC MPC.PWPR.BIT.B0WI = 0; // Release protect MPC.PWPR.BIT.PFSWE = 1; MPC.P26PFS.BIT.PSEL = 0x0A; // Set P26: TXD1 MPC.P30PFS.BIT.PSEL = 0x0A; // Set P30: RXD1 MPC.PWPR.BIT.PFSWE = 0; // Protect MPC.PWPR.BIT.B0WI = 1; PORT2.PMR.BIT.B6 = 1; // P26: peripheral PORT3.PMR.BIT.B0 = 1; // P30: peripheral
次に、ピン設定をします。P26,P30をTXD1,RXD1に設定します。
MPC(マルチピンファンクション)レジスタにて各ピンに任意の周辺機能を付与することができます。
しかし、MPCレジスタはアクセスロックがかかっているため、PWPRレジスタを上コードのように設定し、アクセスロックを解除し、ピンに周辺機能の設定をし、再度ロックをします。
その後、PMR(ポートモードレジスタ)レジスタにてIOピンから周辺機能にピンの状態を変更し、ピンの設定を完了します。
3.SCIの初期化
RX63Nグループ、RX631グループ ユーザーズマニュアル ハードウェア編 Rev1.80(以下データシート)のp.1414の図35.8からSCIの初期化フローチャートの例(調歩同期式モード)を参考に、初期設定を行います。
// SCI1 Settings SCI1.SCR.BIT.TEIE = 0; // Disable TEIE SCI1.SCR.BIT.MPIE = 0; // Normal Mode SCI1.SCR.BIT.RE = 0; // Disable RX SCI1.SCR.BIT.TE = 0; // Disable TX SCI1.SCR.BIT.RIE = 0; // Disable RXI, ERI SCI1.SCR.BIT.TIE = 0; // Disable TXI SCI1.SCR.BIT.CKE = 0; // built in baud rate SCI1.SMR.BIT.CKS = 0; // PCLK SCI1.SMR.BIT.MP= 0; // Disable multiple processor SCI1.SMR.BIT.STOP = 0; // 1 stop bit SCI1.SMR.BIT.PM = 0; // none parity SCI1.SMR.BIT.CHR = 0; // 8bit data length SCI1.SMR.BIT.CM = 0; // 調歩同期式 SCI1.BRR = 12; // 115200bps SCI1.SCR.BIT.RE = 1; // Enable RX SCI1.SCR.BIT.TE = 1; // Enable TX
ここはデータシート通りかと思います。
4.ユーザー関数の定義
ここではprintfでリダイレクされてくる、cahrputとchargetを定義しておきます。
これでSCIの初期設定は完了です。
以下使用ソースコード
SCI.h
#ifndef SCI_H_ #define SCI_H_ void SCI1_initialize(void); #endif /* SCI_H_ */
SCI.c
#include "iodefine.h" #include "machine.h" #include "SCI.h" void SCI1_initialize(void){ // SCI1 SYSTEM.PRCR.WORD = 0xA502; // Release protect MSTP(SCI1) = 0; // Wake up SCI1 SYSTEM.PRCR.WORD = 0xA500; // Protect // Set MPC MPC.PWPR.BIT.B0WI = 0; // Release protect MPC.PWPR.BIT.PFSWE = 1; MPC.P26PFS.BIT.PSEL = 0x0A; // Set P26: TXD1 MPC.P30PFS.BIT.PSEL = 0x0A; // Set P30: RXD1 MPC.PWPR.BIT.PFSWE = 0; // Protect MPC.PWPR.BIT.B0WI = 1; PORT2.PMR.BIT.B6 = 1; // P26: peripheral PORT3.PMR.BIT.B0 = 1; // P30: peripheral // SCI1 Settings SCI1.SCR.BIT.TEIE = 0; // Disable TEIE SCI1.SCR.BIT.MPIE = 0; // Normal Mode SCI1.SCR.BIT.RE = 0; // Disable RX SCI1.SCR.BIT.TE = 0; // Disable TX SCI1.SCR.BIT.RIE = 0; // Disable RXI, ERI SCI1.SCR.BIT.TIE = 0; // Disable TXI SCI1.SCR.BIT.CKE = 0; // built in baud rate SCI1.SMR.BIT.CKS = 0; // PCLK SCI1.SMR.BIT.MP= 0; // Disable multiple processor SCI1.SMR.BIT.STOP = 0; // 1 stop bit SCI1.SMR.BIT.PM = 0; // none parity SCI1.SMR.BIT.CHR = 0; // 8bit data length SCI1.SMR.BIT.CM = 0; // 調歩同期式 SCI1.BRR = 12; // 115200bps SCI1.SCR.BIT.RE = 1; // Enable RX SCI1.SCR.BIT.TE = 1; // Enable TX } void charput(char c) { while(SCI1.SSR.BIT.TEND == 0); SCI1.TDR = c; SCI1.SSR.BIT.TEND = 0; } char charget(void){ char data; data = SCI1.RDR; ICU.IR[VECT_SCI1_RXI1].BIT.IR = 0; return data; }
lowsrc.h
/*Number of I/O Stream*/ #define IOSTREAM 3
lowsrc.c
#include <string.h> #include <stdio.h> #include <stddef.h> #include "lowsrc.h" /* file number */ #define STDIN 0 /* Standard input (console) */ #define STDOUT 1 /* Standard output (console) */ #define STDERR 2 /* Standard error output (console) */ #define FLMIN 0 /* Minimum file number */ #define _MOPENR 0x1 #define _MOPENW 0x2 #define _MOPENA 0x4 #define _MTRUNC 0x8 #define _MCREAT 0x10 #define _MBIN 0x20 #define _MEXCL 0x40 #define _MALBUF 0x40 #define _MALFIL 0x80 #define _MEOF 0x100 #define _MERR 0x200 #define _MLBF 0x400 #define _MNBF 0x800 #define _MREAD 0x1000 #define _MWRITE 0x2000 #define _MBYTE 0x4000 #define _MWIDE 0x8000 /* File Flags */ #define O_RDONLY 0x0001 /* Read only */ #define O_WRONLY 0x0002 /* Write only */ #define O_RDWR 0x0004 /* Both read and Write */ #define O_CREAT 0x0008 /* A file is created if it is not existed */ #define O_TRUNC 0x0010 /* The file size is changed to 0 if it is existed. */ #define O_APPEND 0x0020 /* The position is set for next reading/writing */ /* 0: Top of the file 1: End of file */ /* Special character code */ #define CR 0x0d /* Carriage return */ #define LF 0x0a /* Line feed */ extern const long _nfiles; /* The number of files for input/output files */ char flmod[IOSTREAM]; /* The location for the mode of opened file. */ unsigned char sml_buf[IOSTREAM]; #define FPATH_STDIN "C:\\stdin" #define FPATH_STDOUT "C:\\stdout" #define FPATH_STDERR "C:\\stderr" /* Output one character to standard output */ extern void charput(unsigned char); /* Input one character from standard input */ extern unsigned char charget(void); #include <stdio.h> FILE *_Files[IOSTREAM]; // structure for FILE char *env_list[] = { // Array for environment variables(**environ) "ENV1=temp01", "ENV2=temp02", "ENV9=end", '\0' // Terminal for environment variables }; char **environ = env_list; /****************************************************************************/ /* _INIT_IOLIB */ /* Initialize C library Functions, if necessary. */ /* Define USES_SIMIO on Assembler Option. */ /****************************************************************************/ void _INIT_IOLIB( void ) { /* A file for standard input/output is opened or created. Each FILE */ /* structure members are initialized by the library. Each _Buf member */ /* in it is re-set the end of buffer pointer. */ /* Initializations of File Stream Table */ _Files[0] = stdin; _Files[1] = stdout; _Files[2] = stderr; /* Standard Input File */ if( freopen( FPATH_STDIN, "r", stdin ) == NULL ) stdin->_Mode = 0xffff; /* Not allow the access if it fails to open */ stdin->_Mode = _MOPENR; /* Read only attribute */ stdin->_Mode |= _MNBF; /* Non-buffering for data */ stdin->_Bend = stdin->_Buf + 1; /* Re-set pointer to the end of buffer */ /* Standard Output File */ if( freopen( FPATH_STDOUT, "w", stdout ) == NULL ) stdout->_Mode = 0xffff; /* Not allow the access if it fails to open */ stdout->_Mode |= _MNBF; /* Non-buffering for data */ stdout->_Bend = stdout->_Buf + 1;/* Re-set pointer to the end of buffer */ /* Standard Error File */ if( freopen( FPATH_STDERR, "w", stderr ) == NULL ) stderr->_Mode = 0xffff; /* Not allow the access if it fails to open */ stderr->_Mode |= _MNBF; /* Non-buffering for data */ stderr->_Bend = stderr->_Buf + 1;/* Re-set pointer to the end of buffer */ } /****************************************************************************/ /* _CLOSEALL */ /****************************************************************************/ void _CLOSEALL( void ) { long i; for( i=0; i < _nfiles; i++ ) { /* Checks if the file is opened or not */ if( _Files[i]->_Mode & (_MOPENR | _MOPENW | _MOPENA ) ) fclose( _Files[i] ); /* Closes the file */ } } /**************************************************************************/ /* open:file open */ /* Return value:File number (Pass) */ /* -1 (Failure) */ /**************************************************************************/ long open(const char *name, /* File name */ long mode, /* Open mode */ long flg) /* Open flag */ { if( strcmp( name, FPATH_STDIN ) == 0 ) /* Standard Input file? */ { if( ( mode & O_RDONLY ) == 0 ) return -1; flmod[STDIN] = mode; return STDIN; } else if( strcmp( name, FPATH_STDOUT ) == 0 )/* Standard Output file? */ { if( ( mode & O_WRONLY ) == 0 ) return -1; flmod[STDOUT] = mode; return STDOUT; } else if(strcmp(name, FPATH_STDERR ) == 0 ) /* Standard Error file? */ { if( ( mode & O_WRONLY ) == 0 ) return -1; flmod[STDERR] = mode; return STDERR; } else return -1; /*Others */ } long close( long fileno ) { return 1; } /**************************************************************************/ /* write:Data write */ /* Return value:Number of write characters (Pass) */ /* -1 (Failure) */ /**************************************************************************/ long write(long fileno, /* File number */ const unsigned char *buf, /* The address of destination buffer */ long count) /* The number of chacter to write */ { long i; /* A variable for counter */ unsigned char c; /* An output character */ /* Checking the mode of file , output each character */ /* Checking the attribute for Write-Only, Read-Only or Read-Write */ if(flmod[fileno]&O_WRONLY || flmod[fileno]&O_RDWR) { if( fileno == STDIN ) return -1; /* Standard Input */ else if( (fileno == STDOUT) || (fileno == STDERR) ) /* Standard Error/output */ { for( i = count; i > 0; --i ) { c = *buf++; charput(c); } return count; /*Return the number of written characters */ } else return -1; /* Incorrect file number */ } else return -1; /* An error */ } long read( long fileno, unsigned char *buf, long count ) { long i; /* Checking the file mode with the file number, each character is input and stored the buffer */ if((flmod[fileno]&_MOPENR) || (flmod[fileno]&O_RDWR)){ for(i = count; i > 0; i--){ *buf = charget(); if(*buf==CR){ /* Replace the new line character */ *buf = LF; } buf++; } return count; } else { return -1; } } long lseek( long fileno, long offset, long base ) { return -1L; } #ifdef _REENTRANT // For Reentrant Library (generated lbgrx with -reent option) #define MALLOC_SEM 1 /* Semaphore No. for malloc */ #define STRTOK_SEM 2 /* Semaphore No. for strtok */ #define FILE_TBL_SEM 3 /* Semaphore No. for fopen */ #define MBRLEN_SEM 4 /* Semaphore No. for mbrlen */ #define FPSWREG_SEM 5 /* Semaphore No. for FPSW register */ #define FILES_SEM 6 /* Semaphore No. for _Files */ #define SEMSIZE 26 /* FILES_SEM + _nfiles (assumed _nfiles=20) */ #define TRUE 1 #define FALSE 0 #define OK 1 #define NG 0 extern long *errno_addr(void); extern long wait_sem(long); extern long signal_sem(long); static long sem_errno; static int force_fail_signal_sem = FALSE; static int semaphore[SEMSIZE]; /******************************************************************************/ /* errno_addr: Acquisition of errno address */ /* Return value: errno address */ /******************************************************************************/ long *errno_addr(void) { /* Return the errno address of the current task */ return (&sem_errno); } /******************************************************************************/ /* wait_sem: Defines the specified numbers of semaphores */ /* Return value: OK(=1) (Normal) */ /* NG(=0) (Error) */ /******************************************************************************/ long wait_sem(long semnum) /* Semaphore ID */ { if((0 < semnum) && (semnum < SEMSIZE)) { if(semaphore[semnum] == FALSE) { semaphore[semnum] = TRUE; return(OK); } } return(NG); } /******************************************************************************/ /* signal_sem: Releases the specified numbers of semaphores */ /* Return value: OK(=1) (Normal) */ /* NG(=0) (Error) */ /******************************************************************************/ long signal_sem(long semnum) /* Semaphore ID */ { if(!force_fail_signal_sem) { if((0 <= semnum) && (semnum < SEMSIZE)) { if( semaphore[semnum] == TRUE ) { semaphore[semnum] = FALSE; return(OK); } } } return(NG); } #endif
20160818の記事