aboutsummaryrefslogtreecommitdiff
path: root/msp430/libraries/MspFlash
diff options
context:
space:
mode:
Diffstat (limited to 'msp430/libraries/MspFlash')
-rw-r--r--msp430/libraries/MspFlash/MspFlash.cpp62
-rw-r--r--msp430/libraries/MspFlash/MspFlash.h83
-rw-r--r--msp430/libraries/MspFlash/examples/flash_readwrite/flash_readwrite.ino151
-rw-r--r--msp430/libraries/MspFlash/keywords.txt29
4 files changed, 325 insertions, 0 deletions
diff --git a/msp430/libraries/MspFlash/MspFlash.cpp b/msp430/libraries/MspFlash/MspFlash.cpp
new file mode 100644
index 0000000..3495e62
--- /dev/null
+++ b/msp430/libraries/MspFlash/MspFlash.cpp
@@ -0,0 +1,62 @@
+/*
+ MspFlash.h - Read/Write flash memory library for MSP430 Energia
+ Copyright (c) 2012 Peter Brier. All right reserved.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+#include "MspFlash.h"
+#include <msp430.h>
+#include <Energia.h>
+
+// The Flash clock must be between 200 and 400 kHz to operate correctly
+// TODO: calculate correct devider (0..64) depending on clock frequenct (F_CPU)
+// Now we set F_CPU/64 is 250khz at F_CPU = 16MHz
+
+#define FLASHCLOCK FSSEL1+((F_CPU/400000L) & 63); // SCLK
+
+// erase flash, make sure pointer is in the segment you wish to erase, otherwise you may erase you program or some data
+void MspFlashClass::erase(unsigned char *flash)
+{
+ disableWatchDog(); // Disable WDT
+ FCTL2 = FWKEY+FLASHCLOCK; // SMCLK/2
+ FCTL3 = FWKEY; // Clear LOCK
+ FCTL1 = FWKEY+ERASE; //Enable segment erase
+ *flash = 0; // Dummy write, erase Segment
+ FCTL3 = FWKEY+LOCK; // Done, set LOCK
+ enableWatchDog(); // Enable WDT
+}
+
+// load from memory, at segment boundary
+void MspFlashClass::read(unsigned char *flash, unsigned char *dest, int len)
+{
+ while(len--)
+ *(dest++) = *(flash++);
+}
+
+// save in to flash (at segment boundary)
+void MspFlashClass::write(unsigned char *flash, unsigned char *src, int len)
+{
+ disableWatchDog(); // Disable WDT
+ FCTL2 = FWKEY+FLASHCLOCK; // SMCLK/2
+ FCTL3 = FWKEY; // Clear LOCK
+ FCTL1 = FWKEY+WRT; // Enable write
+ while(len--) // Copy data
+ *(flash++) = *(src++);
+ FCTL1 = FWKEY; //Done. Clear WRT
+ FCTL3 = FWKEY+LOCK; // Set LOCK
+ enableWatchDog(); // Enable WDT
+}
+
+MspFlashClass Flash;
diff --git a/msp430/libraries/MspFlash/MspFlash.h b/msp430/libraries/MspFlash/MspFlash.h
new file mode 100644
index 0000000..afa131c
--- /dev/null
+++ b/msp430/libraries/MspFlash/MspFlash.h
@@ -0,0 +1,83 @@
+/*
+ MspFlash.h - Read/Write flash memory library for MSP430 Energia
+ Copyright (c) 2012 Peter Brier. All right reserved.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+ Provide access to the MSP430 flash memory controller.
+ All flash memory can be read, erased and written (except SEGMENT_A, the LOCK bits are not in the code, for a good reason).
+ Flash can only be erased per 512 byte segments (except the 4 special information segments, they are 64 bytes in size)
+
+ The same flash locations can be written multiple times with new values, but flash bits can only be reset (from 1 to 0) and cannot
+ change to a 1 (you need to flash erase the whole segment)
+
+ functions:
+ ~~~~~~~~~~
+ erase(): Erase a flash segment, all bytes in the segment will read 0xFF after an erase
+
+ read(): Read flash locations (actually just a proxy for memcpy)
+
+ write(): Write flash locations (actually just a proxy for memcpy), the same location can be written multiple times,
+ but once a bit is reset, you cannot set it with a subsequent write, you need to flash the complete segment to do so.
+
+ NOTE: you are flashing the program memory, you can modify EVERYTHING (program and data) this is usually not what you want.
+ Be carefull when flashing data. You may use SEG_B to SEG_D for normal use, they should not be filled by the compiler with code
+ or static data. If you wish to use main memory without wasting any space, you need to inform the linker NOT to use the required
+ segments. This is done in the linker script (this is not for the faint of heart).
+
+ An alternative approach is to allocate a static variable with a size of AT LEAST 2 SEGMENTS in your program.
+ This makes sure there is at least ONE COMPLETE SEGMENT in this static variable, so there is no colleteral damage when you flash this
+ area. You need to find the pointer to the start of the next segment. There is a macro define to do this: SEGPTR(x)
+ A example that makes 2 segments available for flashing by allocating 3 segments of constant data:
+
+ static const unsigned char flash[3*512] = {0};
+
+ Flash segments: |...SEGMENT-0...|...SEGMENT-1...|...SEGMENT-2...|...SEGMENT-3...|...SEGMENT-4...|...SEGMENT-5...|
+ Program output: |Program code.......|flash[3*512***********************************]|Other data.................|
+ Available segments: |-------------------------------|+++++++++++++++|+++++++++++++++|-------------------------------|
+
+
+*/
+
+#ifndef MSP_FLASH_h
+#define MSP_FLASH_h
+
+#define SEGMENT_SIZE 512 // main segment size (smallest flasheable area)
+#define INFO_SIZE 64 // information flah sizes (SEG_A to SEG_D)
+
+// segment addresses of 64 byte segments
+#define SEGMENT_D ((unsigned char*)0x1000)
+#define SEGMENT_C ((unsigned char*)0x1000+64)
+#define SEGMENT_B ((unsigned char*)0x1000+128)
+// #define SEGMENT_A ((unsigned char*)0x1000+192) // NOTE: Contains chip calibarion data, do not change or erase (the protection bit should prevent this happening)
+
+// Segment start addresses of 512 byte segments 0..63 (depending on device flash size)
+#define SEGMENT(x) ( (unsigned char*) 0xFFFF - (x)*SEG_SIZE )
+
+// return segment pointer inside variable. Note: return start of NEXT segment
+#define SEGPTR(x) ( (unsigned char *) (((unsigned short)(&x)+512) & 0xFE00) )
+
+class MspFlashClass
+{
+ public:
+ void erase(unsigned char *flash);
+ void read(unsigned char *flash, unsigned char *dest, int len);
+ void write(unsigned char *flash, unsigned char *src, int len);
+};
+
+extern MspFlashClass Flash;
+
+#endif // MSP_FLASH_h
+
diff --git a/msp430/libraries/MspFlash/examples/flash_readwrite/flash_readwrite.ino b/msp430/libraries/MspFlash/examples/flash_readwrite/flash_readwrite.ino
new file mode 100644
index 0000000..70f3674
--- /dev/null
+++ b/msp430/libraries/MspFlash/examples/flash_readwrite/flash_readwrite.ino
@@ -0,0 +1,151 @@
+/*
+ flas_readwrite.h - Read/Write flash memory library example for MSP430 Energia
+ Copyright (c) 2012 Peter Brier. All right reserved.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+ Provide access to the MSP430 flash memory controller.
+ All flash memory can be read, erased and written (except SEGMENT_A, the LOCK bits are not in the code, for a good reason).
+ Flash can only be erased per 512 byte segments (except the 4 special information segments, they are 64 bytes in size)
+
+ The same flash locations can be written multiple times with new values, but flash bits can only be reset (from 1 to 0) and cannot
+ change to a 1 (you need to flash erase the whole segment)
+
+ functions:
+ ~~~~~~~~~~
+ erase(): Erase a flash segment, all bytes in the segment will read 0xFF after an erase
+
+ read(): Read flash locations (actually just a proxy for memcpy)
+
+ write(): Write flash locations (actually just a proxy for memcpy), the same location can be written multiple times,
+ but once a bit is reset, you cannot set it with a subsequent write, you need to flash the complete segment to do so.
+
+ constants:
+ ~~~~~~~~~~
+ SEGMENT_A // pointer to 64 byte flash segments
+ SEGMENT_B
+ SEGMENT_C
+ SEGMENT_D
+
+ Macros:
+ ~~~~~~~
+ SEGPTR(x) // Return pointer to first complete segment inside variable
+ SEGMENT(n) // Return pointer to start of segment n (n=0..63)
+
+
+ NOTE: you are flashing the program memory, you can modify EVERYTHING (program, data) this is usually not what you want.
+ Be carefull when flashing data. You may use SEG_B to SEG_D for normal use, they should not be filled by the compiler
+ If you wish to use main memory, you need to inform the linker NOT to use the segments you wish to use in the linker script
+ (this is not for the faint of heart).
+
+ An alternative approach is to allocate a static variable with a size of AT LEAST 2 SEGMENTS in your program.
+ This makes sure there is at least ONE COMPLETE SEGMENT in this static variable, so there is no colleteral damage when you flash this
+ area. You need to find the pointer to the start of the next segment. There is a macro define to do this: SEGPTR(x)
+ A example that makes 2 segments available for flashing by allocating 3 segments of constant data:
+
+
+ Using the example:
+ ~~~~~~~~~~~~~~~~~~
+
+ On the launchpad; put the two UART jumpers in HARDWARE SERIAL position (horizontal position) and use the terminal window to connect
+ to the board (9600baud).
+
+ 'e' Erase the flash segment
+ 'w' Write "Hello World" to the flash
+ 'r' Read the contents of the flash, and print as byte values and characters. stop at the first NULL byte
+
+ - When you program the launchpad and read the flash, a single "0" character should be read (mem contains zero values)
+ Writing the flash before you have erased it is not possible (you cannot program OFF bits to ON bits)
+ - When you erase the flash, 0xFF values will be read back
+ - When you write the flash, "Hello World" will be read back
+
+
+*/
+
+#include "MspFlash.h"
+
+
+// Two options to use for flash: One of the info flash segments, or a part of the program memory
+// either define a bit of constant program memory, and pass a pointer to the start of a segment to the flash functions,
+
+//*** Option 1: use program memory, uncomment these lines and you have 512 bytes of flash available (1024 bytes allocated) ****
+//const unsigned char data[2*SEGMENT_SIZE] = {0};
+//#define flash SEGPTR(data)
+//
+
+//*** Option 2: use one of the 64 byte info segments, uncomment this line. Use SEGMENT_B, SEGMENT_C or SEGMENT_D (each 64 bytes, 192 bytes in total)
+#define flash SEGMENT_D
+//
+
+
+void setup()
+{
+ // put your setup code here, to run once:
+ Serial.begin(9600);
+}
+
+void loop() {
+ // put your main code here, to run repeatedly:
+ if ( Serial.available() )
+ {
+ switch ( Serial.read() )
+ {
+ case 'e': doErase(); break;
+ case 'r': doRead(); break;
+ case 'w': doWrite(); break;
+ case 10:
+ case 13: break;
+ default: doHelp();
+ }
+ }
+}
+
+void doRead()
+{
+ unsigned char p = 0;
+ int i=0;
+ Serial.println("Read:");
+ do
+ {
+ Flash.read(flash+i, &p, 1);
+ Serial.write(p);
+ Serial.print(":");
+ Serial.println(p);
+ } while ( p && (i++ < 16) );
+ Serial.println(".");
+}
+
+
+void doErase()
+{
+ Serial.println("Erase");
+ Flash.erase(flash);
+ Serial.println("Done.");
+}
+
+void doWrite()
+{
+ Serial.println("Write");
+ Flash.write(flash, (unsigned char*) "Hello World!" ,13);
+ Serial.println("Done.");
+}
+
+void doHelp()
+{
+ int div = (F_CPU/400000L) & 63;
+ Serial.println("flash test: e, r, w");
+ Serial.println(F_CPU);
+ Serial.println(div);
+}
diff --git a/msp430/libraries/MspFlash/keywords.txt b/msp430/libraries/MspFlash/keywords.txt
new file mode 100644
index 0000000..72b8fc2
--- /dev/null
+++ b/msp430/libraries/MspFlash/keywords.txt
@@ -0,0 +1,29 @@
+#######################################
+# Syntax Coloring Map
+#######################################
+
+#######################################
+# Datatypes (KEYWORD1)
+#######################################
+
+Flash KEYWORD1
+
+#######################################
+# Methods and Functions (KEYWORD2)
+#######################################
+erase KEYWORD2
+read KEYWORD2
+write KEYWORD2
+
+
+#######################################
+# Constants (LITERAL1)
+#######################################
+SEGMENT KEYWORD2
+SEGMENT_A LITERAL1
+SEGMENT_B LITERAL1
+SEGMENT_C LITERAL1
+SEGMENT_D LITERAL1
+SEG_SIZE LITERAL1
+INFO_SIZE LITERAL1
+SEGPTR KEYWORD2 \ No newline at end of file