From f044da4ff39c0e72d3dd0efb8b6b5eb26719838c Mon Sep 17 00:00:00 2001 From: Marti Bolivar Date: Mon, 7 Mar 2011 15:40:47 -0500 Subject: FSMC working but slow (~6 MHz). --- examples/test-fsmc.cpp | 200 +++++++++++++++++++++++-------------------------- libmaple/fsmc.c | 120 ++++++++++++----------------- 2 files changed, 141 insertions(+), 179 deletions(-) diff --git a/examples/test-fsmc.cpp b/examples/test-fsmc.cpp index f4fd068..ff55330 100644 --- a/examples/test-fsmc.cpp +++ b/examples/test-fsmc.cpp @@ -1,119 +1,109 @@ +#include +#include #include "wirish.h" #include "fsmc.h" -#define LED_PIN 23 // hack for maple native -#define DISC_PIN 14 // hack for USB on native - -// System control block registers -#define SCB_BASE (SCB_Reg*)(0xE000ED00) - -// This stuff should ultimately get moved to util.h or scb.h or w/e. -// Also in interactive test program and the HardFault IRQ handler. -typedef struct { - volatile uint32 CPUID; - volatile uint32 ICSR; - volatile uint32 VTOR; - volatile uint32 AIRCR; - volatile uint32 SCR; - volatile uint32 CCR; - volatile uint32 SHPR1; - volatile uint32 SHPR2; - volatile uint32 SHPR3; - volatile uint32 SHCRS; - volatile uint32 CFSR; - volatile uint32 HFSR; - uint32 pad1; - volatile uint32 MMAR; - volatile uint32 BFAR; -} SCB_Reg; - -SCB_Reg *scb; - -uint16 *ptr; -int toggle = 0; -int count = 0; +#define LED BOARD_LED_PIN + +// Start of FSMC SRAM bank 1 +static uint16 *const ptr_start = (uint16*)0x60000000; +// End of Maple Native SRAM chip address space (512K 16-bit words) +static uint16 *const ptr_end = (uint16*)0x60080000; +// For snprintf +static char buf[100]; void setup() { - uint32 id; - scb = (SCB_Reg*)SCB_BASE; - - pinMode(LED_PIN, OUTPUT); - pinMode(DISC_PIN, OUTPUT); - digitalWrite(DISC_PIN,1); - digitalWrite(LED_PIN,1); - - Serial1.begin(9600); - Serial1.println("Hello World!"); - - Serial1.print("Init... "); - fsmc_native_sram_init(); - Serial1.println("Done."); - - // Start of channel1 SRAM bank (through to 0x63FFFFFF, though only a chunk - // of this is valid) - ptr = (uint16*)(0x60000000); - - Serial1.print("Writing... "); - *ptr = 0x1234; - Serial1.println("Done."); - - Serial1.print("Reading... "); - id = *ptr; - Serial1.print("Done: "); // shouldn't be 0xFFFFFFFF - Serial1.println(id,BIN); - - Serial1.println("Dumping System Control Block Registers"); - Serial1.print("CPUID: "); - id = scb->CPUID; - Serial1.println(id,BIN); - Serial1.print("ICSR: "); - id = scb->ICSR; - Serial1.println(id,BIN); - Serial1.print("CFSR: "); - id = scb->CFSR; - Serial1.println(id,BIN); - Serial1.print("HFSR: "); - id = scb->HFSR; - Serial1.println(id,BIN); - Serial1.print("MMAR: "); - id = scb->MMAR; - Serial1.println(id,BIN); - Serial1.print("BFAR: "); - id = scb->BFAR; - Serial1.println(id,BIN); - - Serial1.println("Now testing all memory addresses... (will hardfault at the end)"); - delay(3000); + pinMode(LED, OUTPUT); + digitalWrite(LED, HIGH); + + Serial1.begin(115200); + Serial1.println("Hello World!"); + + Serial1.print("Initializing RAM chip... "); + fsmc_native_sram_init(); + Serial1.println("Done."); } -void loop() { - digitalWrite(LED_PIN, toggle); - toggle ^= 1; - delay(1); - - for(int i = 0; i<100; i++) { // modify this to speed things up - count++; - ptr++; - //delay(10); // tweak this to test SRAM resiliance over time - *ptr = (0x0000FFFF & count); - if(*ptr != (0x0000FFFF & count)) { - Serial1.println("ERROR: mismatch, halting"); - while(1) { } +void test_single_write() { + uint16 *ptr = ptr_start; + uint16 tmp; + + Serial1.print("Writing 0x1234... "); + *ptr = 0x1234; + Serial1.println("Done."); + + Serial1.print("Reading... "); + tmp = *ptr; + Serial1.print("Done: 0x"); + Serial1.println(tmp, HEX); + + if (tmp != 0x1234) { + Serial1.println("Mismatch, abort."); + ASSERT(0); + } +} + +void test_all_addresses() { + uint32 start, end; + uint16 count = 0; + uint16 *ptr; + Serial1.println("Now writing all memory addresses (unrolled loop)"); + start = micros(); + for (ptr = ptr_start; ptr < ptr_end;) { + *ptr++ = count++; + *ptr++ = count++; + *ptr++ = count++; + *ptr++ = count++; + *ptr++ = count++; + *ptr++ = count++; + *ptr++ = count++; + *ptr++ = count++; + *ptr++ = count++; + *ptr++ = count++; + *ptr++ = count++; + *ptr++ = count++; + *ptr++ = count++; + *ptr++ = count++; + *ptr++ = count++; + *ptr++ = count++; + } + end = micros(); + Serial1.print("Done. Elapsed time (us): "); + Serial1.println(end - start); + + Serial1.println("Validating writes."); + for (ptr = ptr_start, count = 0; ptr < ptr_end; ptr++, count++) { + if (*ptr != count) { + snprintf(buf, sizeof buf, "mismatch: %p = 0x%xu, should be 0x%xu.", + ptr, *ptr, count); + Serial1.println(buf); + ASSERT(0); } - } - - Serial1.print((uint32)(ptr),HEX); - Serial1.print(": "); - Serial1.println(*ptr,BIN); + } + ptrdiff_t nwrites = ptr_end - ptr_start; + double us_per_write = double(end-start) / double(nwrites); + Serial1.println("Done; all writes seem valid."); + snprintf(buf, sizeof buf, + "Number of writes = %d; avg. time per write = %g us (%g MHz)", + nwrites, us_per_write, 1 / us_per_write); + Serial1.println(buf); +} + +__attribute__((constructor)) void premain() { + init(); } int main(void) { - init(); - setup(); + setup(); + + test_single_write(); + test_all_addresses(); + + Serial1.println("Tests pass, finished."); + + while (true) + ; - while (1) { - loop(); - } - return 0; + return 0; } diff --git a/libmaple/fsmc.c b/libmaple/fsmc.c index 49526f4..61fd06c 100644 --- a/libmaple/fsmc.c +++ b/libmaple/fsmc.c @@ -31,11 +31,6 @@ #include "gpio.h" #include "fsmc.h" -/* These values determined for a particular SRAM chip by following the - * calculations in the ST FSMC application note. */ -#define FSMC_ADDSET 0x0 -#define FSMC_DATAST 0x3 - /* Sets up the FSMC peripheral to use the SRAM chip on the maple * native as an external segment of system memory space. This * implementation is for the IS62WV51216BLL 8mbit chip (55ns @@ -45,55 +40,55 @@ void fsmc_native_sram_init(void) { /* First we setup all the GPIO pins. */ /* Data lines... */ - gpio_set_mode(GPIOD_BASE, 0, MODE_AF_OUTPUT_PP); - gpio_set_mode(GPIOD_BASE, 1, MODE_AF_OUTPUT_PP); - gpio_set_mode(GPIOD_BASE, 8, MODE_AF_OUTPUT_PP); - gpio_set_mode(GPIOD_BASE, 9, MODE_AF_OUTPUT_PP); - gpio_set_mode(GPIOD_BASE, 10, MODE_AF_OUTPUT_PP); - gpio_set_mode(GPIOD_BASE, 14, MODE_AF_OUTPUT_PP); - gpio_set_mode(GPIOD_BASE, 15, MODE_AF_OUTPUT_PP); - gpio_set_mode(GPIOE_BASE, 7, MODE_AF_OUTPUT_PP); - gpio_set_mode(GPIOE_BASE, 8, MODE_AF_OUTPUT_PP); - gpio_set_mode(GPIOE_BASE, 9, MODE_AF_OUTPUT_PP); - gpio_set_mode(GPIOE_BASE, 10, MODE_AF_OUTPUT_PP); - gpio_set_mode(GPIOE_BASE, 11, MODE_AF_OUTPUT_PP); - gpio_set_mode(GPIOE_BASE, 12, MODE_AF_OUTPUT_PP); - gpio_set_mode(GPIOE_BASE, 13, MODE_AF_OUTPUT_PP); - gpio_set_mode(GPIOE_BASE, 14, MODE_AF_OUTPUT_PP); - gpio_set_mode(GPIOE_BASE, 15, MODE_AF_OUTPUT_PP); + gpio_set_mode(GPIOD_BASE, 0, MODE_AF_OUTPUT_PP); /* D2 */ + gpio_set_mode(GPIOD_BASE, 1, MODE_AF_OUTPUT_PP); /* D3 */ + gpio_set_mode(GPIOD_BASE, 8, MODE_AF_OUTPUT_PP); /* D13 */ + gpio_set_mode(GPIOD_BASE, 9, MODE_AF_OUTPUT_PP); /* D14 */ + gpio_set_mode(GPIOD_BASE, 10, MODE_AF_OUTPUT_PP); /* D15 */ + gpio_set_mode(GPIOD_BASE, 14, MODE_AF_OUTPUT_PP); /* D0 */ + gpio_set_mode(GPIOD_BASE, 15, MODE_AF_OUTPUT_PP); /* D1 */ + gpio_set_mode(GPIOE_BASE, 7, MODE_AF_OUTPUT_PP); /* D4 */ + gpio_set_mode(GPIOE_BASE, 8, MODE_AF_OUTPUT_PP); /* D5 */ + gpio_set_mode(GPIOE_BASE, 9, MODE_AF_OUTPUT_PP); /* D6 */ + gpio_set_mode(GPIOE_BASE, 10, MODE_AF_OUTPUT_PP); /* D7 */ + gpio_set_mode(GPIOE_BASE, 11, MODE_AF_OUTPUT_PP); /* D8 */ + gpio_set_mode(GPIOE_BASE, 12, MODE_AF_OUTPUT_PP); /* D9 */ + gpio_set_mode(GPIOE_BASE, 13, MODE_AF_OUTPUT_PP); /* D10 */ + gpio_set_mode(GPIOE_BASE, 14, MODE_AF_OUTPUT_PP); /* D11 */ + gpio_set_mode(GPIOE_BASE, 15, MODE_AF_OUTPUT_PP); /* D12 */ /* Address lines... */ - gpio_set_mode(GPIOD_BASE, 11, MODE_AF_OUTPUT_PP); - gpio_set_mode(GPIOD_BASE, 12, MODE_AF_OUTPUT_PP); - gpio_set_mode(GPIOD_BASE, 13, MODE_AF_OUTPUT_PP); - gpio_set_mode(GPIOF_BASE, 0, MODE_AF_OUTPUT_PP); - gpio_set_mode(GPIOF_BASE, 1, MODE_AF_OUTPUT_PP); - gpio_set_mode(GPIOF_BASE, 2, MODE_AF_OUTPUT_PP); - gpio_set_mode(GPIOF_BASE, 3, MODE_AF_OUTPUT_PP); - gpio_set_mode(GPIOF_BASE, 4, MODE_AF_OUTPUT_PP); - gpio_set_mode(GPIOF_BASE, 5, MODE_AF_OUTPUT_PP); - gpio_set_mode(GPIOF_BASE, 12, MODE_AF_OUTPUT_PP); - gpio_set_mode(GPIOF_BASE, 13, MODE_AF_OUTPUT_PP); - gpio_set_mode(GPIOF_BASE, 14, MODE_AF_OUTPUT_PP); - gpio_set_mode(GPIOF_BASE, 15, MODE_AF_OUTPUT_PP); - gpio_set_mode(GPIOG_BASE, 0, MODE_AF_OUTPUT_PP); - gpio_set_mode(GPIOG_BASE, 1, MODE_AF_OUTPUT_PP); - gpio_set_mode(GPIOG_BASE, 2, MODE_AF_OUTPUT_PP); - gpio_set_mode(GPIOG_BASE, 3, MODE_AF_OUTPUT_PP); - gpio_set_mode(GPIOG_BASE, 4, MODE_AF_OUTPUT_PP); - gpio_set_mode(GPIOG_BASE, 5, MODE_AF_OUTPUT_PP); + gpio_set_mode(GPIOD_BASE, 11, MODE_AF_OUTPUT_PP); /* A16 */ + gpio_set_mode(GPIOD_BASE, 12, MODE_AF_OUTPUT_PP); /* A17 */ + gpio_set_mode(GPIOD_BASE, 13, MODE_AF_OUTPUT_PP); /* A18 */ + gpio_set_mode(GPIOF_BASE, 0, MODE_AF_OUTPUT_PP); /* A0 */ + gpio_set_mode(GPIOF_BASE, 1, MODE_AF_OUTPUT_PP); /* A1 */ + gpio_set_mode(GPIOF_BASE, 2, MODE_AF_OUTPUT_PP); /* A2 */ + gpio_set_mode(GPIOF_BASE, 3, MODE_AF_OUTPUT_PP); /* A3 */ + gpio_set_mode(GPIOF_BASE, 4, MODE_AF_OUTPUT_PP); /* A4 */ + gpio_set_mode(GPIOF_BASE, 5, MODE_AF_OUTPUT_PP); /* A5 */ + gpio_set_mode(GPIOF_BASE, 12, MODE_AF_OUTPUT_PP); /* A6 */ + gpio_set_mode(GPIOF_BASE, 13, MODE_AF_OUTPUT_PP); /* A7 */ + gpio_set_mode(GPIOF_BASE, 14, MODE_AF_OUTPUT_PP); /* A8 */ + gpio_set_mode(GPIOF_BASE, 15, MODE_AF_OUTPUT_PP); /* A9 */ + gpio_set_mode(GPIOG_BASE, 0, MODE_AF_OUTPUT_PP); /* A10 */ + gpio_set_mode(GPIOG_BASE, 1, MODE_AF_OUTPUT_PP); /* A11 */ + gpio_set_mode(GPIOG_BASE, 2, MODE_AF_OUTPUT_PP); /* A12 */ + gpio_set_mode(GPIOG_BASE, 3, MODE_AF_OUTPUT_PP); /* A13 */ + gpio_set_mode(GPIOG_BASE, 4, MODE_AF_OUTPUT_PP); /* A14 */ + gpio_set_mode(GPIOG_BASE, 5, MODE_AF_OUTPUT_PP); /* A15 */ /* And control lines... */ - gpio_set_mode(GPIOD_BASE, 4, MODE_AF_OUTPUT_PP); // NOE - gpio_set_mode(GPIOD_BASE, 5, MODE_AF_OUTPUT_PP); // NWE + gpio_set_mode(GPIOD_BASE, 4, MODE_AF_OUTPUT_PP); /* NOE */ + gpio_set_mode(GPIOD_BASE, 5, MODE_AF_OUTPUT_PP); /* NWE */ - gpio_set_mode(GPIOD_BASE, 7, MODE_AF_OUTPUT_PP); // NE1 - gpio_set_mode(GPIOG_BASE, 9, MODE_AF_OUTPUT_PP); // NE2 - gpio_set_mode(GPIOG_BASE, 10, MODE_AF_OUTPUT_PP); // NE3 - gpio_set_mode(GPIOG_BASE, 12, MODE_AF_OUTPUT_PP); // NE4 + gpio_set_mode(GPIOD_BASE, 7, MODE_AF_OUTPUT_PP); /* NE1 */ + gpio_set_mode(GPIOG_BASE, 9, MODE_AF_OUTPUT_PP); /* NE2 */ + gpio_set_mode(GPIOG_BASE, 10, MODE_AF_OUTPUT_PP); /* NE3 */ + gpio_set_mode(GPIOG_BASE, 12, MODE_AF_OUTPUT_PP); /* NE4 */ - gpio_set_mode(GPIOE_BASE, 0, MODE_AF_OUTPUT_PP); // NBL0 - gpio_set_mode(GPIOE_BASE, 1, MODE_AF_OUTPUT_PP); // NBL1 + gpio_set_mode(GPIOE_BASE, 0, MODE_AF_OUTPUT_PP); /* NBL0 */ + gpio_set_mode(GPIOE_BASE, 1, MODE_AF_OUTPUT_PP); /* NBL1 */ /* Next enable the clock */ rcc_clk_enable(RCC_FSMC); @@ -102,32 +97,9 @@ void fsmc_native_sram_init(void) { * channels are in "Bank 1" of the FSMC) */ bank = (FSMC_Bank*)(FSMC1_BASE); - /* Everything else is cleared (BCR1) */ - bank->BCR = 0x0000; - - /* Memory type is SRAM */ - bank->BCR &= ~(FSMC_BCR_MTYP); // '00' - - /* Databus width is 16bits */ - bank->BCR &= ~(FSMC_BCR_MWID); - bank->BCR |= 0x1 << 4; // '01' - - /* Memory is nonmultiplexed */ - bank->BCR &= ~(FSMC_BCR_MUXEN); // '0' - - /* Need write enable to write to the chip */ - bank->BCR |= FSMC_BCR_WREN; - - /* Set ADDSET */ - bank->BTR &= ~(FSMC_BTR_ADDSET); - bank->BTR |= (FSMC_BTR_ADDSET | FSMC_ADDSET); - - /* Set DATAST */ - bank->BTR &= ~(FSMC_BTR_DATAST); - bank->BTR |= (FSMC_BTR_DATAST | (FSMC_DATAST << 8)); - - /* Enable channel 1 */ - bank->BCR |= FSMC_BCR_MBKEN; // '1' + /* FIXME replace with macros from fsmc.h */ + bank->BCR = (1 << 12) | (1 << 4) | 1; + bank->BTR = (0xF << 16) | (0x3 << 8) | 1; /* (FSMC_BWTR3 not used for this simple configuration.) */ } -- cgit v1.2.3