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

SWD.cpp

Committer:
va009039
Date:
2013-09-08
Revision:
3:d7a7cde0bfb8
Parent:
0:27d35fa263b5
Child:
4:5e4107edcbdb

File content as of revision 3:d7a7cde0bfb8:

// SWD.cpp 2013/9/7
#include "SWD.h"
#include <algorithm>
#include "mydebug.h"

SWD::SWD(PinName swdio, PinName swclk, PinName reset)
    : _swdio(swdio), _swclk(swclk), _nreset(reset)
{
    conf.turnaround = 1;
    conf.data_phase = 0;
    idle_cycles = 0;
    retry_count = 100;
    
    _cpu_delay_count = 2;
    TransferAbort = false;
}

void SWD::Setup()
{
    _swclk = 1;
    _swdio.output();
    _swdio = 1;
    _nreset.input();
    _nreset.mode(PullUp);
}

void SWD::reset()
{
    SWJPins(0x00, 0x80);
    SWJPins(0x80, 0x80);
}

void SWD::JTAG2SWD()
{
    const uint8_t data1[] = {0xff,0xff,0xff,0xff,0xff,0xff,0xff};
    const uint8_t data2[] = {0x9e,0xe7};
    const uint8_t data3[] = {0x00};
    SWJSequence(sizeof(data1)*8, data1);
    SWJSequence(sizeof(data2)*8, data2);
    SWJSequence(sizeof(data1)*8, data1);
    SWJSequence(sizeof(data3)*8, data3);
}

void SWD::SWJSequence(int count, const uint8_t* data)
{
    for(int n = 0; n < count; n++) {
        uint8_t val = data[n/8];
        write_bit(val>>(n%8));
    }
}

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)
{
    uint32_t parity = 0;
    for(int i = 0; i < n; i++) {
        parity += data>>i;
    }
    return parity & 1;
}

uint8_t SWD::rawTransfer(uint8_t request, uint32_t *data)
{
    write_bit(1);          // start bit
    write_bit(request, 4); // APnDP,RnW,A2,A3
    write_bit(calc_parity(request, 4)); // parity bit
    write_bit(0);       // stop bit
    write_bit(1);       // park bit
    
    _swdio.input();
    clock_cycle(conf.turnaround);
    
    uint8_t ack = read_bit(3);
    if (ack == SWD_OK) {
        if (request & SWD_RnW) { // read
            uint32_t val = read_bit(32);
            uint32_t parity = read_bit(1);
            if (parity ^ calc_parity(val, 32)) {
                ack = SWD_ERROR;
            }
            if (data) {
                *data = val;
            }
            clock_cycle(conf.turnaround);
            _swdio.output();
        } else {                        // write
            clock_cycle(conf.turnaround);
            _swdio.output();
            uint32_t val = *data;
            write_bit(val, 32);
            write_bit(calc_parity(val, 32));
        }
        if (idle_cycles) {
            _swdio = 0;
            clock_cycle(idle_cycles);
        }
        _swdio = 1;
        return ack;
    }

    if (ack == SWD_WAIT || ack == SWD_FAULT) {
        if (conf.data_phase && (request & SWD_RnW)) {
            clock_cycle(32+1);
        }
        clock_cycle(conf.turnaround);
        _swdio.output();
        if (conf.data_phase && ((request & SWD_RnW) == 0)) {
            _swdio = 0;
            clock_cycle(32+1);
        }
        _swdio = 1;
        return ack;
    }
    clock_cycle(32 + 1 + conf.turnaround);
    _swdio.output();
    return ack;
}

void SWD::pin_delay()
{
    __IO int n = _cpu_delay_count;
    while(n-- > 0)
        ;
}

void SWD::clock_cycle(int n)
{
    while(n-- > 0) {
        _swclk = 0;
        pin_delay();
        _swclk = 1;
        pin_delay();
    }    
}

void SWD::write_bit(uint32_t data, int n)
{
    for(int i = 0; i < n; i++) {
        _swdio = (data>>i) & 1;
        clock_cycle();
    }
}

uint32_t SWD::read_bit(int n)
{
    uint32_t data = 0;
    for(int i = 0; i < n; i++) {
        _swclk = 0;
        pin_delay();
        uint32_t val = _swdio & 1;
        data |= val<<i;
        _swclk = 1;
        pin_delay();
    }    
    return data;
}