Problem to write files in the flash memory!

I'm working on a project that I need to write a file in the flash memory, but when I calling the function to open file (fs_open), the microcontroller crashes completely and the following message appears:


->E: ***** MPU FAULT *****
->E: Stacking error (context area might be not valid)
->E: Data Access Violation
->E: MMFAR Address: 0x200159b8
->E: r0/a1: 0x8625890d r1/a2: 0x911daf84 r2/a3: 0x8779922f
->E: r3/a4: 0xfe8bd497 r12/ip: 0xd8dc16c8 r14/lr: 0xb98b5e52
->E: xpsr: 0x5fd38800
->E: Faulting instruction address (r15/pc): 0xac1da62a
->E: >>> ZEPHYR FATAL ERROR 2: Stack overflow on CPU 0
->E: Current thread: 0x20001be8 (unknown)
->E: Halting system

- Libraries used to file system:

#include <zephyr/storage/flash_map.h>
#include <zephyr/fs/fs.h>
#include <zephyr/fs/littlefs.h>
- Functions to WriteFile, ReadFile, RemoveFile, etc:
ssize_t sirros_readFile(char * file_name, char* file_content, size_t file_size, off_t file_pos) {
	char caminho_arquivo[MAX_FILE_PATH_LEN];
	struct fs_file_t file;
	int ret;
	ssize_t read_size;
	snprintf(caminho_arquivo, sizeof(caminho_arquivo), "%s%s", mp->mnt_point, file_name);
	fs_file_t_init(&file);

	ret = fs_open(&file, caminho_arquivo, FS_O_READ);
	if (ret)
		return 0;
		
	if (file_pos != 0)
		fs_seek(&file, file_pos, FS_SEEK_SET);

	read_size = fs_read(&file, file_content, file_size);
	ret = fs_close(&file);
	file_content[read_size] = 0;
	return read_size;
}

bool sirros_writeFile(char * file_name, char* file_content, size_t file_size, off_t file_pos) {
	//printf("entrei na writeFile");
	char caminho_arquivo[MAX_FILE_PATH_LEN];
	struct fs_file_t file;
	int ret;
	size_t written_size = 0;
	//printf("parte 1");
	snprintf(caminho_arquivo, sizeof(caminho_arquivo), "%s%s", mp->mnt_point, file_name);
	//printf("parte 2");
	fs_file_t_init(&file);
	//printf("parte 3");
	ret = fs_open(&file, caminho_arquivo, FS_O_CREATE | FS_O_WRITE);
	//printf("parte 4");
	if(ret < 0)
		return false;
    //printf("parte 5");
	if (file_pos != 0)
		fs_seek(&file, file_pos, FS_SEEK_SET);
   
	if(file_size == 0)
		file_size = strlen(file_content);

	written_size = fs_write(&file, file_content, file_size);
	ret = fs_close(&file);
	return written_size == file_size;
}

bool sirros_appendFile(char * file_name, char* file_content, size_t file_size) {
	char caminho_arquivo[MAX_FILE_PATH_LEN];
	struct fs_file_t file;
	int ret;
	size_t written_size = 0;
	snprintf(caminho_arquivo, sizeof(caminho_arquivo), "%s%s", mp->mnt_point, file_name);
	fs_file_t_init(&file);
		ret = fs_open(&file, caminho_arquivo, FS_O_CREATE | FS_O_APPEND);
	if(ret < 0)
		return false;

	if(file_size == 0)
		file_size = strlen(file_content);

	written_size = fs_write(&file, file_content, file_size);
	ret = fs_close(&file);
	return written_size == file_size;
}

bool sirros_existsFile(char * file_name) {
	char caminho_arquivo[MAX_FILE_PATH_LEN];
	struct fs_file_t file;
	int ret;
	snprintf(caminho_arquivo, sizeof(caminho_arquivo), "%s%s", mp->mnt_point, file_name);
	fs_file_t_init(&file);
	ret = fs_open(&file, caminho_arquivo, 0);
	fs_close(&file);
	return ret == 0;
}

bool sirros_removeFile(char * file_name) {
	char caminho_arquivo[MAX_FILE_PATH_LEN];
	snprintf(caminho_arquivo, sizeof(caminho_arquivo), "%s%s", mp->mnt_point, file_name);
	int ret = fs_unlink(caminho_arquivo);
	return ret == 0;
}
Code snippet where I call the function:
- Write:
	sprintf(payload_id_char, "%d", payload_id);
	sirros_removeFile("/arq_id.txt");
	sirros_writeFile("/arq_id.txt", &payload_id_char, strlen(payload_id_char), 0);
- Read:
	sirros_readFile("/arq_id.txt", payload_id_char, sizeof(payload_id_char), 0);
	payload_id = atoi(payload_id_char);
	printf("payload_id: %i", payload_id);
OBS.: "payload_id" is an int variable and "payload_id_char" is a char variable.
  • Hi

    If you check out the fat_fs and littlefs sample projects in Zephyr you see that the application also does an fs_mount() before accessing the external flash in order to mount the disk, and you need to do that as well if you haven't already.

    Best regards,

    Simon

  • Hi
    I forgot to mention that I call fs_mount before accessing the external flash. Below is the code snippet:

    void sirros_begin() {  //função para inicializar a configuração do dispositivo
    	printf("BEGIN\n");
    	uint32_t ret = 0;
    	if (!fs_mounted) {
    		ret = littlefs_mount(mp);
    		if (ret < 0) {
    			printf("FALHA AO MONTAR O FS");
    			sirros_noParameters();
    			goto final_begin;
    		}
    		fs_mounted = true;
    	}
    

    I also forgot to mention that in other parts of the code, where I apply the same function calls for writing and reading the file, everything works correctly. It's just that specific part I mentioned earlier where the system crashes and that error message appears.

  • So in what file are these code snippets called where it results in this error versus where it works as intended? Are you trying to connect, write and read from the same external flash device in both cases, or is it trying to access another device using different GPIOs for example? I need more details on what you're doing in your application and what the difference(s) between the working and non-working calls to the file system is.

    Best regards,

    Simon

  • Hi 
    Answering your question, yes I'm trying to connect, write and read from the same external flash device in both cases
    I will post here correctly what is and what is not working.

    WORKING:

    The code snippet below, is a function that I call in setup(). The idea is that when my device starts, it updates and assigns the value of the variables that are inside the "/parametros.json" file. (line 69-78)

    void sirros_begin() {  //função para inicializar a configuração do dispositivo
    	printf("BEGIN\n");
    	uint32_t ret = 0;
    	if (!fs_mounted) {
    		ret = littlefs_mount(mp);
    		if (ret < 0) {
    			printf("FALHA AO MONTAR O FS");
    			sirros_noParameters();
    			goto final_begin;
    		}
    		fs_mounted = true;
    	}
    
    	uint8_t baseMac[6];
    	get_mac_address(baseMac);
    	sprintf(sirros.mac_string, "%02X:%02X:%02X:%02X:%02X:%02X", baseMac[0], baseMac[1], baseMac[2], baseMac[3], baseMac[4], baseMac[5]);
    	
    	normal = sirros_existsFile("/parametros.json");
    	backup = sirros_existsFile("/backup.json");
    	printf("normal: %i, backup: %i\n", normal, backup);
    	if ((normal | backup) == 0) {
    		sirros_noParameters();
    		goto final_begin;
    	}
    
    	char parameters_string[CONFIG_FILE_MAX_SIZE];
    	ssize_t read_size = sirros_readFile(normal ? "/parametros.json" : "/backup.json", parameters_string, sizeof(parameters_string), 0);
    	
    	if (read_size <= 0) {
    		printf("NÃO LEU:%i\n", read_size);
    		sirros_noParameters();
    		goto final_begin;
    	}
    
    		
    	printf("Parametros LIDO:%i\n%s\n", read_size, parameters_string);
    	ret = json_obj_parse(parameters_string,//string de entrada com o JSON
    					sizeof(parameters_string),
    					parametersFile_descr,//descrição da struct de configuração
    					ARRAY_SIZE(parametersFile_descr),
    					&sirros);//struct com todas as variáveis de configuração
    	
    	if (ret < 0) {
    		printf("JSON Parse Error: %i\n", ret);
    		if (normal)
    			sirros_removeFile("/parameters.json");
    		else
    			sirros_removeFile("/backup.json");
    		sirros_noParameters();
    	}
    	else {
    		printf("JSON Parse return code: "BYTE_TO_BINARY_PATTERN BYTE_TO_BINARY_PATTERN BYTE_TO_BINARY_PATTERN BYTE_TO_BINARY_PATTERN"\n", 
    				BYTE_TO_BINARY(ret >> 24), BYTE_TO_BINARY(ret >> 16), BYTE_TO_BINARY(ret >> 8), BYTE_TO_BINARY(ret));
    		if(!(ret & 0x01)) { 
    			//se o bit do nome não foi setado, ou seja não encontrou o campo do nome, considera que o arquivo tá bugado
    			sirros_noParameters();
    			goto final_begin;
    		}
    		strcpy(sirros.nome, sirros.nome_buf);		
    		strcpy(sirros.topico, sirros.topico_buf);
    		strcpy(sirros.subtopico, sirros.subtopico_buf);
    		printf("nome_buf: %s\n", sirros.nome_buf);
    		sirros.timeout = constrain(sirros.timeout, 20, 1000);
    		printf("nome: %s\n", sirros.nome);
    		printf("timezone: %i\n", sirros.timezone);
    		printf("readtime: %i\n", sirros.readtime);
    		printf("samples: %i\n", sirros.samples);
    		printf("payload_id: %i\n", sirros.payload_id);
    		if(normal) {
    			read_size = sirros_readFile("/parametros.json", parameters_string, sizeof(parameters_string), 0);
    			sirros_removeFile("/backup.json");
    			sirros_writeFile("/backup.json", parameters_string, strlen(parameters_string), 0);
    		} else {
    			read_size = sirros_readFile("/backup.json", parameters_string, sizeof(parameters_string), 0);
    			sirros_removeFile("/parametros.json");
    			sirros_writeFile("/parametros.json", parameters_string, strlen(parameters_string), 0);
    		}
    	}
    final_begin:
      	if (sirros.subtopico[0] != 0)
    		snprintf(sirros.topico_completo, sizeof(sirros.topico_completo), 
    			"/dev/%s/%s/%s/data", sirros.topico, sirros.subtopico, sirros.nome);
      	else
        	snprintf(sirros.topico_completo, sizeof(sirros.topico_completo), 
    			"/dev/%s/%s/data", sirros.topico, sirros.nome);
    	printf("TOPICO: %s\n", sirros.topico_completo);
    	printf("MAC: %s\n", sirros.mac_string);
    	sirros_bt_begin(sirros.nome);
    }

    NON-WORKING:


    The code snippet below, is a function that I call in loop() in some moments. The idea is write in file the value of variable named "payload_id", because my project works with sleep_mode, so when the code restart, I need the payload_id variable value to stay with its value. (line 23-26)

    void formata_payloads_json() {
    	for (uint8_t eixo = 0; eixo < 3; eixo++) {		
    		for (uint16_t pos = 0; pos < OUTPUT_PAYLOAD_SIZE; pos++) //limpa a string
    			output_payload[eixo][pos] = 0;
    		
    		snprintf(output_payload[eixo], 7, "{\"%c\":[", eixo + 'x');//printa o começo do payload
    
    		char payload_buf[110];
    		uint16_t pos = 0;
    		snprintf(payload_buf, sizeof(payload_buf), "%.2f", accel_real[eixo][pos]);
    		strcat(output_payload[eixo], payload_buf);
    		for (uint16_t pos = 1; pos < sirros.samples; pos++){
    			snprintf(payload_buf, sizeof(payload_buf), ",%.2f", accel_real[eixo][pos]);
    			strcat(output_payload[eixo], payload_buf);
    		}
    
    		snprintf(payload_buf, sizeof(payload_buf),"],\"leitura\":%i,\"unit\":\"us\",\"id\":%i,\"gravidadeZero\":%.2f,\"temperatura\":%f,\"firmware\":\"%s\"}", 
    			sirros.readtime, payload_id, (grav_zero[eixo]/ GRAVIDADE), temperatura_atual, sirros.firmware);
    
    		strcat(output_payload[eixo], payload_buf);
    		printf("Payload do eixo %c:\n%s\n", eixo + 'x', output_payload[eixo]);
    	}
    	payload_id++;
    	sprintf(payload_id_char, "%d", payload_id);
    	sirros_removeFile("/arq_id.txt");
    	sirros_writeFile("/arq_id.txt", &payload_id_char, strlen(payload_id_char), 0);
    }

    I read the file in setup(). Below is the function:

    void setup() {
    	nrf_gpio_cfg_output(MPU_VCC);
    	nrf_gpio_pin_write(MPU_VCC, 0);
    	strcpy(sirros.firmware, FIRMWARE_VERSION);
    	char cmd_response[100];
    	//sirros_parseCMD("set.config({\"nome\":\"beacon-01\",\"topico\":\"sirrosteste\",\"subtopico\":\"predicao\",\"timezone\":-3,\"readtime\":200,\"sleeptime\":120,\"samples\":200,\"timeout\":30})", cmd_response);
    	sirros_begin();
    	sirros_registerCallbackWithoutParameters("set.calibrate", calibrate);
    	sirros_registerCallbackWithoutParameters("get.id", id);
    
    	mpu6050 = DEVICE_DT_GET_ONE(invensense_mpu6050);
    	printf("MPU6050");
    	if (!device_is_ready(mpu6050)) 
    		printk(" nao");
    	printf(" respondeu\n");
    
    	max6675 = DEVICE_DT_GET_ONE(maxim_max6675);
    	printf("MAX6675");
    	if (!device_is_ready(max6675))
    		printk(" nao");
    	printf(" respondeu\n");
    
    	int rc = read_max6675(max6675, &temperatura_atual);
    	if (rc != 0) 
    		printf("MAX ERROR\n");
    
    	transfer_handler.readTransfer = &read_data_callback;
    	transfer_handler.startTransfer = &write_data_callback;
    
    	sirros_readFile("/arq_id.txt", payload_id_char, sizeof(payload_id_char), 0);
    	payload_id = atoi(payload_id_char);
    	printf("payload_id: %i", payload_id);
    
    	calibrate(NULL);
    	leitura();
    }

  • Hi

    Okay, thank you for the thorough explanation. Since you're repeating the non-working loop it seems like on line 23, you're incrementing the payload ID every time, so then it makes sense that it changes value every time. It doesn't seem like you do this in the working application.

    Best regards,

    Simon

Related