diff options
Diffstat (limited to 'msp430/libraries/MspFlash')
| -rw-r--r-- | msp430/libraries/MspFlash/MspFlash.cpp | 62 | ||||
| -rw-r--r-- | msp430/libraries/MspFlash/MspFlash.h | 83 | ||||
| -rw-r--r-- | msp430/libraries/MspFlash/examples/flash_readwrite/flash_readwrite.ino | 151 | ||||
| -rw-r--r-- | msp430/libraries/MspFlash/keywords.txt | 29 |
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 |
