Skip to content

Instantly share code, notes, and snippets.

@agatti
Last active November 1, 2016 13:37
Show Gist options
  • Save agatti/a92574bf726706f77fa26b9fc4934ee2 to your computer and use it in GitHub Desktop.
Save agatti/a92574bf726706f77fa26b9fc4934ee2 to your computer and use it in GitHub Desktop.
/*
* This file is part of the Bus Pirate project
* (http://code.google.com/p/the-bus-pirate/).
*
* Written and maintained by the Bus Pirate project.
*
* To the extent possible under law, the project has
* waived all copyright and related or neighboring rights to Bus Pirate. This
* work is published from United States.
*
* For details see: http://creativecommons.org/publicdomain/zero/1.0/.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/
#include "swd.h"
//#ifdef BP_ENABLE_SWD_SUPPORT
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include "binIO.h"
#include "base.h"
#include "bitbang.h"
extern mode_configuration_t mode_configuration;
#define SWD_CLK BP_CLK
#define SWD_CLK_DIR BP_CLK_DIR
#define SWD_DATA BP_CS
#define SWD_DATA_DIR BP_CS_DIR
/* Sent LSB first, processed MSB first. */
#define SWD_OK 0b00000100
#define SWD_WAIT 0b00000010
#define SWD_FAULT 0b00000001
#define SWD_RESPONSE_OK 0
#define SWD_RESPONSE_WAIT 1
#define SWD_RESPONSE_FAULT 2
#define SWD_RESPONSE_UNKNOWN 3
#define SWD_RESPONSE_PARITY 4
typedef struct {
uint8_t start_bit : 1;
uint8_t ap_dp : 1;
uint8_t read_write : 1;
uint8_t address_bits : 2;
uint8_t parity_bit : 1;
uint8_t stop_bit : 1;
uint8_t park_bit : 1;
} swd_request_t;
#define BINARY_IO_COMMAND_EXIT 0
#define BINARY_IO_COMMAND_SEND_DATA 1
#define BINARY_IO_COMMAND_READ_DATA 2
#define SWD_READ ON
#define SWD_WRITE OFF
static void clock_byte_out(uint8_t value);
static uint8_t clock_byte_in(void);
static void clock_bit_out(bool value);
static bool clock_bit_in(void);
static void pulse_clock_line(void);
static uint8_t read_acknowledgment(void);
void binary_io_swd_version_string(void) {
bp_write_string("SWD1");
}
static const uint8_t REQUEST_PARITY_TABLE = 0b01010110;
static const uint8_t PAYLOAD_PARITY_TABLE[] = {
0b10010110, 0b01101001, 0b01101001, 0b10010110,
0b01101001, 0b10010110, 0b10010110, 0b01101001,
0b01101001, 0b10010110, 0b10010110, 0b01101001,
0b10010110, 0b01101001, 0b01101001, 0b10010110,
0b01101001, 0b10010110, 0b10010110, 0b01101001,
0b10010110, 0b01101001, 0b01101001, 0b10010110,
0b10010110, 0b01101001, 0b01101001, 0b10010110,
0b01101001, 0b10010110, 0b10010110, 0b01101001,
};
/*
* Commands:
*
* 0b00000000 Exit mode.
* 0b00010xxx Send data.
* |||
* ||+--> AP/DP bit
* ++---> Address bits
* [32 bits of data to send]
* -> 0, {1,2,3} = error
* -> 1 = success
*
* 0b00100xxx Read data.
* |||
* ||+--> AP/DP bit
* ++---> Address bits
* -> 0, {1,2,3,4} = error
* -> 1, {byte3, byte2, byte1, byte0}[MSB first] = success
*
*/
void binary_io_swd_loop(void) {
uint8_t input_byte;
uint8_t command;
/* CLK pin -> SWD CLK [ OUTPUT ] */
/* CS pin -> SWD Data [ INPUT / OUTPUT ] */
mode_configuration.high_impedance = ON;
mode_configuration.lsbEN = OFF;
SWD_CLK_DIR = OUTPUT;
SWD_CLK = LOW;
SWD_DATA_DIR = INPUT;
SWD_DATA = LOW;
binary_io_swd_version_string();
while (true) {
input_byte = UART1RX();
command = input_byte >> 4;
switch (command) {
case BINARY_IO_COMMAND_EXIT: {
return;
}
case BINARY_IO_COMMAND_SEND_DATA: {
uint8_t payload[4] = { 0 };
uint8_t index;
uint8_t acknowledgment;
uint8_t parity = 0;
swd_request_t request = { 0 };
for (index = 0; index < sizeof(payload); index++) {
payload[index] = UART1RX();
}
request.start_bit = ON;
request.ap_dp = (input_byte & 0b00000001) ? ON : OFF;
request.address_bits = ((input_byte & 0b00000110) >> 1) & 0b00000011;
request.read_write = SWD_WRITE;
request.parity_bit = ((REQUEST_PARITY_TABLE &
(1 << (input_byte & 0b00000111))) >>
(input_byte & 0b00000111)) & 0b00000001 ? ON : OFF;
request.stop_bit = OFF;
request.park_bit = ON;
clock_byte_out(*((uint8_t *)&request));
pulse_clock_line();
acknowledgment = read_acknowledgment();
if (acknowledgment != SWD_OK) {
UART1TX(BP_BINARY_IO_RESULT_FAILURE);
switch (acknowledgment) {
case SWD_OK:
break;
case SWD_WAIT:
UART1TX(SWD_RESPONSE_WAIT);
break;
case SWD_FAULT:
UART1TX(SWD_RESPONSE_FAULT);
break;
default:
UART1TX(SWD_RESPONSE_UNKNOWN);
break;
}
break;
}
pulse_clock_line();
for (index = 0; index < 4; index++) {
parity += ((payload[index] >> 5) &
(1 << (payload[index] & 0b00000111))) != 0 ? 1 : 0;
}
for (index = 0; index < 4; index++) {
clock_byte_out(payload[index]);
}
clock_bit_out(parity & 0b00000001);
pulse_clock_line();
UART1TX(BP_BINARY_IO_RESULT_SUCCESS);
break;
}
case BINARY_IO_COMMAND_READ_DATA: {
uint8_t payload[4] = { 0 };
uint8_t index;
uint8_t acknowledgment;
uint8_t parity = 0;
bool read_parity;
swd_request_t request = { 0 };
request.start_bit = ON;
request.ap_dp = (input_byte & 0b00000001) ? ON : OFF;
request.address_bits = ((input_byte & 0b00000110) >> 1) & 0b00000011;
request.read_write = SWD_READ;
request.parity_bit = ((REQUEST_PARITY_TABLE &
(1 << (input_byte & 0b00000111))) >>
(input_byte & 0b00000111)) & 0b00000001 ? ON : OFF;
request.stop_bit = OFF;
request.park_bit = ON;
clock_byte_out(*((uint8_t *)&request));
pulse_clock_line();
acknowledgment = read_acknowledgment();
if (acknowledgment != SWD_OK) {
UART1TX(BP_BINARY_IO_RESULT_FAILURE);
switch (acknowledgment) {
case SWD_OK:
break;
case SWD_WAIT:
UART1TX(SWD_RESPONSE_WAIT);
break;
case SWD_FAULT:
UART1TX(SWD_RESPONSE_FAULT);
break;
default:
UART1TX(SWD_RESPONSE_UNKNOWN);
break;
}
break;
}
for (index = 0; index < 4; index++) {
payload[index] = clock_byte_in();
parity += ((payload[index] >> 5) &
(1 << (payload[index] & 0b00000111))) != 0 ? 1 : 0;
}
read_parity = clock_bit_in();
if (read_parity != (parity & 0b00000001)) {
UART1TX(BP_BINARY_IO_RESULT_FAILURE);
UART1TX(SWD_RESPONSE_PARITY);
break;
}
pulse_clock_line();
UART1TX(BP_BINARY_IO_RESULT_SUCCESS);
for (index = 0; index < 4; index++) {
UART1TX(payload[index]);
}
break;
}
default:
UART1TX(BP_BINARY_IO_RESULT_FAILURE);
break;
}
}
}
void clock_byte_out(uint8_t value) {
uint8_t mask = 0b10000000;
SWD_DATA_DIR = OUTPUT;
while (mask != 0) {
SWD_DATA = ((value & mask) == mask) ? HIGH : LOW;
pulse_clock_line();
mask >>= 1;
}
SWD_DATA_DIR = INPUT;
}
uint8_t clock_byte_in(void) {
uint8_t value = 0;
uint8_t index;
SWD_DATA_DIR = INPUT;
for (index = 0; index < 8; index++) {
value |= (SWD_DATA == HIGH) ? 1 : 0;
pulse_clock_line();
value <<= 1;
}
return value;
}
void clock_bit_out(bool value) {
SWD_DATA_DIR = OUTPUT;
SWD_DATA = value;
pulse_clock_line();
SWD_DATA_DIR = INPUT;
}
bool clock_bit_in(void) {
bool result;
SWD_DATA_DIR = INPUT;
result = SWD_DATA;
pulse_clock_line();
return result;
}
void pulse_clock_line(void) {
SWD_CLK = HIGH;
SWD_CLK = LOW;
}
uint8_t read_acknowledgment(void) {
uint8_t buffer;
SWD_DATA_DIR = INPUT;
buffer = SWD_DATA;
pulse_clock_line();
buffer = (buffer << 1) | SWD_DATA;
pulse_clock_line();
buffer = (buffer << 1) | SWD_DATA;
pulse_clock_line();
return buffer;
}
//#endif /* BP_ENABLE_SWD_SUPPORT */
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment