Microchip SPI SRAM 23LC1024 demo

Dependencies:   mbed

Committer:
discypus
Date:
Mon Nov 09 12:12:01 2015 +0000
Revision:
2:e0d7ea47d2a5
Parent:
1:4b45ee2c9b51
Child:
3:b585283f5932
???????

Who changed what in which revision?

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