DAP(Debug Access Port) interface

Dependents:   USBMSD_LPC_HelloWorld lpcterm2 Simple-CMSIS-DAP 11u35_usbLocalFilesystem

TransferCore.cpp

Committer:
va009039
Date:
2013-09-14
Revision:
0:76588be01e71

File content as of revision 0:76588be01e71:

// 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);
}