snapshot hacking
authorDan White <dan@whiteaudio.com>
Fri, 7 Sep 2012 17:58:04 +0000 (12:58 -0500)
committerDan White <dan@whiteaudio.com>
Fri, 7 Sep 2012 17:58:04 +0000 (12:58 -0500)
msp4th/Makefile
msp4th/flash.py [new symlink]
msp4th/x.c
python-lib/flash.py [new file with mode: 0755]
python-lib/usbio.py

index dcf0b574a3a804e42f8efc8eab7e8da91e1e76f7..e377f045a5ed4708a51d5af32847b7729a36f050 100755 (executable)
@@ -5,23 +5,31 @@
 
 MAIN=x.c
 
-default: $(MAIN:.c=.hex) $(MAIN:.c=.xout)
+default: $(MAIN:.c=.hex) $(MAIN:.c=.xout) $(MAIN:.c=.asm)
+
+all: default flash
 
 #msp430-gcc -nostartfiles -mmcu=msp430x2013 -O2 -g -Wall -Wa,-ahlms=$(<:.c=.lst)
 %.a43: %.c
-       msp430-gcc -nostartfiles -mmcu=msp430x2013 -Wall -Wa,-ahlms=$(<:.c=.lst) \
+       msp430-gcc -O0 -nostartfiles -mmcu=msp430xG438 -Wall -Wa,-ahlms=$(<:.c=.lst) \
            -mendup-at=main -o $@ $< -L -Xlinker -T ldscript_ns430
 
+%.asm: %.c
+       msp430-gcc -S -O0 -nostartfiles -mmcu=msp430xG438 -Wall \
+           -mendup-at=main -o $@ $<
+
 %.hex: %.a43
        msp430-objcopy -O ihex $< $@
 
 %.xout: %.a43
-       #msp430-objdump -dSt $< > $@
-       #msp430-objdump --disassemble-all --architecture=msp:54 $< > $@
+       @#msp430-objdump -dSt $< > $@
+       @#msp430-objdump --disassemble-all --architecture=msp:54 $< > $@
        msp430-objdump --disassemble-all $< > $@
 
+flash: $(MAIN:.c=.hex)
+       ./flash.py $<
 
 clean:
-       rm -f *.a43 *.hex *.xout *.lst
+       rm -f *.a43 *.hex *.xout *.lst *.asm
 
 
diff --git a/msp4th/flash.py b/msp4th/flash.py
new file mode 120000 (symlink)
index 0000000..6a60bdf
--- /dev/null
@@ -0,0 +1 @@
+../python-lib/flash.py
\ No newline at end of file
index 4b53fe4cc62137f97bddb83a47fed3a32ff0f96a..63ad6c6242fb01957fc232f1010ec209a2442ab1 100644 (file)
@@ -7,14 +7,13 @@
 // last update 3/9/08
 
 #include <signal.h>
-
-#include <io.h>
+/*#include <io.h>*/
 #include <iomacros.h>
 
 #include "ns430-atoi.h"
 #include "ns430-uart.h"
 
-#define DEBUG_STUFF 1          // just print lots of junk
+#define DEBUG_STUFF 1           // just print lots of junk
 #define CMD_LIST_SIZE 128
 #define MATH_STACK_SIZE 16
 #define ADDR_STACK_SIZE 32
@@ -28,7 +27,8 @@
 // The order is important .... don't insert anything!
 // the order matches the execN function
 
-const uint8_t cmdListBi[] = 
+/*const uint8_t cmdListBi[] = */
+const char cmdListBi[] = 
              {"exit + - * / "                       // 1 -> 5
               ". dup drop swap < "                  // 6 -> 10
               "> = .hb gw dfn "                     // 11 -> 15
@@ -46,13 +46,14 @@ const uint8_t cmdListBi[] =
 
 // these commands are interps
 
-const uint8_t cmdListBi2[] = {"[ : var "};
+/*const uint8_t cmdListBi2[] = {"[ : var "};*/
+const char cmdListBi2[] = {"[ : var "};
 
 // these values point to where in progBi[] these routines start
 
 const int16_t cmdList2N[] = {0,10000,10032,10135};  // need an extra zero at the front
 
-#define LAST_PREDEFINED 40     // update this when we add commands to the built in list
+#define LAST_PREDEFINED 40      // update this when we add commands to the built in list
 
 int16_t mathStack[MATH_STACK_SIZE];
 
@@ -281,7 +282,7 @@ uint8_t lineBuffer[128];      /* input line buffer */
 uint16_t lineBufferPtr;                 /* input line buffer pointer */
 // uint8_t xit;                    /* set to 1 to kill program */
 
-uint8_t wordBuffer[32];                // just get a word
+uint8_t wordBuffer[32];         // just get a word
 
 
 
@@ -431,8 +432,8 @@ interrupt (4) timerInterrupt(void){
 static void __inline__ delay(register unsigned int n){
   __asm__ __volatile__ (
       "1: \n"
-      " dec    %[n] \n"
-      " jne    1b \n"
+      " dec     %[n] \n"
+      " jne     1b \n"
       : [n] "+r"(n));
 }
 
@@ -449,7 +450,8 @@ void emit(uint8_t c){
   */
 
   int16_t i;
-  while ((UART0_SR & TDRE) == 0) {
+  /*while ((UART0_SR & TDRE) == 0) {*/
+  while ((UART0_SR & (TDRE | TXEMPTY)) == 0) {
       // wait for register to clear
       i++;
   }
@@ -472,6 +474,7 @@ uint8_t getKey(){
       // wait for char
   }
   i = UART0_RDR & 0x00ff;
+  delay(100);
   return(i);
 } 
 
@@ -480,7 +483,7 @@ uint8_t getKey(){
 
 void initVars(){
 
-    uint16_t i;
+  uint16_t i;
   // I override the C startup code .... so I must init all vars.
 
   outputCharCntrN = 0;
@@ -510,92 +513,119 @@ void initVars(){
 
 
 uint8_t getKeyB(){
-  uint8_t i;
-  i = lineBuffer[lineBufferPtr];
-  if(i != 0) lineBufferPtr++;
-  return(i);
+  uint8_t c;
+  c = lineBuffer[lineBufferPtr];
+  lineBufferPtr = lineBufferPtr + 1;
+  /*if(c != 0) lineBufferPtr++;*/
+  return(c);
 }
 
 
-void printHexByte(int16_t n);
+/*void printHexByte(uint8_t n);*/
 
 
 
 
 
 void getLine(){
-  int16_t i;
+  uint8_t c;
+  int16_t flag;
   lineBufferPtr = 0;
 
-  emit(0x0D);
-  emit(0x0A);
+  emit('\r');
+  emit('\n');
   emit('>');   // this is our prompt
 
-  i = 1;
-  while(i){  // just hang in loop until we get CR
-    i = getKey();
-    if(i == 0x08){
+  flag = 1;
+  while(flag){  // just hang in loop until we get CR
+    c = getKey();
+    emit(c);
+    printHexByte(c);
+    if(c == '\b'){
       if(lineBufferPtr > 0){
-        emit(0x08);
         emit(' ');
-        emit(0x08);
+        c = 0;
+        emit('\b');
         lineBufferPtr--;
       }
-    } else {
-      emit(i);
-      if(i == 0x0D){
+    } else if (c == '\r'){
+      /*emit(c);*/
+      /*if((c=='\n') || (c=='\r')){*/
+      /*if(c == '\r'){*/
         // hit cr
         lineBuffer[lineBufferPtr] = 0;
-        i = 0;
-      } else {
-
-        lineBuffer[lineBufferPtr++] = i;
+        emit('\n');
+        flag = 0;
+    } else if (c >= ' '){
+        lineBuffer[lineBufferPtr++] = c;
         lineBuffer[lineBufferPtr] = 0;
 
         if(lineBufferPtr > 125){  // prevent overflow of line buffer
-          i=0;
+          flag = 0;
         }
-      }
+      } else {
+          // non-printable char, do nothing
     }
   }
-  emit(0x0A);
   lineBufferPtr = 0;
+  emit('.');
 }
 
 
 void getWord(){
-  int16_t k;
-  uint8_t c;
+  uint8_t k;
+  volatile uint8_t c=1;
   wordBuffer[0] = 0;
   while(wordBuffer[0] == 0){
     k = 0;
-    c = getKeyB();
-    while(( c <= ' ') && ( c != 0 )) c = getKeyB();    /* strip leading spaces */
-    if( c > 0 ){
+    /*
+    while (c != 0){
+        c = getKeyB();
+        emit(c);
+    }
+    */
+    /* strip leading whitespace */
+    while((c <= ' ') && (c != 0)){
+        c = getKeyB();
+        printHexByte(c);
+        emit(c);
+    }
+
+    /* end of buffer, get more text */
+    emit(c);
+    if(c == 0){
+      wordBuffer[0] = 0;
+      getLine();     
+    } else {
       if( c == '"' ){
         c = getKeyB();
-        while((c != '"')&&(c != 0)){
-          if(c != '"') wordBuffer[k++] = c;
+        emit(c);
+        while((c != '"') && (c != 0)){
+          if(c != '"'){
+              wordBuffer[k++] = c;
+          }
           c = getKeyB();
+          emit(c);
         }
       } else {
-        while(c > ' ' && c != 0){
+        while((c > ' ') && (c != 0)){
           wordBuffer[k++] = c;
           c = getKeyB();
+          emit(c);
         }
       }
-      wordBuffer[k] = 0;
-    } else {
-      wordBuffer[0] = 0;
-      getLine();     
     }
   }
+  wordBuffer[k] = 0;
 }
 
-void printString(const uint8_t *c){
-  while(c[0]){
-    emit(c[0]);
-    c++;
+void printString(char *c){
+  uint16_t i;
+  emit('.');
+  i = 0;
+  while(c[i] != 0){
+    emit(c[i]);
+    i = i + 1;
   }
 }
 
@@ -725,7 +755,7 @@ void luFunc(){
 
 void numFunc(){  // the word to test is in wordBuffer
   int16_t i,j,n;
-  printString((const uint8_t *)"in numFunc()\r\n");
+  printString("in numFunc()\r\n");
   printString(wordBuffer);
   // first check for neg sign
   i = 0;
@@ -851,24 +881,24 @@ void printNumber(int16_t n){
   emit(' ');
 }
 
-void printHexChar(int16_t n){
+void printHexChar(uint8_t n){
   n &= 0x0F;
   if(n > 9){
     n += 7;
   }
   n += '0';
-  emit(n);
+  emit((uint8_t)n);
 }
 
-void printHexByte(int16_t n){
+void printHexByte(uint8_t n){
   n &= 0xFF;
   printHexChar(n >> 4);
   printHexChar(n);
 }
 
-void printHexWord(int16_t n){
-  printHexByte(n >> 8);
-  printHexByte(n);
+void printHexWord(uint16_t n){
+  printHexByte((uint8_t)(n >> 8));
+  printHexByte((uint8_t)(n & 0xFF));
 }
 
 void execN(int16_t n); // proto ... this could get recursive
@@ -900,9 +930,9 @@ void execFunc(){
 void execN(int16_t n){
   int16_t i,j,k,m;
   int32_t x,y,z;
-  printString((const uint8_t *)"execN: ");
+  printString("execN: ");
   printNumber(n);
-  printString((const uint8_t *)"\r\n");
+  printString("\r\n");
   switch(n){
     case 1:
   //    xit = 1;
@@ -1057,7 +1087,7 @@ void execN(int16_t n){
 
 
     case 30:  // num
-      printString((const uint8_t *)"in case 30\r\n");
+      printString("in case 30\r\n");
       numFunc();
       break;
 
@@ -1134,7 +1164,7 @@ void execN(int16_t n){
       j = popAddrStack();  // loop address
       k = popAddrStack();  // count
       m = popAddrStack();  // limit
-      k++;                // up the count
+      k++;                 // up the count
       if(k >= m){
         // we are done
       } else {
@@ -1280,7 +1310,7 @@ void processLoop(){            // this processes the forth opcodes.
 
   while(1){
 
-      printString((const uint8_t *)"processLoop()\r\n");
+      printString("processLoop()\r\n");
     if(progCounter > 9999){
       opcode = progBi[progCounter - 10000];
     } else {
@@ -1316,16 +1346,33 @@ int main(void){
 
   /* 8e6 / (16*19200) - 1 = 25.0416 */
   /* 8e6 / (16*2400) - 1 = 207.33 */
-  UART0_BCR = 207;
+  /* 25e6 / (16*2400) - 1 = 207.33 */
+  UART0_BCR = 324;
   UART0_CR = UARTEn;
 
-  emit(0x00);   
+  dint();
+  emit('!');   
+
+  while (1) {
+      uint8_t c;
+      c = getKey();
+      if (c == '`') break;
+      emit(c);
+  }
 
+  emit('t');
+  emit('e');
+  emit('s');
+  emit('t');
+  emit('i');
+  emit('n');
+  emit('g');
+  printString("This is a test of the UART serial printing\r\nit really does work ...\r\n");
 
 //  xit = 0;
   addrStackPtr = ADDR_STACK_SIZE;    // this is one past the end !!!! as it should be
   progCounter = 10000;
-  progPtr = 1;                 // this will be the first opcode
+  progPtr = 1;                  // this will be the first opcode
   i=0;
   cmdListPtr = 0;
   cmdList[0] = 0;
diff --git a/python-lib/flash.py b/python-lib/flash.py
new file mode 100755 (executable)
index 0000000..7d923c7
--- /dev/null
@@ -0,0 +1,274 @@
+#!/usr/bin/env python
+
+import sys
+import optparse
+from intelhex import IntelHex
+from myhdl import intbv
+import mpsse
+
+
+parser = optparse.OptionParser()
+
+parser.add_option('-e', '--erase', dest='erase', default=False,
+        action='store_true', help='Erase flash contents first')
+
+parser.add_option('-v', '--verify', dest='verify', default=False,
+        action='store_true', help='Verify contents with ihex file')
+
+parser.add_option('-p', '--program', dest='program', default=False,
+        action='store_true', help='Verify contents with ihex file')
+
+(opt, args) = parser.parse_args()
+
+#
+# helpers
+#
+
+def str2hex(x):
+    return ''.join(map(lambda h: '%02x' % ord(h), x))
+
+def int2str(value, width):
+    if (width % 8) != 0:
+        raise Exception, 'width must be multiple of 8'
+    v = intbv(value, max=2**width)
+    b = [v[i:i-8] for i in range(width, 0, -8)]
+    return ''.join(map(chr, b))
+
+
+#
+# old libmpsse based code
+#
+class AtoiSPI0(mpsse.MPSSE):
+    def __init__(self, freq):
+        super(AtoiSPI0, self).__init__()
+        self._freq = int(freq)
+        self.Open(0x0403, 0x6011, mpsse.SPI1, int(freq),
+                interface=mpsse.IFACE_A)
+        self._cs = None
+        self._cs_mode = {
+                'flash': mpsse.SPI0,
+                'dac': mpsse.SPI1,
+                'adc': mpsse.SPI1,
+                'convst': mpsse.SPI1,
+                }
+
+    def SetCS(self, name):
+        """Setup the chip-select pins for a given 'name'."""
+        if name == self._cs:
+            return
+
+        if name not in self._cs_mode:
+            raise Exception, 'Unknown CS name: %s' % name
+
+        # different SPI modes require restarting the bus for some reason
+        if self.context.mode != self._cs_mode[name]:
+            self.Close()
+            self.Open(0x0403, 0x6011,
+                    self._cs_mode[name],
+                    self._freq,
+                    interface=mpsse.IFACE_A)
+
+        if name == 'flash':
+            self.context.pidle = self.context.pstop = 0xc8
+            self.context.pstart = 0xc0
+        elif name == 'dac':
+            self.context.pidle = self.context.pstop = 0xc8
+            self.context.pstart = 0xd8
+        elif name == 'adc':
+            self.context.pidle = self.context.pstop = 0xc8
+            self.context.pstart = 0xe8
+        elif name == 'convst':
+            self.context.pidle = self.context.pstop = 0xc8
+            self.context.pstart = 0xf8
+        else:
+            raise Exception, 'Unknown CS name: %s' % name
+
+        self._cs = name
+
+
+# old code
+class M25PExx(object):
+    def __init__(self, spibus):
+        self.bus = spibus
+
+    def _write(self, data):
+        self.bus.SetCS('flash')
+        self.bus.Start()
+        self.bus.Write(data)
+        self.bus.Stop()
+
+    def _exchange(self, data):
+        self.bus.SetCS('flash')
+        self.bus.Start()
+        d = self.bus.Exchange(data)
+        self.bus.Stop()
+        return d
+
+    def writeEnable(self, enable):
+        if enable:
+            x = '\x06'
+        else:
+            x = '\x04'
+        self._write(x)
+
+    def id(self):
+        d = self._exchange('\x9f' + 3*'\x00')
+        return d[1:]
+
+    def status(self):
+        d = self._exchange('\x05\x00')
+        return ord(d[1])
+
+    def read(self, addr, n):
+        a = int2str(addr, 3*8)
+        while not self.isReady():
+            pass
+        d = self._exchange('\x03' + a + n*'\x00')
+        return d[4:]
+
+    def fastRead(self, addr, n):
+        a = int2str(addr, 3*8)
+        while not self.isReady():
+            pass
+        d = self._exchange('\x0b' + a + n*'\x00')
+        return d[4:]
+
+    def writePage(self, addr, data):
+        if ((addr & 0xff) + len(data)) > 256:
+            raise Exception, 'Too much data: %i' % len(data)
+        a = int2str(addr, 3*8)
+        while not self.isReady():
+            pass
+        self._write('\x0a' + a + data)
+
+    def programPage(self, addr, data):
+        if ((addr & 0xff) + len(data)) > 256:
+            raise Exception, 'Too much data: %i' % len(data)
+        a = int2str(addr, 3*8)
+        while not self.isReady():
+            pass
+        self._write('\x02' + a + data)
+
+    def erasePage(self, addr):
+        if (addr & 0xff) != 0:
+            raise Exception, 'Address must be a page boundary: %i' % addr
+        while not self.isReady():
+            pass
+        self._write('\xdb' + a)
+
+    def eraseAll(self):
+        while not self.isReady():
+            pass
+        self._write('\xc7')
+
+    def power(self, on):
+        if on:
+            self._write('\xab')
+        else:
+            self._write('\xb9')
+
+    def isReady(self):
+        return (self.status() & 0x01) == 0
+
+    def write(self, addr, data):
+        if addr & 0xff != 0:
+            raise Exception, 'Address must start on a page boundary (0x....00).'
+
+        n = len(data)
+        nPages = (n // 256) + 1
+        for i in range(nPages):
+            s = i * 256
+            e = min(s+256, len(data))
+            a = addr + s
+            while not self.isReady():
+                print hex(self.status())
+            print 'writing page: %06x %s' % (a, str2hex(data[s:e]))
+            self.writeEnable(True)
+            self.writePage(a, data[s:e])
+            print hex(self.status())
+
+    def program(self, addr, data):
+        if addr & 0xff != 0:
+            raise Exception, 'Address must start on a page boundary (0x....00).'
+
+        n = len(data)
+        nPages = (n // 256) + 1
+        for i in range(nPages):
+            s = i * 256
+            e = min(s+256, len(data))
+            a = addr + s
+            while not self.isReady():
+                pass
+            self.programPage(a, data[s:e])
+
+
+
+
+spi0 = AtoiSPI0(1000e3) #port A
+
+##############################################################################
+# Flash testing
+#
+#flash = M25PExx(spi0, 'flash')
+flash = M25PExx(spi0)
+flash.power(True)
+print flash.status()
+print 'id:', str2hex(flash.id())
+print flash.status()
+print 'data:', str2hex(flash.read(0x4000, 16))
+
+flash.writeEnable(True)
+if opt.erase:
+    flash.eraseAll()
+    print 'erasing',
+    while not flash.isReady():
+        print '.',
+    print
+
+#h = IntelHex('../msp4th/hello-world.hex')
+#h = IntelHex('../msp4th/x.hex')
+h = IntelHex(args[0])
+
+#code space in RAM, only get/send used block of bytes
+a = [a for a in h.addresses() if (a >= 0x4000 and a < 0xff00)]
+alen = max(a) - min(a) + 1
+#alen = 32
+code = h.gets(0x4000, alen)
+if 1:
+    flash.writeEnable(True)
+    flash.write(min(a), code)
+
+# 0xffd0 -- 0xffff are interrupt vectors
+# gcc et.al. for some reason do not give a value for 0xfffe word
+#   the flash loader in ROM jumps to addr pointed here
+#   force to start of RAM
+#
+# the flash uses 256-byte pages, include code from 0xff00 - 0xffcf
+# as it was excluded above
+    vectors = ''.join([chr(h[i]) for i in range(0xff00, 0x10000-2)])
+    vectors += '\x00\x40'
+    flash.write(0xff00, vectors)
+
+while not flash.isReady():
+    print 'waiting...'
+
+if 1:
+    nread = 0
+    c2 = ''
+    while nread < len(code):
+        nr = min(256, len(code)-nread)
+        c = flash.read(0x4000 + nread, nr)
+        c2 += c
+        print 'read: %06x %s' % (0x4000+nread, str2hex(c))
+        nread += nr
+
+    print len(code), len(c2)
+    if 0:
+        for i in range(len(code)):
+            print i, code[i] == c2[i]
+    print len(code), len(c2)
+    print str2hex(code[-4:]), str2hex(c2[-4:])
+    print all([code[i] == c2[i] for i in range(len(code))])
+
+print str2hex(code[:4])
+print str2hex(c2[:4])
index 8e8fdbc7a244d925c5da54a8ccec775f16bbeb80..67c83ca2e5d71665cf3931e58c0818dc82f0d7f0 100644 (file)
@@ -399,7 +399,7 @@ class SPI(object):
                 raise Exception, self.ftdi.get_error_string(self.context)
             r += s
         #NOTE: including ftdi.SEND_IMMEDIATE commands make this redundant
-        #self.ftdi.usb_purge_rx_buffer(self.context)
+        self.ftdi.usb_purge_rx_buffer(self.context)
         return r
 
     def set_freq(self, freq):
@@ -450,7 +450,7 @@ class SPI(object):
             self._pindir |= self.cs['_mask'][1] # chip-select pins are always outputs
             self._pindir &= 0xFB # pin 2/DI is an input for sure
             # most implementations force pin 3/CS to an output, IT DOES NOT
-            # NEED DO BE.  The top 5 pins are available for GPIO, CS, or both
+            # NEED TO BE.  The top 5 pins are available for GPIO, CS, or both
             # in SPI mode.  With a 5-bit one-cold decoder, we can control up to
             # (2**5 - 1) = 31 chips with this port.
 
@@ -463,6 +463,7 @@ class SPI(object):
             else:
                 self._pinstate = pinstate
 
+        #print 'set pins: %02x, %02x' % (self._pinstate, self._pindir)
         cmd = chr(self.ftdi.SET_BITS_LOW) + chr(self._pinstate) + chr(self._pindir)
         self._raw_write(cmd)
 
@@ -493,19 +494,30 @@ class SPI(object):
         mode, pins = self.cs[device]
 
         # set SK before asserting CS to not violate timing
-        if True:
+        if False:
             # first, ensure SK starts in the correct state
             p = self._pinstate
-            if mode in (0, 1):
+            #if mode == 0:
+                #p &= 0xfe
+            #elif mode == 1:
+                #p |= 0x01
+            if mode == 0:
+                #p |= 0x01
+                p &= 0xfe
+            elif mode == 1:
                 p |= 0x01
             elif mode in (2, 3):
                 p &= 0xfe
             cmd = chr(self.ftdi.SET_BITS_LOW) + chr(p) + chr(self._pindir)
+            #print 'set pins: %02x, %02x' % (self._pinstate, self._pindir)
+            #print '%s; mask %02x, mode %02x, pins %02x' % (device, mask, mode, pins)
+            #print 'pins: %02x' % p
 
             p &= ~mask
             p += pins & mask
             self._pinstate = p
             cmd += chr(self.ftdi.SET_BITS_LOW) + chr(p) + chr(self._pindir)
+            #print 'set pins: %02x, %02x' % (self._pinstate, self._pindir)
         # old behavior: set CS and SK in same command
         else:
             p = self._pinstate & ~mask
@@ -580,6 +592,7 @@ class SPI(object):
                 self._write_cmd(device, data) +
                 self._cs_cmd_cache['_idle'])
         self._raw_write(cmd)
+        #print 'write to %s: %s' % (device, str2hex(data))
 
     def read(self, device, n):
         """Read data from the selected device, DO pin stays in its last
@@ -600,7 +613,10 @@ class SPI(object):
                 self._exchange_cmd(device, data) +
                 self._cs_cmd_cache['_idle'])
         self._raw_write(cmd)
-        return self._raw_read(len(data))
+        #print 'exchange %s: %s' % (device, str2hex(data))
+        r = self._raw_read(len(data))
+        #print ' ', str2hex(r)
+        return r
 
 
 
@@ -1429,20 +1445,24 @@ class ADS8201(object):
 
 
 class M25PExx(object):
-    def __init__(self, spibus):
+    def __init__(self, spibus, csname):
         self.bus = spibus
+        self.csname = csname
 
     def _write(self, data):
-        self.bus.SetCS('flash')
-        self.bus.Start()
-        self.bus.Write(data)
-        self.bus.Stop()
+        self.bus.write(self.csname, data)
+        #self.bus.SetCS('flash')
+        #self.bus.Start()
+        #self.bus.Write(data)
+        #self.bus.Stop()
 
     def _exchange(self, data):
-        self.bus.SetCS('flash')
-        self.bus.Start()
-        d = self.bus.Exchange(data)
-        self.bus.Stop()
+        d = self.bus.exchange(self.csname, data)
+        #self.bus.SetCS('flash')
+        #self.bus.Start()
+        #d = self.bus.Exchange(data)
+        #self.bus.Stop()
+        #print str2hex(d)
         return d
 
     def writeEnable(self, enable):
@@ -1522,11 +1542,12 @@ class M25PExx(object):
             e = min(s+256, len(data))
             a = addr + s
             while not self.isReady():
-                print hex(self.status())
+                pass
+                #print hex(self.status())
             print 'writing page: %06x %s' % (a, str2hex(data[s:e]))
             self.writeEnable(True)
             self.writePage(a, data[s:e])
-            print hex(self.status())
+            #print hex(self.status())
 
     def program(self, addr, data):
         if addr & 0xff != 0:
@@ -1551,14 +1572,14 @@ class AtoiSPI0(SPI):
                 interface=ftdi.INTERFACE_A,
                 cs={'_idle': (-1, 0xc8),
                     '_mask': (-1, 0x38), #TODO
-                    'flash': (0, 0xc0),
+                    'flash': (3, 0xc0),
                     'dac':   (1, 0xd8),
                     'adc':   (1, 0xe8),
                     'convst': (1, 0xf8)},
                 freq=int(freq),
                 vid=0x0403,
                 pid=0x6011,
-                pindir=0xc0,
+                pindir=0xc8,
                 pinstate=0xc8,
                 latency=1
                 )