SH7125でシリアル通信
AKI-H8/3069F-LANからAKI-SH7125+ベースボードに変更したため、ファームウェアの作り直し。
- マイコンのHello WorldといえばLEDの点滅。まずはベースボードのLED点滅。あっさり完了。
- 次に、割り込みを使わないポーリングによるシリアル通信(1byte版)。あっさり完了。
- 次に、割り込みを使ったシリアル通信(1byte版)。あっさり完了。
- 次に、リングバッファを使ったシリアル通信。リングバッファのソースは、H8/3069Fのときに書いたソースを移植であっさり完了。
gccからHEWになって良かったこと。
- iodefine.hが自動生成されてI/Oレジスタの参照や代入がとっても楽になった
gccからHEWになって良くないところ。
あと、フラッシュROMの書き込みは、ルネサス純正のFDTに変えたが、h8writeよりも劇的に高速。これは楽チン。
RAMが8kbyteしかないため、リングバッファは、送信用500byte、受信用500byteにしてみた。あと、リングバッファのオーバーフローチェックは入れていない。シリアル通信の割り込みもエラー関係の割り込みもハンドリングしていない。受信処理や送信処理が追いつかないときは、データが破棄されると思われる。
シリアル通信のソースは、下記。
Serial.h
//Serial.h //Eiji Kamiya //Licence : New BSD #ifndef __SERIAL_H__ #define __SERIAL_H__ #include "typedefine.h" //初期化 void InitializeSerial(void); //文字列送信 void SerialPuts(const char *str); //1文字送信 void SerialPutc(char ch); //バイト配列送信 void SerialWriteData(uint8* buf,int16 size); //受信バッファにあるデータサイズ int16 GetRecieveBufferDataSize(); //1文字受信 int16 SerialGetc(); //バイト配列受信 int16 SerialReadData(uint8* buf,int16 size); #endif//__SERIAL_H__
Serial.c
/***********************************************************************/ /* */ /* FILE :Serial.c */ /* DESCRIPTION :Main Program */ /* CPU TYPE :SH7125 */ /* */ /* This file is generated by Renesas Project Generator (Ver.4.5). */ /* */ /***********************************************************************/ //シリアル通信割り込み版 //AKI-SH7125+ベースボード //Eiji Kamiya //Licence : New BSD #include <string.h> #include "typedefine.h" #include "iodefine.h" #include "Serial.h" #include "RingBuffer.h" //定数定義 //構造体定義 //グローバル変数 RingBuffer g_send; //送信用リングバッファ RingBuffer g_recieve; //受信用リングバッファ //プロトタイプ宣言 //シリアル通信:1文字送信(同期処理) void PutChar(char ch); //シリアル通信:1文字受信(同期処理) char GetChar(); //シリアル通信:初期化 void InitializeSerial(void) { int i; //リングバッファ InitializeRingBuffer(&g_send); InitializeRingBuffer(&g_recieve); //スタンバイコントロールレジスタ(省電力モード) STB.CR3.BIT._SCI1=0;//SCI1起動 //送受信割込禁止、送受信禁止 SCI1.SCSCR.BYTE=0x00; //シリアルモードレジスタ:通信フォーマット、クロックソースを選択 SCI1.SCSMR.BYTE=0x00; //ビットレートレジスタ //25MHz, 9600bpsのときBRR=(25000000/(32*9600)) - 1 = 80 //25Mhz,38400bpsのときBRR=(25000000/(32*38400))- 1 = 19 SCI1.SCBRR=19; for(i=0;i<100000;i++){ } //ピンファンクションコントローラ //RXD1(PA3) PACRL1(14-12):001 PFC.PACRL1.BYTE.H=0x10; //TXD1(PA4) PACRL2(2-0):001 PFC.PACRL2.BYTE.L=0x01; //シリアルコントロールレジスタ SCI1.SCSCR.BIT.TE=1; //送信可 SCI1.SCSCR.BIT.RE=1; //受信可 SCI1.SCSCR.BIT.RIE=1; //受信割り込みON SCI1.SCSCR.BIT.TIE=0; //送信割り込みOFF } //シリアル通信:文字列送信 void SerialPuts(const char* str) { int16 len=strlen(str); int16 capa=GetRingBufferCapacity(&g_send); char ch; if(len>capa){//送信バッファより長い文字列のとき len=capa; } WriteRingBuffer(&g_send,(const uint8*)str,0,len); SCI1.SCSCR.BIT.TIE=1; //送信割り込みON } //シリアル通信:1文字送信 void SerialPutc(char ch) { int16 capa=GetRingBufferCapacity(&g_send); if(capa==0){//送信バッファがいっぱいのとき return; } WriteRingBufferByte(&g_send,ch); SCI1.SCSCR.BIT.TIE=1; //送信割り込みON } //バイト配列送信 void SerialWriteData(uint8* buf,int16 size) { int len=GetRingBufferCapacity(&g_send); if(size>len){//送信バッファの空き領域よりデータが大きいとき size=len; } WriteRingBuffer(&g_send,buf,0,size); SCI1.SCSCR.BIT.TIE=1; //送信割り込みON } //受信バッファにあるデータサイズ int16 GetRecieveBufferDataSize() { return GetRingBufferSize(&g_recieve); } //1文字受信 int16 SerialGetc() { if(IsRingBufferEmpty(&g_recieve)){//空のとき return -1; } return ReadRingBufferByte(&g_recieve); } //バイト配列受信 int16 SerialReadData(uint8* buf,int16 size) { int len=GetRingBufferSize(&g_recieve); if(size>len){ size=len; } ReadRingBuffer(&g_recieve,buf,0,size); return size; } //シリアル通信:1文字送信(同期処理) void PutChar(char ch) { while (SCI1.SCSSR.BIT.TDRE==0); SCI1.SCSSR.BIT.TDRE=0;//フラグをクリア SCI1.SCTDR=ch; } //シリアル通信:1文字受信(同期処理) char GetChar() { char ch; while ((SCI1.SCSSR.BYTE & 0x40)==0); ch = SCI1.SCRDR; SCI1.SCSSR.BYTE = SCI1.SCSSR.BYTE & 0xBF; return ch; } //シリアル通信:受信割り込み //intprg.cのINT_SCI1_RXI1に記述を追加すること void int_sci1_rxi() { WriteRingBufferByte(&g_recieve,GetChar()); } //シリアル通信:送信割り込み //intprg.cのINT_SCI1_TXI1に記述を追加すること void int_sci1_txi() { char ch; if(IsRingBufferEmpty(&g_send)==false){//送信バッファにデータがあるとき ch=ReadRingBufferByte(&g_send); PutChar(ch); if(IsRingBufferEmpty(&g_send)){//送信バッファにデータがなくなったとき SCI1.SCSCR.BIT.TIE=0; //送信割り込みOFF } } }
RingBuffer.h
//RingBuffer ibis inc. Eiji Kamiya 2008/9/5- //Licence : New BSD #ifndef _RING_BUFFER_ #define _RING_BUFFER_ #include "typedefine.h" //---------------------------------------------------------------------------- // 定数定義 //---------------------------------------------------------------------------- #define RING_BUFFER_SIZE 500 //リングバッファサイズ //---------------------------------------------------------------------------- // 構造体定義 //---------------------------------------------------------------------------- //リングバッファ //start==endの場合はデータが空、フルの場合は、endがstart-1 //よって最大限データが格納できるのは、RING_BUFFER_SIZE-1バイトまで。 typedef struct { uint8 buffer[RING_BUFFER_SIZE]; //バッファ int16 start; //データ開始位置(ここが指している値を含む) int16 end; //データ終了位置(ここが指している値は含まない) } RingBuffer; //---------------------------------------------------------------------------- // マクロ //---------------------------------------------------------------------------- //リングバッファが空か #define IsRingBufferEmpty(ring_ptr) ((ring_ptr)->start==(ring_ptr)->end) //---------------------------------------------------------------------------- // プロトタイプ宣言 //---------------------------------------------------------------------------- //リングバッファの初期化 void InitializeRingBuffer(RingBuffer* ring); //リングバッファのデータサイズ int16 GetRingBufferSize(RingBuffer* ring); //リングバッファで2byteピーク int16 GetRingBufferShort(RingBuffer* ring,int16 offset); //リングバッファで1byte読み込み uint8 ReadRingBufferByte(RingBuffer* ring); //リングバッファで2byte読み込み int16 ReadRingBufferShort(RingBuffer* ring); //リングバッファで配列読み込み void ReadRingBuffer(RingBuffer* ring,uint8 buf[],int16 offset,int16 size); //リングバッファの空きデータサイズ int16 GetRingBufferCapacity(RingBuffer* ring); //リングバッファで1byte書きこみ void WriteRingBufferByte(RingBuffer* ring,uint8 ch); //リングバッファに配列書き込み void WriteRingBuffer(RingBuffer* ring,const uint8 buf[],int16 offset,int16 size); #endif//_RING_BUFFER_
RingBuffer.c
//RingBuffer.c ibis inc. Eiji Kamiya 2008/9/5- //Licence : New BSD #include "RingBuffer.h" //---------------------------------------------------------------------------- // グローバル変数の宣言 //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- //リングバッファの初期化 void InitializeRingBuffer(RingBuffer* ring) { ring->start=0; ring->end=0; } //リングバッファのデータサイズ int16 GetRingBufferSize(RingBuffer* ring) { if(ring->end >= ring->start){//境をまたいでいないとき return ring->end -ring->start; } return RING_BUFFER_SIZE - (ring->start - ring->end); } //リングバッファでshortピーク int16 GetRingBufferShort(RingBuffer* ring,int16 offset) { int16 a,b; int16 o=(ring->start + offset)%RING_BUFFER_SIZE; if( o + 2 <= RING_BUFFER_SIZE){//またがないとき a=ring->buffer[o]; b=ring->buffer[o+1]; } else {//1バイトまたぐとき a=ring->buffer[o]; b=ring->buffer[0]; } return (a&0xff)|(b<<8); } //リングバッファで1byte読み込み uint8 ReadRingBufferByte(RingBuffer* ring) { uint8 a; a=ring->buffer[ring->start]; ring->start++; ring->start%=RING_BUFFER_SIZE; return a; } //リングバッファでshort読み込み int16 ReadRingBufferShort(RingBuffer* ring) { int16 a,b; a=ring->buffer[ring->start]; b=ring->buffer[(ring->start+1)%RING_BUFFER_SIZE]; ring->start+=2; ring->start%=RING_BUFFER_SIZE; return (a&0xff)|(b<<8); } //リングバッファで配列読み込み void ReadRingBuffer(RingBuffer* ring,uint8 buf[],int16 offset,int16 size) { int16 i; uint8* p=buf+offset; for(i=0;i<size;i++){ *(p++)=ring->buffer[ring->start]; ring->start++; ring->start%=RING_BUFFER_SIZE; } } //リングバッファの空きデータサイズ int16 GetRingBufferCapacity(RingBuffer* ring) { if(ring->end >= ring->start){//境をまたいでいないとき return RING_BUFFER_SIZE-(ring->end -ring->start)-1; } return ring->start - ring->end -1; } //リングバッファで1byte書きこみ void WriteRingBufferByte(RingBuffer* ring,uint8 ch) { ring->buffer[ring->end++]=ch; ring->end%=RING_BUFFER_SIZE; } //リングバッファに配列書き込み void WriteRingBuffer(RingBuffer* ring,const uint8 buf[],int16 offset,int16 size) { int16 i; uint8* p=buf+offset; for(i=0;i<size;i++){ ring->buffer[ring->end]=*(p++); ring->end++; ring->end%=RING_BUFFER_SIZE; } }
intprg.c
// 221 SCI1 RXI1 void INT_SCI1_RXI1(void){int_sci1_rxi();} // 222 SCI1 TXI1 void INT_SCI1_TXI1(void){int_sci1_txi();}
main.c
//Licence : New BSD //メイン void main(void) { //メイン void main(void) { int size; //受信したサイズ uint8 buf[64]; //受信バッファ //初期化 InitializeSerial(); INTC.IPRL.BIT._SCI1 = 0xF;//SCI1の割り込みレベル設定 SerialPuts("AKI-SH7125 firmware ver.0.01\r\n"); //メイン //受信したデータをそのままエコーバックするだけ while(1){ size=GetRecieveBufferDataSize(); if(size>0){ size=SerialReadData(buf,sizeof(buf)); SerialWriteData(buf,size); } } }