mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2024-09-20 23:36:31 +08:00
First pass rewrite of flashmem driver for optimization. Lot of changes here. Provides PoC of saving and recalling a tag in Standalone mode. Added some printing passthrough to client to azccomodate for vt100 eye-candyness. FastREAD mode implemented for flashmem, testable from client. Beta but functionnal. Reading the whole flash with 1Kb to 32kb buffers was ~730ms, now 380ms Max (even at 24Mhz spi baudrate)
This commit is contained in:
parent
41ca388edc
commit
8d673fa1bf
|
@ -24,7 +24,7 @@ APP_CFLAGS = -DWITH_CRC \
|
|||
-DWITH_FLASH \
|
||||
-DWITH_SMARTCARD \
|
||||
-DWITH_HFSNOOP \
|
||||
-DWITH_LF_SAMYRUN \
|
||||
-DWITH_HF_COLIN \
|
||||
-fno-strict-aliasing -ffunction-sections -fdata-sections
|
||||
|
||||
### IMPORTANT - move the commented variable below this line
|
||||
|
@ -106,12 +106,9 @@ ARMSRC = fpgaloader.c \
|
|||
parity.c \
|
||||
usb_cdc.c \
|
||||
cmd.c \
|
||||
lf_samyrun.c \
|
||||
vtsend.c
|
||||
# lf_samyrun.c \
|
||||
# lf_hidbrute.c \
|
||||
# lf_proxbrute.c \
|
||||
# hf_mattyrun.c \
|
||||
vtsend.c \
|
||||
hf_colin.c \
|
||||
lib_AT91SAM7.c
|
||||
|
||||
VERSIONSRC = version.c \
|
||||
fpga_version_info.c
|
||||
|
@ -120,7 +117,6 @@ VERSIONSRC = version.c \
|
|||
include ../common/Makefile.common
|
||||
|
||||
COMMON_FLAGS = -Os
|
||||
|
||||
OBJS = $(OBJDIR)/fullimage.s19
|
||||
FPGA_COMPRESSOR = ../client/fpga_compress
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -16,18 +16,21 @@
|
|||
#ifndef __HF_COLIN_H
|
||||
#define __HF_COLIN_H
|
||||
|
||||
#include <stdbool.h> // for bool
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "standalone.h" // standalone definitions
|
||||
|
||||
#include "proxmark3.h"
|
||||
#include "mifareutil.h"
|
||||
#include "iso14443a.h"
|
||||
//#include "printf.h"
|
||||
#include "protocols.h"
|
||||
#include "util.h"
|
||||
#include "standalone.h" // standalone definitions
|
||||
#include <stdbool.h> // for bool
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
//#include <stdio.h>
|
||||
#include "vtsend.h"
|
||||
#include "apps.h"
|
||||
#include "usb_cmd.h" // mifare1ksim flags
|
||||
#include "printf.h"
|
||||
|
||||
#define _RED_ "\x1b[31m"
|
||||
#define _GREEN_ "\x1b[32m"
|
||||
|
@ -38,14 +41,19 @@
|
|||
#define _WHITE_ "\x1b[0m"
|
||||
#define _ORANGE_ _YELLOW_
|
||||
|
||||
#define NTIME(n) for (int _index = 0; _index < n; _index++)
|
||||
|
||||
int cjat91_saMifareChkKeys(uint8_t blockNo, uint8_t keyType, bool clearTrace, uint8_t keyCount, uint8_t *datain, uint64_t *key);
|
||||
void e_MifareECardLoad(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);
|
||||
void saMifareMakeTag(void);
|
||||
int saMifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);
|
||||
void cjPrintBigArray(const char *bigar, int len, uint8_t newlines, uint8_t debug);
|
||||
void WriteTagToFlash(uint8_t index, size_t size);
|
||||
|
||||
const char clearTerm[8] = {0x1b, 0x5b, 0x48, 0x1b, 0x5b, 0x32, 0x4a, '\0'};
|
||||
|
||||
|
||||
|
||||
#define LOGO logo_kigiv
|
||||
|
||||
const char sub_banner[] = " From Vigik : \"20 years of (un)security without a single update\"";
|
||||
|
@ -410,7 +418,7 @@ const char logo_kigiv[] = {
|
|||
0x38, 0x3b, 0x35, 0x3b, 0x35, 0x39, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x39, 0x6d, 0x31, 0x0d, 0x0a};
|
||||
unsigned int logo_kigiv_len = 9303;
|
||||
|
||||
const char logo_kigiv_nocolor[] = {
|
||||
/*const char logo_kigiv_nocolor[] = {
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x30, 0x30, 0x30, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
|
@ -494,6 +502,6 @@ const char logo_kigiv_nocolor[] = {
|
|||
0x30, 0x31, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x31, 0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x31, 0x31,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x31, 0x30, 0x31, 0x31, 0x0d, 0x0a};
|
||||
unsigned int logo_kigiv_nocolor_len = 2153;
|
||||
unsigned int logo_kigiv_nocolor_len = 2153;*/
|
||||
|
||||
#endif /* __HF_COLIN_H */
|
||||
|
|
|
@ -33,10 +33,6 @@
|
|||
#include "i2c.h"
|
||||
#endif
|
||||
|
||||
#ifdef WITH_FPC
|
||||
#include "usart.h"
|
||||
#endif
|
||||
|
||||
//=============================================================================
|
||||
// A buffer where we can queue things up to be sent through the FPGA, for
|
||||
// any purpose (fake tag, as reader, whatever). We go MSB first, since that
|
||||
|
@ -78,26 +74,24 @@ void PrintToSendBuffer(void) {
|
|||
}
|
||||
|
||||
void print_result(char *name, uint8_t *buf, size_t len) {
|
||||
|
||||
uint8_t *p = buf;
|
||||
uint16_t tmp = len & 0xFFF0;
|
||||
|
||||
for(; p-buf < tmp; p += 16) {
|
||||
Dbprintf("[%s: %02d/%02d] %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
|
||||
if ( len % 16 == 0 ) {
|
||||
for(; p-buf < len; p += 16)
|
||||
Dbprintf("[%s:%d/%d] %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
|
||||
name,
|
||||
p-buf,
|
||||
len,
|
||||
p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7],p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15]
|
||||
);
|
||||
}
|
||||
if (len % 16 != 0) {
|
||||
char s[46] = {0};
|
||||
char *sp = s;
|
||||
for (; p-buf < len; p++ ) {
|
||||
sprintf(sp, "%02x ", p[0] );
|
||||
sp += 3;
|
||||
}
|
||||
Dbprintf("[%s: %02d/%02d] %s", name, p-buf, len, s);
|
||||
else {
|
||||
for(; p-buf < len; p += 8)
|
||||
Dbprintf("[%s:%d/%d] %02x %02x %02x %02x %02x %02x %02x %02x",
|
||||
name,
|
||||
p-buf,
|
||||
len,
|
||||
p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -107,7 +101,7 @@ void print_result(char *name, uint8_t *buf, size_t len) {
|
|||
|
||||
void DbpStringEx(char *str, uint32_t cmd) {
|
||||
#if DEBUG
|
||||
uint8_t len = strlen(str);
|
||||
byte_t len = strlen(str);
|
||||
cmd_send(CMD_DEBUG_PRINT_STRING, len, cmd, 0, (byte_t*)str, len);
|
||||
#endif
|
||||
}
|
||||
|
@ -119,7 +113,7 @@ void DbpString(char *str) {
|
|||
}
|
||||
|
||||
#if 0
|
||||
void DbpIntegers(int x1, int x2, int x3) {
|
||||
void DbpIntegers(inst x1, int x2, int x3) {
|
||||
cmd_send(CMD_DEBUG_PRINT_INTEGERS,x1,x2,x3,0,0);
|
||||
}
|
||||
#endif
|
||||
|
@ -440,7 +434,7 @@ void printStandAloneModes(void) {
|
|||
DbpString(" LF HID corporate 1000 bruteforce - (Federico dotta & Maurizio Agazzini)");
|
||||
#endif
|
||||
#if defined(WITH_HF_MATTYRUN)
|
||||
DbpString(" HF Mifare sniff/clone - aka MattyRun (Matías A. Ré Medina)");
|
||||
DbpString(" HF Mifare sniff/clone - aka MattyRun (Mat<EFBFBD>as A. R<> Medina)");
|
||||
#endif
|
||||
#if defined(WITH_HF_COLIN)
|
||||
DbpString(" HF Mifare ultra fast sniff/sim/clone - aka VIGIKPWN (Colin Brigato)");
|
||||
|
@ -448,7 +442,6 @@ void printStandAloneModes(void) {
|
|||
|
||||
//DbpString("Running ");
|
||||
//Dbprintf(" Is Device attached to USB| %s", USB_ATTACHED() ? "Yes" : "No");
|
||||
//Dbprintf(" Is Device attached to FPC| %s", 0 ? "Yes" : "No");
|
||||
//Dbprintf(" Is USB_reconnect value | %d", GetUSBreconnect() );
|
||||
//Dbprintf(" Is USB_configured value | %d", GetUSBconfigured() );
|
||||
|
||||
|
@ -1077,7 +1070,6 @@ void UsbPacketReceived(uint8_t *packet, int len) {
|
|||
#endif
|
||||
case CMD_BUFF_CLEAR:
|
||||
BigBuf_Clear();
|
||||
BigBuf_free();
|
||||
break;
|
||||
|
||||
case CMD_MEASURE_ANTENNA_TUNING:
|
||||
|
@ -1114,7 +1106,7 @@ void UsbPacketReceived(uint8_t *packet, int len) {
|
|||
len = MIN( (numofbytes - i), USB_CMD_DATA_SIZE);
|
||||
isok = cmd_send(CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K, i, len, BigBuf_get_traceLen(), mem + startidx + i, len);
|
||||
if (!isok)
|
||||
Dbprintf("transfer to client failed :: | bytes between %d - %d (%d)", i, i+len, len);
|
||||
Dbprintf("transfer to client failed :: | bytes between %d - %d", i, len);
|
||||
}
|
||||
// Trigger a finish downloading signal with an ACK frame
|
||||
// iceman, when did sending samplingconfig array got attached here?!?
|
||||
|
@ -1160,7 +1152,7 @@ void UsbPacketReceived(uint8_t *packet, int len) {
|
|||
len = MIN((numofbytes - i), USB_CMD_DATA_SIZE);
|
||||
isok = cmd_send(CMD_DOWNLOADED_EML_BIGBUF, i, len, 0, mem + startidx + i, len);
|
||||
if (!isok)
|
||||
Dbprintf("transfer to client failed :: | bytes between %d - %d (%d)", i, i+len, len);
|
||||
Dbprintf("transfer to client failed :: | bytes between %d - %d", i, len);
|
||||
}
|
||||
// Trigger a finish downloading signal with an ACK frame
|
||||
cmd_send(CMD_ACK, 1, 0, 0, 0, 0);
|
||||
|
@ -1177,6 +1169,7 @@ void UsbPacketReceived(uint8_t *packet, int len) {
|
|||
uint16_t isok = 0;
|
||||
uint32_t startidx = c->arg[0];
|
||||
uint16_t len = c->arg[1];
|
||||
uint8_t fast = c->arg[2];
|
||||
|
||||
Dbprintf("FlashMem read | %d - %d", startidx, len);
|
||||
|
||||
|
@ -1184,14 +1177,23 @@ void UsbPacketReceived(uint8_t *packet, int len) {
|
|||
|
||||
uint8_t *mem = BigBuf_malloc(size);
|
||||
|
||||
|
||||
if (fast) {
|
||||
FlashInit(1);
|
||||
//FlashInit();
|
||||
Flash_CheckBusy(BUSY_TIMEOUT);
|
||||
}
|
||||
for(size_t i = 0; i < len; i += size) {
|
||||
len = MIN((len - i), size);
|
||||
|
||||
memset(mem, 0, len);
|
||||
|
||||
Dbprintf("FlashMem reading | %d | %d | %d", startidx + i, i, len);
|
||||
|
||||
if (!fast){
|
||||
isok = Flash_ReadData(startidx + i, mem, len);
|
||||
}
|
||||
if (fast){
|
||||
isok = Flash_FastReadDataCont(startidx + i, mem, len);
|
||||
}
|
||||
if ( isok == len ) {
|
||||
print_result("Chunk: ", mem, len);
|
||||
} else {
|
||||
|
@ -1199,6 +1201,9 @@ void UsbPacketReceived(uint8_t *packet, int len) {
|
|||
break;
|
||||
}
|
||||
}
|
||||
if (fast){
|
||||
FlashStop();
|
||||
}
|
||||
LED_B_OFF();
|
||||
break;
|
||||
}
|
||||
|
@ -1271,21 +1276,36 @@ void UsbPacketReceived(uint8_t *packet, int len) {
|
|||
size_t len = 0;
|
||||
uint32_t startidx = c->arg[0];
|
||||
uint32_t numofbytes = c->arg[1];
|
||||
uint8_t fast = c->arg[2];
|
||||
|
||||
// arg0 = startindex
|
||||
// arg1 = length bytes to transfer
|
||||
// arg2 = RFU
|
||||
|
||||
|
||||
if (fast) {
|
||||
FlashInit(1);
|
||||
//FlashInit();
|
||||
Flash_CheckBusy(BUSY_TIMEOUT);
|
||||
}
|
||||
for (size_t i = 0; i < numofbytes; i += USB_CMD_DATA_SIZE) {
|
||||
len = MIN((numofbytes - i), USB_CMD_DATA_SIZE);
|
||||
|
||||
if (!fast){
|
||||
isok = Flash_ReadData(startidx + i, mem, len);
|
||||
}
|
||||
if (fast){
|
||||
isok = Flash_FastReadDataCont(startidx + i, mem, len);
|
||||
}
|
||||
if (!isok )
|
||||
Dbprintf("reading flash memory failed :: | bytes between %d - %d", i, len);
|
||||
|
||||
isok = cmd_send(CMD_DOWNLOADED_FLASHMEM, i, len, 0, mem, len);
|
||||
if (!isok)
|
||||
Dbprintf("transfer to client failed :: | bytes between %d - %d (%d)", i, i+len, len);
|
||||
Dbprintf("transfer to client failed :: | bytes between %d - %d", i, len);
|
||||
}
|
||||
if (fast){
|
||||
FlashStop();
|
||||
}
|
||||
|
||||
cmd_send(CMD_ACK, 1, 0, 0, 0, 0);
|
||||
LED_B_OFF();
|
||||
break;
|
||||
|
@ -1297,7 +1317,7 @@ void UsbPacketReceived(uint8_t *packet, int len) {
|
|||
|
||||
bool isok = Flash_ReadData(FLASH_MEM_SIGNATURE_OFFSET, info->signature, FLASH_MEM_SIGNATURE_LEN);
|
||||
|
||||
if (FlashInit()) {
|
||||
if (FlashInit(0)) {
|
||||
Flash_UniqueID( info->flashid);
|
||||
FlashStop();
|
||||
}
|
||||
|
@ -1392,8 +1412,6 @@ void __attribute__((noreturn)) AppMain(void) {
|
|||
|
||||
LEDsoff();
|
||||
|
||||
usb_enable();
|
||||
|
||||
// The FPGA gets its clock from us from PCK0 output, so set that up.
|
||||
AT91C_BASE_PIOA->PIO_BSR = GPIO_PCK0;
|
||||
AT91C_BASE_PIOA->PIO_PDR = GPIO_PCK0;
|
||||
|
@ -1419,16 +1437,22 @@ void __attribute__((noreturn)) AppMain(void) {
|
|||
StartTickCount();
|
||||
|
||||
#ifdef WITH_LCD
|
||||
LCDInit();
|
||||
// LCDInit();
|
||||
#endif
|
||||
|
||||
#ifdef WITH_SMARTCARD
|
||||
I2C_init();
|
||||
// I2C_init();
|
||||
#endif
|
||||
|
||||
#ifdef WITH_FPC
|
||||
usart_init();
|
||||
// usart_init();
|
||||
#endif
|
||||
|
||||
// This is made as late as possible to ensure enumeration without timeout
|
||||
// against device such as http://www.hobbytronics.co.uk/usb-host-board-v2
|
||||
usb_disable();
|
||||
usb_enable();
|
||||
|
||||
uint8_t rx[sizeof(UsbCommand)];
|
||||
|
||||
for(;;) {
|
||||
|
@ -1464,6 +1488,10 @@ void __attribute__((noreturn)) AppMain(void) {
|
|||
RunMod();
|
||||
#endif
|
||||
|
||||
// when here, we are no longer in standalone mode.
|
||||
// reseting the variables which keeps track of usb re-attached/configured
|
||||
//SetUSBreconnect(0);
|
||||
//SetUSBconfigured(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,39 +1,43 @@
|
|||
#include "flashmem.h"
|
||||
|
||||
|
||||
#define MCK 48000000
|
||||
//#define FLASH_BAUD 24000000
|
||||
//define FLASH_BAUD 33000000
|
||||
#define FLASH_BAUD MCK/2
|
||||
#define FLASH_FASTBAUD MCK
|
||||
|
||||
/* here: use NCPS2 @ PA10: */
|
||||
#define SPI_CSR_NUM 2 // Chip Select register[] 0,1,2,3 (at91samv512 has 4)
|
||||
|
||||
/* PCS_0 for NPCS0, PCS_1 for NPCS1 ... */
|
||||
#define PCS_0 ((0<<0)|(1<<1)|(1<<2)|(1<<3)) // 0xE - 1110
|
||||
#define PCS_1 ((1<<0)|(0<<1)|(1<<2)|(1<<3)) // 0xD - 1101
|
||||
#define PCS_2 ((1<<0)|(1<<1)|(0<<2)|(1<<3)) // 0xB - 1011
|
||||
#define PCS_3 ((1<<0)|(1<<1)|(1<<2)|(0<<3)) // 0x7 - 0111
|
||||
|
||||
// TODO
|
||||
#if (SPI_CSR_NUM == 0)
|
||||
#define SPI_MR_PCS PCS_0
|
||||
#elif (SPI_CSR_NUM == 1)
|
||||
#define SPI_MR_PCS PCS_1
|
||||
#elif (SPI_CSR_NUM == 2)
|
||||
#define SPI_MR_PCS PCS_2
|
||||
#elif (SPI_CSR_NUM == 3)
|
||||
#define SPI_MR_PCS PCS_3
|
||||
#else
|
||||
#error "SPI_CSR_NUM invalid"
|
||||
// not realy - when using an external address decoder...
|
||||
// but this code takes over the complete SPI-interace anyway
|
||||
#endif
|
||||
#define SPI_CSR_NUM 2
|
||||
#define SPI_PCS(npcs) ((~(1 << (npcs)) & 0xF) << 16)
|
||||
/// Calculates the value of the CSR SCBR field given the baudrate and MCK.
|
||||
#define SPI_SCBR(baudrate, masterClock) ((uint32_t) ((masterClock) / (baudrate)) << 8)
|
||||
/// Calculates the value of the CSR DLYBS field given the desired delay (in ns)
|
||||
#define SPI_DLYBS(delay, masterClock) ((uint32_t) ((((masterClock) / 1000000) * (delay)) / 1000) << 16)
|
||||
/// Calculates the value of the CSR DLYBCT field given the desired delay (in ns)
|
||||
#define SPI_DLYBCT(delay, masterClock) ((uint32_t) ((((masterClock) / 1000000) * (delay)) / 32000) << 24)
|
||||
|
||||
|
||||
/*
|
||||
读取指令,可以从一个位置开始持续的读,最多能将整块芯片读取完
|
||||
页写指令,每次写入为1-256字节,但是不能跨越256字节边界
|
||||
擦除指令,擦除指令后必须将CS拉高,否则不会执行
|
||||
*/
|
||||
|
||||
void FlashSetup(void) {
|
||||
// PA1 -> SPI_NCS3 chip select (MEM)
|
||||
// PA10 -> SPI_NCS2 chip select (LCD)
|
||||
// initialize
|
||||
bool FlashInit(bool fast) {
|
||||
FlashSetup(fast);
|
||||
|
||||
StartTicks();
|
||||
|
||||
if (Flash_CheckBusy(BUSY_TIMEOUT)) {
|
||||
StopTicks();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void FlashSetup(bool fast){
|
||||
//WDT_DISABLE
|
||||
AT91C_BASE_WDTC->WDTC_WDMR = AT91C_WDTC_WDDIS;
|
||||
|
||||
// PA10 -> SPI_NCS2 chip select (FLASHMEM)
|
||||
// PA11 -> SPI_NCS0 chip select (FPGA)
|
||||
// PA12 -> SPI_MISO Master-In Slave-Out
|
||||
// PA13 -> SPI_MOSI Master-Out Slave-In
|
||||
|
@ -54,27 +58,71 @@ void FlashSetup(void) {
|
|||
//enable the SPI Peripheral clock
|
||||
AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_SPI);
|
||||
|
||||
|
||||
//reset spi needs double SWRST, see atmel's errata on this case
|
||||
AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SWRST;
|
||||
AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SWRST;
|
||||
|
||||
// Enable SPI
|
||||
AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SPIEN;
|
||||
|
||||
// NPCS2 Mode 0
|
||||
AT91C_BASE_SPI->SPI_MR =
|
||||
( 0 << 24) | // Delay between chip selects (take default: 6 MCK periods)
|
||||
(0xB << 16) | // Peripheral Chip Select (selects SPI_NCS2 or PA10)
|
||||
( 0 << 7) | // Local Loopback Disabled
|
||||
( 1 << 4) | // Mode Fault Detection disabled
|
||||
( 0 << 2) | // Chip selects connected directly to peripheral
|
||||
( 0 << 1) | // Fixed Peripheral Select
|
||||
( 1 << 0); // Master Mode
|
||||
(0 << 24) | // Delay between chip selects = DYLBCS/MCK BUT:
|
||||
// If DLYBCS is less than or equal to six, six MCK periods
|
||||
// will be inserted by default.
|
||||
SPI_PCS(SPI_CSR_NUM) | // Peripheral Chip Select (selects SPI_NCS2 or PA10)
|
||||
( 0 << 7) | // Disable LLB (1=MOSI2MISO test mode)
|
||||
( 1 << 4) | // Disable ModeFault Protection
|
||||
( 0 << 3) | // makes spi operate at MCK (1 is MCK/2)
|
||||
( 0 << 2) | // Chip selects connected directly to peripheral
|
||||
AT91C_SPI_PS_FIXED | // Fixed Peripheral Select
|
||||
AT91C_SPI_MSTR; // Master Mode
|
||||
|
||||
int baudrate = FLASH_BAUD;
|
||||
uint8_t csaat = 1;
|
||||
int dlybct = 0;
|
||||
if (fast) {
|
||||
baudrate = FLASH_FASTBAUD;
|
||||
//csaat = 0;
|
||||
dlybct = MCK/32;
|
||||
}
|
||||
|
||||
// 8 bit
|
||||
AT91C_BASE_SPI->SPI_CSR[2] =
|
||||
( 0 << 24) | // Delay between Consecutive Transfers (32 MCK periods)
|
||||
( 0 << 16) | // Delay Before SPCK (1 MCK period)
|
||||
( 6 << 8) | // Serial Clock Baud Rate (baudrate = MCK/6 = 24Mhz/6 = 4M baud
|
||||
( 0 << 4) | // Bits per Transfer (8 bits)
|
||||
( 1 << 3) | // Chip Select inactive after transfer
|
||||
( 1 << 1) | // Clock Phase data captured on leading edge, changes on following edge
|
||||
SPI_DLYBCT(dlybct,MCK) | // Delay between Consecutive Transfers (32 MCK periods)
|
||||
SPI_DLYBS(0,MCK) | // Delay Beforce SPCK CLock
|
||||
SPI_SCBR(baudrate,MCK) | // SPI Baudrate Selection
|
||||
AT91C_SPI_BITS_8 | // Bits per Transfer (8 bits)
|
||||
//AT91C_SPI_CSAAT | // Chip Select inactive after transfer
|
||||
// 40.4.6.2 SPI: Bad tx_ready Behavior when CSAAT = 1 and SCBR = 1
|
||||
// If the SPI is programmed with CSAAT = 1, SCBR(baudrate) = 1 and two transfers are performed consecutively on
|
||||
// the same slave with an IDLE state between them, the tx_ready signal does not rise after the second data has been
|
||||
// transferred in the shifter. This can imply for example, that the second data is sent twice.
|
||||
// COLIN :: For now we STILL use CSAAT=1 to avoid having to (de)assert NPCS manually via PIO lines and we deal with delay
|
||||
( csaat << 3) |
|
||||
/* Spi modes:
|
||||
Mode CPOL CPHA NCPHA
|
||||
0 0 0 1 clock normally low read on rising edge
|
||||
1 0 1 0 clock normally low read on falling edge
|
||||
2 1 0 1 clock normally high read on falling edge
|
||||
3 1 1 0 clock normally high read on rising edge
|
||||
However, page 512 of the AT91SAM7Sx datasheet say "Note that in SPI
|
||||
master mode the ATSAM7S512/256/128/64/321/32 does not sample the data
|
||||
(MISO) on the opposite edge where data clocks out (MOSI) but the same
|
||||
edge is used as shown in Figure 36-3 and Figure 36-4." Figure 36-3
|
||||
shows that CPOL=NCPHA=0 or CPOL=NCPHA=1 samples on the rising edge and
|
||||
that the data changes sometime after the rising edge (about 2 ns). To
|
||||
be consistent with normal SPI operation, it is probably safe to say
|
||||
that the data changes on the falling edge and should be sampled on the
|
||||
rising edge. Therefore, it appears that NCPHA should be treated the
|
||||
same as CPHA. Thus:
|
||||
Mode CPOL CPHA NCPHA
|
||||
0 0 0 0 clock normally low read on rising edge
|
||||
1 0 1 1 clock normally low read on falling edge
|
||||
2 1 0 0 clock normally high read on falling edge
|
||||
3 1 1 1 clock normally high read on rising edge
|
||||
*/
|
||||
( 0 << 1) | // Clock Phase data captured on leading edge, changes on following edge
|
||||
( 0 << 0); // Clock Polarity inactive state is logic 0
|
||||
|
||||
// read first, empty buffer
|
||||
|
@ -82,6 +130,7 @@ void FlashSetup(void) {
|
|||
}
|
||||
|
||||
void FlashStop(void) {
|
||||
//Bof
|
||||
//* Reset all the Chip Select register
|
||||
AT91C_BASE_SPI->SPI_CSR[0] = 0;
|
||||
AT91C_BASE_SPI->SPI_CSR[1] = 0;
|
||||
|
@ -104,24 +153,21 @@ void FlashStop(void) {
|
|||
|
||||
// send one byte over SPI
|
||||
uint16_t FlashSendByte(uint32_t data) {
|
||||
uint16_t incoming = 0;
|
||||
|
||||
WDT_HIT();
|
||||
|
||||
// wait until SPI is ready for transfer
|
||||
while ((AT91C_BASE_SPI->SPI_SR & AT91C_SPI_TXEMPTY) == 0) {};
|
||||
//if you are checking for incoming data returned then the TXEMPTY flag is redundant
|
||||
//while ((AT91C_BASE_SPI->SPI_SR & AT91C_SPI_TXEMPTY) == 0) {};
|
||||
|
||||
// send the data
|
||||
AT91C_BASE_SPI->SPI_TDR = data;
|
||||
|
||||
while ((AT91C_BASE_SPI->SPI_SR & AT91C_SPI_TDRE) == 0){};
|
||||
|
||||
// wait recive transfer is complete
|
||||
while ((AT91C_BASE_SPI->SPI_SR & AT91C_SPI_RDRF) == 0)
|
||||
WDT_HIT();
|
||||
while ((AT91C_BASE_SPI->SPI_SR & AT91C_SPI_RDRF) == 0);
|
||||
|
||||
// reading incoming data
|
||||
incoming = ((AT91C_BASE_SPI->SPI_RDR) & 0xFFFF);
|
||||
|
||||
return incoming;
|
||||
return ((AT91C_BASE_SPI->SPI_RDR) & 0xFFFF);
|
||||
}
|
||||
|
||||
// send last byte over SPI
|
||||
|
@ -132,41 +178,35 @@ uint16_t FlashSendLastByte(uint32_t data) {
|
|||
// read state register 1
|
||||
uint8_t Flash_ReadStat1(void) {
|
||||
FlashSendByte(READSTAT1);
|
||||
uint8_t stat1 = FlashSendLastByte(0xFF);
|
||||
// if ( MF_DBGLEVEL > 3 ) Dbprintf("stat1 [%02x]", stat1);
|
||||
return stat1;
|
||||
return FlashSendLastByte(0xFF);
|
||||
}
|
||||
|
||||
// read state register 2
|
||||
uint8_t Flash_ReadStat2(void) {
|
||||
FlashSendByte(READSTAT2);
|
||||
uint8_t stat2 = FlashSendLastByte(0xFF);
|
||||
// if ( MF_DBGLEVEL > 3 ) Dbprintf("stat2 [%02x]", stat2);
|
||||
return stat2;
|
||||
}
|
||||
bool Flash_CheckBusy(uint32_t timeout)
|
||||
{
|
||||
WaitUS(WINBOND_WRITE_DELAY);
|
||||
StartCountUS();
|
||||
uint32_t _time = GetCountUS();
|
||||
|
||||
// determine whether FLASHMEM is busy
|
||||
bool Flash_CheckBusy(uint16_t times) {
|
||||
bool ret = (Flash_ReadStat1() & BUSY);
|
||||
do
|
||||
{
|
||||
if (!(Flash_ReadStat1() & BUSY))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
} while ((GetCountUS() - _time) < timeout);
|
||||
|
||||
if (!ret || !times || !(times--))
|
||||
return ret;
|
||||
|
||||
while (times) {
|
||||
WDT_HIT();
|
||||
SpinDelay(1);
|
||||
ret = (Flash_ReadStat1() & BUSY);
|
||||
if (!ret)
|
||||
break;
|
||||
times--;
|
||||
if (timeout <= (GetCountUS() - _time))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return ret;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// read ID out
|
||||
uint8_t Flash_ReadID(void) {
|
||||
|
||||
if (Flash_CheckBusy(100)) return 0;
|
||||
if (Flash_CheckBusy(BUSY_TIMEOUT)) return 0;
|
||||
|
||||
// Manufacture ID / device ID
|
||||
FlashSendByte(ID);
|
||||
|
@ -188,7 +228,7 @@ uint8_t Flash_ReadID(void) {
|
|||
// read unique id for chip.
|
||||
void Flash_UniqueID(uint8_t *uid) {
|
||||
|
||||
if (Flash_CheckBusy(100)) return;
|
||||
if (Flash_CheckBusy(BUSY_TIMEOUT)) return;
|
||||
|
||||
// reading unique serial number
|
||||
FlashSendByte(UNIQUE_ID);
|
||||
|
@ -209,12 +249,10 @@ void Flash_UniqueID(uint8_t *uid) {
|
|||
|
||||
uint16_t Flash_ReadData(uint32_t address, uint8_t *out, uint16_t len) {
|
||||
|
||||
if (!FlashInit()) return 0;
|
||||
|
||||
Flash_ReadStat1();
|
||||
|
||||
if (!FlashInit(0)) return 0;
|
||||
|
||||
// length should never be zero
|
||||
if (!len || Flash_CheckBusy(100)) return 0;
|
||||
if (!len || Flash_CheckBusy(BUSY_TIMEOUT)) return 0;
|
||||
|
||||
FlashSendByte(READDATA);
|
||||
FlashSendByte((address >> 16) & 0xFF);
|
||||
|
@ -231,6 +269,55 @@ uint16_t Flash_ReadData(uint32_t address, uint8_t *out, uint16_t len) {
|
|||
return len;
|
||||
}
|
||||
|
||||
/* This ensure we can ReadData without having to cycle through initialization everytime */
|
||||
uint16_t Flash_ReadDataCont(uint32_t address, uint8_t *out, uint16_t len) {
|
||||
|
||||
// length should never be zero
|
||||
if (!len) return 0;
|
||||
|
||||
FlashSendByte(READDATA);
|
||||
FlashSendByte((address >> 16) & 0xFF);
|
||||
FlashSendByte((address >> 8) & 0xFF);
|
||||
FlashSendByte((address >> 0) & 0xFF);
|
||||
|
||||
uint16_t i = 0;
|
||||
for (; i < (len - 1); i++)
|
||||
out[i] = FlashSendByte(0xFF);
|
||||
|
||||
out[i] = FlashSendLastByte(0xFF);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
uint16_t Flash_FastReadDataCont(uint32_t address, uint8_t *out, uint16_t len) {
|
||||
|
||||
// length should never be zero
|
||||
if (!len) return 0;
|
||||
|
||||
//if (Flash_CheckBusy(BUSY_TIMEOUT))
|
||||
//{return 0;}
|
||||
|
||||
FlashSendByte(FASTREAD);
|
||||
FlashSendByte((address >> 16) & 0xFF);
|
||||
FlashSendByte((address >> 8) & 0xFF);
|
||||
FlashSendByte((address >> 0) & 0xFF);
|
||||
FlashSendByte(0xFF);
|
||||
//Flash_CheckBusy(BUSY_TIMEOUT);
|
||||
|
||||
|
||||
uint16_t i = 0;
|
||||
for (; i < (len - 1); i++)
|
||||
out[i] = FlashSendByte(0xFF);
|
||||
|
||||
out[i] = FlashSendLastByte(0xFF);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////
|
||||
|
||||
// Write data can only program one page. A page has 256 bytes.
|
||||
// if len > 256, it might wrap around and overwrite pos 0.
|
||||
uint16_t Flash_WriteData(uint32_t address, uint8_t *in, uint16_t len) {
|
||||
|
@ -251,12 +338,13 @@ uint16_t Flash_WriteData(uint32_t address, uint8_t *in, uint16_t len) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (!FlashInit()) {
|
||||
if (!FlashInit(0)) {
|
||||
if ( MF_DBGLEVEL > 3 ) Dbprintf("Flash_WriteData init fail");
|
||||
return 0;
|
||||
}
|
||||
|
||||
Flash_ReadStat1();
|
||||
Flash_CheckBusy(BUSY_TIMEOUT);
|
||||
//Flash_ReadStat1();
|
||||
|
||||
Flash_WriteEnable();
|
||||
|
||||
|
@ -275,22 +363,61 @@ uint16_t Flash_WriteData(uint32_t address, uint8_t *in, uint16_t len) {
|
|||
return len;
|
||||
}
|
||||
|
||||
uint16_t Flash_WriteDataCont(uint32_t address, uint8_t *in, uint16_t len) {
|
||||
|
||||
// length should never be zero
|
||||
if (!len)
|
||||
return 0;
|
||||
|
||||
// Max 256 bytes write
|
||||
if (((address & 0xFF) + len) > 256) {
|
||||
Dbprintf("Flash_WriteData 256 fail [ 0x%02x ] [ %u ]", (address & 0xFF)+len, len );
|
||||
return 0;
|
||||
}
|
||||
|
||||
// out-of-range
|
||||
if ( (( address >> 16 ) & 0xFF ) > MAX_BLOCKS) {
|
||||
Dbprintf("Flash_WriteData, block out-of-range");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//Flash_CheckBusy(100);
|
||||
//SpinDelay(1);
|
||||
Flash_CheckBusy(BUSY_TIMEOUT);
|
||||
//Flash_ReadStat1();
|
||||
Flash_WriteEnable();
|
||||
|
||||
FlashSendByte(PAGEPROG);
|
||||
FlashSendByte((address >> 16) & 0xFF);
|
||||
FlashSendByte((address >> 8) & 0xFF);
|
||||
FlashSendByte((address >> 0) & 0xFF);
|
||||
|
||||
uint16_t i = 0;
|
||||
for (; i < (len - 1); i++)
|
||||
FlashSendByte(in[i]);
|
||||
|
||||
FlashSendLastByte(in[i]);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
bool Flash_WipeMemoryPage(uint8_t page) {
|
||||
if (!FlashInit()) {
|
||||
if (!FlashInit(0)) {
|
||||
if ( MF_DBGLEVEL > 3 ) Dbprintf("Flash_WriteData init fail");
|
||||
return false;
|
||||
}
|
||||
Flash_ReadStat1();
|
||||
|
||||
// Each block is 64Kb. One block erase takes 1s ( 1000ms )
|
||||
Flash_WriteEnable(); Flash_Erase64k(page); Flash_CheckBusy(1000);
|
||||
Flash_WriteEnable(); Flash_Erase64k(page); Flash_CheckBusy(BUSY_TIMEOUT);
|
||||
|
||||
FlashStop();
|
||||
return true;
|
||||
}
|
||||
// Wipes flash memory completely, fills with 0xFF
|
||||
bool Flash_WipeMemory() {
|
||||
if (!FlashInit()) {
|
||||
if (!FlashInit(0)) {
|
||||
if ( MF_DBGLEVEL > 3 ) Dbprintf("Flash_WriteData init fail");
|
||||
return false;
|
||||
}
|
||||
|
@ -298,10 +425,10 @@ bool Flash_WipeMemory() {
|
|||
|
||||
// Each block is 64Kb. Four blocks
|
||||
// one block erase takes 1s ( 1000ms )
|
||||
Flash_WriteEnable(); Flash_Erase64k(0); Flash_CheckBusy(1000);
|
||||
Flash_WriteEnable(); Flash_Erase64k(1); Flash_CheckBusy(1000);
|
||||
Flash_WriteEnable(); Flash_Erase64k(2); Flash_CheckBusy(1000);
|
||||
Flash_WriteEnable(); Flash_Erase64k(3); Flash_CheckBusy(1000);
|
||||
Flash_WriteEnable(); Flash_Erase64k(0); Flash_CheckBusy(BUSY_TIMEOUT);
|
||||
Flash_WriteEnable(); Flash_Erase64k(1); Flash_CheckBusy(BUSY_TIMEOUT);
|
||||
Flash_WriteEnable(); Flash_Erase64k(2); Flash_CheckBusy(BUSY_TIMEOUT);
|
||||
Flash_WriteEnable(); Flash_Erase64k(3); Flash_CheckBusy(BUSY_TIMEOUT);
|
||||
|
||||
FlashStop();
|
||||
return true;
|
||||
|
@ -366,25 +493,13 @@ void Flash_EraseChip(void) {
|
|||
FlashSendLastByte(CHIPERASE);
|
||||
}
|
||||
|
||||
// initialize
|
||||
bool FlashInit(void) {
|
||||
FlashSetup();
|
||||
|
||||
StartTicks();
|
||||
|
||||
if (Flash_CheckBusy(100)) {
|
||||
StopTicks();
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( MF_DBGLEVEL > 3 ) Dbprintf("FlashInit OK");
|
||||
return true;
|
||||
}
|
||||
|
||||
void Flashmem_print_status(void) {
|
||||
DbpString("Flash memory");
|
||||
|
||||
if (!FlashInit()) {
|
||||
if (!FlashInit(0)) {
|
||||
DbpString(" init....................FAIL");
|
||||
return;
|
||||
}
|
||||
|
@ -414,4 +529,4 @@ void Flashmem_print_status(void) {
|
|||
);
|
||||
|
||||
FlashStop();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
#define WRITEENABLE 0x06
|
||||
|
||||
#define READDATA 0x03
|
||||
#define FASTREAD 0x0B
|
||||
#define PAGEPROG 0x02
|
||||
|
||||
#define SECTORERASE 0x20
|
||||
|
@ -57,27 +58,17 @@
|
|||
// Not used or not support command
|
||||
#define RELEASE 0xAB
|
||||
#define POWERDOWN 0xB9
|
||||
#define FASTREAD 0x0B
|
||||
#define SUSPEND 0x75
|
||||
#define RESUME 0x7A
|
||||
|
||||
#define BUSY_TIMEOUT 1000000000L
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
|
||||
// Chip specific instructions //
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~ Winbond ~~~~~~~~~~~~~~~~~~~~~~~~~//
|
||||
#define WINBOND_MANID 0xEF
|
||||
#define WINBOND_DEVID 0x11
|
||||
#define PAGESIZE 0x100
|
||||
#define WINBOND_WRITE_DELAY 0x02
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~ Microchip ~~~~~~~~~~~~~~~~~~~~~~~~//
|
||||
#define MICROCHIP_MANID 0xBF
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
|
||||
// Definitions //
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
|
||||
|
||||
#define SPI_CLK 75000000 //Hex equivalent of 75MHz
|
||||
#define SPI_CLK 48000000
|
||||
|
||||
#define BUSY 0x01
|
||||
#define WRTEN 0x02
|
||||
|
@ -113,14 +104,17 @@
|
|||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
|
||||
extern void Dbprintf(const char *fmt, ...);
|
||||
|
||||
void FlashSetup(void);
|
||||
bool FlashInit(bool fast);
|
||||
void FlashSetup(bool fast);
|
||||
void FlashStop(void);
|
||||
bool Flash_WaitIdle(void);
|
||||
uint8_t Flash_ReadStat1(void);
|
||||
uint8_t Flash_ReadStat2(void);
|
||||
uint16_t FlashSendByte(uint32_t data);
|
||||
|
||||
bool Flash_CheckBusy(uint32_t timeout);
|
||||
|
||||
|
||||
void Flash_WriteEnable();
|
||||
bool Flash_WipeMemoryPage(uint8_t page);
|
||||
bool Flash_WipeMemory();
|
||||
|
@ -128,12 +122,16 @@ bool Flash_Erase4k(uint8_t block, uint8_t sector);
|
|||
//bool Flash_Erase32k(uint32_t address);
|
||||
bool Flash_Erase64k(uint8_t block);
|
||||
|
||||
bool FlashInit();
|
||||
|
||||
void Flash_UniqueID(uint8_t *uid);
|
||||
uint8_t Flash_ReadID(void);
|
||||
uint16_t Flash_ReadData(uint32_t address, uint8_t *out, uint16_t len);
|
||||
|
||||
uint16_t Flash_ReadDataCont(uint32_t address, uint8_t *out, uint16_t len);
|
||||
uint16_t Flash_FastReadDataCont(uint32_t address, uint8_t *out, uint16_t len);
|
||||
|
||||
uint16_t Flash_WriteData(uint32_t address, uint8_t *in, uint16_t len);
|
||||
uint16_t Flash_WriteDataCont(uint32_t address, uint8_t *in, uint16_t len);
|
||||
void Flashmem_print_status(void);
|
||||
|
||||
#endif
|
|
@ -15,9 +15,10 @@
|
|||
static int CmdHelp(const char *Cmd);
|
||||
int usage_flashmem_read(void){
|
||||
PrintAndLogEx(NORMAL, "Read flash memory on device");
|
||||
PrintAndLogEx(NORMAL, "Usage: mem read o <offset> l <len>");
|
||||
PrintAndLogEx(NORMAL, "Usage: mem read o <offset> l <len> [f]");
|
||||
PrintAndLogEx(NORMAL, " o <offset> : offset in memory");
|
||||
PrintAndLogEx(NORMAL, " l <len> : length");
|
||||
PrintAndLogEx(NORMAL, " f : fastRead mode");
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(NORMAL, "Examples:");
|
||||
PrintAndLogEx(NORMAL, " mem read o 0 l 32"); // read 32 bytes starting at offset 0
|
||||
|
@ -41,6 +42,7 @@ int usage_flashmem_save(void){
|
|||
PrintAndLogEx(NORMAL, " o <offset> : offset in memory");
|
||||
PrintAndLogEx(NORMAL, " l <length> : length");
|
||||
PrintAndLogEx(NORMAL, " f <filename> : file name");
|
||||
PrintAndLogEx(NORMAL, " + : fast read mode");
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(NORMAL, "Examples:");
|
||||
PrintAndLogEx(NORMAL, " mem save f myfile"); // download whole flashmem to file myfile
|
||||
|
@ -79,9 +81,14 @@ int CmdFlashMemRead(const char *Cmd) {
|
|||
uint8_t cmdp = 0;
|
||||
bool errors = false;
|
||||
uint32_t start_index = 0, len = 0;
|
||||
uint8_t fast = 0;
|
||||
|
||||
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
|
||||
switch (tolower(param_getchar(Cmd, cmdp))) {
|
||||
case 'f':
|
||||
fast = 1;
|
||||
cmdp += 1;
|
||||
break;
|
||||
case 'o':
|
||||
start_index = param_get32ex(Cmd, cmdp+1, 0, 10);
|
||||
cmdp += 2;
|
||||
|
@ -107,7 +114,7 @@ int CmdFlashMemRead(const char *Cmd) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
UsbCommand c = {CMD_READ_FLASH_MEM, {start_index, len, 0}};
|
||||
UsbCommand c = {CMD_READ_FLASH_MEM, {start_index, len, fast}};
|
||||
clearCommandBuffer();
|
||||
SendCommand(&c);
|
||||
return 0;
|
||||
|
@ -221,6 +228,7 @@ int CmdFlashMemSave(const char *Cmd){
|
|||
uint8_t cmdp = 0;
|
||||
bool errors = false;
|
||||
uint32_t start_index = 0, len = FLASH_MEM_MAX_SIZE;
|
||||
uint8_t fast = 0;
|
||||
|
||||
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
|
||||
switch (tolower(param_getchar(Cmd, cmdp))) {
|
||||
|
@ -233,6 +241,10 @@ int CmdFlashMemSave(const char *Cmd){
|
|||
start_index = param_get32ex(Cmd, cmdp+1, 0, 10);
|
||||
cmdp += 2;
|
||||
break;
|
||||
case '+':
|
||||
fast = 1;
|
||||
cmdp += 1;
|
||||
break;
|
||||
case 'f':
|
||||
//File handling
|
||||
if ( param_getstr(Cmd, cmdp+1, filename, FILE_PATH_SIZE) >= FILE_PATH_SIZE ) {
|
||||
|
|
|
@ -199,7 +199,31 @@ void UsbCommandReceived(UsbCommand* _ch) {
|
|||
memset(s, 0x00, sizeof(s));
|
||||
size_t len = MIN(c->arg[0], USB_CMD_DATA_SIZE);
|
||||
memcpy(s, c->d.asBytes, len);
|
||||
|
||||
|
||||
//#define FLAG_RAWPRINT 0x0111
|
||||
//#define FLAG_NOOPT 0x0000
|
||||
//#define FLAG_NOLOG 0x0001
|
||||
//#define FLAG_NONEWLINE 0x0010
|
||||
//#define FLAG_NOPROMPT 0x0100
|
||||
uint64_t flag = c->arg[1];
|
||||
if (flag > 0) { // FLAG_RAWPRINT) {
|
||||
switch (flag) {
|
||||
case FLAG_RAWPRINT: {
|
||||
printf("%s", s);
|
||||
} return; break;
|
||||
case FLAG_NONEWLINE: {
|
||||
printf("%s\r", s);
|
||||
} return; break;
|
||||
case FLAG_NOLOG: {
|
||||
printf("%s\r\n", s);
|
||||
} return; break;
|
||||
// printf("%s", s);
|
||||
fflush(stdout);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// print debug line on same row. escape seq \r
|
||||
if ( c->arg[1] == CMD_MEASURE_ANTENNA_TUNING_HF) {
|
||||
PrintAndLogEx(NORMAL, "\r#db# %s", s);
|
||||
|
|
Loading…
Reference in a new issue