Question about NFC on Ameba RTL8195AM Dev Board

Hi
I want to test NFC function on RTL8195AM Dev Board.

I have questions about NFC:

  1. There are no example code, so I searched the package, found that there is nfc_api.c. I write some test code for NFC, it did not working, I quote my code here:
#include "FreeRTOS.h"
#include "task.h"
#include "diag.h"
#include "device.h"
#include "main.h"
#include "log_uart_api.h"
#include "nfc_api.h"

nfctag_t nfcobj;
uint32_t nfcvalue;

void my_nfc_event_cb(void *arg, void *buf, unsigned int page) {
    int i;
    printf("\n\rNFC Event[%d] : ", page);
    for(i=0;i<32;i++) {
        printf("%02X ", ((unsigned char *)buf)[i]);
    }
    printf("\n\r");
}

void nfc_thread(void* arg) {
    // ----------------------------------------------------
    // Initial NFC Reader
    printf("\n\rInitializing NFC ...\n\r");
    nfc_init(&nfcobj, &nfcvalue);
    while (1) {
        printf("\n\rNFC Reading...\n\r");
        nfc_read(&nfcobj, my_nfc_event_cb, NULL);
        vTaskDelay(1500);
    }
}

//========================================================================================================
void main(void) {
    // ----------------------------------------------------
	/* Initialize log uart and at command service */
	console_init();
	if(xTaskCreate(nfc_thread, ((const char*)"init"), 512 + 768, NULL, tskIDLE_PRIORITY + 3 + PRIORITIE_OFFSET, NULL) != pdPASS)
		printf("\n\r%s xTaskCreate(nfc_thread) failed", __FUNCTION__);

    // ----------------------------------------------------
    // FreeRTOS main loop
#if defined(CONFIG_KERNEL) && !TASK_SCHEDULER_DISABLED
	#ifdef PLATFORM_FREERTOS
	vTaskStartScheduler();
	#endif
#else
	RtlConsolTaskRom(NULL);
#endif
}

  1. I found that R19 and R20 near the antenna are not connected, I guess the antenna is not powered. Should I soldering them directly?

Thanks for your help!

@walkerfleck

nfc example for the SDK can be found here.

yes, you will need to solder the leads to the nfc antenna for the example to work.

1 Like

Hi @wyy

Thanks, it is informative to me.
I have another question by the way, I found the example code is using thread, I suppose that it needs RtOS to run. I also found RtOS is needed for wifi functions, according to my test, the bare-metal mode seem not work for wifi APIs. Is that true that FreeRTOS is needed for some SDK functions?

yes, bare-metal should work for the simpler peripheral functions (e.g. SPI, UART), but anything involving networking would probably need the RTOS.

Hi @wyy

I spent a lot of time to test the nfc example in GCC environment, there was a linking problem, which said the __get_IPSR() function is missing in cmsis.o. I googled for answer and added the function for it:

#pragma diag_suppress 994
__attribute__((naked))
uint32_t __get_IPSR(void)
{
   __asm(" MRS R0, IPSR\n");
}
// Restore warnings about any non-void function not returning a value
#pragma diag_default 994

After image built, I flashed the image successfully. But the system hung and no response.
The UART log stopped like this:
image

I even can’t use the GDB, it hung after I entered “step” command at the first line of main().

Can’t figure out how to identify the problem.

Hi @walkerfleck

It seems to be an issue with the CMSIS_OS API layer, the __get_IPSR function is already defined, but it cant seem to find it.

After getting rid of all CMSIS_OS function calls and replacing with FreeRTOS, I managed to get it working with my phone. It should also be possible to change the example to use no RTOS at all.

/*
 *  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 "FreeRTOS.h"
#include "task.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
};

unsigned int evt = 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;
    evt |= 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);

    evt &= ~NFC_EV_WRITE;

    while(1) {
        if (evt & NFC_EV_WRITE) {
            //osDelay(300);
            vTaskDelay(300/portTICK_RATE_MS);

            nfc_store_tag_content();

            memset(nfc_tag_dirty, 0, NFC_MAX_PAGE_NUM);
            evt &= ~NFC_EV_WRITE;
        }
    }
}

/**
  * @brief  Main program.
  * @param  None
  * @retval None
  */
void main(void)
{
    xTaskCreate(nfc_task, ((const char*)"nfc_thread"), 1024, NULL, tskIDLE_PRIORITY + 1, 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);
}
1 Like

Yeah, It’s the issue from CMSIS_OS API, it worked from my side also, after I removed all CMSIS_OS API calls.

Thanks a lot!

1 Like