Microchip 23K256 (SPI SRAM) sample code for https://www.switch-science.com/catalog/1072/ module.

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 /*
00002  * sample for Microchip 23K256 (SRAM, SPI 20MHz)
00003  */
00004 
00005 #include "mbed.h"
00006 
00007 /** Serial port for DEBUG */
00008 Serial pc(USBTX, USBRX);
00009 
00010 DigitalIn user_button(USER_BUTTON);
00011 
00012 /** */
00013 SPI spi(SPI_MOSI, SPI_MISO, SPI_SCK);
00014 
00015 /** */
00016 DigitalOut cs(SPI_CS);
00017 
00018 /**
00019  * USERボタンが押されるまで待つ。
00020  */
00021 void
00022 wait_until_user_button_pressed() {
00023     while (user_button) {
00024         __nop();
00025     }
00026     pc.printf("USER button is pressed\r\n");
00027     wait(0.2);
00028 }
00029 
00030 /*
00031  * SPI COMMAND (Microchip 23K256 SRAM)
00032  * 1byte read/write 
00033  * page read/write 
00034  * sequential read/write
00035  * status/configuration register read/write
00036  */
00037 enum Microchip23K256Commnd {
00038     READ  = 0x03u,
00039     WRITE = 0x02u,
00040     RDSR = 0x05u,
00041     WRSR = 0x01u,
00042 };
00043 
00044 /** SRAM Mode (Microchip 23K256 SRAM) */
00045 enum Microchip23K256Mode {
00046     MODE_MASK = 0xc0u,
00047     BYTE = 0x00u,
00048     PAGE = 0x80u,
00049     SEQUENTIAL = 0x40u,
00050 };
00051 
00052 /**
00053  * assert CS
00054  */
00055 inline void
00056 assert_CS() {
00057     cs = 0;
00058 }
00059 
00060 /**
00061  * negate CS
00062  */
00063 inline void
00064 negate_CS() {
00065     cs = 1;
00066 }
00067 
00068 /**
00069  * ステータスレジスタ読みだし
00070  * @return レジスタ値
00071  */
00072 inline uint8_t
00073 read_status_register() {
00074     assert_CS();
00075     spi.write(RDSR);
00076     const uint8_t status = spi.write(0x00);
00077     negate_CS();
00078     
00079     return status;
00080 }
00081 
00082 /**
00083  * ステータスレジスタ書き込み
00084  * @param[in] status
00085  */
00086 inline void
00087 write_status_register(const uint8_t status) {
00088     assert_CS();
00089     spi.write(WRSR);
00090     spi.write(status);
00091     negate_CS();
00092 }
00093 
00094 /**
00095  * モードを切り替える。
00096  * @param[in] mode モード
00097  * @return 切替前のモード
00098  * @invariant ステータスレジスタ中のモード以外のフラグは変更しない。
00099  */
00100 inline uint8_t
00101 change_mode(const unsigned int next_mode) {
00102     const uint8_t previous_status = read_status_register();
00103     const uint8_t previous_mode = previous_status & MODE_MASK;
00104     if (next_mode != previous_mode) {
00105         const uint8_t next_status = (previous_status & ~MODE_MASK) | uint8_t(next_mode);
00106         write_status_register(next_status);
00107     }
00108     return previous_mode;
00109 }
00110 
00111 /**
00112  * 1byte read
00113  * @param[in] address アドレス 16bit。容量32KBなので、MSBは無視する
00114  * @return データ
00115  * @pre byteモードに切り替えていること。
00116  */
00117 uint8_t
00118 read_byte(const uint16_t address) {
00119     const uint8_t address_high = (address >> (8 * 1)) & 0xFFu;
00120     const uint8_t address_low  = (address >> (8 * 0)) & 0xFFu;
00121     
00122     assert_CS();
00123     spi.write(READ);
00124     spi.write(address_high);
00125     spi.write(address_low);
00126     const uint8_t data = spi.write(0);
00127     negate_CS();
00128 
00129     return data;
00130 }
00131 
00132 /**
00133  * 1byte write
00134  * @param[in] address アドレス 16bit。容量32KBなので、MSBは無視する
00135  * @param[in] data データ
00136  * @pre byteモードに切り替えていること。
00137  */
00138 void
00139 write_byte(const uint16_t address, const uint8_t data) {
00140     const uint8_t address_high = (address >> (8 * 1)) & 0xFFu;
00141     const uint8_t address_low  = (address >> (8 * 0)) & 0xFFu;
00142 
00143     assert_CS();
00144     spi.write(WRITE);
00145     spi.write(address_high);
00146     spi.write(address_low);
00147     spi.write(data);
00148     negate_CS();
00149 }
00150 
00151 /**
00152  * 連続読み出し
00153  * @pre pageモードかbyteモードに切り替えていること。
00154  */
00155 void
00156 read_bytes(const uint16_t address, uint8_t __restrict data[], const uint16_t size) {
00157     const uint8_t address_high = (address >> (8 * 1)) & 0xFFu;
00158     const uint8_t address_low  = (address >> (8 * 0)) & 0xFFu;
00159 
00160     assert_CS();
00161     spi.write(READ);
00162     spi.write(address_high);
00163     spi.write(address_low);
00164     for (uint16_t i = 0; i < size; ++i) {
00165         data[i] = spi.write(0x00);
00166     }
00167     negate_CS();
00168 }
00169 
00170 /**
00171  * 連続書き込み
00172  * @pre pageモードかbyteモードに切り替えていること。
00173  */
00174 void
00175 write_bytes(const uint16_t address, const uint8_t __restrict data[], const uint16_t size) {
00176     const uint8_t address_high = (address >> (8 * 1)) & 0xFFu;
00177     const uint8_t address_low  = (address >> (8 * 0)) & 0xFFu;
00178 
00179     assert_CS();
00180     spi.write(WRITE);
00181     spi.write(address_high);
00182     spi.write(address_low);
00183     for (uint16_t i = 0; i < size; ++i) {
00184         spi.write(data[i]);
00185     }
00186     negate_CS();
00187 }
00188 
00189 /*
00190  *
00191  */
00192 
00193 
00194 /** 動作確認用 SPI buffer */
00195 uint8_t buf[256] = {};
00196 
00197 /**
00198  * 動作確認用。TODO: テストコードにすること。
00199  */
00200 void
00201 try_byte_access() {
00202     const uint8_t size = 16;
00203     
00204     change_mode(BYTE);
00205 
00206     // write data
00207     for (int i = 0; i < size; i++) {
00208         write_byte(i, i);
00209     }
00210 
00211     // read data
00212     for (int i = 0; i < size; i++) {
00213         buf[i] = read_byte(i);
00214     }
00215 
00216     // show data (to SERIAL)
00217     pc.printf("byte access test: result\r\n");
00218     for (int i = 0; i < size; i++) {
00219         pc.printf("  %04x : %02x %s\r\n", i, buf[i], (buf[i] ==i)?"OK":"BAD");
00220     }
00221 }
00222 
00223 /**
00224  * 動作確認用。TODO: テストコードにすること。
00225  */
00226 void
00227 try_page_access() {
00228     const uint16_t address = 0x1000;
00229     const uint16_t size = 32;
00230 
00231     change_mode(PAGE);
00232 
00233     // write
00234     for (uint16_t i = 0; i < size; ++i) {
00235         buf[i] = i;
00236     }
00237     write_bytes(address, buf, size);
00238 
00239     // read
00240     for (uint16_t i = 0; i < size; ++i) {
00241         buf[i] = 0;
00242     }
00243 
00244     read_bytes(address, buf, size);
00245 
00246     // show data (to SERIAL)
00247     pc.printf("page access test: result\r\n");
00248     for (int i = 0; i < size; i++) {
00249         pc.printf("  %04x : %02x %s\r\n", address + i, buf[i], (buf[i] ==i)?"OK":"BAD");
00250     }
00251 }
00252 
00253 /**
00254  * 動作確認用。TODO: テストコードにすること。
00255  */
00256 void
00257 try_sequential_access() {
00258     const uint16_t address = 0x2000;
00259     const uint16_t size = 256;
00260 
00261     change_mode(SEQUENTIAL);
00262 
00263     // write
00264     for (uint16_t i = 0; i < size; ++i) {
00265         buf[i] = i;
00266     }
00267 
00268     write_bytes(address, buf, size);
00269 
00270     // read
00271     for (uint16_t i = 0; i < size; ++i) {
00272         buf[i] = 0;
00273     }
00274 
00275     read_bytes(address, buf, size);
00276 
00277     // show data (to SERIAL)
00278     pc.printf("sequential access test: result\r\n");
00279     for (int i = 0; i < size; i++) {
00280         pc.printf("  %04x : %02x %s\r\n", address + i, buf[i], (buf[i] ==i)?"OK":"BAD");
00281     }
00282 }
00283 
00284 
00285 /**
00286  *
00287  * @pre SPI初期化済初期和美であること。バイトモードであること
00288  */
00289 void
00290 try_single_byte_access() {
00291     const uint8_t address_high = (0x12 >> (8 * 1)) & 0xFFu;
00292     const uint8_t address_low  = (0x13 >> (8 * 0)) & 0xFFu;
00293 
00294     const uint8_t command_write = 0x02u;
00295     const uint8_t command_read = 0x03u;
00296     
00297     const uint8_t data = 0x55;
00298 
00299     // 1byte write
00300     cs = 0;
00301     spi.write(command_write);
00302     spi.write(address_high);
00303     spi.write(address_low);
00304     spi.write(data);
00305     cs = 1;
00306     
00307     // 1byte read
00308     cs = 0;
00309     spi.write(command_read);
00310     spi.write(address_high);
00311     spi.write(address_low);
00312     const uint8_t value = spi.write(0);
00313     cs = 1;
00314 
00315     pc.printf("write: %02x -> read: %02x\r\n", data, value);
00316 }
00317 
00318 
00319 /**
00320  * 動作確認用。TODO: テストコードにすること。
00321  */
00322 int
00323 main()
00324 {
00325     pc.baud(115200);
00326     pc.printf("CPU SystemCoreClock is %.2f MHz\r\n", (float)SystemCoreClock/1.0e6f);
00327 
00328     // initialize SPI
00329     spi.format(8, 0);   // 8bit, mode=0
00330     spi.frequency(20 * 1000 * 1000);    // max 20MHz
00331     negate_CS();
00332 
00333     // test
00334     pc.printf("\r\npush user button to start: try_single_byte_access\r\n");
00335     wait_until_user_button_pressed();
00336     try_single_byte_access();
00337 
00338     pc.printf("\r\npush user button to start: try_byte_access\r\n");
00339     wait_until_user_button_pressed();
00340     try_byte_access();
00341 
00342     pc.printf("\r\npush user button to start: try_page_access\r\n");
00343     wait_until_user_button_pressed();
00344     try_page_access();
00345 
00346     pc.printf("\r\npush user button to start: try_sequential_access\r\n");
00347     wait_until_user_button_pressed();
00348     try_sequential_access();
00349 
00350     pc.printf("\r\nTEST END\r\n\r\n");
00351 
00352     for(;;) {
00353     }
00354 }