Using note-c library on different platform such as FreeRTOS

I want to use the note-c library on architecture which uses FreeRTOS as a base.
What I know so far is that it it possible to create a program which can do this as note-c is pure C based api.

I am following a official guide from Blues team which has done this for STM32.

In that guide there are some user-defined function which are only required to get the work done.
These are as mentioned in the guide MX_I2C4_DeInit, noteDebugSerialOutput, noteI2CReceive, noteI2CReset, noteI2CTransmit .

Is there anything else required to take a note of?

I was working to port the note card libratry to ESP-IDF.

I have created the component for the notecard i2c communication But I have got the error regarding some undefined reference to object.
The error is in file n_request.c

n_request.c:327:undefined reference to `NoteUserAgent’

The function for communication is NoteTransaction.

What I have done is that have defined the following function declaration at the top of the file and also included the hote.h file. But the error still exist while building the project.

J *NoteUserAgent(void);

Hi @ujur007,

undefined reference means that the compiler was able to find the declaration in note.h, but the linker was not able to find the objects created when you compiled note-c.

Normally when this happens to me, It means I have forgotten to instruct CMake to compile note-c for me.

Can you share the ninja build output from CMake (a.k.a. build), so we can look to see what’s happening?


Sorry for the inconvenience.

The thing is that there was one file n_ua.c missing in my folder somehow.!! which make this error, and while looking for the solution previously, I forgot to check my folder, rather only looked on Github folders…!!

I will share the IDF component after testing I2C works…!

1 Like


It has been a long since I posted this thread but I was also working on this.
So now during porting the API I have had an issue. The code compiles as needed but seems that it is not working from ESP32 I2C to notecard I2C. Following is the code for that.

bool noteI2CReset(uint16_t dev_addr);
const char * noteI2CTransmit(uint16_t dev_addr, uint8_t *pBuffer, uint16_t size);
const char * noteI2CReceive(uint16_t dev_addr, uint8_t *pBuffer, uint16_t size, uint32_t *available);
void delay(uint32_t ms);
uint32_t ticks(void);

static esp_err_t i2c_master_init(void){
    int i2c_port = CONFIG_I2C_MASTER_PORT;
    i2c_config_t conf = {
        .mode = I2C_MODE_MASTER,
        .sda_io_num = CONFIG_I2C_MASTER_SDA_IO,
        .scl_io_num = CONFIG_I2C_MASTER_SCL_IO,
        .sda_pullup_en = GPIO_PULLUP_ENABLE,
        .scl_pullup_en = GPIO_PULLUP_ENABLE,
        .master.clk_speed = I2C_MASTER_FREQ_HZ,
    i2c_param_config(i2c_port, &conf);
    return i2c_driver_install(i2c_port, conf.mode, 0, 0, 0);   
const char * noteI2CTransmit(uint16_t dev_addr, uint8_t *pBuffer, uint16_t size){
    esp_err_t err;
    const char * errstr = NULL;
    uint8_t send_buffer[256];
    send_buffer[0] = (size & NOTE_I2C_BUFFER_SIZE);    
    memcpy(&send_buffer[1], pBuffer, send_buffer[0]);    
    err = i2c_master_write_to_device(CONFIG_I2C_MASTER_PORT, dev_addr, send_buffer, sizeof(send_buffer[0] + send_buffer[1]), 1000 / portTICK_PERIOD_MS);

    switch(err) {
    case ESP_OK:
        errstr = NULL;
    case ESP_FAIL:
        errstr = "Error in i2c Transmission";
    return errstr;
const char * noteI2CReceive(uint16_t dev_addr, uint8_t *pBuffer, uint16_t size, uint32_t *available){
    esp_err_t error;
    const char * errstr;    
    uint8_t query_request[2];
    query_request[0] = 0x00;
    query_request[1] = (size & NOTE_I2C_BUFFER_SIZE);

    uint8_t goodbyte = 0;
    uint8_t availbyte = 0;

    error = i2c_master_write_to_device(CONFIG_I2C_MASTER_PORT, dev_addr, query_request, sizeof(query_request), 1000 / portTICK_PERIOD_MS);

    case ESP_OK:
        errstr = NULL;
    case ESP_FAIL:
        errstr = "Failed to Transmit";

    if (!errstr){
        uint8_t buffer[NOTE_I2C_BUFFER_SIZE];
        int readlen = (size + 2);
        error = i2c_master_read_from_device(CONFIG_I2C_MASTER_PORT, dev_addr, buffer, readlen, 1000 / portTICK_PERIOD_MS);

        if(error == ESP_OK){
            availbyte = buffer[0];
            goodbyte = buffer[1];

            if(goodbyte != size) {
                ESP_LOGE(TAG, "i2c: incorrect amount of data");
                memcpy(pBuffer, &buffer[2], buffer[1]);
    if (errstr != NULL){
        return errstr;
    *available = availbyte;
    return NULL;

bool noteI2CReset(uint16_t dev_addr)
    const char * err;
    //uint8_t buffer[NOTE_I2C_BUFFER_SIZE];
    uint32_t available = 0;
  // Empty the Notecard send buffer
    err = noteI2CReceive(dev_addr, NULL, 0, &available);
    return err;

void delay(uint32_t ms)

uint32_t ticks(void)
    return (esp_timer_get_time() / 1000);

Then inside the main function I do something like this

NoteSetFn(malloc, free, delay, ticks);
    // Set Notecard I2C Interface
NoteSetFnI2C(NOTE_I2C_ADDR_DEFAULT, NOTE_I2C_BUFFER_SIZE, noteI2CReset, noteI2CTransmit, noteI2CReceive);
J *req = NoteNewRequest("hub.set");
JAddStringToObject(req, "product", BLUES_PRODUCT_UID);
JAddStringToObject(req, "mode", "continuous");
vTaskDelay(10 * 1000 / portTICK_PERIOD_MS);