Chihiro H
/
Microchip23K256_demo
Microchip 23K256 (SPI SRAM) sample code for https://www.switch-science.com/catalog/1072/ module.
main.cpp
- Committer:
- discypus
- Date:
- 2015-02-16
- Revision:
- 4:b1021974c3e7
- Parent:
- 3:65a33de8fa08
- Child:
- 5:fb6ac7306443
File content as of revision 4:b1021974c3e7:
/* * test for * - Microchip 23K256 * - SRAM * - SPI 20MHz */ #include "mbed.h" /** Serial port for DEBUG */ Serial pc(USBTX, USBRX); DigitalIn user_button(USER_BUTTON); /** * USERボタンが押されるまで待つ。 */ void wait_until_user_button_pressed() { while (user_button) { __nop(); } pc.printf("USER button is pressed\r\n"); wait(0.2); } /** */ //DigitalOut user_led(LED1); // SPI1 SCK /** * * @param[in] interval_sec 点滅間隔(単位=秒) * @param[in] times 点滅回数 */ //void //flash_led(const float interval_sec, const uint16_t times) { // user_led = 1; // for (uint16_t i = 0; i < times * 2; ++i) { // wait(interval_sec); // user_led = !user_led; // } //} /** */ SPI spi(SPI_MOSI, SPI_MISO, SPI_SCK); /** */ DigitalOut cs(SPI_CS); /* * SPI COMMAND (Microchip 23K256 SRAM) * 1byte read/write * page read/write * sequential read/write * status/configuration register read/write */ enum Microchip23K256Commnd { READ = 0x03u, WRITE = 0x02u, RDSR = 0x05u, WRSR = 0x01u, }; /** SRAM Mode */ enum Microchip23K256Mode { MODE_MASK = 0xc0u, BYTE = 0x00u, PAGE = 0x80u, SEQUENTIAL = 0x40u, }; /** * assert CS */ inline void assert_CS() { cs = 0; } /** * negate CS */ inline void negate_CS() { cs = 1; } /** * レジスタ読みだし * @return レジスタ値 */ inline uint8_t read_status_register() { assert_CS(); spi.write(RDSR); const uint8_t status = spi.write(0x00); negate_CS(); return status; } /** * レジスタ書き込み * @param[in] status */ inline void write_status_register(const uint8_t status) { assert_CS(); spi.write(WRSR); spi.write(status); negate_CS(); } /** * モードを切り替える。 * @param[in] mode モード * @return 切替前のモード * @invariant モード以外のフラグは変更しない。 */ inline uint8_t change_mode(const unsigned int next_mode) { const uint8_t previous_status = read_status_register(); const uint8_t previous_mode = previous_status & MODE_MASK; if (next_mode != previous_mode) { const uint8_t next_status = (previous_status & ~MODE_MASK) | uint8_t(next_mode); write_status_register(next_status); } return previous_mode; } /** * 1byte読み出し * @param[in] address アドレス 16bit。容量32KBなので、MSBは無視する * @return データ * @pre byteモードに切り替えていること。 */ uint8_t read_byte(const uint16_t address) { const uint8_t address_high = (address >> (8 * 1)) & 0xFFu; const uint8_t address_low = (address >> (8 * 0)) & 0xFFu; assert_CS(); spi.write(READ); spi.write(address_high); spi.write(address_low); const uint8_t data = spi.write(0x00); negate_CS(); return data; } /** * 1byte書き込み * @param[in] address アドレス 16bit。容量32KBなので、MSBは無視する * @param[in] data データ * @pre byteモードに切り替えていること。 */ void write_byte(const uint16_t address, const uint8_t data) { const uint8_t address_high = (address >> (8 * 1)) & 0xFFu; const uint8_t address_low = (address >> (8 * 0)) & 0xFFu; assert_CS(); spi.write(WRITE); spi.write(address_high); spi.write(address_low); spi.write(data); negate_CS(); } /** * 連続読み出し * @pre pageモードかbyteモードに切り替えていること。 */ void read_bytes(const uint16_t address, uint8_t __restrict data[], const uint16_t size) { const uint8_t address_high = (address >> (8 * 1)) & 0xFFu; const uint8_t address_low = (address >> (8 * 0)) & 0xFFu; assert_CS(); spi.write(READ); spi.write(address_high); spi.write(address_low); for (uint16_t i = 0; i < size; ++i) { data[i] = spi.write(0x00); } negate_CS(); } /** * 連続書き込み * @pre pageモードかbyteモードに切り替えていること。 */ void write_bytes(const uint16_t address, const uint8_t __restrict data[], const uint16_t size) { const uint8_t address_high = (address >> (8 * 1)) & 0xFFu; const uint8_t address_low = (address >> (8 * 0)) & 0xFFu; assert_CS(); spi.write(WRITE); spi.write(address_high); spi.write(address_low); for (uint16_t i = 0; i < size; ++i) { spi.write(data[i]); } negate_CS(); } /* * */ /** 動作確認用 SPI buffer */ uint8_t buf[256] = {}; /** * 動作確認用。TODO: テストコードにすること。 */ void try_byte_access() { const uint8_t size = 16; change_mode(BYTE); // write data for (int i = 0; i < size; i++) { write_byte(i, i); } // read data for (int i = 0; i < size; i++) { buf[i] = read_byte(i); } // show data (to SERIAL) pc.printf("byte access test: result\r\n"); for (int i = 0; i < size; i++) { pc.printf(" %04x : %02x %s\r\n", i, buf[i], (buf[i] ==i)?"OK":"BAD"); } } /** * 動作確認用。TODO: テストコードにすること。 */ void try_page_access() { const uint16_t address = 0x1000; const uint16_t size = 32; change_mode(PAGE); // write for (uint16_t i = 0; i < size; ++i) { buf[i] = i; } write_bytes(address, buf, size); // read for (uint16_t i = 0; i < size; ++i) { buf[i] = 0; } read_bytes(address, buf, size); // show data (to SERIAL) pc.printf("page access test: result\r\n"); for (int i = 0; i < size; i++) { pc.printf(" %04x : %02x %s\r\n", address + i, buf[i], (buf[i] ==i)?"OK":"BAD"); } } /** * 動作確認用。TODO: テストコードにすること。 */ void try_sequential_access() { const uint16_t address = 0x2000; const uint16_t size = 256; change_mode(SEQUENTIAL); // write for (uint16_t i = 0; i < size; ++i) { buf[i] = i; } write_bytes(address, buf, size); // read for (uint16_t i = 0; i < size; ++i) { buf[i] = 0; } read_bytes(address, buf, size); // show data (to SERIAL) pc.printf("sequential access test: result\r\n"); for (int i = 0; i < size; i++) { pc.printf(" %04x : %02x %s\r\n", address + i, buf[i], (buf[i] ==i)?"OK":"BAD"); } } /** * * @pre SPI初期化済初期和美であること。バイトモードであること */ void try_single_byte_access() { // 1byte write assert_CS(); spi.write(0x02u); // write command spi.write(0); // address spi.write(0); // address spi.write(0x5a); // data nagate_CS(); // 1byte read assert_CS(); spi.write(0x03u); // read command spi.write(0); // address spi.write(0); // address const uint8_t value = spi.write(0); // data nagate_CS(); pc.printf("read: 0x%02x\r\n", value); } /** * 動作確認用。TODO: テストコードにすること。 */ int main() { pc.baud(115200); pc.printf("CPU SystemCoreClock is %.2f MHz\r\n", (float)SystemCoreClock/1.0e6f); // initialize SPI spi.format(8, 0); // 8bit, mode=0 spi.frequency(20 * 1000 * 1000); // max 20MHz negate_CS(); // test pc.printf("\r\npush user button to start: try_single_byte_access\r\n"); wait_until_user_button_pressed(); try_single_byte_access(); pc.printf("\r\npush user button to start: try_byte_access\r\n"); wait_until_user_button_pressed(); try_byte_access(); pc.printf("\r\npush user button to start: try_page_access\r\n"); wait_until_user_button_pressed(); try_page_access(); pc.printf("\r\npush user button to start: try_sequential_access\r\n"); wait_until_user_button_pressed(); try_sequential_access(); pc.printf("\r\nTEST END\r\n\r\n"); for(;;) { // flash_led(0.125, 8); // flash_led(0.50, 2); } }