open-ameba/RTL00_SDKV35a/example_sources/nfc/src/main.c
2016-12-14 04:21:37 +03:00

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);
}