diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 194f4b6bc..2a766608b 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -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 diff --git a/armsrc/fpgaloader.c b/armsrc/fpgaloader.c index 058250cc7..e4ab1ab0b 100644 --- a/armsrc/fpgaloader.c +++ b/armsrc/fpgaloader.c @@ -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); } diff --git a/client/cmdanalyse.c b/client/cmdanalyse.c index 40ddfc809..d79387d9d 100644 --- a/client/cmdanalyse.c +++ b/client/cmdanalyse.c @@ -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 "); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h This help"); + PrintAndLogEx(NORMAL, " d 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"); diff --git a/common/cmd.c b/common/cmd.c index 85dd97f9d..c82cc1e3a 100644 --- a/common/cmd.c +++ b/common/cmd.c @@ -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; iUS_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; + +} \ No newline at end of file diff --git a/common/usart.h b/common/usart.h new file mode 100644 index 000000000..3623451d5 --- /dev/null +++ b/common/usart.h @@ -0,0 +1,21 @@ +#ifndef __USART_H +#define __USART_H + +#include +#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 diff --git a/include/usb_cmd.h b/include/usb_cmd.h index d33ab3d7d..4de39eef4 100644 --- a/include/usb_cmd.h +++ b/include/usb_cmd.h @@ -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