diff options
author | Marti Bolivar <mbolivar@leaflabs.com> | 2011-03-07 15:40:47 -0500 |
---|---|---|
committer | Marti Bolivar <mbolivar@leaflabs.com> | 2011-03-07 15:40:47 -0500 |
commit | f044da4ff39c0e72d3dd0efb8b6b5eb26719838c (patch) | |
tree | 4149ec5f57d09161147558d9fca8f86ddd74abe3 | |
parent | e17fec9095668d37452ff7a57c7378316b22caf6 (diff) | |
download | librambutan-f044da4ff39c0e72d3dd0efb8b6b5eb26719838c.tar.gz librambutan-f044da4ff39c0e72d3dd0efb8b6b5eb26719838c.zip |
FSMC working but slow (~6 MHz).
-rw-r--r-- | examples/test-fsmc.cpp | 200 | ||||
-rw-r--r-- | 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 <stdio.h>
+#include <stddef.h>
#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.) */ } |