Note-c in concurrency design patterns such as freertos

Hi,

I am porting the note-c driver from the github example project for my msp430 architecture.

I am using I2C to communicate with the notecard and it is running freertos.

I am struggling to find code examples for freertos (or any rtos for that manner) on here or the developer page. Reading through note-c I see it relies heavily on the heap memory (static variables). This is a bit tricky when when using RTOS.

Am I missing some resource to get this going with an RTOS?

Where I am stuck is during the initialization of the note-c driver.

I currently only have one task in my firmware. And that is initializing the

bool notehub_init( void )
{
	// Register callbacks with note-c subsystem that it needs for I/O, memory, timer
	NoteSetFn(malloc, free, delay, millis);
	// Register callbacks for Notecard I/O, or just do the initialization
//#if NOTECARD_USE_I2C
	NoteSetFnI2C(NOTE_I2C_ADDR_DEFAULT, NOTE_I2C_MAX_DEFAULT, noteI2CReset, noteI2CTransmit, noteI2CReceive);
//#else
//	//NoteSetFnSerial(noteSerialReset, noteSerialTransmit, noteSerialAvailable, noteSerialReceive);
//#endif

	// "NoteNewRequest()" uses the bundled "J" json package to allocate a "req", which is a JSON object
	// for the request to which we will then add Request arguments.  The function allocates a "req"
	// request structure using malloc() and initializes its "req" field with the type of request.
	J *req = NoteNewRequest("hub.set");

	// This command causes the data to be delivered to the Project on notehub.io that has claimed
	// this Product ID.  (see above)
#ifdef PRODUCT_UID
	if (PRODUCT_UID[0]) {
		JAddStringToObject(req, "product", PRODUCT_UID);
	}
#endif
	// This command determines how often the Notecard connects to the service.  If "continuous" the Notecard
	// immediately establishes a session with the service at notehub.io, and keeps it active continuously.
	// Because of the power requirements of a continuous connection, a battery powered device would instead
	// only sample its sensors occasionally, and would only upload to the service on a periodic basis.
	//#if myLiveDemo
	JAddStringToObject(req, "mode", "continuous");
	//#else
	//JAddStringToObject(req, "mode", "periodic");
	//JAddNumberToObject(req, "outbound", 60);
	//#endif

	// Issue the request, telling the Notecard how and how often to access the service.
	// This results in a JSON message to Notecard formatted like:
	//     { "req"     : "hub.set",
	//       "product" : PRODUCT_UID,
	//       "mode"    : "continuous"
	//     }
	// Note that NoteRequest() always uses free() to release the request data structure, and it
	// returns "true" if success and "false" if there is any failure.
	return NoteRequest(req);
}

I am reaching NoteRequest(req) and within that function it runs NoteTransaction(req) and in that routine it seems to serialize the message correctly but fails in the hook _Transaction(json, NULL)

const char *NoteJSONTransaction(char *json, char **jsonResponse)
{
    if (notecardTransaction == NULL || hookActiveInterface == interfaceNone) {
        return "i2c or serial interface must be selected";    //fails here!
    }
    return notecardTransaction(json, jsonResponse);
}

The strange thing is that when I hover over the variables that it is evaluating it is not NULL and the second is set to 2

I got the evaluation expression correct by declaring hookActiveInterface as volatile. Guess my compiler was messing with the code.

1 Like

Hey @Embedded_iceman glad to hear that you’re unblocked for now. In terms of examples, we do have some for Zephyr, and FreeRTOS is next on the list for us to have in the coming weeks, but in the meantime, please hit us up here if you run into other challenges.

2 Likes

Great that you found a workaround. It sounds like the initialization and transaction calls are running on separate threads. When this happens non-volatile variables may not be updated between threads unless there’s a memory fence or other synchronization primitive (e.g. a mutex.)

Here are some other approaches that don’t require that you alter the code:

  1. Ensure that all calls to note-c happen on the same thread. One way of doing this is to build a small service that runs its own thread, servicing requests from a queue. std::promise can help with the implementation of this.

  2. Use a mutex around all note-c calls. This will ensure that the memory is correctly synchronized between threads.

The cause of this is essentially caching and delayed writes, typically from registers back to memory which are part of the optimizations that the compiler performs. The volatile keyword instructs the compiler make all changes to that variable immediate so it’s visible to other threads.

I am keeping things simple for now, all is running on a single thread.

I did turn of compiler optimizations, that solved the original post without modifying the library.

But I am encountering another issue, let me know if I should create another post for that.

When the initial reset command is sent on boot, I get stuck polling the i2c transmit interrupt flag in EUSCI_B_I2C_masterSendMultiByteStart(). I suspect am not breaking into the ISR (not sure if its the debugger fault). I have checked and rechecked the hardware but it measures and seems to be ok, nothing holding the lines. I am not sure if the interrupt is configured correctly, it is ISR priority issue, or note-c-msp430.

1 Like

I found the issue! pretty tough cookie. the pin function register P1SEL0 and P1SEL1 is swapped in EUSCI_B_I2C_initMaster API that is called in noteI2CReset. My workaround to this is to reswap those registers after calling that init API