DAP(Debug Access Port) interface

Dependents:   USBMSD_LPC_HelloWorld lpcterm2 Simple-CMSIS-DAP 11u35_usbLocalFilesystem

Revision:
0:76588be01e71
--- /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);
+}