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

Dependencies:   mbed

Committer:
discypus
Date:
Sun Feb 22 04:07:28 2015 +0000
Revision:
5:fb6ac7306443
Parent:
4:b1021974c3e7
2015-02-22

Who changed what in which revision?

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