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

Dependencies:   mbed

Committer:
discypus
Date:
Mon Feb 16 04:08:20 2015 +0000
Revision:
4:b1021974c3e7
Parent:
3:65a33de8fa08
Child:
5:fb6ac7306443
cs?????????????????????????

Who changed what in which revision?

UserRevisionLine numberNew contents of line
discypus 2:0248049e65f1 1 /*
discypus 2:0248049e65f1 2 * test for
discypus 3:65a33de8fa08 3 * - Microchip 23K256
discypus 3:65a33de8fa08 4 * - SRAM
discypus 3:65a33de8fa08 5 * - SPI 20MHz
discypus 2:0248049e65f1 6 */
discypus 2:0248049e65f1 7
discypus 0:82c01bfc06e1 8 #include "mbed.h"
discypus 0:82c01bfc06e1 9
discypus 2:0248049e65f1 10 /** Serial port for DEBUG */
discypus 2:0248049e65f1 11 Serial pc(USBTX, USBRX);
discypus 2:0248049e65f1 12
discypus 3:65a33de8fa08 13 DigitalIn user_button(USER_BUTTON);
discypus 2:0248049e65f1 14
discypus 2:0248049e65f1 15 /**
discypus 2:0248049e65f1 16 * USERボタンが押されるまで待つ。
discypus 2:0248049e65f1 17 */
discypus 2:0248049e65f1 18 void
discypus 2:0248049e65f1 19 wait_until_user_button_pressed() {
discypus 3:65a33de8fa08 20 while (user_button) {
discypus 2:0248049e65f1 21 __nop();
discypus 2:0248049e65f1 22 }
discypus 2:0248049e65f1 23 pc.printf("USER button is pressed\r\n");
discypus 4:b1021974c3e7 24 wait(0.2);
discypus 2:0248049e65f1 25 }
discypus 2:0248049e65f1 26
discypus 0:82c01bfc06e1 27 /** */
discypus 3:65a33de8fa08 28 //DigitalOut user_led(LED1); // SPI1 SCK
discypus 3:65a33de8fa08 29
discypus 3:65a33de8fa08 30 /**
discypus 3:65a33de8fa08 31 *
discypus 3:65a33de8fa08 32 * @param[in] interval_sec 点滅間隔(単位=秒)
discypus 3:65a33de8fa08 33 * @param[in] times 点滅回数
discypus 3:65a33de8fa08 34 */
discypus 3:65a33de8fa08 35 //void
discypus 3:65a33de8fa08 36 //flash_led(const float interval_sec, const uint16_t times) {
discypus 3:65a33de8fa08 37 // user_led = 1;
discypus 3:65a33de8fa08 38 // for (uint16_t i = 0; i < times * 2; ++i) {
discypus 3:65a33de8fa08 39 // wait(interval_sec);
discypus 3:65a33de8fa08 40 // user_led = !user_led;
discypus 3:65a33de8fa08 41 // }
discypus 3:65a33de8fa08 42 //}
discypus 3:65a33de8fa08 43
discypus 3:65a33de8fa08 44 /** */
discypus 0:82c01bfc06e1 45 SPI spi(SPI_MOSI, SPI_MISO, SPI_SCK);
discypus 0:82c01bfc06e1 46
discypus 0:82c01bfc06e1 47 /** */
discypus 0:82c01bfc06e1 48 DigitalOut cs(SPI_CS);
discypus 0:82c01bfc06e1 49
discypus 0:82c01bfc06e1 50 /*
discypus 0:82c01bfc06e1 51 * SPI COMMAND (Microchip 23K256 SRAM)
discypus 0:82c01bfc06e1 52 * 1byte read/write
discypus 0:82c01bfc06e1 53 * page read/write
discypus 0:82c01bfc06e1 54 * sequential read/write
discypus 0:82c01bfc06e1 55 * status/configuration register read/write
discypus 0:82c01bfc06e1 56 */
discypus 0:82c01bfc06e1 57 enum Microchip23K256Commnd {
discypus 0:82c01bfc06e1 58 READ = 0x03u,
discypus 0:82c01bfc06e1 59 WRITE = 0x02u,
discypus 0:82c01bfc06e1 60 RDSR = 0x05u,
discypus 0:82c01bfc06e1 61 WRSR = 0x01u,
discypus 0:82c01bfc06e1 62 };
discypus 0:82c01bfc06e1 63
discypus 0:82c01bfc06e1 64 /** SRAM Mode */
discypus 0:82c01bfc06e1 65 enum Microchip23K256Mode {
discypus 0:82c01bfc06e1 66 MODE_MASK = 0xc0u,
discypus 0:82c01bfc06e1 67 BYTE = 0x00u,
discypus 0:82c01bfc06e1 68 PAGE = 0x80u,
discypus 0:82c01bfc06e1 69 SEQUENTIAL = 0x40u,
discypus 0:82c01bfc06e1 70 };
discypus 0:82c01bfc06e1 71
discypus 0:82c01bfc06e1 72 /**
discypus 0:82c01bfc06e1 73 * assert CS
discypus 0:82c01bfc06e1 74 */
discypus 0:82c01bfc06e1 75 inline void
discypus 0:82c01bfc06e1 76 assert_CS() {
discypus 0:82c01bfc06e1 77 cs = 0;
discypus 0:82c01bfc06e1 78 }
discypus 0:82c01bfc06e1 79
discypus 0:82c01bfc06e1 80 /**
discypus 0:82c01bfc06e1 81 * negate CS
discypus 0:82c01bfc06e1 82 */
discypus 0:82c01bfc06e1 83 inline void
discypus 0:82c01bfc06e1 84 negate_CS() {
discypus 0:82c01bfc06e1 85 cs = 1;
discypus 0:82c01bfc06e1 86 }
discypus 0:82c01bfc06e1 87
discypus 0:82c01bfc06e1 88 /**
discypus 0:82c01bfc06e1 89 * レジスタ読みだし
discypus 0:82c01bfc06e1 90 * @return レジスタ値
discypus 0:82c01bfc06e1 91 */
discypus 0:82c01bfc06e1 92 inline uint8_t
discypus 0:82c01bfc06e1 93 read_status_register() {
discypus 0:82c01bfc06e1 94 assert_CS();
discypus 0:82c01bfc06e1 95 spi.write(RDSR);
discypus 0:82c01bfc06e1 96 const uint8_t status = spi.write(0x00);
discypus 0:82c01bfc06e1 97 negate_CS();
discypus 0:82c01bfc06e1 98
discypus 0:82c01bfc06e1 99 return status;
discypus 0:82c01bfc06e1 100 }
discypus 0:82c01bfc06e1 101
discypus 0:82c01bfc06e1 102 /**
discypus 0:82c01bfc06e1 103 * レジスタ書き込み
discypus 0:82c01bfc06e1 104 * @param[in] status
discypus 0:82c01bfc06e1 105 */
discypus 0:82c01bfc06e1 106 inline void
discypus 0:82c01bfc06e1 107 write_status_register(const uint8_t status) {
discypus 0:82c01bfc06e1 108 assert_CS();
discypus 0:82c01bfc06e1 109 spi.write(WRSR);
discypus 0:82c01bfc06e1 110 spi.write(status);
discypus 0:82c01bfc06e1 111 negate_CS();
discypus 0:82c01bfc06e1 112 }
discypus 0:82c01bfc06e1 113
discypus 0:82c01bfc06e1 114 /**
discypus 0:82c01bfc06e1 115 * モードを切り替える。
discypus 0:82c01bfc06e1 116 * @param[in] mode モード
discypus 0:82c01bfc06e1 117 * @return 切替前のモード
discypus 0:82c01bfc06e1 118 * @invariant モード以外のフラグは変更しない。
discypus 0:82c01bfc06e1 119 */
discypus 0:82c01bfc06e1 120 inline uint8_t
discypus 0:82c01bfc06e1 121 change_mode(const unsigned int next_mode) {
discypus 0:82c01bfc06e1 122 const uint8_t previous_status = read_status_register();
discypus 0:82c01bfc06e1 123 const uint8_t previous_mode = previous_status & MODE_MASK;
discypus 0:82c01bfc06e1 124 if (next_mode != previous_mode) {
discypus 0:82c01bfc06e1 125 const uint8_t next_status = (previous_status & ~MODE_MASK) | uint8_t(next_mode);
discypus 0:82c01bfc06e1 126 write_status_register(next_status);
discypus 0:82c01bfc06e1 127 }
discypus 0:82c01bfc06e1 128 return previous_mode;
discypus 0:82c01bfc06e1 129 }
discypus 0:82c01bfc06e1 130
discypus 0:82c01bfc06e1 131 /**
discypus 0:82c01bfc06e1 132 * 1byte読み出し
discypus 0:82c01bfc06e1 133 * @param[in] address アドレス 16bit。容量32KBなので、MSBは無視する
discypus 0:82c01bfc06e1 134 * @return データ
discypus 0:82c01bfc06e1 135 * @pre byteモードに切り替えていること。
discypus 0:82c01bfc06e1 136 */
discypus 0:82c01bfc06e1 137 uint8_t
discypus 0:82c01bfc06e1 138 read_byte(const uint16_t address) {
discypus 1:793321f410a9 139 const uint8_t address_high = (address >> (8 * 1)) & 0xFFu;
discypus 1:793321f410a9 140 const uint8_t address_low = (address >> (8 * 0)) & 0xFFu;
discypus 1:793321f410a9 141
discypus 0:82c01bfc06e1 142 assert_CS();
discypus 0:82c01bfc06e1 143 spi.write(READ);
discypus 1:793321f410a9 144 spi.write(address_high);
discypus 1:793321f410a9 145 spi.write(address_low);
discypus 0:82c01bfc06e1 146 const uint8_t data = spi.write(0x00);
discypus 0:82c01bfc06e1 147 negate_CS();
discypus 0:82c01bfc06e1 148
discypus 0:82c01bfc06e1 149 return data;
discypus 0:82c01bfc06e1 150 }
discypus 0:82c01bfc06e1 151
discypus 0:82c01bfc06e1 152 /**
discypus 0:82c01bfc06e1 153 * 1byte書き込み
discypus 0:82c01bfc06e1 154 * @param[in] address アドレス 16bit。容量32KBなので、MSBは無視する
discypus 0:82c01bfc06e1 155 * @param[in] data データ
discypus 0:82c01bfc06e1 156 * @pre byteモードに切り替えていること。
discypus 0:82c01bfc06e1 157 */
discypus 0:82c01bfc06e1 158 void
discypus 0:82c01bfc06e1 159 write_byte(const uint16_t address, const uint8_t data) {
discypus 1:793321f410a9 160 const uint8_t address_high = (address >> (8 * 1)) & 0xFFu;
discypus 1:793321f410a9 161 const uint8_t address_low = (address >> (8 * 0)) & 0xFFu;
discypus 1:793321f410a9 162
discypus 0:82c01bfc06e1 163 assert_CS();
discypus 0:82c01bfc06e1 164 spi.write(WRITE);
discypus 1:793321f410a9 165 spi.write(address_high);
discypus 1:793321f410a9 166 spi.write(address_low);
discypus 0:82c01bfc06e1 167 spi.write(data);
discypus 0:82c01bfc06e1 168 negate_CS();
discypus 0:82c01bfc06e1 169 }
discypus 0:82c01bfc06e1 170
discypus 0:82c01bfc06e1 171 /**
discypus 0:82c01bfc06e1 172 * 連続読み出し
discypus 0:82c01bfc06e1 173 * @pre pageモードかbyteモードに切り替えていること。
discypus 0:82c01bfc06e1 174 */
discypus 0:82c01bfc06e1 175 void
discypus 0:82c01bfc06e1 176 read_bytes(const uint16_t address, uint8_t __restrict data[], const uint16_t size) {
discypus 1:793321f410a9 177 const uint8_t address_high = (address >> (8 * 1)) & 0xFFu;
discypus 1:793321f410a9 178 const uint8_t address_low = (address >> (8 * 0)) & 0xFFu;
discypus 1:793321f410a9 179
discypus 0:82c01bfc06e1 180 assert_CS();
discypus 0:82c01bfc06e1 181 spi.write(READ);
discypus 1:793321f410a9 182 spi.write(address_high);
discypus 1:793321f410a9 183 spi.write(address_low);
discypus 0:82c01bfc06e1 184 for (uint16_t i = 0; i < size; ++i) {
discypus 0:82c01bfc06e1 185 data[i] = spi.write(0x00);
discypus 0:82c01bfc06e1 186 }
discypus 0:82c01bfc06e1 187 negate_CS();
discypus 0:82c01bfc06e1 188 }
discypus 0:82c01bfc06e1 189
discypus 0:82c01bfc06e1 190 /**
discypus 0:82c01bfc06e1 191 * 連続書き込み
discypus 0:82c01bfc06e1 192 * @pre pageモードかbyteモードに切り替えていること。
discypus 0:82c01bfc06e1 193 */
discypus 0:82c01bfc06e1 194 void
discypus 0:82c01bfc06e1 195 write_bytes(const uint16_t address, const uint8_t __restrict data[], const uint16_t size) {
discypus 1:793321f410a9 196 const uint8_t address_high = (address >> (8 * 1)) & 0xFFu;
discypus 1:793321f410a9 197 const uint8_t address_low = (address >> (8 * 0)) & 0xFFu;
discypus 1:793321f410a9 198
discypus 0:82c01bfc06e1 199 assert_CS();
discypus 0:82c01bfc06e1 200 spi.write(WRITE);
discypus 1:793321f410a9 201 spi.write(address_high);
discypus 1:793321f410a9 202 spi.write(address_low);
discypus 0:82c01bfc06e1 203 for (uint16_t i = 0; i < size; ++i) {
discypus 0:82c01bfc06e1 204 spi.write(data[i]);
discypus 0:82c01bfc06e1 205 }
discypus 0:82c01bfc06e1 206 negate_CS();
discypus 0:82c01bfc06e1 207 }
discypus 0:82c01bfc06e1 208
discypus 0:82c01bfc06e1 209 /*
discypus 0:82c01bfc06e1 210 *
discypus 0:82c01bfc06e1 211 */
discypus 0:82c01bfc06e1 212
discypus 0:82c01bfc06e1 213
discypus 0:82c01bfc06e1 214 /** 動作確認用 SPI buffer */
discypus 0:82c01bfc06e1 215 uint8_t buf[256] = {};
discypus 0:82c01bfc06e1 216
discypus 0:82c01bfc06e1 217 /**
discypus 0:82c01bfc06e1 218 * 動作確認用。TODO: テストコードにすること。
discypus 0:82c01bfc06e1 219 */
discypus 0:82c01bfc06e1 220 void
discypus 0:82c01bfc06e1 221 try_byte_access() {
discypus 0:82c01bfc06e1 222 const uint8_t size = 16;
discypus 0:82c01bfc06e1 223
discypus 0:82c01bfc06e1 224 change_mode(BYTE);
discypus 0:82c01bfc06e1 225
discypus 0:82c01bfc06e1 226 // write data
discypus 0:82c01bfc06e1 227 for (int i = 0; i < size; i++) {
discypus 0:82c01bfc06e1 228 write_byte(i, i);
discypus 0:82c01bfc06e1 229 }
discypus 0:82c01bfc06e1 230
discypus 0:82c01bfc06e1 231 // read data
discypus 0:82c01bfc06e1 232 for (int i = 0; i < size; i++) {
discypus 0:82c01bfc06e1 233 buf[i] = read_byte(i);
discypus 0:82c01bfc06e1 234 }
discypus 0:82c01bfc06e1 235
discypus 0:82c01bfc06e1 236 // show data (to SERIAL)
discypus 0:82c01bfc06e1 237 pc.printf("byte access test: result\r\n");
discypus 0:82c01bfc06e1 238 for (int i = 0; i < size; i++) {
discypus 4:b1021974c3e7 239 pc.printf(" %04x : %02x %s\r\n", i, buf[i], (buf[i] ==i)?"OK":"BAD");
discypus 0:82c01bfc06e1 240 }
discypus 0:82c01bfc06e1 241 }
discypus 0:82c01bfc06e1 242
discypus 0:82c01bfc06e1 243 /**
discypus 0:82c01bfc06e1 244 * 動作確認用。TODO: テストコードにすること。
discypus 0:82c01bfc06e1 245 */
discypus 0:82c01bfc06e1 246 void
discypus 0:82c01bfc06e1 247 try_page_access() {
discypus 1:793321f410a9 248 const uint16_t address = 0x1000;
discypus 0:82c01bfc06e1 249 const uint16_t size = 32;
discypus 0:82c01bfc06e1 250
discypus 1:793321f410a9 251 change_mode(PAGE);
discypus 1:793321f410a9 252
discypus 0:82c01bfc06e1 253 // write
discypus 0:82c01bfc06e1 254 for (uint16_t i = 0; i < size; ++i) {
discypus 0:82c01bfc06e1 255 buf[i] = i;
discypus 0:82c01bfc06e1 256 }
discypus 1:793321f410a9 257 write_bytes(address, buf, size);
discypus 0:82c01bfc06e1 258
discypus 0:82c01bfc06e1 259 // read
discypus 0:82c01bfc06e1 260 for (uint16_t i = 0; i < size; ++i) {
discypus 0:82c01bfc06e1 261 buf[i] = 0;
discypus 0:82c01bfc06e1 262 }
discypus 0:82c01bfc06e1 263
discypus 1:793321f410a9 264 read_bytes(address, buf, size);
discypus 0:82c01bfc06e1 265
discypus 0:82c01bfc06e1 266 // show data (to SERIAL)
discypus 0:82c01bfc06e1 267 pc.printf("page access test: result\r\n");
discypus 0:82c01bfc06e1 268 for (int i = 0; i < size; i++) {
discypus 4:b1021974c3e7 269 pc.printf(" %04x : %02x %s\r\n", address + i, buf[i], (buf[i] ==i)?"OK":"BAD");
discypus 0:82c01bfc06e1 270 }
discypus 0:82c01bfc06e1 271 }
discypus 0:82c01bfc06e1 272
discypus 0:82c01bfc06e1 273 /**
discypus 0:82c01bfc06e1 274 * 動作確認用。TODO: テストコードにすること。
discypus 0:82c01bfc06e1 275 */
discypus 0:82c01bfc06e1 276 void
discypus 0:82c01bfc06e1 277 try_sequential_access() {
discypus 1:793321f410a9 278 const uint16_t address = 0x2000;
discypus 0:82c01bfc06e1 279 const uint16_t size = 256;
discypus 0:82c01bfc06e1 280
discypus 1:793321f410a9 281 change_mode(SEQUENTIAL);
discypus 1:793321f410a9 282
discypus 0:82c01bfc06e1 283 // write
discypus 0:82c01bfc06e1 284 for (uint16_t i = 0; i < size; ++i) {
discypus 0:82c01bfc06e1 285 buf[i] = i;
discypus 0:82c01bfc06e1 286 }
discypus 0:82c01bfc06e1 287
discypus 1:793321f410a9 288 write_bytes(address, buf, size);
discypus 0:82c01bfc06e1 289
discypus 0:82c01bfc06e1 290 // read
discypus 0:82c01bfc06e1 291 for (uint16_t i = 0; i < size; ++i) {
discypus 0:82c01bfc06e1 292 buf[i] = 0;
discypus 0:82c01bfc06e1 293 }
discypus 0:82c01bfc06e1 294
discypus 1:793321f410a9 295 read_bytes(address, buf, size);
discypus 0:82c01bfc06e1 296
discypus 0:82c01bfc06e1 297 // show data (to SERIAL)
discypus 0:82c01bfc06e1 298 pc.printf("sequential access test: result\r\n");
discypus 0:82c01bfc06e1 299 for (int i = 0; i < size; i++) {
discypus 4:b1021974c3e7 300 pc.printf(" %04x : %02x %s\r\n", address + i, buf[i], (buf[i] ==i)?"OK":"BAD");
discypus 0:82c01bfc06e1 301 }
discypus 0:82c01bfc06e1 302 }
discypus 0:82c01bfc06e1 303
discypus 0:82c01bfc06e1 304
discypus 4:b1021974c3e7 305 /**
discypus 4:b1021974c3e7 306 *
discypus 4:b1021974c3e7 307 * @pre SPI初期化済初期和美であること。バイトモードであること
discypus 4:b1021974c3e7 308 */
discypus 0:82c01bfc06e1 309 void
discypus 0:82c01bfc06e1 310 try_single_byte_access() {
discypus 4:b1021974c3e7 311 // 1byte write
discypus 4:b1021974c3e7 312 assert_CS();
discypus 4:b1021974c3e7 313 spi.write(0x02u); // write command
discypus 4:b1021974c3e7 314 spi.write(0); // address
discypus 4:b1021974c3e7 315 spi.write(0); // address
discypus 4:b1021974c3e7 316 spi.write(0x5a); // data
discypus 4:b1021974c3e7 317 nagate_CS();
discypus 0:82c01bfc06e1 318
discypus 4:b1021974c3e7 319 // 1byte read
discypus 4:b1021974c3e7 320 assert_CS();
discypus 4:b1021974c3e7 321 spi.write(0x03u); // read command
discypus 4:b1021974c3e7 322 spi.write(0); // address
discypus 4:b1021974c3e7 323 spi.write(0); // address
discypus 4:b1021974c3e7 324 const uint8_t value = spi.write(0); // data
discypus 4:b1021974c3e7 325 nagate_CS();
discypus 0:82c01bfc06e1 326
discypus 0:82c01bfc06e1 327 pc.printf("read: 0x%02x\r\n", value);
discypus 0:82c01bfc06e1 328 }
discypus 0:82c01bfc06e1 329
discypus 2:0248049e65f1 330
discypus 0:82c01bfc06e1 331 /**
discypus 0:82c01bfc06e1 332 * 動作確認用。TODO: テストコードにすること。
discypus 0:82c01bfc06e1 333 */
discypus 0:82c01bfc06e1 334 int
discypus 0:82c01bfc06e1 335 main()
discypus 0:82c01bfc06e1 336 {
discypus 4:b1021974c3e7 337 pc.baud(115200);
discypus 3:65a33de8fa08 338 pc.printf("CPU SystemCoreClock is %.2f MHz\r\n", (float)SystemCoreClock/1.0e6f);
discypus 2:0248049e65f1 339
discypus 3:65a33de8fa08 340 // initialize SPI
discypus 0:82c01bfc06e1 341 spi.format(8, 0); // 8bit, mode=0
discypus 0:82c01bfc06e1 342 spi.frequency(20 * 1000 * 1000); // max 20MHz
discypus 0:82c01bfc06e1 343 negate_CS();
discypus 0:82c01bfc06e1 344
discypus 0:82c01bfc06e1 345 // test
discypus 3:65a33de8fa08 346 pc.printf("\r\npush user button to start: try_single_byte_access\r\n");
discypus 2:0248049e65f1 347 wait_until_user_button_pressed();
discypus 0:82c01bfc06e1 348 try_single_byte_access();
discypus 2:0248049e65f1 349
discypus 3:65a33de8fa08 350 pc.printf("\r\npush user button to start: try_byte_access\r\n");
discypus 2:0248049e65f1 351 wait_until_user_button_pressed();
discypus 0:82c01bfc06e1 352 try_byte_access();
discypus 2:0248049e65f1 353
discypus 3:65a33de8fa08 354 pc.printf("\r\npush user button to start: try_page_access\r\n");
discypus 3:65a33de8fa08 355 wait_until_user_button_pressed();
discypus 0:82c01bfc06e1 356 try_page_access();
discypus 2:0248049e65f1 357
discypus 3:65a33de8fa08 358 pc.printf("\r\npush user button to start: try_sequential_access\r\n");
discypus 2:0248049e65f1 359 wait_until_user_button_pressed();
discypus 0:82c01bfc06e1 360 try_sequential_access();
discypus 2:0248049e65f1 361
discypus 3:65a33de8fa08 362 pc.printf("\r\nTEST END\r\n\r\n");
discypus 0:82c01bfc06e1 363
discypus 3:65a33de8fa08 364 for(;;) {
discypus 3:65a33de8fa08 365 // flash_led(0.125, 8);
discypus 3:65a33de8fa08 366 // flash_led(0.50, 2);
discypus 3:65a33de8fa08 367 }
discypus 0:82c01bfc06e1 368 }