add: FPC connector skeleton usart. Not working but if will be a starting point for those who might want to help out with it.

This commit is contained in:
Chris 2018-07-30 09:54:44 +02:00
parent 08d9d9daf9
commit bacf8aff0f
8 changed files with 384 additions and 32 deletions

View file

@ -1053,6 +1053,21 @@ void UsbPacketReceived(uint8_t *packet, int len) {
}
#endif
#ifdef WITH_FPC
case CMD_FPC_SEND: {
// char header[] = {"*** Iceman Usart ***"};
// uint32_t res = usart_writebuffer((uint8_t *)header, sizeof(header), 10000);
//temp++;
uint8_t got = usart_read(10000);
if ( got > 0 ) {
Dbprintf("got %02x", got);
usart_write(got, 10000);
}
cmd_send(CMD_ACK,0,0,0,0,0);
break;
}
#endif
case CMD_BUFF_CLEAR:
BigBuf_Clear();
break;
@ -1292,7 +1307,7 @@ void UsbPacketReceived(uint8_t *packet, int len) {
switch(c->arg[0]) {
case 0: SetAdcMuxFor(GPIO_MUXSEL_LOPKD); break;
case 2: SetAdcMuxFor(GPIO_MUXSEL_HIPKD); break;
#ifndef WITH_FPC
#ifndef WITH_FPC
case 1: SetAdcMuxFor(GPIO_MUXSEL_LORAW); break;
case 3: SetAdcMuxFor(GPIO_MUXSEL_HIRAW); break;
#endif
@ -1307,12 +1322,6 @@ void UsbPacketReceived(uint8_t *packet, int len) {
break;
case CMD_PING:
cmd_send(CMD_ACK,0,0,0,0,0);
#ifdef WITH_FPC
char header[] = {"*** Iceman Usart ***"};
uint32_t res = usart_writebuffer((uint8_t *)header, sizeof(header), 100000);
Dbprintf("after sending FPC [%x]", res);
#endif
break;
#ifdef WITH_LCD
case CMD_LCD_RESET:
@ -1406,6 +1415,7 @@ void __attribute__((noreturn)) AppMain(void) {
#ifdef WITH_SMARTCARD
I2C_init();
#endif
#ifdef WITH_FPC
usart_init();
#endif

View file

@ -145,7 +145,7 @@ void FpgaSetupSscExt(uint8_t clearPCER) {
// clock comes from TK pin, no clock output, outputs change on falling
// edge of TK, sample on rising edge of TK, start on positive-going edge of sync
AT91C_BASE_SSC->SSC_TCMR = SSC_CLOCK_MODE_SELECT(2) | SSC_CLOCK_MODE_START(5);
AT91C_BASE_SSC->SSC_TCMR = SSC_CLOCK_MODE_SELECT(2) | SSC_CLOCK_MODE_START(5);
// tx framing is the same as the rx framing
AT91C_BASE_SSC->SSC_TFMR = AT91C_BASE_SSC->SSC_RFMR;
@ -462,9 +462,11 @@ void SetAdcMuxFor(uint32_t whichGpio) {
GPIO_MUXSEL_HIRAW;
LOW(GPIO_MUXSEL_HIPKD);
LOW(GPIO_MUXSEL_LOPKD);
#ifndef WITH_FPC
LOW(GPIO_MUXSEL_HIRAW);
LOW(GPIO_MUXSEL_LORAW);
LOW(GPIO_MUXSEL_LOPKD);
#endif
HIGH(whichGpio);
}

View file

@ -53,7 +53,6 @@ int usage_analyse_crc(void){
PrintAndLogEx(NORMAL, " analyse crc 137AF00A0A0D");
return 0;
}
int usage_analyse_nuid(void){
PrintAndLogEx(NORMAL, "Generate 4byte NUID from 7byte UID");
PrintAndLogEx(NORMAL, "");
@ -66,6 +65,18 @@ int usage_analyse_nuid(void){
PrintAndLogEx(NORMAL, " analyse nuid 11223344556677");
return 0;
}
int usage_analyse_a(void) {
PrintAndLogEx(NORMAL, "my personal garbage test command");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Usage: analyse a [h] d <bytes>");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h This help");
PrintAndLogEx(NORMAL, " d <bytes> bytes to send to device");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, " analyse a d 137AF00A0A0D");
return 0;
}
static uint8_t calculateLRC( uint8_t* bytes, uint8_t len) {
uint8_t LRC = 0;
@ -484,7 +495,7 @@ int CmdAnalyseA(const char *Cmd){
cmdp += 2;
break;
case 'h':
return usage_analyse_checksum();
return usage_analyse_a();
default:
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
errors = true;
@ -492,9 +503,20 @@ int CmdAnalyseA(const char *Cmd){
}
}
//Validations
if (errors || cmdp == 0 ) return usage_analyse_checksum();
if (errors || cmdp == 0 ) return usage_analyse_a();
UsbCommand c = {CMD_FPC_SEND, {0, 0, 0}};
clearCommandBuffer();
SendCommand(&c);
UsbCommand resp;
if (!WaitForResponseTimeout(CMD_ACK, &resp, 2500)) {
return 1;
}
PrintAndLogEx(NORMAL, "got ack");
return 0;
PrintAndLogEx(NORMAL, "-- " _BLUE_(its my message) "\n");
PrintAndLogEx(NORMAL, "-- " _RED_(its my message) "\n");
PrintAndLogEx(NORMAL, "-- " _YELLOW_(its my message) "\n");

View file

@ -31,23 +31,30 @@
*/
#include "cmd.h"
// (iceman 2017) this method is not used anymore. uart_win32 /uart_posix is used instead
bool cmd_receive(UsbCommand* cmd) {
// Check if there is a usb packet available
if (!usb_poll_validate_length()) return false;
// Try to retrieve the available command frame
size_t rxlen = usb_read((byte_t*)cmd, sizeof(UsbCommand));
// (iceman) this check is wrong. Since USB can send packages which is not sizeof(usbcommand) 544 bytes.
// hence, I comment it out
// Check if the transfer was complete
//if (rxlen != sizeof(UsbCommand)) return false;
// Received command successfully
//return true;
return (rxlen);
// check if there is a FPC USART1 message?
/*
size_t fpc_rxlen = usart_read((uint8_t*)cmd, sizeof(UsbCommand));
if ( fpc_rxlen )
return true;
*/
// Check if there is a usb packet available
if (!usb_poll_validate_length()) return false;
// Try to retrieve the available command frame
usb_read((uint8_t*)cmd, sizeof(UsbCommand));
// (iceman) this check is wrong. Since USB can send packages which is not sizeof(usbcommand) 544 bytes.
// hence, I comment it out
// Check if the transfer was complete
//if (rxlen != sizeof(UsbCommand)) return false;
// Received command successfully
//return true;
return true;
}
bool cmd_send(uint64_t cmd, uint64_t arg0, uint64_t arg1, uint64_t arg2, void* data, size_t len) {
@ -56,7 +63,7 @@ bool cmd_send(uint64_t cmd, uint64_t arg0, uint64_t arg1, uint64_t arg2, void* d
// 0x00 the whole command.
for (size_t i=0; i < sizeof(UsbCommand); i++)
((byte_t*)&txcmd)[i] = 0x00;
((uint8_t*)&txcmd)[i] = 0x00;
// Compose the outgoing command frame
txcmd.cmd = cmd;
@ -68,13 +75,15 @@ bool cmd_send(uint64_t cmd, uint64_t arg0, uint64_t arg1, uint64_t arg2, void* d
if (data && len) {
len = MIN(len, USB_CMD_DATA_SIZE);
for (size_t i=0; i<len; i++) {
txcmd.d.asBytes[i] = ((byte_t*)data)[i];
txcmd.d.asBytes[i] = ((uint8_t*)data)[i];
}
}
//usart_send( (uint8_t*)&txcmd, sizeof(UsbCommand));
// Send frame and make sure all bytes are transmitted
if ( usb_write( (byte_t*)&txcmd, sizeof(UsbCommand)) != 0)
return false;
if ( usb_write( (uint8_t*)&txcmd, sizeof(UsbCommand)) != 0)
return false;
return true;
}

View file

@ -36,6 +36,7 @@
#include "common.h"
#include "usb_cmd.h"
#include "usb_cdc.h"
#include "usart.h"
#include "proxmark3.h"
bool cmd_receive(UsbCommand* cmd);

283
common/usart.c Normal file
View file

@ -0,0 +1,283 @@
#include "usart.h"
#include "apps.h"
#define USART_INTERRUPT_LEVEL 7
#define AT91_BAUD_RATE 115200
volatile AT91PS_PDC pPDC = AT91C_BASE_PDC_US1;
volatile AT91PS_USART pUS1 = AT91C_BASE_US1;
volatile AT91PS_AIC pAIC = AT91C_BASE_AIC;
volatile AT91PS_PIO pPIOA = AT91C_BASE_PIOA;
#define usart_rx_ready {(pUS1->US_CSR & AT91C_US_RXRDY)}
#define usart_tx_ready {(pUS1->US_CSR & AT91C_US_TXRDY)}
void usart_close(void) {
// Reset the USART mode
pUS1->US_MR = 0;
// Reset the baud rate divisor register
pUS1->US_BRGR = 0;
// Reset the Timeguard Register
pUS1->US_TTGR = 0;
// Disable all interrupts
pUS1->US_IDR = 0xFFFFFFFF;
//* Abort the Peripheral Data Transfers
//AT91F_PDC_Close((AT91PS_PDC) &(pUSART->US_RPR));
// Disable receiver and transmitter and stop any activity immediately
pUS1->US_CR = AT91C_US_TXDIS | AT91C_US_RXDIS | AT91C_US_RSTTX | AT91C_US_RSTRX;
}
/// Reads data from an USART peripheral, filling the provided buffer until it
/// becomes full. This function returns immediately with 1 if the buffer has
/// been queued for transmission; otherwise 0.
/// \param data Pointer to the buffer where the received data will be stored.
/// \param len Size of the data buffer (in bytes).
uint8_t usart_readbuffer(uint8_t *data, size_t len) {
// Check if the first PDC bank is free
if ((pUS1->US_RCR == 0) && (pUS1->US_RNCR == 0)) {
pUS1->US_RPR = (uint32_t)data;
pUS1->US_RCR = len;
pUS1->US_PTCR = AT91C_PDC_RXTEN;
return 1;
}
// Check if the second PDC bank is free
else if (pUS1->US_RNCR == 0) {
pUS1->US_RNPR = (uint32_t)data;
pUS1->US_RNCR = len;
return 1;
} else {
return 0;
}
}
/// Reads and return a packet of data on the specified USART peripheral. This
/// function operates asynchronously, so it waits until some data has been
/// received.
/// \param timeout Time out value (0 -> no timeout).
uint8_t usart_read(uint32_t timeout) {
if (timeout == 0) {
while ((pUS1->US_CSR & AT91C_US_RXRDY) == 0) {};
}
else {
while ((pUS1->US_CSR & AT91C_US_RXRDY) == 0) {
if (timeout == 0) {
DbpString("USART_Read: Timed out.");
return 0;
}
timeout--;
}
}
uint8_t res = pUS1->US_RHR;
Dbprintf(" usar got %02x", res);
return res;
}
/// Sends one packet of data through the specified USART peripheral. This
/// function operates synchronously, so it only returns when the data has been
/// actually sent.
/// \param data Data to send including 9nth bit and sync field if necessary (in
/// the same format as the US_THR register in the datasheet).
/// \param timeOut Time out value (0 = no timeout).
void usart_write( uint8_t data, uint32_t timeout) {
if ( timeout == 0) {
while ((pUS1->US_CSR & AT91C_US_TXEMPTY) == 0) {};
} else {
while ((pUS1->US_CSR & AT91C_US_TXEMPTY) == 0) {
if (timeout == 0) {
DbpString("USART_Write: Timed out.");
return;
}
timeout--;
}
}
pUS1->US_THR = data;
}
uint8_t usart_writebuffer(uint8_t *data, size_t len, uint32_t timeout) {
// Check if the first PDC bank is free
if ((pUS1->US_TCR == 0) && (pUS1->US_TNCR == 0)) {
pUS1->US_TPR = (uint32_t)data;
pUS1->US_TCR = len;
pUS1->US_PTCR = AT91C_PDC_TXTEN;
return 1;
}
// Check if the second PDC bank is free
else if (pUS1->US_TNCR == 0) {
pUS1->US_TNPR = (uint32_t)data;
pUS1->US_TNCR = len;
return 1;
}
else {
return 0;
}
}
// interupt version
void Usart_c_irq_handler(void) {
// get Usart status register
uint32_t status = pUS1->US_CSR;
if ( status & AT91C_US_RXRDY){
// Get byte and send
pUS1->US_THR = (pUS1->US_RHR & 0x1FF);
LED_B_INV();
}
// tx
if ( status & AT91C_US_TXRDY){
LED_D_INV();
}
if ( status & AT91C_US_OVRE) {
// clear US_RXRDY
(void)(pUS1->US_RHR & 0x1FF);
pUS1->US_THR = ('O' & 0x1FF);
}
// Check error
if ( status & AT91C_US_PARE) {
pUS1->US_THR = ('P' & 0x1FF);
}
if ( status & AT91C_US_FRAME) {
pUS1->US_THR = ('F' & 0x1FF);
}
if ( status & AT91C_US_TIMEOUT){
pUS1->US_CR = AT91C_US_STTTO;
pUS1->US_THR = ('T' & 0x1FF);
}
// Reset the status bit
pUS1->US_CR = AT91C_US_RSTSTA;
}
__inline unsigned int AT91F_AIC_ConfigureIt (
AT91PS_AIC pAIC, // \arg pointer to the AIC registers
unsigned int irq_id, // \arg interrupt number to initialize
unsigned int priority, // \arg priority to give to the interrupt
unsigned int src_type, // \arg activation and sense of activation
void (*newHandler) (void) ) // \arg address of the interrupt handler
{
unsigned int oldHandler;
unsigned int mask;
oldHandler = pAIC->AIC_SVR[irq_id];
mask = (0x1 << irq_id);
// Disable the interrupt on the interrupt controller
pAIC->AIC_IDCR = mask;
// Save the interrupt handler routine pointer and the interrupt priority
pAIC->AIC_SVR[irq_id] = (unsigned int) newHandler;
// Store the Source Mode Register
pAIC->AIC_SMR[irq_id] = (src_type | priority);
// Clear the interrupt on the interrupt controller
pAIC->AIC_ICCR = mask;
return oldHandler;
}
void usart_init(void) {
// disable & reset receiver / transmitter
pUS1->US_CR = AT91C_US_RSTRX | AT91C_US_RSTTX | AT91C_US_RXDIS | AT91C_US_TXDIS;
//enable the USART 1 Peripheral clock
AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_US1);
// Configure PIO controllers to peripheral mode A
pPIOA->PIO_ASR = (AT91C_PA21_RXD1 | AT91C_PA22_TXD1);
// Disable PIO control of the following pins, allows use by the SPI peripheral
pPIOA->PIO_PDR = (AT91C_PA21_RXD1 | AT91C_PA22_TXD1);
// kill pull-ups
// pPIOA->PIO_PPUDR = ~(AT91C_PA21_RXD1 | AT91C_PA22_TXD1);
// pPIOA->PIO_MDDR = (AT91C_PA21_RXD1 | AT91C_PA22_TXD1);
// Pull-up Enable
pPIOA->PIO_PPUER |= (AT91C_PA21_RXD1 | AT91C_PA22_TXD1);
// MultiDriver Enable
//pPIOA->PIO_MDER |= (AT91C_PA21_RXD1 | AT91C_PA22_TXD1);
// Enable the pins to be controlled
pPIOA->PIO_PER |= (AT91C_PA21_RXD1 | AT91C_PA22_TXD1);
// Configure the pins to be outputs
pPIOA->PIO_OER |= (AT91C_PA21_RXD1 | AT91C_PA22_TXD1);
//enable PIO in input mode
//pPIOA->PIO_ODR = AT91C_PA21_RXD1;
// set mode
pUS1->US_MR = AT91C_US_USMODE_NORMAL | // normal mode
AT91C_US_CLKS_CLOCK | // MCK
AT91C_US_CHRL_8_BITS | // 8 bits
AT91C_US_PAR_NONE | // parity: none
AT91C_US_NBSTOP_1_BIT | // 1 stop bit
AT91C_US_CHMODE_NORMAL; // channel mode: normal
// baud rate
// CD = MCK / (16 * baud)
// MCK = 24027428 (pm3 runs on 24MHZ clock PMC_PCKR[0] )
// baudrate 115200
// 16*115200 = 1843200
// 24027428 / 1843200 == 13 --< CD
// baudrate 460800
// 16*460800 = 7372800
// 24027428 / 7372800 == 3
pUS1->US_BRGR = 24*1024*1024/(115200*16); // OVER=0 16
// Write the Timeguard Register
pUS1->US_TTGR = 0;
pUS1->US_RTOR = 0;
pUS1->US_FIDI = 0;
pUS1->US_IF = 0;
// Enable USART IT error and RXRDY
// Write to the IER register
// pUS1->US_IER = (AT91C_US_TIMEOUT | AT91C_US_FRAME | AT91C_US_OVRE | AT91C_US_RXRDY);
// open Usart 1 interrupt
/*
AT91F_AIC_ConfigureIt(
pAIC,
AT91C_ID_US1,
USART_INTERRUPT_LEVEL,
AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL,
Usart_c_irq_handler
);
*/
// enable interupt
// pAIC->AIC_IECR = (1 << AT91C_ID_US1);
// trigger interrup software
// pAIC->AIC_ISCR = (1 << AT91C_ID_US1) ;
// enable RX + TX
pUS1->US_CR = AT91C_US_RXEN | AT91C_US_TXEN;
}

21
common/usart.h Normal file
View file

@ -0,0 +1,21 @@
#ifndef __USART_H
#define __USART_H
#include <stddef.h>
#include "proxmark3.h"
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
extern void Dbprintf(const char *fmt, ...);
void usart_init(void);
void usart_close(void);
uint32_t usart_rx_ready();
uint32_t usart_tx_ready();
uint8_t usart_read(uint32_t timeout);
uint8_t usart_readbuffer(uint8_t *data, size_t len);
void usart_write( uint8_t data, uint32_t timeout);
uint8_t usart_writebuffer(uint8_t *data, size_t len, uint32_t timeout);
#endif

View file

@ -83,6 +83,10 @@ typedef struct{
#define CMD_SMART_SETBAUD 0x0144
#define CMD_SMART_SETCLOCK 0x0145
// RDV40, FPC serial
#define CMD_FPC_SEND 0x0160
#define CMD_FPC_READ 0x0161
// For low-frequency tags
#define CMD_READ_TI_TYPE 0x0202
#define CMD_WRITE_TI_TYPE 0x0203