semihost server example program

Dependencies:   SWD mbed USBLocalFileSystem BaseDAP USBDAP

/media/uploads/va009039/kl46z-lpc800-360x480.jpg

LPCXpresso
LPC11U68
LPCXpresso
LPC1549
FRDM-KL46ZEA LPC4088 QSB
app-board
LPC1768
app-board
LPC810LPC1114FN28
serverserverserverserverserverclientclient
SWDIOD12D12D12p25p21p4(P0_2)p12
SWCLKD10D10D10p26p22p3(P0_3)p3
nRESET
*option
D6D6D6p34p30p1(P0_5)p23
GNDGNDGNDGNDp1p1p7p22
3.3VP3V3P3V3P3V3p44p40p6p21
flash writeSW2(P0_1)SW3(P1_9)SW1p14
joystick
center
p14
joystick
center

client example:

Import programlpc810-semihost_helloworld

semihost client example program

Files at this revision

API Documentation at this revision

Comitter:
va009039
Date:
Sun Sep 08 14:13:15 2013 +0000
Parent:
2:32e9437348ad
Child:
4:5e4107edcbdb
Commit message:
add softwarereset(),flash.init()

Changed in this revision

Flash.cpp Show annotated file Show diff for this revision Revisions of this file
Flash.h Show annotated file Show diff for this revision Revisions of this file
SWD.cpp Show annotated file Show diff for this revision Revisions of this file
SWD.h Show annotated file Show diff for this revision Revisions of this file
Semihost.cpp Show annotated file Show diff for this revision Revisions of this file
Target2.cpp Show annotated file Show diff for this revision Revisions of this file
Target2.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
tests/DAP.cpp Show annotated file Show diff for this revision Revisions of this file
tests/DAP.h Show annotated file Show diff for this revision Revisions of this file
tests/test1_DAP.cpp Show annotated file Show diff for this revision Revisions of this file
tests/test_Semihost.cpp Show annotated file Show diff for this revision Revisions of this file
--- a/Flash.cpp	Thu Sep 05 09:34:12 2013 +0000
+++ b/Flash.cpp	Sun Sep 08 14:13:15 2013 +0000
@@ -1,8 +1,13 @@
-// Flash.cpp 2013/9/5
+// Flash.cpp 2013/9/6
 #include "Flash.h"
 #include "Target2.h"
 #include "mydebug.h"
 
+#define SYSMEMREMAP  0x40048000
+#define MAINCLKSEL   0x40048070
+#define MAINCLKUEN   0x40048074
+#define SYSAHBCLKDIV 0x40048078
+
 Flash::Flash(Target2* target, Serial* usbpc) :_target(target),_pc(usbpc)
 {
     _setup();
@@ -14,6 +19,29 @@
     _target->wait_status(TARGET_HALTED);
 }
 
+bool Flash::init()
+{
+    _pc->printf("Initializing.");
+    if (_target->idcode == 0x0bb11477) { // LPC1114FN28
+        _target->writeMemory(MAINCLKSEL, 0);  // Select Internal RC Oscillator
+        _target->writeMemory(MAINCLKUEN, 1);  // Update Main Clock Source
+        _target->writeMemory(MAINCLKUEN, 0);  // Toggle Update Register
+        _target->writeMemory(MAINCLKUEN, 1);
+        uint32_t data = _target->readMemory(MAINCLKUEN); // Wait until updated
+        if (!(data & 1)) {
+            _pc->printf("\nerror MAINCLKUEN=%08x\n", data);
+            return false;
+        }
+        _target->writeMemory(SYSAHBCLKDIV, 1);// Set Main Clock divider to 1
+        _target->writeMemory(SYSMEMREMAP, 2); // User Flash Mode
+    } else {
+        _pc->printf("\nerror idcode=%08x\n", _target->idcode);
+        return false;
+    }
+    _pc->printf("passed.\n");
+    return true;
+}
+
 bool Flash::write(const char* filename)
 {
     FILE* fp = fopen(filename, "rb");
@@ -25,11 +53,7 @@
     uint8_t buf[256];
     bool passed = false;
     for(int addr = 0; addr < 0x8000; addr += sizeof(buf)) {
-        if (feof(fp)) {
-            passed = true;
-            break;
-        }
-        fread(buf, sizeof(buf), 1, fp);
+        int ret = fread(buf, 1, sizeof(buf), fp);
         if (!_patch(buf, sizeof(buf), addr)) {
             break;
         }
@@ -52,6 +76,10 @@
             }
         }
         _pc->printf(".");
+        if (ret < sizeof(buf)) {
+            passed = true;
+            break;
+        }
     }
     fclose(fp);
     if (passed) {
--- a/Flash.h	Thu Sep 05 09:34:12 2013 +0000
+++ b/Flash.h	Sun Sep 08 14:13:15 2013 +0000
@@ -1,4 +1,4 @@
-// Flash.h 2013/9/5
+// Flash.h 2013/9/6
 #pragma once
 #include "Target2.h"
 
@@ -7,6 +7,7 @@
 class Flash {
 public:
     Flash(Target2* target, Serial* usbpc);
+    bool init();
     bool write(const char* filename);
     bool eraseAll();
     bool verify(const char* filename);
--- a/SWD.cpp	Thu Sep 05 09:34:12 2013 +0000
+++ b/SWD.cpp	Sun Sep 08 14:13:15 2013 +0000
@@ -1,5 +1,6 @@
-// SWD.cpp 2013/9/1
+// SWD.cpp 2013/9/7
 #include "SWD.h"
+#include <algorithm>
 #include "mydebug.h"
 
 SWD::SWD(PinName swdio, PinName swclk, PinName reset)
@@ -8,8 +9,10 @@
     conf.turnaround = 1;
     conf.data_phase = 0;
     idle_cycles = 0;
+    retry_count = 100;
     
     _cpu_delay_count = 2;
+    TransferAbort = false;
 }
 
 void SWD::Setup()
@@ -23,10 +26,8 @@
 
 void SWD::reset()
 {
-    _nreset.output();
-    _nreset = 0;
-    wait_ms(50);
-    _nreset.input();
+    SWJPins(0x00, 0x80);
+    SWJPins(0x80, 0x80);
 }
 
 void SWD::JTAG2SWD()
@@ -48,6 +49,76 @@
     }
 }
 
+uint8_t SWD::SWJPins(uint32_t value, uint32_t select ,int waittime_us)
+{
+    if (select & 0x01) { // swclk
+        _swclk = (value & 0x01) ? 1 : 0; 
+    }
+    if (select & 0x02) { // swdio
+        _swdio = (value & 0x02) ? 1 : 0;
+    }
+    if (select & 0x80) { // nReset
+        if (value & 0x80) {
+            _nreset.input();
+        } else {    
+            _nreset.output();
+            _nreset = 0;
+        }
+    }
+    if (waittime_us) {
+        waittime_us = std::min(waittime_us, 3000000);
+        Timer t;
+        t.reset();
+        t.start();
+        while(t.read_us() < waittime_us) {
+            if (select & 0x01) { // swclk
+                if (_swclk ^ ((value & 0x01) ? 1 : 0)) {
+                    continue;
+                } 
+            }
+            if (select & 0x02) { // swdio
+                if (_swdio ^ ((value & 0x02) ? 1 : 0)) {
+                    continue;
+                }
+            }
+            if (select & 0x80) { // nReset
+                if (_nreset ^ ((value & 0x80) ? 1 : 0)) {
+                    continue;
+                }
+            }
+            break;
+        }
+    }
+    return (_swclk ? 0x01 : 0x00) | (_swdio ? 0x02 : 0x00) | (_nreset ? 0x80 : 0x00);
+}
+
+void SWD::SWJClock(uint32_t clock)
+{
+}
+
+void SWD::TransferConfigure(int _idle_cycles, int _retry_count)
+{
+    idle_cycles = _idle_cycles;
+    retry_count = _retry_count; 
+}
+
+void SWD::Configure(int turnaround, int data_phase)
+{
+    conf.turnaround = turnaround;
+    conf.data_phase = data_phase;
+}
+
+uint8_t SWD::Transfer(uint8_t request, uint32_t *data)
+{
+    for(int retry = retry_count; retry >= 0; retry--) {
+        uint8_t ack = rawTransfer(request, data);
+        if (ack != SWD_WAIT || TransferAbort) {
+            return ack;
+        }
+    }
+    return SWD_WAIT;
+}
+
 #pragma Otime
 
 static uint32_t calc_parity(uint32_t data, int n)
@@ -59,7 +130,7 @@
     return parity & 1;
 }
 
-uint8_t SWD::Transfer(uint8_t request, uint32_t *data)
+uint8_t SWD::rawTransfer(uint8_t request, uint32_t *data)
 {
     write_bit(1);          // start bit
     write_bit(request, 4); // APnDP,RnW,A2,A3
--- a/SWD.h	Thu Sep 05 09:34:12 2013 +0000
+++ b/SWD.h	Sun Sep 08 14:13:15 2013 +0000
@@ -1,4 +1,4 @@
-// SWD.h 2013/9/1
+// SWD.h 2013/9/8
 #pragma once
 #include "mbed.h"
 
@@ -7,6 +7,7 @@
 #define SWD_FAULT  0x04
 #define SWD_ERROR  0x08
 
+#define SWD_APnDP  0x01
 #define SWD_RnW    0x02
 
 #define DP_ABORT       0<<0|0<<1|0x00
@@ -55,13 +56,16 @@
     SWD(PinName swdio, PinName swclk, PinName reset);
     void Setup();
     void SWJSequence(int count, const uint8_t* data);
-    uint8_t SWJPins(uint32_t value, uint32_t select ,uint32_t wait_us);
+    uint8_t SWJPins(uint32_t value, uint32_t select ,int waittime_us = 0);
     void SWJClock(uint32_t clock);
+    void TransferConfigure(int idle_cycles, int retry_count);
     void Configure(int turnaround, int data_phase);
     void JTAG2SWD();
     uint8_t Transfer(uint8_t request, uint32_t *data);
+    __IO bool TransferAbort;
     void reset();
 private:
+    uint8_t rawTransfer(uint8_t request, uint32_t *data);
     void pin_delay();
     void clock_cycle(int n = 1);
     void write_bit(uint32_t data, int n = 1);
@@ -72,6 +76,7 @@
         int data_phase;
     } conf;
     int idle_cycles;
+    int retry_count;
     int _cpu_delay_count;
     DigitalInOut _swdio;
     DigitalOut _swclk;
--- a/Semihost.cpp	Thu Sep 05 09:34:12 2013 +0000
+++ b/Semihost.cpp	Sun Sep 08 14:13:15 2013 +0000
@@ -1,4 +1,4 @@
-// Semihost.cpp 2013/9/5
+// Semihost.cpp 2013/9/8
 #include "Semihost.h"
 #include "mydebug.h"
 
@@ -234,7 +234,7 @@
 
 int Semihost::usr_reset(uint32_t arg) // 0x102
 {
-    _target->Reset();
+    _target->SoftwareReset();
     _target->setup();
     return 0;
 }
--- a/Target2.cpp	Thu Sep 05 09:34:12 2013 +0000
+++ b/Target2.cpp	Sun Sep 08 14:13:15 2013 +0000
@@ -1,7 +1,9 @@
-// Target2.cpp 2013/9/5
+// Target2.cpp 2013/9/8
 #include "Target2.h"
 #include "mydebug.h"
 
+#define SYSMEMREMAP  0x40048000
+
 #define CoreDebug_BASE      (0xE000EDF0UL)
 #define DHCSR (CoreDebug_BASE+0)
 #define DCRSR (CoreDebug_BASE+4) 
@@ -43,7 +45,8 @@
     if (ack != SWD_OK) {
         return false;
     }
-    TEST_ASSERT(data == 0x0bb11477);
+    idcode = data;
+    //TEST_ASSERT(data == 0x0bb11477);
 
     Abort();
 
@@ -111,9 +114,15 @@
     return true;
 }
 
-void Target2::Reset()
+void Target2::HardwareReset()
 {
-    _swd.reset();
+    _swd.SWJPins(0x00, 0x80); // nReset off
+    _swd.SWJPins(0x80, 0x80); // nReset on
+}
+
+void Target2::SoftwareReset()
+{
+    writeMemory(NVIC_AIRCR, 0x05fa0004);
 }
 
 uint32_t Target2::readMemory(uint32_t addr)
@@ -190,7 +199,6 @@
 void Target2::_setaddr(uint32_t addr)
 {
     uint32_t ctl = CSW_VALUE|CSW_SIZE32;
-    TEST_ASSERT(ctl == 0x23000052);
     uint8_t ack = _swd.Transfer(AP_CSW, &ctl);
     TEST_ASSERT(ack == SWD_OK);
 
@@ -207,7 +215,6 @@
 void Target2::_setaddr8(uint32_t addr)
 {
     uint32_t ctl = CSW_VALUE|CSW_SIZE8;
-    TEST_ASSERT(ctl == 0x23000050);
     uint8_t ack = _swd.Transfer(AP_CSW, &ctl);
     TEST_ASSERT(ack == SWD_OK);
 
--- a/Target2.h	Thu Sep 05 09:34:12 2013 +0000
+++ b/Target2.h	Sun Sep 08 14:13:15 2013 +0000
@@ -1,4 +1,4 @@
-// Target2.h 2013/9/4
+// Target2.h 2013/9/8
 #pragma once
 #include "mbed.h"
 #include "SWD.h"
@@ -45,7 +45,7 @@
     void resume();
     void step();
     void Abort();
-    void Reset();
+    void HardwareReset();
     void SoftwareReset();
     int getStatus();
     bool wait_status(int status, int timeout_ms = 500);
@@ -66,6 +66,8 @@
     CoreReg lr; 
     CoreReg pc;
     CoreReg xpsr;
+    
+    uint32_t idcode;
 private:
     void _setaddr(uint32_t addr); 
     void _setaddr8(uint32_t addr); 
--- a/main.cpp	Thu Sep 05 09:34:12 2013 +0000
+++ b/main.cpp	Sun Sep 08 14:13:15 2013 +0000
@@ -1,4 +1,4 @@
-// main.cpp 2013/9/5
+// main.cpp 2013/9/8
 #if 1
 #include "Target2.h"
 #include "Flash.h"
@@ -30,9 +30,8 @@
 }
 
 int main() {
-    //pc.baud(9600);
     pc.baud(921600);
-    pc.printf("\ndumb-terminal with flash writer using swd\n");
+    pc.printf("\ndumb-terminal with semihosting\n");
 
     const char* filename = "/local/1114FN28.LPC";
     pc.printf("%s\n", filename);
@@ -40,12 +39,12 @@
     Target2* LPC1114 = new Target2(p21,p22,p17, &pc); // SWDIO(dp12),SWCLK(dp3),nReset(dp23),Stream
     LPC1114->setup();
     Flash flash(LPC1114, &pc);
+    flash.init();
     if (flash.eraseAll()) {
         flash.write(filename);
     }
-
     target_uart.baud(9600);
-    LPC1114->Reset();
+    LPC1114->SoftwareReset();
     Terminal(LPC1114);
 }
 #endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/DAP.cpp	Sun Sep 08 14:13:15 2013 +0000
@@ -0,0 +1,340 @@
+// DAP.cpp 2013/9/7
+#include "DAP.h"
+
+#define DAP_OK                          0
+#define DAP_ERROR                       0xFF
+
+#define DAP_TRANSFER_MATCH_VALUE        (1<<4)
+#define DAP_TRANSFER_MATCH_MASK         (1<<5)
+
+// DAP Port
+#define DAP_PORT_AUTODETECT             0       // Autodetect Port
+#define DAP_PORT_DISABLED               0       // Port Disabled (I/O pins in High-Z)
+#define DAP_PORT_SWD                    1       // SWD Port (SWCLK, SWDIO) + nRESET
+
+DAP::DAP(SWD* swd) : _swd(swd)
+{
+}
+
+int DAP::Command(uint8_t* request, uint8_t* response)
+{
+    switch(*request) {
+        case 0x00: return Info(request, response);
+        case 0x01: return LED(request, response); 
+        case 0x02: return Connect(request, response); 
+        case 0x03: return Disconnect(request, response);
+        case 0x04: return TransferConfigure(request, response);
+        case 0x05: return Transfer(request, response);
+        case 0x06: return TransferBlock(request, response);
+
+        case 0x08: return WriteABORT(request, response);
+    
+        case 0x10: return SWJ_Pins(request, response);
+        case 0x11: return SWJ_Clock(request, response);
+        case 0x12: return SWJ_Sequence(request, response);
+        case 0x13: return SWD_Configure(request, response);
+ 
+    };
+    *response = 0xff; // invalid
+    return 1;    
+}
+
+int DAP::Info(uint8_t* request, uint8_t* response) // 0x00
+{
+    const char* info_str[] = {
+        NULL,     // 1 VENDOR
+        NULL,     // 2 PRODUCT
+        NULL,     // 3 SER_NUM
+        "1.0",    // 4 FW_VER
+        NULL,     // 5 DEVICE_VENDOR
+        NULL,     // 6 DEVICE_NAME
+    };
+    const char* s;
+    int slen;
+    response[0] = 0x00; // Info
+    int length = 2;
+    int id = request[1];
+    switch(id) {
+        case 1 ... 6: // VENDOR PRODUCT SER_NUM FW_VER DEVICE_VENDOR DEVICE_NAME
+            slen = 0;
+            s = info_str[id-1];
+            if (s) {     
+                slen = strlen(s) + 1;
+                memcpy(response+2, s, slen);
+            }
+            response[1] = slen;    
+            length += slen;
+            break;
+        case 0xf0:          // CAPABILITIES
+            response[1] = sizeof(uint8_t);
+            response[2] = 0x01; // SWD
+            length += sizeof(uint8_t);
+            break;
+        case 0xfe:          // PACKET_COUNT
+            response[1] = sizeof(uint8_t);
+            response[2] = 1;
+            length += sizeof(uint8_t);
+            break;
+        case 0xff:          // PACKET_SIZE
+            response[1] = sizeof(uint16_t);
+            *reinterpret_cast<uint16_t*>(response+2) = 64;
+            length += sizeof(uint16_t);
+            break;
+        default:
+            response[1] = DAP_ERROR;
+            break;
+    }
+    return length;
+}
+
+int DAP::LED(uint8_t* request, uint8_t* response) // 0x01
+{
+    response[0] = 0x01; // LED
+    response[1] = DAP_OK;
+    return 2;
+}
+   
+int DAP::Connect(uint8_t* request, uint8_t* response) // 0x02
+{
+    response[0] = 0x02; // Connect
+    response[1] = DAP_PORT_DISABLED;
+    if (request[1] == DAP_PORT_AUTODETECT || request[1] == DAP_PORT_SWD) {
+        response[1] = DAP_PORT_SWD;
+        _swd->Setup();
+    }
+    return 2;
+}
+
+int DAP::Disconnect(uint8_t* request, uint8_t* response) // 0x03
+{
+    response[0] = 0x03; // disconnect
+    response[1] = DAP_OK;
+    return 2;
+}
+
+int DAP::TransferConfigure(uint8_t* request, uint8_t* response) // 0x04
+{
+    uint8_t idle_cycles = request[1];
+    uint16_t retry_count = *reinterpret_cast<uint16_t*>(request+2);
+    transfer.match_retry = *reinterpret_cast<uint16_t*>(request+4);
+    _swd->TransferConfigure(idle_cycles, retry_count);
+    response[0] = 0x04; //tansfer configure
+    response[1] = DAP_OK;
+    return 2;
+}
+
+int DAP::Transfer(uint8_t* request, uint8_t* response) // 0x05
+{
+    bool post_read = false;
+    bool check_write = false;
+    uint8_t swd_request;
+    uint8_t ack = 0;
+    int reqpos = 2;
+    int respos = 3;
+    int response_count = 0;
+    for(int request_count = request[reqpos++]; request_count > 0; request_count--, response_count++) {
+        swd_request = request[reqpos++];
+        if (swd_request & SWD_RnW) { // read register
+            if (post_read) {
+                if ((swd_request & SWD_APnDP) && !(swd_request & DAP_TRANSFER_MATCH_VALUE)) {
+                    ack = _swd->Transfer(swd_request, reinterpret_cast<uint32_t*>(response+respos));
+                } else {
+                    ack = _swd->Transfer(DP_RDBUFF, reinterpret_cast<uint32_t*>(response+respos));
+                    post_read = false;
+                }
+                if (ack != SWD_OK) {
+                    break;
+                }
+                respos += sizeof(uint32_t);
+            }
+            if (swd_request & DAP_TRANSFER_MATCH_VALUE) {
+                uint32_t match_value = *reinterpret_cast<uint32_t*>(request+reqpos);
+                reqpos += sizeof(uint32_t);
+                if (swd_request & SWD_APnDP) {
+                    ack = _swd->Transfer(swd_request, NULL);
+                    if (ack != SWD_OK) {
+                        break;
+                    }
+                }
+                bool match = false;
+                for(int retry = transfer.match_retry; retry >= 0 && !match; retry--) {
+                    uint32_t data;
+                    ack = _swd->Transfer(swd_request, &data);
+                    if (ack == SWD_OK && (data&transfer.match_mask) == match_value) {
+                        match = true;
+                    }
+                }
+                if (!match) {
+                    break;
+                }
+            } else {
+                if (swd_request & SWD_APnDP) {
+                    if (post_read) {
+                        ack = _swd->Transfer(swd_request, NULL);
+                        if (ack != SWD_OK) {
+                            break;
+                        }
+                        post_read = true;
+                    }
+                } else {
+                    ack = _swd->Transfer(swd_request, reinterpret_cast<uint32_t*>(response+respos));
+                    if (ack != SWD_OK) {
+                        break;
+                    }
+                    respos += sizeof(uint32_t);
+                }    
+            }
+            check_write = false;    
+        } else { // write register
+            if (post_read) { // read previous data
+                ack = _swd->Transfer(DP_RDBUFF, reinterpret_cast<uint32_t*>(response+respos));
+                if (ack != SWD_OK) {
+                    break;
+                }
+                respos += sizeof(uint32_t);
+                post_read = false;
+            }    
+            uint32_t data = *reinterpret_cast<uint32_t*>(request+reqpos);
+            reqpos += sizeof(uint32_t);
+            if (swd_request & DAP_TRANSFER_MATCH_MASK) {
+                transfer.match_mask = data;
+                ack = SWD_OK;
+            } else {
+                ack = _swd->Transfer(swd_request, &data);
+                if (ack != SWD_OK) {
+                    break;
+                }
+                check_write = true;
+            }     
+        }
+    }
+    if (ack == SWD_OK) {
+        if (post_read) { // read previous data
+            ack = _swd->Transfer(DP_RDBUFF, reinterpret_cast<uint32_t*>(response+respos));
+            if (ack == SWD_OK) {
+                respos += sizeof(uint32_t);
+            }
+        } else if (check_write) { // check last write
+            ack = _swd->Transfer(DP_RDBUFF, NULL);
+        }
+    }
+    response[0] = 0x05; // transfer
+    response[1] = response_count;
+    response[2] = ack;
+    return respos;
+}
+
+int DAP::TransferBlock(uint8_t* request, uint8_t* response) // 0x06
+{
+    uint8_t swd_request;
+    uint8_t ack = 0;
+    int reqpos = 2;
+    int respos = 4;
+    int response_count = 0;
+    int request_count = *reinterpret_cast<uint16_t*>(request+reqpos);
+    reqpos += sizeof(uint16_t);
+    if (request_count == 0) {
+        goto end;
+    }
+    swd_request = request[reqpos++];
+    if (swd_request & SWD_RnW) { // read register block
+        if (swd_request & SWD_APnDP) { // post AP read
+            ack = _swd->Transfer(swd_request, NULL);
+            if (ack != SWD_OK) {
+                goto end;
+            }
+        }
+        while(request_count--) { // read DP/AP register
+            if (request_count == 0 && (swd_request & SWD_APnDP)) { // last AP read
+                swd_request = DP_RDBUFF;
+            }
+            ack = _swd->Transfer(swd_request, reinterpret_cast<uint32_t*>(response+respos));
+            if (ack != SWD_OK) {
+                goto end;
+            }
+            respos += sizeof(uint32_t);
+            response_count++;
+        }
+    } else { // write register block
+        while(request_count--) {
+            ack = _swd->Transfer(swd_request, reinterpret_cast<uint32_t*>(request+reqpos));
+            if (ack != SWD_OK) {
+                goto end;
+            }
+            response_count++;
+        }
+        ack = _swd->Transfer(DP_RDBUFF, NULL);
+    }
+end:
+    response[0] = 0x06; // transfer block
+    *reinterpret_cast<uint16_t*>(response+1) = response_count;
+    response[3] = ack;    
+    return respos; 
+}
+
+int DAP::WriteABORT(uint8_t* request, uint8_t* response) // 0x08
+{
+    uint32_t data = *reinterpret_cast<uint32_t*>(request+2);
+    uint8_t ack = _swd->Transfer(DP_ABORT, &data);
+    response[0] = 0x08; // write abort
+    response[1] = ack == SWD_OK ? DAP_OK : DAP_ERROR;
+    return 2;
+}
+
+int DAP::Delay(uint8_t* request, uint8_t* response) // 0x09
+{
+    int waittime_ms = *reinterpret_cast<uint16_t*>(request+1);
+    wait_ms(waittime_ms);
+    response[0] = 0x09;
+    response[1] = DAP_OK;
+    return 2;
+}
+
+int DAP::ResetTarget(uint8_t* request, uint8_t* response) // 0x0A
+{
+    response[0] = 0x0a;
+    response[1] = 0;
+    response[2] = DAP_OK;
+    return 3;
+}
+
+int DAP::SWJ_Pins(uint8_t* request, uint8_t* response) // 0x10
+{
+    uint32_t value = request[1];
+    uint32_t select = request[2];
+    uint32_t waittime_us = *reinterpret_cast<uint32_t*>(request+3);
+    response[0] = 0x10; // swj pins
+    response[1] = _swd->SWJPins(value, select, waittime_us);
+    return 2;    
+}
+
+int DAP::SWJ_Clock(uint8_t* request, uint8_t* response) // 0x11
+{
+    uint32_t clock = *reinterpret_cast<uint32_t*>(request+1);
+    _swd->SWJClock(clock);
+    response[0] = 0x11; // swj clock
+    response[1] = DAP_OK;
+    return 2;
+}
+
+int DAP::SWJ_Sequence(uint8_t* request, uint8_t* response) // 0x12
+{
+    int count = request[1];
+    if (count == 0) {
+        count = 256;
+    }
+    _swd->SWJSequence(count, request+2);
+    response[0] = 0x12; // swj sequence
+    response[1] = DAP_OK;
+    return 2;
+}
+
+int DAP::SWD_Configure(uint8_t* request, uint8_t* response) // 0x13
+{
+    uint8_t cfg = request[1];
+    _swd->Configure((cfg&0x03)+1, cfg&0x04 ? 1: 0); 
+    response[0] = 0x13; // swd configure
+    response[1] = DAP_OK;
+    return 2;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/DAP.h	Sun Sep 08 14:13:15 2013 +0000
@@ -0,0 +1,33 @@
+// DAP.h 2013/9/7
+#pragma once
+#include "SWD.h"
+
+class DAP {
+public:
+    DAP(SWD* swd);
+    int Command(uint8_t* request, uint8_t* response);
+    
+    int Info(uint8_t* request, uint8_t* response);          // 0x00
+    int LED(uint8_t* request, uint8_t* response);           // 0x01
+    int Connect(uint8_t* request, uint8_t* response);       // 0x02
+    int Disconnect(uint8_t* request, uint8_t* response);    // 0x03
+    int TransferConfigure(uint8_t* request, uint8_t* response);// 0x04
+    int Transfer(uint8_t* request, uint8_t* response);      // 0x05
+    int TransferBlock(uint8_t* request, uint8_t* response); // 0x06
+
+    int WriteABORT(uint8_t* request, uint8_t* response);    // 0x08
+    int Delay(uint8_t* request, uint8_t* response);         // 0x09
+    int ResetTarget(uint8_t* request, uint8_t* response);   // 0x0A
+    int SWJ_Pins(uint8_t* request, uint8_t* response);      // 0x10
+    int SWJ_Clock(uint8_t* request, uint8_t* response);     // 0x11
+    int SWJ_Sequence(uint8_t* request, uint8_t* response);  // 0x12
+    int SWD_Configure(uint8_t* request, uint8_t* response); // 0x13
+
+private:
+  struct {                 // Transfer Configuration
+    uint16_t  match_retry; // Number of retries if read value does not match
+    uint32_t  match_mask;  // Match Mask
+  } transfer;
+protected:
+    SWD* _swd;
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test1_DAP.cpp	Sun Sep 08 14:13:15 2013 +0000
@@ -0,0 +1,298 @@
+// test1_DAP.cpp 2013/9/8
+#if 0
+#include "DAP.h"
+#include "mytest.h"
+#include "mydebug.h"
+
+Serial pc(USBTX, USBRX);
+
+SWD* swd;
+DAP* dap;
+uint8_t recv[64];
+
+TEST(DAP1,setup) {
+    swd = new SWD(p21,p22,p17); // SWDIO(dp12),SWCLK(dp3),nReset(dp23)
+    dap = new DAP(swd);
+}
+
+TEST(DAP1,Info_PRODUCT) {
+    const uint8_t req[] = {0x00,0x02};
+    const uint8_t res[] = {0x00,0x00};
+    int len = dap->Command((uint8_t*)req, recv);
+    ASSERT_TRUE(len == sizeof(res));
+    ASSERT_TRUE(memcmp(recv, res, len) == 0);
+}
+
+TEST(DAP1,Info_SER_NUM) {
+    const uint8_t req[] = {0x00,0x03};
+    const uint8_t res[] = {0x00,0x00};
+    int len = dap->Command((uint8_t*)req, recv);
+    ASSERT_TRUE(len == sizeof(res));
+    ASSERT_TRUE(memcmp(recv, res, len) == 0);
+}
+
+TEST(DAP1,Info_FW_VER) {
+    const uint8_t req[] = {0x00,0x04};
+    const uint8_t res[] = {0x00,0x04,0x31,0x2e,0x30,0x00};
+    int len = dap->Command((uint8_t*)req, recv);
+    ASSERT_TRUE(len == sizeof(res));
+    ASSERT_TRUE(memcmp(recv, res, len) == 0);
+}
+
+TEST(DAP1,Info_VENDOR) {
+    const uint8_t req[] = {0x00,0x01};
+    const uint8_t res[] = {0x00,0x00};
+    int len = dap->Command((uint8_t*)req, recv);
+    ASSERT_TRUE(len == sizeof(res));
+    ASSERT_TRUE(memcmp(recv, res, len) == 0);
+}
+
+TEST(DAP1,Info_PRODUCT_2) {
+    const uint8_t req[] = {0x00,0x02};
+    const uint8_t res[] = {0x00,0x00};
+    int len = dap->Command((uint8_t*)req, recv);
+    ASSERT_TRUE(len == sizeof(res));
+    ASSERT_TRUE(memcmp(recv, res, len) == 0);
+}
+
+TEST(DAP1,Info_PACKET_SIZE) {
+    const uint8_t req[] = {0x00,0xff};
+    const uint8_t res[] = {0x00,0x02,0x40,0x00};
+    int len = dap->Command((uint8_t*)req, recv);
+    ASSERT_TRUE(len == sizeof(res));
+    ASSERT_TRUE(memcmp(recv, res, len) == 0);
+}
+
+TEST(DAP1,Info_PACKET_COUNT) {
+    const uint8_t req[] = {0x00,0xfe};
+    const uint8_t res[] = {0x00,0x01,0x01};
+    int len = dap->Command((uint8_t*)req, recv);
+    ASSERT_TRUE(len == sizeof(res));
+    ASSERT_TRUE(memcmp(recv, res, len) == 0);
+}
+
+TEST(DAP1,Connect_SWD) {
+    const uint8_t req[] = {0x02,0x01};
+    const uint8_t res[] = {0x02,0x01};
+    int len = dap->Command((uint8_t*)req, recv);
+    ASSERT_TRUE(len == sizeof(res));
+    ASSERT_TRUE(memcmp(recv, res, len) == 0);
+}
+
+TEST(DAP1,SWJ_Clock_5000_Hz) {
+    const uint8_t req[] = {0x11,0x88,0x13,0x00,0x00};
+    const uint8_t res[] = {0x11,0x00};
+    int len = dap->Command((uint8_t*)req, recv);
+    ASSERT_TRUE(len == sizeof(res));
+    ASSERT_TRUE(memcmp(recv, res, len) == 0);
+}
+
+TEST(DAP1,TransferConfigure) {
+    const uint8_t req[] = {0x04,0x00,0x64,0x00,0x00,0x00};
+    const uint8_t res[] = {0x04,0x00};
+    int len = dap->Command((uint8_t*)req, recv);
+    ASSERT_TRUE(len == sizeof(res));
+    ASSERT_TRUE(memcmp(recv, res, len) == 0);
+}
+
+TEST(DAP1,SWD_Configure) {
+    const uint8_t req[] = {0x13,0x00};
+    const uint8_t res[] = {0x13,0x00};
+    int len = dap->Command((uint8_t*)req, recv);
+    ASSERT_TRUE(len == sizeof(res));
+    ASSERT_TRUE(memcmp(recv, res, len) == 0);
+}
+
+TEST(DAP1,LED_DEBUGGER_CONNECTED_ON) {
+    const uint8_t req[] = {0x01,0x00,0x01};
+    const uint8_t res[] = {0x01,0x00};
+    int len = dap->Command((uint8_t*)req, recv);
+    ASSERT_TRUE(len == sizeof(res));
+    ASSERT_TRUE(memcmp(recv, res, len) == 0);
+}
+
+TEST(DAP1,SWJ_Sequence_1_51) {
+    const uint8_t req[] = {0x12,0x33, 0xff,0xff,0xff,0xff,0xff,0xff,0xff};
+    const uint8_t res[] = {0x12,0x00};
+    int len = dap->Command((uint8_t*)req, recv);
+    ASSERT_TRUE(len == sizeof(res));
+    ASSERT_TRUE(memcmp(recv, res, len) == 0);
+}
+
+TEST(DAP1,SWJ_Sequence_2_16) {
+    const uint8_t req[] = {0x12,0x10, 0x9e,0xe7};
+    const uint8_t res[] = {0x12,0x00};
+    int len = dap->Command((uint8_t*)req, recv);
+    ASSERT_TRUE(len == sizeof(res));
+    ASSERT_TRUE(memcmp(recv, res, len) == 0);
+}
+
+TEST(DAP1,SWJ_Sequence_3_51) {
+    const uint8_t req[] = {0x12,0x33, 0xff,0xff,0xff,0xff,0xff,0xff,0xff};
+    const uint8_t res[] = {0x12,0x00};
+    int len = dap->Command((uint8_t*)req, recv);
+    ASSERT_TRUE(len == sizeof(res));
+    ASSERT_TRUE(memcmp(recv, res, len) == 0);
+}
+
+TEST(DAP1,SWJ_Sequence_4_8) {
+    const uint8_t req[] = {0x12,0x08, 0x00};
+    const uint8_t res[] = {0x12,0x00};
+    int len = dap->Command((uint8_t*)req, recv);
+    ASSERT_TRUE(len == sizeof(res));
+    ASSERT_TRUE(memcmp(recv, res, len) == 0);
+}
+
+TEST(DAP1,Transfer_DP_IDCODE) {
+    const uint8_t req[] = {0x05, 0x00, 0x01, 0x02};
+    const uint8_t res[] = {0x05, 0x01, 0x01, 0x77,0x14,0xb1,0x0b};
+    int len = dap->Command((uint8_t*)req, recv);
+    ASSERT_TRUE(len == sizeof(res));
+    ASSERT_TRUE(memcmp(recv, res, len) == 0);
+}
+
+TEST(DAP1,Transfer_DP_SELECT) {
+    const uint8_t req[] = {0x05, 0x00, 0x01, 0x08, 0x00,0x00,0x00,0x00};
+    //SWD: DP_SELECT 00000000 request=08(DP nW 8) wdata=00000000 rdata=00000000 ack=01
+    //SWD: DP_RDBUFF 10008000 request=0e(DP R c) wdata=ffffffff rdata=10008000 ack=01
+    const uint8_t res[] = {0x05, 0x01, 0x01};
+    int len = dap->Command((uint8_t*)req, recv);
+    ASSERT_TRUE(len == sizeof(res));
+    ASSERT_TRUE(memcmp(recv, res, len) == 0);
+}
+
+TEST(DAP1,Transfer_DP_CTRL_STAT_W) {
+    const uint8_t req[] = {0x05,0x00, 0x01, 0x04, 0x00,0x00,0x00,0x50};
+    //SWD: DP_CTRL_STAT W 50000000 request=04(DP nW 4) wdata=50000000 rdata=50000000 ack=01
+    //SWD: DP_RDBUFF 10008000 request=0e(DP R c) wdata=ffffffff rdata=10008000 ack=01
+    const uint8_t res[] = {0x05,0x01, 0x01};
+    int len = dap->Command((uint8_t*)req, recv);
+    ASSERT_TRUE(len == sizeof(res));
+    ASSERT_TRUE(memcmp(recv, res, len) == 0);
+}
+
+TEST(DAP1,Transfer_DP_CTRL_STAT_R) {
+    const uint8_t req[] = {0x05,0x00, 0x01, 0x06};
+    //SWD: DP_CTRL_STAT R f0000040 request=06(DP R 4) wdata=00000040 rdata=f0000040 ack=01
+    const uint8_t res[] = {0x05,0x01, 0x01, 0x40,0x00,0x00,0xf0};
+    int len = dap->Command((uint8_t*)req, recv);
+    ASSERT_TRUE(len == sizeof(res));
+    ASSERT_TRUE(memcmp(recv, res, len) == 0);
+}
+
+TEST(DAP1,WriteABORT) {
+    const uint8_t req[] = {0x08,0x00,0x1e,0x00,0x00,0x00};
+    //SWD: DP_ABORT 0000001e request=00(DP nW 0) wdata=0000001e rdata=0000001e ack=01
+    const uint8_t res[] = {0x08,0x00};
+    int len = dap->Command((uint8_t*)req, recv);
+    ASSERT_TRUE(len == sizeof(res));
+    ASSERT_TRUE(memcmp(recv, res, len) == 0);
+}
+
+TEST(DAP1,Transfer_DP_CTRL_STAT_W_2) {
+    const uint8_t req[] = {0x05,0x00, 0x01, 0x04, 0x00,0x00,0x00,0x54};
+    //SWD: DP_CTRL_STAT W 54000000 request=04(DP nW 4) wdata=54000000 rdata=54000000 ack=01
+    //SWD: DP_RDBUFF 10008000 request=0e(DP R c) wdata=ffffffff rdata=10008000 ack=01
+    const uint8_t res[] = {0x05,0x01, 0x01};
+    int len = dap->Command((uint8_t*)req, recv);
+    ASSERT_TRUE(len == sizeof(res));
+    ASSERT_TRUE(memcmp(recv, res, len) == 0);
+}
+
+TEST(DAP1,Transfer_DP_CTRL_STAT_W_3) {
+    const uint8_t req[] = {0x05,0x00, 0x01, 0x04, 0x00,0x0f,0x00,0x50};
+    //SWD: DP_CTRL_STAT W 50000f00 request=04(DP nW 4) wdata=50000f00 rdata=50000f00 ack=01
+    //SWD: DP_RDBUFF 10008000 request=0e(DP R c) wdata=ffffffff rdata=10008000 ack=01
+    const uint8_t res[] = {0x05,0x01, 0x01};
+    int len = dap->Command((uint8_t*)req, recv);
+    ASSERT_TRUE(len == sizeof(res));
+    ASSERT_TRUE(memcmp(recv, res, len) == 0);
+}
+
+TEST(DAP1,Transfer_AP_CSW) {
+    const uint8_t req[] = {0x05,0x00, 0x01, 0x01, 0x52,0x00,0x00,0x23};
+    //SWD: AP_CSW W 23000052 request=01(AP nW 0) wdata=23000052 rdata=23000052 ack=01
+    //SWD: DP_RDBUFF 10008000 request=0e(DP R c) wdata=ffffffff rdata=10008000 ack=01
+    const uint8_t res[] = {0x05,0x01, 0x01};
+    int len = dap->Command((uint8_t*)req, recv);
+    ASSERT_TRUE(len == sizeof(res));
+    ASSERT_TRUE(memcmp(recv, res, len) == 0);
+}
+
+TEST(DAP1,Transfer_AP_TAR) {
+    const uint8_t req[] = {0x05,0x00, 0x01, 0x05, 0xf0,0xff,0x0f,0xe0};
+    //SWD: AP_TAR W e00ffff0 request=05(AP nW 4) wdata=e00ffff0 rdata=e00ffff0 ack=01
+    //SWD: DP_RDBUFF 10008000 request=0e(DP R c) wdata=ffffffff rdata=10008000 ack=01
+    const uint8_t res[] = {0x05,0x01, 0x01};
+    int len = dap->Command((uint8_t*)req, recv);
+    ASSERT_TRUE(len == sizeof(res));
+    ASSERT_TRUE(memcmp(recv, res, len) == 0);
+}
+
+TEST(DAP1,TransferBlock_AP_DRW_R) {
+    const uint8_t req[] = {0x06,0x00, 0x04,0x00, 0x0f};
+    //SWD: AP_DRW R 10008000 request=0f(AP R c) wdata=ffffffff rdata=10008000 ack=01
+    //SWD: AP_DRW R 0000000d request=0f(AP R c) wdata=00000006 rdata=0000000d ack=01
+    //SWD: AP_DRW R 00000010 request=0f(AP R c) wdata=0000000d rdata=00000010 ack=01
+    //SWD: AP_DRW R 00000005 request=0f(AP R c) wdata=00000010 rdata=00000005 ack=01
+    //SWD: DP_RDBUFF 000000b1 request=0e(DP R c) wdata=00000005 rdata=000000b1 ack=01
+    const uint8_t res[] = {0x06, 0x04,0x00, 0x01, 
+        0x0d,0x00,0x00,0x00, 0x10,0x00,0x00,0x00, 0x05,0x00,0x00,0x00, 0xb1,0x00,0x00,0x00};
+    int len = dap->Command((uint8_t*)req, recv);
+    ASSERT_TRUE(len == sizeof(res));
+    ASSERT_TRUE(memcmp(recv, res, 4) == 0);
+    ASSERT_TRUE(memcmp(recv, res, len) == 0);
+}
+
+TEST(DAP1,SWJ_Pins_nRESET_OFF) {
+    const uint8_t req[] = {0x10,0x00,0x80,0x00,0x00,0x00,0x00,};
+    //DAP: SWJ_Pins wait: 0 us nRESET OFF
+    const uint8_t res[] = {0x10,0x03};
+    int len = dap->Command((uint8_t*)req, recv);
+    ASSERT_TRUE(len == sizeof(res));
+    ASSERT_TRUE(memcmp(recv, res, len) == 0);
+}
+
+TEST(DAP1,SWJ_Pins_nRESET_ON) {
+    const uint8_t req[] = {0x10,0x80,0x80,0x00,0x00,0x00,0x00,};
+    //DAP: SWJ_Pins wait: 0 us nRESET ON
+    const uint8_t res[] = {0x10,0x83};
+    int len = dap->Command((uint8_t*)req, recv);
+    ASSERT_TRUE(len == sizeof(res));
+    ASSERT_TRUE(memcmp(recv, res, len) == 0);
+}
+
+TEST(DAP1,SWJ_Pins) {
+    const uint8_t req[] = {0x10,0x00,0x00,0x00,0x00,0x00,0x00,};
+    //DAP: SWJ_Pins wait: 0 us nRESET ON
+    const uint8_t res[] = {0x10,0x83};
+    int len = dap->Command((uint8_t*)req, recv);
+    ASSERT_TRUE(len == sizeof(res));
+    ASSERT_TRUE(memcmp(recv, res, len) == 0);
+}
+
+TEST(DAP1,Disconnect) {
+    const uint8_t req[] = {0x03};
+    const uint8_t res[] = {0x03,0x00};
+    int len = dap->Command((uint8_t*)req, recv);
+    ASSERT_TRUE(len == sizeof(res));
+    ASSERT_TRUE(memcmp(recv, res, len) == 0);
+}
+
+TEST(DAP1,LED_DEBUGGER_CONNECTED_OFF) {
+    const uint8_t req[] = {0x01,0x00,0x00};
+    const uint8_t res[] = {0x01,0x00};
+    int len = dap->Command((uint8_t*)req, recv);
+    ASSERT_TRUE(len == sizeof(res));
+    ASSERT_TRUE(memcmp(recv, res, len) == 0);
+}
+
+int main() {
+    pc.baud(921600);
+    //pc.baud(9600);
+    DBG("%s", __FILE__);
+
+    RUN_ALL_TESTS();
+    exit(0);
+}
+#endif
--- a/tests/test_Semihost.cpp	Thu Sep 05 09:34:12 2013 +0000
+++ b/tests/test_Semihost.cpp	Sun Sep 08 14:13:15 2013 +0000
@@ -1,4 +1,4 @@
-// test_Semihost.cpp 2013/9/5
+// test_Semihost.cpp 2013/9/6
 #if 0
 #include "Semihost.h"
 #include "Flash.h"
@@ -49,7 +49,9 @@
 #if 1
 TEST(Flash1,flash1) {
     Flash flash(&target, &pc);
-    bool r = flash.eraseAll();
+    bool r = flash.init();
+    ASSERT_TRUE(r);
+    r = flash.eraseAll();
     ASSERT_TRUE(r);
     r = flash.write("/local/SEMIHOST.LPC");
     ASSERT_TRUE(r);
@@ -83,6 +85,3 @@
     exit(0);
 }
 #endif
-
-
-