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

Dependencies:   mbed

Committer:
discypus
Date:
Fri Oct 31 13:07:40 2014 +0000
Revision:
1:793321f410a9
Parent:
0:82c01bfc06e1
Child:
2:0248049e65f1
sequential ???OK?

Who changed what in which revision?

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