CY8CKIT-049に1MBitSRAMをつける
Ver.1.001 2020.10.12

更新履歴
2020. 8.24 Ver.1.000 新規作成
2020.10.12 Ver.1.001 ソフト修正

【初めに】
PSoC4200 CY8CKIT-049には、メモリが4KBしかありません。そこで、IO接続で、PSoC4200 CY8CKIT-049に1MBitSRAMをつないでみましょう。
とりあえず第一弾は、ソフト制御です。
また、PSoC4200 CY8CKIT-049のIO端子は少ないので、アドレスは、外付けにTC74HC163(あるいはTC74HC161)の同期式バイナリーカウンタをつ けます。こうすると、アドレス線が、1MBitSRAMは、128KBなので、17本もありますがそれがすべて外付けカウンタから出るので、データバスと わずかな制御線で済みます。

第2弾は、ハード制御です。最終版は、PSoC4200M CY8CKIT-043を使って、DMAにして、ソフトはほとんど介入なしにしたいと思いま す。

PSoC4200のハード設定

ソフト制御なので、IO端子だけです。とは言え、メッセージを表示するLCDキャラクターディスプレイとUARTをつけます。
ここでは、LCDキャラクターディスプレイはデータ4本制御3本のものを使います。



図1回路図

これは回路図ですが、配線は一つもありません。ソフトIOなので、配線は不要なのです。



図2 IO端子の設定
 
出力端子を配置し、Nameを書き、HW connectionのチェックを外します。同様に、WE、LD0,LD1,A16,CLKOUT,C_ENも同じようにします。



図3 データバスの設定1

出力端子を回路図に1つおき、このように設定します。双方向バスは、Bidrectionalでは、ありません。Bidrectionalは、I2Cの sda端子専用です。
Degital input Degital outputにそれぞれチェックを入れ、抵抗プルアップにします。データバスに書くときはデータバスに書きますが、データーバスから読むときは、データバ スに0x0FFかいて、バスをすべてハイにして、データバスを読みます。こうしないと読めません。



図4 データバスの設定2

Mappingのタブをクリックして、Display as busにチェックを入れます。

UARTとLCD_Charの設定はありません。

端子割り付け

端子割り付けは、このようにしました。



図5 端子割り当て

P4(0)、P4(1)は、CY8CKIT-049の配線から決まってしまいます。
また、P1(7)は、SARADCの基準電圧安定化のコンデンサC3とジャンパーR2が、CY8CKIT-049の配線で決まっていますので、R2をはん だごてではずしました。不都合なら、ほかのPINに移動してもいいです。
でも、CY8CKIT-049の配線でP4(2)、P4(3)は、CMOD、CTANKが、つながっていますし、P1(6)には、LED、P0(7)に は、SWがつながっています。
それぞれ、直列にジャンパーがあるので、半田ごてで外すこともできます。
それ以外のPINでは制約はありません。なお、P3(2)、P3(3)はSWD制御線で、プログラマ、デバッガに使いますので、これも使えません。


外付け回路部品の配線

電源は、CY8CKIT-049のP4VDDとGNDを使うといいです。J2のGNDとGNDをつないでおきます。

LCDキャラクターディスプレイの配線


LCDキャラクターディスプレイの配線は、Cypressのマニュアル(LCD_CharのDatasheet)より、



図6 LCD キャラクターディスプレイの配線方法

となっています。電源(Vcc)とGND(Vss)にセラコン0.1uFをつけてください。

TC74HC163(または、TC74HC161)

4bitのバイナリカウンタです。TC74HC161とTC74HC163の違いは、CLEAR(CLR)が、非同期か同期かの違いで、ここでは、 CLEARを使っていませんので、どちらでもかまわないです。


図7 TC74HC163(TC74HC161)のピン接続図

これを4個使って、16bitカウンタにします。同期式カウンタなので、CLKOUT(CK)の立ち上がりで、変化しますので、ほかの入力端子が変化して も、何も起きません。ですから、他の端子の変化タイミングには、CKのHLD,SETUPタイムを満足しておれば、関係しません。ですから、プログラムの 依存性は低いです。
さて、メモリは128KBなので、アドレスは17本で1本足りませんので、IO端子A16を用意しました。したがって、カウンタは16bitで折り返して しまうので、注意が必要です。



図8 16bitカウンタの回路図

この回路図のLeは、LOADで、Rstは、CLR、P0-P3は、A-D、Q0-Q3は、QA-QD、TCはCOに対応します。D7-D0は DATA_BUS7-0に対応します。
電源とGNDは書かれていませんが、全部配線します。IC毎に電源(Vcc)とGNDにセラコン0.1uFをつけてください。

LD0をLにして、CLKOUTをLからHにすると、その立ち上がりで、DATA_BUS7-0が、カウンタに読み込まれて、カウンタのA7_0に出力さ れます。同様にLD1をLにしてCLKOUTをLからHにすると、その立ち上がりで、DATABUS7-0が、カウンタに読み込まれて、A15-8に出力 されます。
したがって、ラッチにもなります。LD0,LD1をともに、Lにして、DATABUSに0を書いて、CLKOUTをLからHにすると、その立ち上がりで、 DATA_BUS7-0が、カウンタに読み込まれて、A15-0が、皆0になります。ですから、CLEAR端子は要らないのです。

カウンタにDATABUSから、アドレスを読み込ませれば、ダイレクトアクセスができます。
また、カウンタにDATABUSから、アドレスを読み込ませて、メモリを読み書きして、C_ENをHにし、CLKOUTをLからHにすると、その立ち上が りで、カウンタがカウントアップして、次のアドレスを示します。したがって、次にメモリを読み書きすれば、次にアドレスになっているので、いちいちアドレ スを指定しなくてもC_ENをHにし、CLKOUTをLからHにすると、その立ち上がりで、カウンタがカウントアップして、次のアドレスを示しますので、 連続してアクセスできます。

1MBitSRAM(M68AF127B)

1MBitSRAM(M68AF127B)のピン接続図は以下に示します。



図9 1MBitSRAM(M68AF127B)のピン接続図 

Gは、OE、WはWEにつなぎます。A0-15は、16bitカウンタから、A16はA16につなぎます。Vccは電源です。VssはGNDです。
NCはなにもつなぎません。E1は、GNDへ、E2は電源(Vcc)につなぎます。電源(Vcc)とGND(Vss)にセラコン0.1uFをつけてくださ い。


図9−1 1MBitSRAM(M68AF127B)の動作表

リードは、WEをH,OEをLにします。ライトはWEをLにします。WEがLだとOEは無視されて、ライトになります。
E1をHにすると、スタンバイモードとなって、超低消費電力になります。ここでは、スタンバイモードは使っていません。



図10 完成図

GNDを使い切ったはんだ吸い取り線で強化し、ケミコン33UFをところどころに入れました。
TC74HC163は、DIP品はなく、SOPパッケージを使っています。したがって、TC74HC161AF,TC74HC163AFです。


プログラムmain.c

現在メモリテストプログラムだけできています。エラーすると、そこで止まります。
エラーがなければ、永遠に続けます。

#include "project.h"
#include <stddef.h>     // sprinf用
#include <stdlib.h>
     // sprinf用
#include <stdio.h>     // sprinf用


void write_counter_low_byte(uint8 address_low)
{
    C_EN_Write(0);   // Count_EN L
    DATA_BUS_Write(address_low);
    LD0_Write(0);   // LD0 L
    CLKOUT_Write(1);   // CLK H
    CLKOUT_Write(0);   // CLK L
    LD0_Write(1);   // LD0 H
    DATA_BUS_Write(0xff);
}
   
void write_counter_high_byte(uint8 address_high)
{
    C_EN_Write(0);   // Count_EN L
    DATA_BUS_Write(address_high);
    LD1_Write(0);   // LD1 L
    CLKOUT_Write(1);   // CLK H
    CLKOUT_Write(0);   // CLK L
    LD1_Write(1);   // LD1 H
    DATA_BUS_Write(0xff);
}

void count_up(void)
{
    CLKOUT_Write(0);   // CLK L
    C_EN_Write(1);   // Count_EN H
    CLKOUT_Write(0);   // CLK L
    CLKOUT_Write(1);   // CLK H
    CLKOUT_Write(0);   // CLK L
    C_EN_Write(0);   // Count_EN L
 }



uint8 mem_read(uint16 address)
{
uint8 low;
uint8 high;
uint8 data;   
    C_EN_Write(0);   // Count_EN L
    low=address & 0x0ff;
    high=address>>8;
    write_counter_low_byte(low);
    write_counter_high_byte(high);
    WE_Write(1);   // WE H
    DATA_BUS_Write(0x0ff);
    OE_Write(0);   // OE L
    data=DATA_BUS_Read();
    data=DATA_BUS_Read();
    OE_Write(1);   // OE H
    return(data);
}

uint8 mem_read_start(uint16 address)
{
uint8 low;
uint8 high;
int data;   
    low=address & 0x0ff;
    high=address>>8;
    write_counter_low_byte(low);
    write_counter_high_byte(high);
    WE_Write(1);   // WE H
    DATA_BUS_Write(0x0ff);
    OE_Write(0);   // OE L
    data=DATA_BUS_Read();
    data=DATA_BUS_Read();
    OE_Write(1);   // OE H
    count_up();
    return((uint8)data);
}

uint8 mem_read_next(void)
{
int data;   
    WE_Write(1);   // WE H
    DATA_BUS_Write(0x0ff);
    OE_Write(0);   // OE L
    data=DATA_BUS_Read();
    data=DATA_BUS_Read();
    OE_Write(1);   // OE H
    count_up();
    DATA_BUS_Write(0x0ff);
    return((uint8) data);
}

uint8 mem_read_hold(void)
{
int data;   
    WE_Write(1);   // WE H
    DATA_BUS_Write(0x0ff);
   OE_Write(0);   // OE L
    data=DATA_BUS_Read();
    data=DATA_BUS_Read();
    OE_Write(1);   // OE H
    return((uint8)data);
}

void mem_write(uint16 address,uint8 data)
{
uint8 low;
uint8 high;
    low=address & 0x0ff;
    high=address>>8;
    write_counter_low_byte(low);
    write_counter_high_byte(high);
    WE_Write(1);   // WE H
    DATA_BUS_Write(data);
    WE_Write(0);   // WE L
    WE_Write(1);   // WE H
    DATA_BUS_Write(0x0ff);
}

void mem_write_start(uint16 address,uint8 data)
{
uint8 low;
uint8 high;
    low=address & 0xff;
    high=address>>8;
    write_counter_low_byte(low);
    write_counter_high_byte(high);
    CLKOUT_Write(0);
    DATA_BUS_Write(data);
    WE_Write(0);   // WE L
    WE_Write(1);   // WE H
    DATA_BUS_Write(0xff);
    count_up();
}

void mem_write_next(uint8 data)
{
    DATA_BUS_Write(data);
    WE_Write(0);   // WE L
    WE_Write(1);   // WE H
    DATA_BUS_Write(0xff);
    count_up();
}
void mem_write_hold(uint8 data)
{
    DATA_BUS_Write(data);
    WE_Write(0);   // WE L
    WE_Write(1);   // WE H
    DATA_BUS_Write(0xff);
}


int main(void)
{
uint16 address;
uint8 data;
uint8 test_data;
uint8 a16=0;   
uint8 pass=0;
char buffer[40];

    CyGlobalIntEnable; /* Enable global interrupts. */

    /* Place your initialization/startup code here (e.g. MyInst_Start()) */
    LCD_Char_1_Start() ;
    UART_1_Start();
    CyDelay(1000);
    LCD_Char_1_Position(0, 0) ;
    LCD_Char_1_PrintString("MEMORY TEST     ") ;
    sprintf(buffer,"\n Memory test \n");
    UART_1_UartPutString(buffer) ;
    LCD_Char_1_Position(1, 0) ;
    LCD_Char_1_PrintString("LCD TEST     ") ;
    sprintf(buffer,"LCD test \n");
    UART_1_UartPutString(buffer) ;
    UART_1_UartPutCRLF(1) ;

    // init terminal
    LD0_Write(1);   // LD0 H
    LD1_Write(1);   // LD1 H
    CLKOUT_Write(0);   // CLK L
    C_EN_Write(0);   // C_EN L
    OE_Write(1);   // OE H
    WE_Write(1);   // WE H
    A16_Write(a16);   // A16
   
    address=0;
    DATA_BUS_Write(0xff);
   
    LCD_Char_1_Position(1, 0) ;
    LCD_Char_1_PrintString("                ") ;
   

    for(;;){

    // test 55 
    test_data=0x00;
    write_counter_low_byte(0);
    write_counter_high_byte(0);

    for(address=0;address!=0xffff;address++){
      mem_write_next(test_data);
      test_data--;
    }
   
    test_data=0;
    write_counter_low_byte(0);
    write_counter_high_byte(0);

    for(address=0;address!=0xffff;address++){
      data=mem_read_next();
      if(data != test_data){
       LCD_Char_1_Position(1, 0) ;
       LCD_Char_1_PrintInt16(address) ;
       LCD_Char_1_PrintString(" ") ;
       LCD_Char_1_PrintInt8(test_data) ;
       LCD_Char_1_PrintString(" ") ;
       LCD_Char_1_PrintInt8(data) ;
       LCD_Char_1_PrintString(" ") ;
       sprintf(buffer,"ERORR %04x %02x %02x \n",address,test_data,data);
       UART_1_UartPutString(buffer) ;
       UART_1_UartPutCRLF(1) ;
      for(;;){};
     };
    test_data--;
    };

    pass++;
    LCD_Char_1_Position(1, 0) ;
    LCD_Char_1_PrintString("PASS= ") ;
    LCD_Char_1_PrintInt8(pass) ;
    LCD_Char_1_PrintString(" SEQRDS") ;

    sprintf(buffer,"PASS=%d  SEQRDS\n" ,pass);
    UART_1_UartPutString(buffer) ;
    UART_1_UartPutCRLF(1) ;
   
    for(address=0;address!=0xffff;address++){
      mem_write(address,0x55);
    };
//2020.10.12 追加
    write_counter_low_byte(0);
    write_counter_high_byte(0);
//2020.10.12ここまで  
    for(address=0;address!=0xffff;address++){
      data=mem_read_next();
      if(data != 0x55){
        LCD_Char_1_Position(1, 0) ;
       LCD_Char_1_PrintInt16(address) ;
       LCD_Char_1_PrintString(" ") ;
       LCD_Char_1_PrintInt8(0x55) ;
       LCD_Char_1_PrintString(" ") ;
       LCD_Char_1_PrintInt8(data) ;
       LCD_Char_1_PrintString(" ") ;

      sprintf(buffer,"EROOR %04x %02x %02x \n",address,0x55,data);
      UART_1_UartPutString(buffer) ;
      UART_1_UartPutCRLF(1) ;
       for(;;){};
     };
    };
       pass++;

    LCD_Char_1_Position(1, 0) ;
       LCD_Char_1_PrintString("PASS= ") ;
       LCD_Char_1_PrintInt8(pass) ;
       LCD_Char_1_PrintString(" SEQRD ") ;

      sprintf(buffer,"PASS=%d  SEQRD\n" ,pass);
      UART_1_UartPutString(buffer) ;
      UART_1_UartPutCRLF(1) ;
   
   
    for(address=0;address!=0xffff;address++){
      mem_write(address,0xaa);
      };
   
    write_counter_low_byte(0);
    write_counter_high_byte(0);
    for(address=0;address!=0xffff;address++){
       data=mem_read_next();
       if(data != 0xaa){
       
       LCD_Char_1_Position(0, 0) ;
       LCD_Char_1_PrintInt16(address) ;
       LCD_Char_1_PrintString(" ") ;
       LCD_Char_1_PrintInt8(0xaa) ;
       LCD_Char_1_PrintString(" ") ;
       LCD_Char_1_PrintInt8(data) ;
       LCD_Char_1_PrintString(" ") ;

      sprintf(buffer,"ERORR %04x %02x %02x \n",address,0xaa,data);
      UART_1_UartPutString(buffer) ;
      UART_1_UartPutCRLF(1) ;
   
       for(;;){};
     };
    };
       pass++;
   
       LCD_Char_1_Position(1, 0) ;
       LCD_Char_1_PrintString("PASS= ") ;
       LCD_Char_1_PrintInt8(pass) ;
       LCD_Char_1_PrintString(" SEQRD") ;

       sprintf(buffer,"PASS=%d  SEQRD\n" ,pass);
       UART_1_UartPutString(buffer) ;
       UART_1_UartPutCRLF(1) ;

    write_counter_low_byte(0);
    write_counter_high_byte(0);
   
    for(address=0;address!=0xffff;address++){
        mem_write_next (0x55);
     };
   
    for(address=0;address!=0xffff;address++){
      data=mem_read(address);
      if(data != 0x55){

       LCD_Char_1_Position(0, 0) ;
       LCD_Char_1_PrintInt16(address) ;
       LCD_Char_1_PrintString(" ") ;
       LCD_Char_1_PrintInt8(0x55) ;
       LCD_Char_1_PrintString(" ") ;
       LCD_Char_1_PrintInt8(data) ;
       LCD_Char_1_PrintString(" ") ;
       sprintf(buffer,"ERORR %04x %02x %02x \n",address,0x55,data);
       UART_1_UartPutString(buffer) ;
       UART_1_UartPutCRLF(1) ;
      for(;;){};
      };
    }
       pass++;

       LCD_Char_1_Position(1, 0) ;
       LCD_Char_1_PrintString("PASS= ") ;
       LCD_Char_1_PrintInt8(pass) ;
       LCD_Char_1_PrintString(" DIR RD") ;
       sprintf(buffer,"PASS=%d  DIR RD\n" ,pass);
       UART_1_UartPutString(buffer) ;
       UART_1_UartPutCRLF(1) ;
   
    write_counter_low_byte(0);
    write_counter_high_byte(0);

    for(address=0;address!=0xffff;address++){
        mem_write_next(0xaa);
     };

    for(address=0;address!=0xffff;address++){
      data=mem_read(address);
      if(data != 0xaa){
       LCD_Char_1_PrintInt16(address) ;
       LCD_Char_1_PrintString(" ") ;
       LCD_Char_1_PrintInt8(0xaa) ;
       LCD_Char_1_PrintString(" ") ;
       LCD_Char_1_PrintInt8(data) ;
       LCD_Char_1_PrintString(" ") ;

       sprintf(buffer,"ERORR %04x %02x %02x \n",address,0xaa,data);
       UART_1_UartPutString(buffer) ;
       UART_1_UartPutCRLF(1) ;
       for(;;){};
      };
    }

       pass++;

    LCD_Char_1_Position(1, 0) ;
       LCD_Char_1_PrintString("PASS= ") ;
       LCD_Char_1_PrintInt8(pass) ;
       LCD_Char_1_PrintString(" DIRRD") ;

       sprintf(buffer,"PASS=%d  DIRRD\n" ,pass);
       UART_1_UartPutString(buffer) ;
       UART_1_UartPutCRLF(1) ;
   
    if (a16==0){
        a16=1;
    }else{
        a16=0;
    };

    A16_Write(a16);   // A16

      LCD_Char_1_Position(0, 0) ;
       LCD_Char_1_PrintString("A16= ") ;
       LCD_Char_1_PrintInt8(a16) ;
       LCD_Char_1_PrintString("       ") ;

       sprintf(buffer,"A16=%d  \n" ,a16);
       UART_1_UartPutString(buffer) ;
       UART_1_UartPutCRLF(1) ;
}
      /*    END OF FILE */
}