DAP(Debug Access Port) interface

Dependents:   USBMSD_LPC_HelloWorld lpcterm2 Simple-CMSIS-DAP 11u35_usbLocalFilesystem

Files at this revision

API Documentation at this revision

Comitter:
va009039
Date:
Sat Sep 14 11:21:12 2013 +0000
Commit message:
first commit

Changed in this revision

BaseDAP.cpp Show annotated file Show diff for this revision Revisions of this file
BaseDAP.h Show annotated file Show diff for this revision Revisions of this file
TransferCore.cpp Show annotated file Show diff for this revision Revisions of this file
TransferCore.h Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/BaseDAP.cpp	Sat Sep 14 11:21:12 2013 +0000
@@ -0,0 +1,233 @@
+// BaseDAP.cpp 2013/9/14
+#include "BaseDAP.h"
+
+BaseDAP::BaseDAP(SWD* swd) : _swd(swd)
+{
+}
+
+BaseDAP::~BaseDAP()
+{
+}
+
+int BaseDAP::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);
+        
+        case 0x80 ... 0x9f: return Vendor(request, response);
+    };
+    return Invalid(request, response);
+}
+
+/* virtual */ const char* BaseDAP::getInfo(int id)
+{
+    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
+    };
+    if (id >= 1 && id <= 6) {
+        return info_str[id-1];
+    }
+    return NULL;
+}
+
+/* virtual */ int BaseDAP::Info(uint8_t* request, uint8_t* response) // 0x00
+{
+    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 = getInfo(id);
+            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);
+            ST<uint16_t>(response+2, 64);
+            length += sizeof(uint16_t);
+            break;
+        default:
+            response[1] = DAP_ERROR;
+            break;
+    }
+    return length;
+}
+
+/* virtual */ void BaseDAP::infoLED(int select, int value)
+{
+}
+
+int BaseDAP::LED(uint8_t* request, uint8_t* response) // 0x01
+{
+    infoLED(request[1], request[2]&1);
+    response[0] = 0x01; // LED
+    response[1] = DAP_OK;
+    return 2;
+}
+   
+int BaseDAP::Connect(uint8_t* request, uint8_t* response) // 0x02
+{
+    response[0] = 0x02; // Connect
+    response[1] = DAP_PORT_DISABLED;
+    if (_swd) {
+        if (request[1] == DAP_PORT_AUTODETECT || request[1] == DAP_PORT_SWD) {
+            response[1] = DAP_PORT_SWD;
+            _swd->Setup();
+        }
+    }
+    return 2;
+}
+
+int BaseDAP::Disconnect(uint8_t* request, uint8_t* response) // 0x03
+{
+    response[0] = 0x03; // disconnect
+    response[1] = DAP_OK;
+    return 2;
+}
+
+int BaseDAP::TransferConfigure(uint8_t* request, uint8_t* response) // 0x04
+{
+    uint8_t idle_cycles = request[1];
+    uint16_t retry_count = LD<uint16_t>(request+2);
+    transfer.match_retry = LD<uint16_t>(request+4);
+    _swd->TransferConfigure(idle_cycles, retry_count);
+    response[0] = 0x04; //tansfer configure
+    response[1] = DAP_OK;
+    return 2;
+}
+
+int BaseDAP::Transfer(uint8_t* request, uint8_t* response) // 0x05
+{
+    return transfer.Transfer(_swd, request, response);
+}
+
+int BaseDAP::TransferBlock(uint8_t* request, uint8_t* response) // 0x06
+{
+    return transfer.TransferBlock(_swd, request, response);
+}
+
+int BaseDAP::WriteABORT(uint8_t* request, uint8_t* response) // 0x08
+{
+    uint32_t data = LD<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 BaseDAP::Delay(uint8_t* request, uint8_t* response) // 0x09
+{
+    int waittime_ms = LD<uint16_t>(request+1);
+    wait_ms(waittime_ms);
+    response[0] = 0x09;
+    response[1] = DAP_OK;
+    return 2;
+}
+
+int BaseDAP::ResetTarget(uint8_t* request, uint8_t* response) // 0x0A
+{
+    response[0] = 0x0a;
+    response[1] = 0;
+    response[2] = DAP_OK;
+    return 3;
+}
+
+int BaseDAP::SWJ_Pins(uint8_t* request, uint8_t* response) // 0x10
+{
+    uint32_t value = request[1];
+    uint32_t select = request[2];
+    uint32_t waittime_us = LD<uint32_t>(request+3);
+    response[0] = 0x10; // swj pins
+    response[1] = _swd->SWJPins(value, select, waittime_us);
+    return 2;    
+}
+
+int BaseDAP::SWJ_Clock(uint8_t* request, uint8_t* response) // 0x11
+{
+    uint32_t clock = LD<uint32_t>(request+1);
+    _swd->SWJClock(clock);
+    response[0] = 0x11; // swj clock
+    response[1] = DAP_OK;
+    return 2;
+}
+
+int BaseDAP::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 BaseDAP::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;
+}
+
+/* virtual */ int BaseDAP::Vendor(uint8_t* request, uint8_t* response) // 0x80 ... 0x9f
+{
+    switch(request[0]) {
+        case 0x80: return Vendor0(request, response);
+    }
+    response[0] = 0xff; // invalid
+    return 1;    
+}
+
+int BaseDAP::Vendor0(uint8_t* request, uint8_t* response) // 0x80
+{
+    const char* board_id = "1040123456789"; // lpc11u24
+    int len = strlen(board_id);
+    response[0] = 0x80;
+    response[1] = len;
+    memcpy(response+2, board_id, len);  
+    return len + 1;
+}
+
+/* virtual */ int BaseDAP::Invalid(uint8_t* request, uint8_t* response)
+{
+    response[0] = 0xff; // invalid
+    return 1;    
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/BaseDAP.h	Sat Sep 14 11:21:12 2013 +0000
@@ -0,0 +1,98 @@
+// BaseDAP.h 2013/9/14
+#pragma once
+#include "SWD.h"
+#include "TransferCore.h"
+
+// DAP Status Code
+#define DAP_OK                          0
+#define DAP_ERROR                       0xFF
+
+// 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(Debug Access Port) interface
+ * 
+ * Example:
+ * @code
+ * #include "BaseDAP.h"
+ * #include "USBDAP.h"
+ * 
+ * USBDAP hid(64, 64, 0x0d28, 0x0204);
+ * 
+ * SWD swd(p21,p22,p17); // SWDIO(dp12),SWCLK(dp3),nReset(dp23)
+ * DigitalOut connected(LED1);
+ * DigitalOut running(LED2);
+ * class myDAP : public BaseDAP {
+ * public:
+ *     myDAP(SWD* swd):BaseDAP(swd){};
+ *     virtual void infoLED(int select, int value) {
+ *         switch(select) {
+ *             case 0: connected = value; break;
+ *             case 1: running = value; break;
+ *         }
+ *     } 
+ * };
+ * 
+ * int main()
+ * {
+ *     HID_REPORT recv_report;
+ *     HID_REPORT send_report;
+ * 
+ *     myDAP* dap = new myDAP(&swd);
+ *     while(1) {
+ *         if(hid.readNB(&recv_report)) {
+ *             dap->Command(recv_report.data, send_report.data);
+ *             send_report.length = 64;
+ *             hid.send(&send_report);
+ *         }
+ *     }    
+ * }
+ * @endcode
+ */
+class BaseDAP {
+public:
+    /** Create a DAP(Debug Access Port) interface
+     * @param swd assign SWD interface
+     */
+    BaseDAP(SWD* swd);
+    virtual ~BaseDAP();
+    /** Process command
+     * @param request request data(64 bytes)
+     * @param response response data(64 bytes)
+     * @returns response length 
+     */
+    int Command(uint8_t* request, uint8_t* response);
+protected:
+    virtual const char* getInfo(int id);
+    /** LED indicator
+     * @param selct 0...connected LED, 1...running LED
+     * @param value 0...OFF, 1...ON
+     */
+    virtual void infoLED(int select, int value);
+
+    virtual 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
+    int Vendor0(uint8_t* request, uint8_t* response);       // 0x80
+    /** vendor command
+     */
+    virtual int Vendor(uint8_t* request, uint8_t* response);// 0x80-0x9f
+    virtual int Invalid(uint8_t* request, uint8_t* response);
+
+    TransferCore transfer;
+    SWD* _swd;
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/TransferCore.cpp	Sat Sep 14 11:21:12 2013 +0000
@@ -0,0 +1,184 @@
+// TransferCore.cpp 2013/9/14
+#include "TransferCore.h"
+
+void transData::init(uint8_t* base, int pos)
+{
+    _base = base;
+    _pos = pos;
+}
+
+void transData::append(uint32_t data)
+{
+    ST<uint32_t>(_base+_pos, data);
+    _pos += sizeof(uint32_t);
+}
+
+uint8_t* transData::data()
+{
+    return _base;
+}
+
+int transData::length()
+{
+    return _pos;
+}
+
+int TransferCore::Transfer(SWD* swd, uint8_t* request, uint8_t* response) // 0x05
+{
+    _swd = swd;
+    reqData.init(request, 2);
+    resData.init(response, 3);
+    post_read = check_write = false;
+    response_count = 0;
+    uint8_t ack = 0;
+    for(int count = reqData.get<uint8_t>(); count > 0; count--) {
+        uint8_t cmd = reqData.get<uint8_t>();
+        if (cmd & SWD_RnW) { // read register
+            ack = read(cmd);
+            check_write = false;
+        } else { // write register
+            ack = write(cmd);
+        }
+        if (ack != SWD_OK) {
+            break;
+        }
+        response_count++;
+    }
+    if (ack == SWD_OK) {
+        if (post_read) { // read previous data
+            uint32_t data;
+            ack = _swd->Transfer(DP_RDBUFF, &data);
+            resData.append(data);
+        } else if (check_write) { // check last write
+            ack = _swd->Transfer(DP_RDBUFF, NULL);
+        }
+    }
+    resData.data()[0] = 0x05; // transfer
+    resData.data()[1] = response_count;
+    resData.data()[2] = ack;
+    return resData.length();
+}
+
+uint8_t TransferCore::read(uint8_t cmd)
+{
+    uint8_t ack = 0;
+    uint32_t data;
+    if (post_read) {
+        if ((cmd & SWD_APnDP) && !(cmd & DAP_TRANSFER_MATCH_VALUE)) {
+            ack = _swd->Transfer(cmd, &data); // next post_read
+        } else {
+            ack = _swd->Transfer(DP_RDBUFF, &data);
+            post_read = false;
+        }
+        if (ack != SWD_OK) {
+            return ack;
+        }
+        resData.append(data);
+    }
+    if (cmd & DAP_TRANSFER_MATCH_VALUE) {
+        uint32_t match_value = reqData.get<uint32_t>();
+        if (cmd & SWD_APnDP) {
+            ack = _swd->Transfer(cmd, NULL);
+            if (ack != SWD_OK) {
+                return ack;
+            }
+        }
+        for(int retry = match_retry; retry >= 0; retry--) {
+            ack = _swd->Transfer(cmd, &data);
+            if (ack == SWD_OK && (data&match_mask) == match_value) {
+                return ack;
+            }
+        }
+        return ack | DAP_TRANSFER_MISMATCH; 
+    } else {
+        if (cmd & SWD_APnDP) {
+            if (post_read == false) {
+                ack = _swd->Transfer(cmd, NULL);
+                post_read = true;
+            }
+        } else {
+            ack = _swd->Transfer(cmd, &data);
+            resData.append(data);
+        }    
+    }
+    return ack;
+}
+
+uint8_t TransferCore::write(uint8_t cmd)
+{
+    if (post_read) { // read previous data
+        uint32_t data;
+        uint8_t ack = _swd->Transfer(DP_RDBUFF, &data);
+        if (ack != SWD_OK) {
+            return ack;
+        }
+        resData.append(data);
+        post_read = false;
+    }    
+    if (cmd & DAP_TRANSFER_MATCH_MASK) {
+        match_mask = reqData.get<uint32_t>();
+        return SWD_OK;
+    }
+    check_write = true;
+    uint32_t data = reqData.get<uint32_t>();
+    return _swd->Transfer(cmd, &data);
+}
+
+int TransferCore::TransferBlock(SWD* swd, uint8_t* request, uint8_t* response)
+{
+    _swd = swd;
+    reqData.init(request, 2);
+    resData.init(response, 4);
+    uint8_t ack = 0;
+    response_count = 0;
+    int count = reqData.get<uint16_t>();
+    if (count > 0) {
+        uint8_t cmd = reqData.get<uint8_t>();
+        if (cmd & SWD_RnW) { // read register block
+            ack = read_block(cmd, count);
+        } else { // write register block
+            ack = write_block(cmd, count);
+        }
+    }
+    resData.data()[0] = 0x06; // transfer block
+    ST<uint16_t>(resData.data()+1, response_count);
+    resData.data()[3] = ack;    
+    return resData.length(); 
+}
+
+uint8_t TransferCore::read_block(uint8_t cmd, int count)
+{
+    if (cmd & SWD_APnDP) { // post AP read
+        uint8_t ack = _swd->Transfer(cmd, NULL);
+        if (ack != SWD_OK) {
+            return ack;
+        }
+    }
+    uint8_t ack = 0;
+    while(count-- > 0) { // read DP/AP register
+        if (count == 0 && (cmd & SWD_APnDP)) { // last AP read
+            cmd = DP_RDBUFF;
+        }
+        uint32_t data;
+        ack = _swd->Transfer(cmd, &data);
+        if (ack != SWD_OK) {
+            break;
+        }
+        resData.append(data);
+        response_count++;
+    }
+    return ack;
+}
+
+uint8_t TransferCore::write_block(uint8_t cmd, int count)
+{
+    while(count-- > 0) {
+        uint32_t data = reqData.get<uint32_t>();
+        uint8_t ack = _swd->Transfer(cmd, &data);
+        if (ack != SWD_OK) {
+            return ack;
+        }
+        response_count++;
+    }
+    return _swd->Transfer(DP_RDBUFF, NULL);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/TransferCore.h	Sat Sep 14 11:21:12 2013 +0000
@@ -0,0 +1,66 @@
+// TransferCore.h 2013/9/14
+#pragma once
+#include "SWD.h"
+
+// DAP Transfer Request
+#define DAP_TRANSFER_MATCH_VALUE        (1<<4)
+#define DAP_TRANSFER_MATCH_MASK         (1<<5)
+
+// DAP Transfer Response
+#define DAP_TRANSFER_MISMATCH           (1<<4)
+
+template<typename T>
+T LD(uint8_t* buf) {
+    T data = 0;
+    for(int i = sizeof(T)-1; i >= 0; i--) {
+        data <<= 8;
+        data |= buf[i];
+    }
+    return data;
+}
+
+template<typename T>
+void ST(uint8_t* buf, T data) {
+    for(int i = 0; i < sizeof(T); i++) {
+        buf[i] = data>>(8*i);
+    }
+}
+
+class transData {
+public:
+    void init(uint8_t* base, int pos);
+    void append(uint32_t data);
+    uint8_t* data();
+    int length();
+
+    template<typename T>
+    T get() {
+        T data = LD<T>(_base+_pos);
+        _pos += sizeof(T);
+        return data;
+    }
+protected:
+    uint8_t* _base;
+    int _pos;
+};
+
+class TransferCore {
+public:
+    int Transfer(SWD* swd, uint8_t* request, uint8_t* response);
+    int TransferBlock(SWD* swd, uint8_t* request, uint8_t* response);
+    uint16_t  match_retry; // Number of retries if read value does not match
+    uint32_t  match_mask;  // Match Mask
+private:
+    uint8_t read(uint8_t cmd);
+    uint8_t write(uint8_t cmd);
+    uint8_t read_block(uint8_t cmd, int count);
+    uint8_t write_block(uint8_t cmd, int count);
+
+    bool post_read;
+    bool check_write;
+    transData reqData;  
+    transData resData;
+    int response_count;
+protected:
+    SWD* _swd;
+};