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

Dependencies:   mbed

Committer:
discypus
Date:
Sun Nov 02 03:22:21 2014 +0000
Revision:
3:65a33de8fa08
Parent:
2:0248049e65f1
Child:
4:b1021974c3e7
USER?????????????????????????????

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