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

Dependencies:   mbed

Committer:
discypus
Date:
Fri Oct 31 12:45:25 2014 +0000
Revision:
0:82c01bfc06e1
Child:
1:793321f410a9
??????????OK.; ????????0x20????????0x00-0x1f?????????

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