mirror of
https://github.com/RfidResearchGroup/ChameleonMini.git
synced 2026-05-12 11:20:37 -07:00
Due to some readers and/or card standards there might be problems with
the comparatively large write times of the external flash memory. This is why we are looking for a better solution on this problem in the next hardware revision. Having the memory concept of future revisions in mind, we changed the firmware from it's current memory concept, which is using the external flash as a direct memory for reading/writing of card (or application) memory contents to a different one. With this new version, the memory that is directly accessed by the application (through MemoryWrite and MemoryRead) now resides within the local RAM of the microcontroller, thus limiting the maximum card size to 1KB. However, the flash is still used to store multiple other card dumps, that are now recalled and stored upon 1) Changing the current setting to another card. This applies also to using the CYCLE_SETTINGS button action. 2) The newly introduced button actions MEM_RECALL and MEM_STORE Consider this new concept as a feature, since it is now easily possible to, for example emulate a payment card and recall the original contents (stored in flash) upon button press. However, note that the modified card contents are lost, if they are not written back to flash before powering the Chameleon off. For the future we are thinking about using external non-volatile RAM to store the current card to prevent this from happening. That way, we can have a very consistent memory concept and are still able to recall or store the memory from flash. Note that the previous Firmware version that uses the flash in a direct fashion is still available for those that don't care about the write times and need the full unlimited memory size.
This commit is contained in:
@@ -57,6 +57,7 @@
|
||||
#include "Random.h"
|
||||
#include "Common.h"
|
||||
#include "Settings.h"
|
||||
#include "Memory.h"
|
||||
|
||||
static const char PROGMEM ButtonActionTable[][32] =
|
||||
{
|
||||
@@ -66,7 +67,9 @@ static const char PROGMEM ButtonActionTable[][32] =
|
||||
[BUTTON_ACTION_UID_RIGHT_INCREMENT] = "UID_RIGHT_INCREMENT",
|
||||
[BUTTON_ACTION_UID_LEFT_DECREMENT] = "UID_LEFT_DECREMENT",
|
||||
[BUTTON_ACTION_UID_RIGHT_DECREMENT] = "UID_RIGHT_DECREMENT",
|
||||
[BUTTON_ACTION_CYCLE_SETTINGS] = "CYCLE_SETTINGS"
|
||||
[BUTTON_ACTION_CYCLE_SETTINGS] = "CYCLE_SETTINGS",
|
||||
[BUTTON_ACTION_STORE_MEM] = "STORE_MEM",
|
||||
[BUTTON_ACTION_RECALL_MEM] = "RECALL_MEM",
|
||||
};
|
||||
|
||||
void ButtonInit(void)
|
||||
@@ -167,6 +170,10 @@ void ButtonTick(void)
|
||||
ApplicationSetUid(UidBuffer);
|
||||
} else if (ButtonAction == BUTTON_ACTION_CYCLE_SETTINGS) {
|
||||
SettingsCycle();
|
||||
} else if (ButtonAction == BUTTON_ACTION_STORE_MEM) {
|
||||
MemoryStore();
|
||||
} else if (ButtonAction == BUTTON_ACTION_RECALL_MEM) {
|
||||
MemoryRecall();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -202,7 +209,14 @@ void ButtonGetActionList(char* ListOut, uint16_t BufferSize)
|
||||
|
||||
void ButtonSetActionById(ButtonActionEnum Action)
|
||||
{
|
||||
#ifndef BUTTON_SETTING_GLOBAL
|
||||
GlobalSettings.ActiveSettingPtr->ButtonAction = Action;
|
||||
#else
|
||||
/* Write button action to all settings when using global settings */
|
||||
for (uint8_t i=0; i<SETTINGS_COUNT; i++) {
|
||||
GlobalSettings.Settings[i].ButtonAction = Action;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void ButtonGetActionByName(char* ActionOut, uint16_t BufferSize)
|
||||
@@ -224,3 +238,4 @@ bool ButtonSetActionByName(const char* Action)
|
||||
/* Button action not found */
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -72,6 +72,8 @@ typedef enum {
|
||||
BUTTON_ACTION_UID_LEFT_DECREMENT,
|
||||
BUTTON_ACTION_UID_RIGHT_DECREMENT,
|
||||
BUTTON_ACTION_CYCLE_SETTINGS,
|
||||
BUTTON_ACTION_STORE_MEM,
|
||||
BUTTON_ACTION_RECALL_MEM,
|
||||
|
||||
/* This has to be last element */
|
||||
BUTTON_ACTION_COUNT
|
||||
|
||||
Binary file not shown.
@@ -1,3 +1,3 @@
|
||||
:1000000000002106000600060006000600060006A5
|
||||
:1000000000002506000600060006000600060006A1
|
||||
:03001000000600E7
|
||||
:00000001FF
|
||||
|
||||
Binary file not shown.
+1308
-1250
File diff suppressed because it is too large
Load Diff
+10280
-9506
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -53,6 +53,7 @@
|
||||
* policies, either expressed or implied, of the ORIGINAL AUTHORS.
|
||||
*/
|
||||
|
||||
|
||||
#include "Memory.h"
|
||||
#include "Configuration.h"
|
||||
#include "Common.h"
|
||||
@@ -72,6 +73,10 @@
|
||||
#define FLASH_STATUS_REG_PROTECT_BIT (1<<1)
|
||||
#define FLASH_STATUS_REG_PAGESIZE_BIT (1<<0)
|
||||
|
||||
#define FLASH_PAGE_SIZE 256
|
||||
|
||||
static uint8_t Memory[MEMORY_SIZE_PER_SETTING];
|
||||
|
||||
INLINE uint8_t SPITransferByte(uint8_t Data)
|
||||
{
|
||||
MEMORY_FLASH_USART.DATA = Data;
|
||||
@@ -188,9 +193,9 @@ INLINE void FlashRead(void* Buffer, uint32_t Address, uint16_t ByteCount)
|
||||
INLINE void FlashWrite(const void* Buffer, uint32_t Address, uint16_t ByteCount)
|
||||
{
|
||||
while(ByteCount > 0) {
|
||||
uint16_t PageAddress = Address / MEMORY_PAGE_SIZE;
|
||||
uint8_t ByteAddress = Address % MEMORY_PAGE_SIZE;
|
||||
uint16_t PageBytes = MIN(MEMORY_PAGE_SIZE - ByteAddress, ByteCount);
|
||||
uint16_t PageAddress = Address / FLASH_PAGE_SIZE;
|
||||
uint8_t ByteAddress = Address % FLASH_PAGE_SIZE;
|
||||
uint16_t PageBytes = MIN(FLASH_PAGE_SIZE - ByteAddress, ByteCount);
|
||||
|
||||
FlashMemoryToBuffer(PageAddress);
|
||||
FlashWriteBuffer(Buffer, ByteAddress, PageBytes);
|
||||
@@ -233,32 +238,56 @@ void MemoryInit(void)
|
||||
/* Configure for 256 byte Dataflash if not already done. */
|
||||
FlashConfigurePageSize();
|
||||
}
|
||||
|
||||
/* Load permanent flash contents to memory at startup */
|
||||
MemoryRecall();
|
||||
}
|
||||
|
||||
void MemoryReadBlock(void* Buffer, uint16_t Address, uint16_t ByteCount)
|
||||
{
|
||||
uint32_t FlashAddress = (uint32_t) Address + (uint32_t) GlobalSettings.ActiveSetting * MEMORY_SIZE_PER_SETTING;
|
||||
FlashRead(Buffer, FlashAddress, ByteCount);
|
||||
uint8_t* SrcPtr = &Memory[Address];
|
||||
uint8_t* DstPtr = (uint8_t*) Buffer;
|
||||
|
||||
/* Prevent Buf Ovfs */
|
||||
ByteCount = MIN(ByteCount, MEMORY_SIZE_PER_SETTING - Address);
|
||||
|
||||
while(ByteCount--) {
|
||||
*DstPtr++ = *SrcPtr++;
|
||||
}
|
||||
}
|
||||
|
||||
void MemoryWriteBlock(const void* Buffer, uint16_t Address, uint16_t ByteCount)
|
||||
{
|
||||
uint32_t FlashAddress = (uint32_t) Address + (uint32_t) GlobalSettings.ActiveSetting * MEMORY_SIZE_PER_SETTING;
|
||||
FlashWrite(Buffer, FlashAddress, ByteCount);
|
||||
uint8_t* SrcPtr = (uint8_t*) Buffer;
|
||||
uint8_t* DstPtr = &Memory[Address];
|
||||
|
||||
/* Prevent Buf Ovfs */
|
||||
ByteCount = MIN(ByteCount, MEMORY_SIZE_PER_SETTING - Address);
|
||||
|
||||
while(ByteCount--) {
|
||||
*DstPtr++ = *SrcPtr++;
|
||||
}
|
||||
}
|
||||
|
||||
void MemoryClear(void)
|
||||
{
|
||||
uint32_t PageAddress = ((uint32_t) GlobalSettings.ActiveSetting * MEMORY_SIZE_PER_SETTING) / MEMORY_PAGE_SIZE;
|
||||
uint16_t PageCount = MEMORY_SIZE_PER_SETTING / MEMORY_PAGE_SIZE;
|
||||
|
||||
while(PageCount > 0) {
|
||||
FlashClearPage(PageAddress);
|
||||
PageCount--;
|
||||
PageAddress++;
|
||||
for (uint16_t i=0; i<MEMORY_SIZE_PER_SETTING; i++) {
|
||||
Memory[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void MemoryRecall(void)
|
||||
{
|
||||
/* Recall memory from permanent flash */
|
||||
FlashRead(Memory, (uint32_t) GlobalSettings.ActiveSetting * MEMORY_SIZE_PER_SETTING, MEMORY_SIZE_PER_SETTING);
|
||||
}
|
||||
|
||||
void MemoryStore(void)
|
||||
{
|
||||
/* Store current memory into permanent flash */
|
||||
FlashWrite(Memory, (uint32_t) GlobalSettings.ActiveSetting * MEMORY_SIZE_PER_SETTING, MEMORY_SIZE_PER_SETTING);
|
||||
}
|
||||
|
||||
bool MemoryUploadBlock(void* Buffer, uint32_t BlockAddress, uint16_t ByteCount)
|
||||
{
|
||||
if (BlockAddress >= MEMORY_SIZE_PER_SETTING) {
|
||||
@@ -267,10 +296,23 @@ bool MemoryUploadBlock(void* Buffer, uint32_t BlockAddress, uint16_t ByteCount)
|
||||
} else {
|
||||
/* Calculate bytes left in memory and start writing */
|
||||
uint32_t BytesLeft = MEMORY_SIZE_PER_SETTING - BlockAddress;
|
||||
ByteCount = MIN(ByteCount, BytesLeft);
|
||||
MemoryWriteBlock(Buffer, BlockAddress, ByteCount);
|
||||
uint32_t FlashAddress = (uint32_t) BlockAddress + (uint32_t) GlobalSettings.ActiveSetting * MEMORY_SIZE_PER_SETTING;
|
||||
ByteCount = MIN(ByteCount, BytesLeft);
|
||||
|
||||
/* Store into flash */
|
||||
FlashWrite(Buffer, FlashAddress, ByteCount);
|
||||
|
||||
/* Store to local memory */
|
||||
uint8_t* DstPtr = &Memory[BlockAddress];
|
||||
uint8_t* SrcPtr = (uint8_t*) Buffer;
|
||||
|
||||
while(ByteCount--) {
|
||||
*DstPtr++ = *SrcPtr++;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool MemoryDownloadBlock(void* Buffer, uint32_t BlockAddress, uint16_t ByteCount)
|
||||
@@ -281,9 +323,17 @@ bool MemoryDownloadBlock(void* Buffer, uint32_t BlockAddress, uint16_t ByteCount
|
||||
} else {
|
||||
/* Calculate bytes left in memory and issue reading */
|
||||
uint32_t BytesLeft = MEMORY_SIZE_PER_SETTING - BlockAddress;
|
||||
ByteCount = MIN(ByteCount, BytesLeft);
|
||||
MemoryReadBlock(Buffer, BlockAddress, ByteCount);
|
||||
//uint32_t FlashAddress = (uint32_t) BlockAddress + (uint32_t) GlobalSettings.ActiveSetting * MEMORY_SIZE_PER_SETTING;
|
||||
ByteCount = MIN(ByteCount, BytesLeft);
|
||||
|
||||
/* Output local memory contents */
|
||||
uint8_t* DstPtr = (uint8_t*) Buffer;
|
||||
uint8_t* SrcPtr = &Memory[BlockAddress];
|
||||
|
||||
while(ByteCount--) {
|
||||
*DstPtr++ = *SrcPtr++;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -65,16 +65,20 @@
|
||||
#define MEMORY_FLASH_MISO PIN2_bm
|
||||
#define MEMORY_FLASH_SCK PIN1_bm
|
||||
|
||||
#define MEMORY_PAGE_SIZE 256
|
||||
#define MEMORY_SIZE_PER_SETTING ((uint32_t) 256 * MEMORY_PAGE_SIZE) /* Multiple of memory page size */
|
||||
#define MEMORY_SIZE_PER_SETTING 1024
|
||||
|
||||
void MemoryInit(void);
|
||||
void MemoryReadBlock(void* Buffer, uint16_t Address, uint16_t ByteCount);
|
||||
void MemoryWriteBlock(const void* Buffer, uint16_t Address, uint16_t ByteCount);
|
||||
void MemoryClear(void);
|
||||
|
||||
|
||||
void MemoryRecall(void);
|
||||
void MemoryStore(void);
|
||||
|
||||
/* For use with XModem */
|
||||
bool MemoryUploadBlock(void* Buffer, uint32_t BlockAddress, uint16_t ByteCount);
|
||||
bool MemoryDownloadBlock(void* Buffer, uint32_t BlockAddress, uint16_t ByteCount);
|
||||
|
||||
#endif /* MEMORY_H_ */
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
@ECHO OFF
|
||||
SET COMPORT=COM21
|
||||
SET COMPORT=COM5
|
||||
SET BATCHISP=C:\Programme\Atmel\Flip 3.4.7\bin
|
||||
SET TIMEOUT=5
|
||||
SET COMMAND=UPGRADE
|
||||
|
||||
@@ -94,12 +94,18 @@ void SettingsCycle(void) {
|
||||
|
||||
void SettingsSetActiveById(uint8_t Setting) {
|
||||
if (Setting < SETTINGS_COUNT) {
|
||||
/* Store current memory contents permanently */
|
||||
MemoryStore();
|
||||
|
||||
GlobalSettings.ActiveSetting = Setting;
|
||||
GlobalSettings.ActiveSettingPtr =
|
||||
&GlobalSettings.Settings[GlobalSettings.ActiveSetting];
|
||||
|
||||
/* Settings have changed. Progress changes through system */
|
||||
ConfigurationInit();
|
||||
|
||||
/* Recall new memory contents */
|
||||
MemoryRecall();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user