usart working... when debugged...

This commit is contained in:
Philippe Teuwen 2019-04-20 19:17:32 +02:00
parent 7ca1e98776
commit 6e744043f5
9 changed files with 162 additions and 118 deletions

View file

@ -1106,16 +1106,17 @@ static void PacketReceived(PacketCommandNG *packet) {
uint8_t my_rx[20];
memset(my_rx, 0, sizeof(my_rx));
res = usart_readbuffer(my_rx, sizeof(my_rx));
res = usart_readbuffer(my_rx);
WaitMS(1);
Dbprintf("GOT %d | %c%c%c%c%c%c%c%c", res, my_rx[0], my_rx[1], my_rx[2], my_rx[3], my_rx[4], my_rx[5], my_rx[6], my_rx[7]);
*/
char dest[USB_CMD_DATA_SIZE] = {'\0'};
if (usart_dataavailable()) {
char dest[USART_FIFOLEN] = {'\0'};
uint16_t available = usart_rxdata_available();
if (available > 0) {
Dbprintf("RX DATA!");
uint16_t len = usart_readbuffer((uint8_t *)dest);
uint16_t len = usart_read_ng((uint8_t *)dest, available);
dest[len] = '\0';
Dbprintf("RX: %d | %02X %02X %02X %02X %02X %02X %02X %02X ", len, dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]);
}
@ -1142,7 +1143,7 @@ static void PacketReceived(PacketCommandNG *packet) {
uint8_t my_rx[sizeof(PacketCommandOLD)];
while (!BUTTON_PRESS() && !usb_poll_validate_length()) {
LED_B_INV();
if (usart_readbuffer(my_rx) ) {
if (usart_read_ng(my_rx) ) {
//PacketReceived(my_rx, sizeof(my_rx));
PacketCommandOLD *my = (PacketCommandOLD *)my_rx;
@ -1568,7 +1569,7 @@ void __attribute__((noreturn)) AppMain(void) {
if (ret == PM3_SUCCESS) {
PacketReceived(&rx);
} else if (ret != PM3_ENODATA) {
Dbprintf("Error in frame reception");
Dbprintf("Error in frame reception: %d", ret);
// TODO DOEGOX if error, shall we resync ?
}

View file

@ -563,6 +563,21 @@ void CloseProxmark(void) {
memset(&USB_communication_thread, 0, sizeof(pthread_t));
}
// Gives a rough estimate of the communication delay based on channel & baudrate
// Max communication delay is when sending largest frame and receiving largest frame
// Empirical measures on FTDI with physical cable:
// "hw pingng 512"
// usb -> 6..32ms
// 460800 -> 40..70ms
// 9600 -> 1100..1150ms
// ~ = 12000000 / USART_BAUD_RATE
// Let's take 2x (maybe we need more for BT link?)
static size_t communication_delay(void) {
if (send_via_fpc) // needed also for Windows USB USART??
return 2 * (12000000 / uart_speed);
return 100;
}
/**
* @brief Waits for a certain response type. This method waits for a maximum of
* ms_timeout milliseconds for a specified response command.
@ -580,14 +595,18 @@ bool WaitForResponseTimeoutW(uint32_t cmd, PacketResponseNG *response, size_t ms
if (response == NULL)
response = &resp;
// Add delay depending on the communication channel & speed
ms_timeout += communication_delay();
uint64_t start_time = msclock();
// Wait until the command is received
while (true) {
while (getReply(response)) {
if (cmd == CMD_UNKNOWN || response->cmd == cmd)
if (cmd == CMD_UNKNOWN || response->cmd == cmd) {
// PrintAndLogEx(INFO, "Waited %i ms", msclock() - start_time);
return true;
}
}
if (msclock() - start_time > ms_timeout)
@ -600,6 +619,7 @@ bool WaitForResponseTimeoutW(uint32_t cmd, PacketResponseNG *response, size_t ms
show_warning = false;
}
}
// PrintAndLogEx(INFO, "Wait timeout after %i ms", msclock() - start_time);
return false;
}

View file

@ -431,7 +431,7 @@ int main(int argc, char *argv[]) {
if (speed == 0)
#ifdef WITH_FPC_HOST
// Let's assume we're talking by default to pm3 over usart in this mode
speed = AT91_BAUD_RATE;
speed = USART_BAUD_RATE;
#else
speed = 460800;
#endif

View file

@ -227,8 +227,8 @@ int16_t receive_ng(PacketCommandNG *rx) {
#ifdef WITH_FPC_HOST
// Check if there is a FPC packet available
return receive_ng_internal(rx, usart_read_ng, true);
#else
return PM3_ENODATA;
if (usart_rxdata_available() > 0)
return receive_ng_internal(rx, usart_read_ng, true);
#endif
return PM3_ENODATA;
}

View file

@ -38,119 +38,123 @@ void usart_close(void) {
}
*/
static uint8_t us_inbuf[sizeof(PacketCommandOLD)];
static uint8_t us_outbuf[sizeof(PacketResponseOLD)];
/*
// transfer from client to device
inline int16_t usart_readbuffer(uint8_t *data) {
uint32_t rcr = pUS1->US_RCR;
if (rcr < sizeof(us_inbuf)) {
pUS1->US_PTCR = AT91C_PDC_RXTDIS;
memcpy(data, us_inbuf, sizeof(us_inbuf) - rcr);
// Reset DMA buffer
pUS1->US_RPR = (uint32_t)us_inbuf;
pUS1->US_RCR = sizeof(us_inbuf);
pUS1->US_PTCR = AT91C_PDC_RXTEN;
return sizeof(us_inbuf) - rcr;
} else {
return 0;
}
}
*/
static uint8_t us_inbuf1[USART_BUFFLEN];
static uint8_t us_inbuf2[USART_BUFFLEN];
uint8_t *usart_cur_inbuf = NULL;
uint16_t usart_cur_inbuf_off = 0;
static uint8_t us_rxfifo[USART_FIFOLEN];
static size_t us_rxfifo_low = 0;
static size_t us_rxfifo_high = 0;
uint8_t check = 0;
inline int16_t usart_readbuffer(uint8_t *data) {
// Check if the first PDC bank is free
if (pUS1->US_RCR == 0) {
pUS1->US_RPR = (uint32_t)data;
pUS1->US_RCR = sizeof(PacketCommandOLD);
pUS1->US_PTCR = AT91C_PDC_RXTEN | AT91C_PDC_TXTEN;
check = 0;
return 2;
} else {
return 0;
}
}
void usart_readcheck(uint8_t *data, size_t len) {
if (pUS1->US_RCR < len) {
if (check == 0) {
StartCountUS();
check = 1;
static void usart_fill_rxfifo(void) {
if (pUS1->US_RNCR == 0) { // One buffer got filled, backup buffer being used
// TODO check if we have room...
uint16_t available = USART_BUFFLEN - usart_cur_inbuf_off;
for (uint16_t i = 0; i < available; i++) {
us_rxfifo[us_rxfifo_high++] = usart_cur_inbuf[usart_cur_inbuf_off + i];
if (us_rxfifo_high == sizeof(us_rxfifo))
us_rxfifo_high = 0;
}
//300ms
if (GetCountUS() > 300000) {
pUS1->US_RPR = (uint32_t)data;
pUS1->US_RCR = len;
check = 0;
// Give next buffer
pUS1->US_RNPR = (uint32_t)usart_cur_inbuf;
pUS1->US_RNCR = USART_BUFFLEN;
// Swap current buff
if (usart_cur_inbuf == us_inbuf1)
usart_cur_inbuf = us_inbuf2;
else
usart_cur_inbuf = us_inbuf1;
usart_cur_inbuf_off = 0;
}
if (pUS1->US_RCR < USART_BUFFLEN - usart_cur_inbuf_off) { // Current buffer partially filled
uint16_t available = USART_BUFFLEN - pUS1->US_RCR - usart_cur_inbuf_off;
// TODO check if we have room...
for (uint16_t i = 0; i < available; i++) {
us_rxfifo[us_rxfifo_high++] = usart_cur_inbuf[usart_cur_inbuf_off + i];
if (us_rxfifo_high == sizeof(us_rxfifo))
us_rxfifo_high = 0;
}
} else {
check = 0;
usart_cur_inbuf_off += available;
}
}
inline bool usart_dataavailable(void) {
return pUS1->US_RCR < sizeof(us_inbuf);
uint16_t usart_rxdata_available(void) {
usart_fill_rxfifo();
if (us_rxfifo_low <= us_rxfifo_high)
return us_rxfifo_high - us_rxfifo_low;
else
return sizeof(us_rxfifo) - us_rxfifo_low + us_rxfifo_high;
}
inline int16_t usart_readcommand(uint8_t *data) {
if (pUS1->US_RCR == 0)
return usart_readbuffer(data);
return 0;
}
extern bool reply_via_fpc;
extern void Dbprintf(const char *fmt, ...);
#define Dbprintf_usb(...) {\
bool tmp = reply_via_fpc;\
reply_via_fpc = false;\
Dbprintf(__VA_ARGS__);\
reply_via_fpc = tmp;}
uint32_t usart_read_ng(uint8_t *data, size_t len) {
// TODO DOEGOX
return 0;
if (len == 0) return 0;
uint32_t packetSize, nbBytesRcv = 0;
uint32_t try = 0;
// uint32_t highest_observed_try = 0;
// Empirical max try observed: 3000000 / USART_BAUD_RATE
// Let's take 10x
uint32_t maxtry = 10 * ( 3000000 / USART_BAUD_RATE );
while (len) {
uint32_t available = usart_rxdata_available();
packetSize = MIN(available, len);
if (available > 0) {
// Dbprintf_usb("Dbg USART ask %d bytes, available %d bytes, packetsize %d bytes", len, available, packetSize);
// highest_observed_try = MAX(highest_observed_try, try);
try = 0;
}
len -= packetSize;
while (packetSize--) {
data[nbBytesRcv++] = us_rxfifo[us_rxfifo_low++];
if (us_rxfifo_low == sizeof(us_rxfifo))
us_rxfifo_low = 0;
}
if (try++ == maxtry) {
Dbprintf_usb("Dbg USART TIMEOUT");
break;
}
}
// highest_observed_try = MAX(highest_observed_try, try);
// Dbprintf_usb("Dbg USART max observed try %i", highest_observed_try);
return nbBytesRcv;
}
inline bool usart_commandavailable(void) {
return (pUS1->US_RCR == 0);
}
/*
// transfer from device to client
inline int16_t usart_writebuffer(uint8_t *data, size_t len) {
// Wait for one free PDC bank
while (pUS1->US_TCR && pUS1->US_TNCR) {};
// ? alternative to wait for end of transmissions?
// while (!(pUS1->US_CSR & AT91C_US_ENDTX)) {};
if (pUS1->US_CSR & AT91C_US_ENDTX) {
memcpy(us_outbuf, data, len);
pUS1->US_TPR = (uint32_t)us_outbuf;
// Check if the current PDC bank is free
if (pUS1->US_TCR == 0) {
pUS1->US_TPR = (uint32_t)data;
pUS1->US_TCR = len;
pUS1->US_PTCR = AT91C_PDC_TXTEN;
while (!(pUS1->US_CSR & AT91C_US_ENDTX)) {};
pUS1->US_PTCR = AT91C_PDC_TXTDIS;
return len;
}
// Check if the backup PDC bank is free
else if (pUS1->US_TNCR == 0) {
pUS1->US_TNPR = (uint32_t)data;
pUS1->US_TNCR = len;
} else {
// we shouldn't be here
return 0;
}
// Make sure TX transfer is enabled
pUS1->US_PTCR = AT91C_PDC_TXTEN;// | AT91C_PDC_RXTEN;
//wait until finishing all transfers
while (pUS1->US_TNCR || pUS1->US_TCR) {};
return len;
}
*/
// transfer from device to client
inline int16_t usart_writebuffer(uint8_t *data, size_t len) {
while (pUS1->US_TCR && pUS1->US_TNCR) {};
// Check if the first PDC bank is free
if (pUS1->US_TCR == 0) {
memcpy(us_outbuf, data, len);
pUS1->US_TPR = (uint32_t)us_outbuf;
pUS1->US_TCR = sizeof(us_outbuf);
pUS1->US_PTCR = AT91C_PDC_TXTEN | AT91C_PDC_RXTEN;
}
// Check if the second PDC bank is free
else if (pUS1->US_TNCR == 0) {
memcpy(us_outbuf, data, len);
pUS1->US_TNPR = (uint32_t)us_outbuf;
pUS1->US_TNCR = sizeof(us_outbuf);
pUS1->US_PTCR = AT91C_PDC_TXTEN | AT91C_PDC_RXTEN;
}
//wait until finishing transfer
while (pUS1->US_TCR && pUS1->US_TNCR) {};
return 0;
}
void usart_init(void) {
@ -185,9 +189,7 @@ void usart_init(void) {
// all interrupts disabled
pUS1->US_IDR = 0xFFFF;
pUS1->US_BRGR = 48054841 / (AT91_BAUD_RATE << 3);
// Need speed?
//pUS1->US_BRGR = 48054841 / (460800 << 3);
pUS1->US_BRGR = 48054841 / (USART_BAUD_RATE << 3);
// Write the Timeguard Register
pUS1->US_TTGR = 0;
@ -195,9 +197,13 @@ void usart_init(void) {
pUS1->US_FIDI = 0;
pUS1->US_IF = 0;
// Disable double buffers for now
// Initialize DMA buffers
pUS1->US_TPR = (uint32_t)0;
pUS1->US_TCR = 0;
pUS1->US_TNPR = (uint32_t)0;
pUS1->US_TNCR = 0;
pUS1->US_RPR = (uint32_t)0;
pUS1->US_RCR = 0;
pUS1->US_RNPR = (uint32_t)0;
pUS1->US_RNCR = 0;
@ -205,8 +211,10 @@ void usart_init(void) {
pUS1->US_CR = (AT91C_US_RXEN | AT91C_US_TXEN);
// ready to receive
pUS1->US_RPR = (uint32_t)us_inbuf;
pUS1->US_RCR = 0;
pUS1->US_RNCR = 0;
pUS1->US_RPR = (uint32_t)us_inbuf1;
pUS1->US_RCR = USART_BUFFLEN;
usart_cur_inbuf = us_inbuf1;
pUS1->US_RNPR = (uint32_t)us_inbuf2;
pUS1->US_RNCR = USART_BUFFLEN;
pUS1->US_PTCR = AT91C_PDC_RXTEN;
}

View file

@ -4,17 +4,18 @@
#include <stddef.h>
#include "proxmark3.h"
#define AT91_BAUD_RATE 115200
//#define USART_BAUD_RATE 9600
#define USART_BAUD_RATE 115200
//#define USART_BAUD_RATE 460800
void usart_init(void);
void usart_close(void);
int16_t usart_readbuffer(uint8_t *data);
int16_t usart_writebuffer(uint8_t *data, size_t len);
bool usart_dataavailable(void);
int16_t usart_readcommand(uint8_t *data);
void usart_readcheck(uint8_t *data, size_t len);
uint32_t usart_read_ng(uint8_t *data, size_t len);
uint16_t usart_rxdata_available(void);
#define USART_BUFFLEN 512
#define USART_FIFOLEN (2*USART_BUFFLEN)
bool usart_commandavailable(void);
#endif

View file

@ -103,6 +103,7 @@ bool uart_set_speed(serial_port sp, const uint32_t uiPortSpeed);
/* Gets the current speed of the serial port, in baud.
*/
uint32_t uart_get_speed(const serial_port sp);
extern uint32_t uart_speed;
#endif // _UART_H_

View file

@ -60,6 +60,9 @@
# define SOL_TCP IPPROTO_TCP
#endif
// To memorise baudrate, we don't want to call get_speed systematically
uint32_t uart_speed;
typedef struct termios term_info;
typedef struct {
int fd; // Serial port file descriptor
@ -206,7 +209,8 @@ serial_port uart_open(const char *pcPortName, uint32_t speed) {
}
}
}
printf("[=] UART Setting serial baudrate %u\n", speed);
uart_speed = uart_get_speed(sp);
printf("[=] UART Setting serial baudrate %u\n", uart_speed);
return sp;
}
@ -408,7 +412,10 @@ bool uart_set_speed(serial_port sp, const uint32_t uiPortSpeed) {
// Set port speed (Input and Output)
cfsetispeed(&ti, stPortSpeed);
cfsetospeed(&ti, stPortSpeed);
return (tcsetattr(spu->fd, TCSANOW, &ti) != -1);
bool result = tcsetattr(spu->fd, TCSANOW, &ti) != -1;
if (result)
uart_speed = uiPortSpeed;
return result;
}
uint32_t uart_get_speed(const serial_port sp) {

View file

@ -42,6 +42,9 @@
#ifdef _WIN32
#include <windows.h>
// To memorise baudrate, we don't want to call get_speed systematically
uint32_t uart_speed;
typedef struct {
HANDLE hPort; // Serial port handle
DCB dcb; // Device control settings
@ -121,7 +124,8 @@ serial_port uart_open(const char *pcPortName, uint32_t speed) {
}
}
}
printf("[=] UART Setting serial baudrate %i\n", speed);
uart_speed = uart_get_speed(sp);
printf("[=] UART Setting serial baudrate %u\n", uart_speed);
return sp;
}
@ -152,6 +156,8 @@ bool uart_set_speed(serial_port sp, const uint32_t uiPortSpeed) {
spw->dcb.BaudRate = uiPortSpeed;
bool result = SetCommState(spw->hPort, &spw->dcb);
PurgeComm(spw->hPort, PURGE_RXABORT | PURGE_RXCLEAR);
if (result)
uart_speed = uiPortSpeed;
return result;
}