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:
Simon Küppers
2014-05-11 14:23:53 +02:00
parent 1232afc470
commit b6b005c74a
13 changed files with 12963 additions and 12038 deletions
+16 -1
View File
@@ -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;
}
+2
View File
@@ -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 -1
View File
@@ -1,3 +1,3 @@
:1000000000002106000600060006000600060006A5
:1000000000002506000600060006000600060006A1
:03001000000600E7
:00000001FF
Binary file not shown.
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
File diff suppressed because it is too large Load Diff
+70 -20
View File
@@ -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;
}
}
}
+6 -2
View File
@@ -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
+6
View File
@@ -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();
}
}