This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

nRF9160 odd Flash and MQTT behavior

I'm seeing some odd flash behavior that doesn't make any sense to me.  I have a nRF9160 communicating with AWS via MQTT.  I'm subscribed to two topics, Print and Template.  The Template topic tells my device to save the MQTT payload in Flash.  This appears to be working properly and I confirm this by reading the flash back after writing.  Here is that code:

#define FLASH_STORAGE_ADDRESS   DT_FLASH_AREA_STORAGE_OFFSET


void mqtt_evt_handler(struct mqtt_client * const c,
		      const struct mqtt_evt *evt)
{
    switch (evt->type) {
    ...
    
    case MQTT_EVT_PUBLISH: {
		const struct mqtt_publish_param *p = &evt->param.publish;

		printk("[%s:%d] MQTT PUBLISH result=%d len=%d\n", __func__,
		       __LINE__, evt->result, p->message.payload.len);
		err = publish_get_payload(c,
					  payload_buf,
					  p->message.payload.len);
		if (err) {
			printk("mqtt_read_publish_payload: Failed! %d\n", err);
			printk("Disconnecting MQTT client...\n");

			err = mqtt_disconnect(c);
			if (err) {
				printk("Could not disconnect: %d\n", err);
			}
		}

		if (p->message.topic.qos == MQTT_QOS_1_AT_LEAST_ONCE) {
			const struct mqtt_puback_param ack = {
				.message_id = p->message_id
			};

			/* Send acknowledgment. */
			err = mqtt_publish_qos1_ack(c, &ack);
			if (err) {
				printk("unable to ack\n");
			}
		}

        //printk("TOPIC %s", p->message.topic.topic.utf8);
        if (strcmp(p->message.topic.topic.utf8, TOPIC_UPDATE_TEMPLATE) == 0) {
            printk("Updating Template..\n");
            if (uart1) {
                static struct nvs_fs fs;

                struct flash_pages_info info;
                fs.offset = FLASH_STORAGE_ADDRESS;
                err = flash_get_page_info_by_offs(device_get_binding(DT_FLASH_DEV_NAME),
					 fs.offset, &info);
                if (err) {
                    printk("Unable to get page info");
                }
                fs.sector_size = info.size;
                fs.sector_count = 3U;
                err = nvs_init(&fs, DT_FLASH_DEV_NAME);
                if (err) {
                    printk("Flash Init failed\n");
                }

                flash_tlv_t * tlv = k_malloc(sizeof(flash_tlv_t) + p->message.payload.len);
                if (!tlv) {
                    printk("k_malloc error");
                }
                tlv->type = FLASH_TLV_TYPE_TEMPLATE;
                tlv->length = p->message.payload.len;
                tlv->value = &payload_buf;
                printk("type: %d, length: %d\n", tlv->type, tlv->length);

                err = nvs_delete(&fs, FLASH_STORAGE_ADDRESS);
                if (err) {
                    printk("flash delete error: %d\n", err);
                }

                uint16_t tlv_size = sizeof(flash_tlv_t) + tlv->length;
                printk("tlv size: %d", tlv_size);
                err = nvs_write(&fs, FLASH_STORAGE_ADDRESS, tlv, tlv_size);
                printk("write ret: %d", err);

                // read what we just wrote
                flash_tlv_t * rbuf = k_malloc(tlv_size);
                printk("rbuf size %d\n", tlv_size);
                err = nvs_read(&fs, FLASH_STORAGE_ADDRESS, rbuf, tlv_size);
                printk("rbuf %s\n", rbuf->value);
                if (rbuf) {
                    k_free(rbuf);
                }
                if (tlv) {
                    k_free(tlv);
                }

            } else {
                printk("UART error");
            }

It creates a Type-Length-Value structure from the desired template, writes it to DT_FLASH_AREA_STORAGE_OFFSET, then reads the data back and it matches the expected value.

The problem is in the Print topic.  This topic should read the stored topic from flash and send it over the UART1.  It successfully reads the Type and Length of the stored struct, but then the value is incorrect.  The very odd thing is that the value it shows is the payload of the MQTT message.  So for example, if I send a MQTT message with topic of Print and payload of "Test", the device will see:  Type 1 (TEMPLATE), Length: 1951 (the correct length of the stored template), Value: "Test".  The Value should equal the template stored. Here is my code:

} else if (strcmp(p->message.topic.topic.utf8, TOPIC_PRINT) == 0) {

            printk("Printing..\n"); 
            if (uart1) {
                //TODO this is duplicated and needs cleaned up
                static struct nvs_fs fs;

                struct flash_pages_info info;
                fs.offset = FLASH_STORAGE_ADDRESS;
                err = flash_get_page_info_by_offs(device_get_binding(DT_FLASH_DEV_NAME),
                     fs.offset, &info);
                if (err) {
                    printk("Unable to get page info");
                }
                fs.sector_size = info.size;
                fs.sector_count = 3U;
                err = nvs_init(&fs, DT_FLASH_DEV_NAME);
                if (err) {
                    printk("Flash Init failed\n");
                }

                flash_tlv_t type_length;
                err = nvs_read(&fs, FLASH_STORAGE_ADDRESS, &type_length, sizeof(flash_tlv_t));

                printk("type: %d, length %d\n", type_length.type, type_length.length);

                uint16_t tlv_size = sizeof(flash_tlv_t) + type_length.length;
                printk("tlv size: %d\n", tlv_size);
                flash_tlv_t * tlv_buf = k_malloc(tlv_size);
                if (tlv_buf) {
                    err = nvs_read(&fs, FLASH_STORAGE_ADDRESS, tlv_buf, tlv_size);
                    printk("rbuf1 %s\n", tlv_buf->value);

//                    uart_send_str(uart1, tlv_buf->value);
                    k_free(tlv_buf);
                } else {
                    printk("tlv_buf malloc error");
                }
            } else {
                printk("UART error");
            }

        
        }

I'm reading the same flash address in this topic as I was in the Template topic, and the values are completely different.  I am not writing to flash anywhere other than the Template topic, and I don't see anywhere in the MQTT files where flash is getting written as well.  Am I touching an invalid area of flash?  Can anyone explain this behavior? 

Any help is MUCH appreciated!

Related