mirror of
https://github.com/drasko/open-ameba.git
synced 2025-02-15 16:45:18 +00:00
220 lines
6.8 KiB
C
220 lines
6.8 KiB
C
/*
|
|
* Routines to access hardware
|
|
*
|
|
* Copyright (c) 2015 Realtek Semiconductor Corp.
|
|
*
|
|
* This module is a confidential and proprietary property of RealTek and
|
|
* possession or use of this module requires written permission of RealTek.
|
|
*/
|
|
|
|
#include "cmsis_os.h"
|
|
|
|
#include "diag.h"
|
|
#include "main.h"
|
|
|
|
#include "nfc_api.h"
|
|
#include "flash_api.h"
|
|
|
|
#define NFC_RESTORE_DEFAULT (0)
|
|
|
|
#define NFC_MAX_PAGE_NUM 36
|
|
nfctag_t nfctag;
|
|
unsigned int nfc_tag_content[NFC_MAX_PAGE_NUM];
|
|
unsigned char nfc_tag_dirty[NFC_MAX_PAGE_NUM];
|
|
|
|
#define RTK_NFC_UID 0x58
|
|
unsigned char nfc_default_uid[7] = {
|
|
RTK_NFC_UID, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06
|
|
};
|
|
|
|
osThreadId nfc_tid = 0;
|
|
|
|
#define FLASH_APP_NFC_BASE 0x85000
|
|
flash_t flash_nfc;
|
|
|
|
void nfc_event_listener(void *arg, unsigned int event) {
|
|
switch(event) {
|
|
case NFC_EV_READER_PRESENT:
|
|
DiagPrintf("NFC_EV_READER_PRESENT\r\n");
|
|
break;
|
|
case NFC_EV_READ:
|
|
DiagPrintf("NFC_EV_READ\r\n");
|
|
break;
|
|
case NFC_EV_WRITE:
|
|
DiagPrintf("NFC_EV_WRITE\r\n");
|
|
break;
|
|
case NFC_EV_ERR:
|
|
DiagPrintf("NFC_EV_ERR\r\n");
|
|
break;
|
|
case NFC_EV_CACHE_READ:
|
|
DiagPrintf("NFC_EV_CACHE_READ\r\n");
|
|
break;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* This callback function is called several times if tag is being written multiple pages.
|
|
* DO NOT put heavy task here otherwise it will block tag write and cause timeout failure.
|
|
**/
|
|
void nfc_write_listener(void *arg, unsigned int page, unsigned int pgdat) {
|
|
nfc_tag_content[page] = pgdat;
|
|
nfc_tag_dirty[page] = 1;
|
|
if (nfc_tid) {
|
|
osSignalSet(nfc_tid, NFC_EV_WRITE);
|
|
}
|
|
}
|
|
|
|
int is_valid_nfc_uid() {
|
|
int valid_content = 1;
|
|
|
|
unsigned char uid[7];
|
|
unsigned char bcc[2];
|
|
|
|
uid[0] = (unsigned char)((nfc_tag_content[0] & 0x000000FF) >> 0);
|
|
uid[1] = (unsigned char)((nfc_tag_content[0] & 0x0000FF00) >> 8);
|
|
uid[2] = (unsigned char)((nfc_tag_content[0] & 0x00FF0000) >> 16);
|
|
bcc[0] = (unsigned char)((nfc_tag_content[0] & 0xFF000000) >> 24);
|
|
uid[3] = (unsigned char)((nfc_tag_content[1] & 0x000000FF) >> 0);
|
|
uid[4] = (unsigned char)((nfc_tag_content[1] & 0x0000FF00) >> 8);
|
|
uid[5] = (unsigned char)((nfc_tag_content[1] & 0x00FF0000) >> 16);
|
|
uid[6] = (unsigned char)((nfc_tag_content[1] & 0xFF000000) >> 24);
|
|
bcc[1] = (unsigned char)((nfc_tag_content[2] & 0x000000FF) >> 0);
|
|
|
|
// verify Block Check Character
|
|
if (bcc[0] != (0x88 ^ uid[0] ^ uid[1] ^ uid[2])) {
|
|
valid_content = 0;
|
|
}
|
|
if (bcc[1] != (uid[3] ^ uid[4] ^ uid[5] ^ uid[6])) {
|
|
valid_content = 0;
|
|
}
|
|
|
|
return valid_content;
|
|
}
|
|
|
|
unsigned int generate_default_tag_content() {
|
|
unsigned int page_size = 0;
|
|
|
|
memset(nfc_tag_content, 0, NFC_MAX_PAGE_NUM * sizeof(unsigned int));
|
|
|
|
// calculate Block Check Character
|
|
unsigned char bcc[2];
|
|
bcc[0] = 0x88 ^ nfc_default_uid[0] ^ nfc_default_uid[1] ^ nfc_default_uid[2];
|
|
bcc[1] = nfc_default_uid[3] ^ nfc_default_uid[4] ^ nfc_default_uid[5] ^ nfc_default_uid[6];
|
|
|
|
// generate header
|
|
nfc_tag_content[page_size++] = ((unsigned int)nfc_default_uid[0]) << 0 |
|
|
((unsigned int)nfc_default_uid[1]) << 8 |
|
|
((unsigned int)nfc_default_uid[2]) << 16 |
|
|
((unsigned int) bcc[0]) << 24;
|
|
nfc_tag_content[page_size++] = ((unsigned int)nfc_default_uid[3]) << 0 |
|
|
((unsigned int)nfc_default_uid[4]) << 8 |
|
|
((unsigned int)nfc_default_uid[5]) << 16 |
|
|
((unsigned int)nfc_default_uid[6]) << 24;
|
|
nfc_tag_content[page_size++] = ((unsigned int) bcc[1]) << 0;
|
|
nfc_tag_content[page_size++] = 0x001211E1;
|
|
|
|
// Init tag content as NDEF will-known text message "HELLO WORLD!" in little endian
|
|
nfc_tag_content[page_size++] = 0x01d11303;
|
|
nfc_tag_content[page_size++] = 0x6502540f;
|
|
nfc_tag_content[page_size++] = 0x4c45486e;
|
|
nfc_tag_content[page_size++] = 0x57204f4c;
|
|
nfc_tag_content[page_size++] = 0x444c524f;
|
|
nfc_tag_content[page_size++] = 0x0000fe21;
|
|
|
|
return page_size;
|
|
}
|
|
|
|
void nfc_load_tag_content_from_flash() {
|
|
int i, address, page_size;
|
|
|
|
memset(nfc_tag_content, 0, NFC_MAX_PAGE_NUM * sizeof(unsigned int));
|
|
memset(nfc_tag_dirty, 0, NFC_MAX_PAGE_NUM);
|
|
|
|
for (i = 0, address = FLASH_APP_NFC_BASE; i < NFC_MAX_PAGE_NUM; i++, address+=4) {
|
|
flash_read_word(&flash_nfc, address, &nfc_tag_content[i]);
|
|
}
|
|
|
|
if (!is_valid_nfc_uid() || NFC_RESTORE_DEFAULT) {
|
|
DiagPrintf("Invalid tag content, restore to default value\r\n");
|
|
page_size = generate_default_tag_content();
|
|
|
|
// update to flash
|
|
flash_erase_sector(&flash_nfc, FLASH_APP_NFC_BASE);
|
|
for (i = 0, address = FLASH_APP_NFC_BASE; i < page_size; i++, address += 4) {
|
|
flash_write_word(&flash_nfc, address, nfc_tag_content[i]);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
void nfc_store_tag_content() {
|
|
int i, address;
|
|
int modified_page_count;
|
|
|
|
// dump the modified tag content
|
|
modified_page_count = 0;
|
|
for (i = 4; i < NFC_MAX_PAGE_NUM && nfc_tag_dirty[i]; i++) {
|
|
modified_page_count++;
|
|
DiagPrintf("page:%02d data:%08x\r\n", i, nfc_tag_content[i]);
|
|
}
|
|
|
|
// update to cache from page 4
|
|
nfc_cache_write(&nfctag, &(nfc_tag_content[4]), 4, modified_page_count);
|
|
|
|
modified_page_count += 4; // we also need update tag header to flash which has size 4
|
|
flash_erase_sector(&flash_nfc, FLASH_APP_NFC_BASE);
|
|
for (i = 0, address = FLASH_APP_NFC_BASE; i < modified_page_count; i++, address += 4) {
|
|
flash_write_word(&flash_nfc, address, nfc_tag_content[i]);
|
|
}
|
|
|
|
}
|
|
|
|
void nfc_task(void const *arg) {
|
|
int i;
|
|
osEvent evt;
|
|
|
|
nfc_load_tag_content_from_flash();
|
|
|
|
nfc_init(&nfctag, nfc_tag_content);
|
|
nfc_event(&nfctag, nfc_event_listener, NULL, 0xFF);
|
|
nfc_write(&nfctag, nfc_write_listener, NULL);
|
|
|
|
osSignalClear(nfc_tid, NFC_EV_WRITE);
|
|
|
|
while(1) {
|
|
evt = osSignalWait (0, 0xFFFFFFFF); // wait for any signal with max timeout
|
|
if (evt.status == osEventSignal && (evt.value.signals & NFC_EV_WRITE)) {
|
|
osDelay(300);
|
|
|
|
nfc_store_tag_content();
|
|
|
|
memset(nfc_tag_dirty, 0, NFC_MAX_PAGE_NUM);
|
|
osSignalClear(nfc_tid, NFC_EV_WRITE);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Main program.
|
|
* @param None
|
|
* @retval None
|
|
*/
|
|
void main(void)
|
|
{
|
|
osThreadDef(nfc_task, osPriorityRealtime, 1, 1024);
|
|
nfc_tid = osThreadCreate (osThread (nfc_task), NULL);
|
|
|
|
DBG_INFO_MSG_OFF(_DBG_SPI_FLASH_);
|
|
|
|
//3 3)Enable Schedule, Start Kernel
|
|
#if defined(CONFIG_KERNEL) && !TASK_SCHEDULER_DISABLED
|
|
#ifdef PLATFORM_FREERTOS
|
|
vTaskStartScheduler();
|
|
#endif
|
|
#else
|
|
RtlConsolTaskRom(NULL);
|
|
#endif
|
|
|
|
while(1);
|
|
}
|
|
|