In the attached code i am writing 123, but i am not able to read . Please help

Thread Starter

sreekuttan143

Joined May 20, 2025
5
Moderation: Please use Code quotes

C-like:
#include <string.h> //for memset

#include "W25Qxx.h"

//#include "safe_string.h"

#include "ext_flash.h"

#include "w25qxxConfig.h"

#include <stdio.h>  // For printf

#include <stdbool.h> // For bool_t replacement

#include "FreeRTOS.h" // For pvPortMalloc/vPortFree

#include "task.h"    // For configASSERT

/*#include "crc32.h"

#include "internal_eeprom.h"*/


static uint32_t _write_to_single_sector(uint8_t * log_line, uint16_t length_including_meta, uint32_t next_write_addr, bool_t is_first, uint8_t log_meta);

static uint32_t _write_to_multiple_sectors(uint8_t * log_line, uint16_t length, uint32_t next_write_addr, bool_t from_beginning, uint8_t log_meta);

static uint32_t _find_next_valid_read_start_addr(uint32_t current_write_addr);

static void _turn_on_flash();

static void _turn_off_flash();

static void _read_bytes_from_ext_flash(uint8_t * buff, uint16_t max_buff_len, uint32_t addr, uint16_t length);


bool_t init_ext_flash (){

  bool_t res = FALSE;

  //_turn_on_flash();

  res = (W25qxx_Init() == true) ? TRUE : FALSE;

  //_turn_off_flash();

  return res;

}


void erase_ext_flash(){

  //TODO uncomment it after changing the conf storage to flash;

  W25qxx_EraseChip();

  //_handle_factory_reset();

  //_save_settings_file();

}


void save_fw_chunk_addr_to_storage(uint16_t bit_number, uint16_t data_start, uint32_t new_offset) {

  //if (unlock_flash(TRUE)){

    __set_offset_in_external_storage(bit_number, FALSE);

    __save_32bit_cfg_data_to_external_storage(data_start, new_offset, TRUE, FALSE);

    _save_config_to_external_flash();

    //lock_flash(TRUE);

  //}

}



bool_t save_chunk_to_storage(uint8_t * rx_buff, uint16_t data_length, uint16_t bit_number, uint16_t data_start, uint32_t update_location, uint32_t data_offset, uint8_t type, bool_t need_checking){

  //type = 0 store the fw chunk

  //       1 store the log chunk

  //       2 update the history read address

  //       3 update the history read address before history logs are overflows

  bool_t res = TRUE;

  //_turn_on_flash();

  uint32_t next_write_addr;

  if(type == 0){

   next_write_addr = update_location + data_offset + MAX_FIRMWARE_SIZE_BYTES_LENGTH;

  }else if(type == 1){

    next_write_addr = __get_32bit_cfg_data_from_storage(NXT_LOG_WRITE_ADDR, TRUE) + data_offset;


    if(rx_buff[2] != '$' && rx_buff[3] != ',' && need_checking == TRUE){

      DEVELOPER_PRINT("=================Log doesnt have $ and , so not storing...\n");

      DEVELOPER_PRINT("--> %s\n",rx_buff+2);

      return res;

    }


  }else if(type == 2){

    next_write_addr = __get_32bit_cfg_data_from_storage(NXT_LOG_WRITE_ADDR, TRUE) + data_offset;

    next_write_addr = next_write_addr -12; //to read the log addrs of next oldest log.

  }else{

    next_write_addr = MAX_LOG_WRITABLE_LOCATION - 12;

  }

  //DEVELOPER_PRINT("Log to be saved at: %ld with length: %ld\n",next_write_addr,data_length);

  uint16_t write_sector = next_write_addr / TOTAL_SECTORS;

  uint16_t write_sector_byte_offset = (next_write_addr % SECTOR_SIZE);

  uint8_t * sector_buff = (uint8_t *) pvPortMalloc(SECTOR_SIZE);

  if (sector_buff != NULL){

    uint16_t i;

    W25qxx_ReadSector(sector_buff, write_sector, 0, SECTOR_SIZE);

    for (i = 0; i < data_length; i++) {

      if (write_sector_byte_offset + i < SECTOR_SIZE){

        sector_buff[write_sector_byte_offset + i] = rx_buff;

      } else {

        break;

      }

    }

    W25qxx_EraseSector(write_sector);


    uint8_t try_count =0;

    bool_t is_successful = TRUE;

    while(TRUE){

      is_successful = FALSE;

      if(is_successful == TRUE){

        break;

      }else{

        try_count++;

        if(try_count == 2){

          break;

        }

      }

      W25qxx_WriteSector(sector_buff, write_sector, 0, SECTOR_SIZE);

      /* Verifying the data in the sector */

      W25qxx_ReadSector(sector_buff, write_sector, 0, SECTOR_SIZE);

      for (uint16_t j = 0; j < i; j++){

        if (sector_buff[write_sector_byte_offset + j] != rx_buff[j]){

          res = FALSE;

          is_successful = FALSE;

          DEVELOPER_PRINT("Flash saving failed-----------------\n");

          break;

        }

      }


    }

    vPortFree(sector_buff);

    if (res == TRUE){

      if (i < data_length){

        res = save_chunk_to_storage(rx_buff + i, data_length - i, bit_number, data_start, update_location, data_offset + i, type, FALSE);

      } else {

        if(type == 0){

          save_fw_chunk_addr_to_storage(bit_number, data_start, data_offset + data_length);

        }else if(type == 1){

          __save_32bit_cfg_data_to_external_storage(NXT_LOG_WRITE_ADDR, next_write_addr + data_length, FALSE, FALSE);

            //USER_PRINT("----------> Next Log storage address after %d\n--------------------->\n",__get_32bit_cfg_data_from_storage(NXT_LOG_WRITE_ADDR, TRUE));


          //DEVELOPER_PRINT("------Will store the external_flash config... Comment this as it will happen every 10 mins.");

          //_save_config_to_external_flash(); //will be stored every 10 min

        }

      }

    }

  }

  //_turn_off_flash();

  return res;

}


bool_t is_factory_default_firmware_present() {

  uint8_t data;

  _read_bytes_from_ext_flash(&data, 1, FIRMWARE_FACTORY_START_ADDR, 1);

  return (data == FACTORY_DEFAULT_FW_INSTALLED_FLAG) ? TRUE : FALSE;

}


bool_t set_factory_default_firmware_present_value() {

  //_turn_on_flash();

  uint16_t write_sector = FIRMWARE_FACTORY_START_ADDR / TOTAL_SECTORS;

  uint16_t write_sector_byte_offset = (FIRMWARE_FACTORY_START_ADDR % SECTOR_SIZE);

  uint8_t * sector_buff = (uint8_t *) pvPortMalloc(SECTOR_SIZE);

  if (sector_buff != NULL){

    W25qxx_ReadSector(sector_buff, write_sector, 0, SECTOR_SIZE);

    sector_buff[write_sector_byte_offset] = FACTORY_DEFAULT_FW_INSTALLED_FLAG;

    W25qxx_EraseSector(write_sector);

    W25qxx_WriteSector(sector_buff, write_sector, 0, SECTOR_SIZE);

    vPortFree(sector_buff);

  }

  //_turn_off_flash();

  return is_factory_default_firmware_present();

}


bool_t erase_ext_flash_sector(uint32_t address) {

  uint16_t erase_sector_num = address / TOTAL_SECTORS;

  //_turn_on_flash();

  W25qxx_EraseSector(erase_sector_num);

  //_turn_off_flash();

  return TRUE;

}


void read_update_data(uint8_t * buff, uint16_t max_len, uint32_t addr) {

  //_turn_on_flash();

  int32_t tmp_length = (max_len > SECTOR_SIZE) ? SECTOR_SIZE : max_len;

  int32_t bytes_cnt = 0;

  while (bytes_cnt < max_len){

    _read_bytes_from_ext_flash(buff + bytes_cnt, max_len - bytes_cnt, addr + bytes_cnt, tmp_length);

    bytes_cnt += tmp_length;

    if (bytes_cnt + SECTOR_SIZE > max_len){

      tmp_length = max_len - bytes_cnt;

    } else {

      tmp_length = SECTOR_SIZE;

    }

  }

  //_turn_off_flash();

}


void save_configuration_to_storage(uint8_t * conf_buffer, uint16_t bytes_to_write,uint16_t sector_address)

{

  W25qxx_EraseSector(sector_address);

  W25qxx_WriteSector(conf_buffer,sector_address,0,bytes_to_write);

#ifdef BOOTLOADERPROJECT

  uint8_t sector_buff[2048];

#else

  uint8_t * sector_buff = (uint8_t *) pvPortMalloc(bytes_to_write);

#endif

  if (sector_buff != NULL){

    bool_t res = FALSE;

    W25qxx_ReadSector(sector_buff, sector_address, 0, bytes_to_write);

    for (uint16_t j = 0; j < bytes_to_write-1; j++){

      if (sector_buff[j] != conf_buffer[j]){

        res = TRUE;

        break;

      }

    }

    if(res == TRUE){

      DEVELOPER_PRINT("Flash Data mismatch, rewriting the same data...\n");

      W25qxx_EraseSector(sector_address);

      W25qxx_WriteSector(conf_buffer,sector_address,0,bytes_to_write);

    }else{

      //DEVELOPER_PRINT("Data written to flash successfully...\n");

    }

    // vPortFree(sector_buff);


#ifndef BOOTLOADERPROJECT

    vPortFree(sector_buff);

#endif

  }

}

void read_configuration_from_storage(uint8_t * conf_buffer, uint16_t bytes_to_read, uint16_t sector_address){

  W25qxx_ReadSector(conf_buffer,sector_address,0,bytes_to_read);

}


static void _turn_on_flash(){

  //HAL_GPIO_WritePin(Flash_Ctrl_GPIO_Port, Flash_Ctrl_Pin, GPIO_PIN_SET);

}


static void _turn_off_flash(){

  //HAL_GPIO_WritePin(Flash_Ctrl_GPIO_Port, Flash_Ctrl_Pin, GPIO_PIN_RESET);

}


static uint32_t _write_to_multiple_sectors(uint8_t * log_line, uint16_t log_length, uint32_t next_write_addr, bool_t from_beginning, uint8_t log_meta) {

  /* Multi sector write */

  uint32_t free_in_last_sector;

  uint32_t additional_sectors_needed;

  uint16_t remaining_data_length;

  uint16_t last_wrote_length = 0;


  free_in_last_sector = (SECTOR_SIZE - (next_write_addr % SECTOR_SIZE));

  if (free_in_last_sector > log_length + ((from_beginning == TRUE) ? 2 : 0)){

    free_in_last_sector = log_length + ((from_beginning == TRUE) ? 2 : 0);

  }

  if (free_in_last_sector > 2){

    next_write_addr = _write_to_single_sector(log_line, free_in_last_sector, next_write_addr, from_beginning, log_meta);

    last_wrote_length = free_in_last_sector - ((from_beginning == TRUE) ? 2 : 0);

    if (free_in_last_sector == log_length + ((from_beginning == TRUE) ? 2 : 0)){

      log_length = 0;

    } else {

      log_length -= (free_in_last_sector - ((from_beginning == TRUE) ? 2 : 0));

    }

    from_beginning = FALSE;

  } else if (free_in_last_sector == 2) {

    next_write_addr = _write_to_single_sector(log_line, 2, next_write_addr, from_beginning, log_meta);

    from_beginning = FALSE;

  }

  additional_sectors_needed = log_length / SECTOR_SIZE;

  remaining_data_length = log_length % SECTOR_SIZE;

  for (uint8_t i = 0; i < additional_sectors_needed; i++) {

    uint16_t tmp_length = 0;

    if (log_length > SECTOR_SIZE){

      tmp_length = log_length - SECTOR_SIZE;

    } else {

      tmp_length = SECTOR_SIZE - log_length;

      if (tmp_length > log_length){

        tmp_length = log_length;

      }

    }

    next_write_addr = _write_to_single_sector(log_line + last_wrote_length, tmp_length, next_write_addr, ((i == 0) ? from_beginning : FALSE), log_meta);

    last_wrote_length += tmp_length;

    log_length -= tmp_length;

    from_beginning = FALSE;

  }

  if (remaining_data_length > 0){

    next_write_addr = _write_to_single_sector(log_line + last_wrote_length, remaining_data_length, next_write_addr, from_beginning, log_meta);

  }

  return next_write_addr;

}


void test_read_flash(){

  uint8_t * sector_buff = (uint8_t *) pvPortMalloc(SECTOR_SIZE);

  if (sector_buff != NULL){

    //W25qxx_EraseSector(0);

    memset(sector_buff, 0, SECTOR_SIZE);

    printf("sector_buff before: %lx\n",sector_buff);

    memset(sector_buff, 0, SECTOR_SIZE);

    W25qxx_ReadSector(sector_buff, 0, 0, SECTOR_SIZE);

    printf("sector_buff after: %lx\n",sector_buff);

    vPortFree(sector_buff);

  }

}


static uint32_t _write_to_single_sector(uint8_t * log_line, uint16_t length_including_meta, uint32_t next_write_addr, bool_t is_first, uint8_t log_meta){

  //_turn_on_flash();

  uint8_t * sector_buff = (uint8_t *) pvPortMalloc(SECTOR_SIZE);

  if (sector_buff != NULL){

    uint16_t write_sector = next_write_addr / TOTAL_SECTORS;

    uint16_t write_sector_byte_offset = (next_write_addr % SECTOR_SIZE);

    uint8_t write_start_idx;

    uint16_t i = 0;

    memset(sector_buff, 0, SECTOR_SIZE);

    W25qxx_ReadSector(sector_buff, write_sector, 0, SECTOR_SIZE);

    //printf("sector_buff after: %lx\n",sector_buff);

    //printf("Data already in sector: %s\n",(char *) sector_buff);

    if (is_first == TRUE){

      sector_buff[write_sector_byte_offset] = START_OF_TEXT;

      sector_buff[write_sector_byte_offset + 1] = log_meta;

      write_start_idx = LOG_META_BYTES_LENGTH;

    } else {

      write_start_idx = 0;

    }

    for (i = write_start_idx; i < length_including_meta; i++) {

      sector_buff[write_sector_byte_offset + i] = log_line[i - write_start_idx];

    }

    //printf("Data appended to sector before: %s\n",(char *) sector_buff);

    next_write_addr += i;

    W25qxx_EraseSector(write_sector);

    W25qxx_WriteSector(sector_buff, write_sector, 0, SECTOR_SIZE);

    //printf("Data appended to sector after: %s\n",(char *) sector_buff);

    vPortFree(sector_buff);

    if (next_write_addr > MAX_LOG_WRITABLE_LOCATION){

      next_write_addr = 0;

    }

  }

  //_turn_off_flash();

  return next_write_addr;

}


static uint32_t _find_next_valid_read_start_addr(uint32_t current_write_addr){

  //_turn_on_flash();

  uint8_t * buff = (uint8_t *) pvPortMalloc(SPI_MAX_WRITE_PER_CALL);

  uint32_t new_read_addr = -1;

  if (buff != NULL){

    uint32_t read_bytes = 0;

    while (read_bytes < TOTAL_BYTES && new_read_addr == -1) {

      uint16_t temp_read_len = SPI_MAX_WRITE_PER_CALL;

      if (current_write_addr + SPI_MAX_WRITE_PER_CALL > MAX_LOG_WRITABLE_LOCATION) {

        temp_read_len = (current_write_addr + SPI_MAX_WRITE_PER_CALL) - MAX_LOG_WRITABLE_LOCATION;

      }

      _read_bytes_from_ext_flash(buff, SPI_MAX_WRITE_PER_CALL, current_write_addr, temp_read_len);

      for (uint16_t i = 0; i < SPI_MAX_WRITE_PER_CALL; i++){

        if (buff == START_OF_TEXT){

          new_read_addr = current_write_addr + i;

          break;

        }

      }

      read_bytes += temp_read_len;

      current_write_addr += SPI_MAX_WRITE_PER_CALL;

      if (current_write_addr > MAX_LOG_WRITABLE_LOCATION){

        current_write_addr = 0;

      }

    }

    if (new_read_addr == -1){

      new_read_addr = 0;

    }

    vPortFree(buff);

  }

  //_turn_off_flash();

  return new_read_addr;

}


static void _read_bytes_from_ext_flash(uint8_t * buff, uint16_t max_buff_len, uint32_t addr, uint16_t length) {

  HAL_Delay(100);

  uint16_t read_sector = addr / TOTAL_SECTORS;

  uint16_t read_sector_byte_offset = (addr % SECTOR_SIZE);

  configASSERT((length <= SECTOR_SIZE) && (length <= max_buff_len));

  if((read_sector_byte_offset + length) > SECTOR_SIZE) {

    uint16_t tmp_length = SECTOR_SIZE - read_sector_byte_offset;

    if (tmp_length > max_buff_len){

      tmp_length = max_buff_len;

    }

    printf("reading 1\n");

    W25qxx_ReadSector(buff, read_sector, read_sector_byte_offset, tmp_length);

    length -= tmp_length;

    configASSERT((tmp_length + length) <= max_buff_len);

    W25qxx_ReadSector(buff + tmp_length, read_sector + 1, 0, length);

  } else {

    printf("reading 2\n");

    W25qxx_ReadSector(buff, read_sector, read_sector_byte_offset, length);

  }

  printf("the flash data : %s \n",buff);

}


uint32_t flashWriteData(uint8_t *pBuffer, uint32_t writeAddress, uint32_t noOfBytes) {


  //W25qxx_WriteSector(pBuffer);

  uint32_t noOfBytesWrittenSoFar = 0;

  uint32_t tmpnoOfBytes = noOfBytes;

  //printf("write buff %s\n",pBuffer);

  while (noOfBytesWrittenSoFar < noOfBytes) {

    

    uint32_t write_sector = writeAddress / TOTAL_SECTORS;

    uint32_t write_offset = writeAddress % SECTOR_SIZE;


    uint32_t noOfBytesToWrite;


    if ((write_offset + tmpnoOfBytes) > SECTOR_SIZE) {

      noOfBytesToWrite = SECTOR_SIZE - write_offset;

    } else {

      noOfBytesToWrite = tmpnoOfBytes;

    }

    /*HAL_GPIO_WritePin(GPIOB, GPIO_PIN_13, GPIO_PIN_SET);

    HAL_Delay(500);*/

       /*printf("--------Writing------\n");

       printf("%d\n",write_sector);

       printf("%d\n",write_offset);

       printf("%d\n",noOfBytesToWrite);

       printf("------Wrote--------\n");*/

      



    W25qxx_WriteSector(pBuffer + noOfBytesWrittenSoFar    ,write_sector,write_offset,noOfBytesToWrite);

    /*HAL_GPIO_WritePin(GPIOB, GPIO_PIN_13, GPIO_PIN_RESET);

    HAL_Delay(500);*/

    noOfBytesWrittenSoFar += noOfBytesToWrite;

    writeAddress += noOfBytesToWrite;

    tmpnoOfBytes -= noOfBytesToWrite;

    //break;

  }

  return 0;

}



uint32_t storeLog(uint8_t *TxData, uint32_t currentLogStorageAddress)

{


    char buffer[45];

    memcpy(buffer, TxData, 45); 

    //sprintf(buffer, "%s", TxData);

    printf("FLASH write DATA: %s\n",buffer);

    flashWriteData((uint8_t*)buffer, currentLogStorageAddress, 45);

    // Update the current log storage address

    char read_buffer[45];

    test_read_flash();

    printf("FLASH READ DATA: %s\n",read_buffer);

    currentLogStorageAddress += 45;

    

    return currentLogStorageAddress;

}
 
Last edited by a moderator:

panic mode

Joined Oct 10, 2011
4,864
"In the attached code i am writing 123, but i am not able to read . Please help"
try describing hardware setup

btw. below is your code without double spacing. i find this to be much more readable.
also i only see bunch of primitives to access and manipulate something (esternal EEPROM) but... your code is missing. where is this "123" that you mentioned? do not understand what is it that you are trying to do. i searched for 123 and found nothing.


Some C or C-like code:
#include <string.h> //for memset
#include "W25Qxx.h"
//#include "safe_string.h"
#include "ext_flash.h"
#include "w25qxxConfig.h"
#include <stdio.h>  // For printf
#include <stdbool.h> // For bool_t replacement
#include "FreeRTOS.h" // For pvPortMalloc/vPortFree
#include "task.h"    // For configASSERT
/*#include "crc32.h"
#include "internal_eeprom.h"*/

static uint32_t _write_to_single_sector(uint8_t * log_line, uint16_t length_including_meta, uint32_t next_write_addr, bool_t is_first, uint8_t log_meta);
static uint32_t _write_to_multiple_sectors(uint8_t * log_line, uint16_t length, uint32_t next_write_addr, bool_t from_beginning, uint8_t log_meta);
static uint32_t _find_next_valid_read_start_addr(uint32_t current_write_addr);
static void _turn_on_flash();
static void _turn_off_flash();
static void _read_bytes_from_ext_flash(uint8_t * buff, uint16_t max_buff_len, uint32_t addr, uint16_t length);

bool_t init_ext_flash (){
  bool_t res = FALSE;
  //_turn_on_flash();
  res = (W25qxx_Init() == true) ? TRUE : FALSE;
  //_turn_off_flash();
  return res;
}

void erase_ext_flash(){
  //TODO uncomment it after changing the conf storage to flash;
  W25qxx_EraseChip();
  //_handle_factory_reset();
  //_save_settings_file();
}

void save_fw_chunk_addr_to_storage(uint16_t bit_number, uint16_t data_start, uint32_t new_offset) {
  //if (unlock_flash(TRUE)){
    __set_offset_in_external_storage(bit_number, FALSE);
    __save_32bit_cfg_data_to_external_storage(data_start, new_offset, TRUE, FALSE);
    _save_config_to_external_flash();
    //lock_flash(TRUE);
  //}
}

bool_t save_chunk_to_storage(uint8_t * rx_buff, uint16_t data_length, uint16_t bit_number, uint16_t data_start, uint32_t update_location, uint32_t data_offset, uint8_t type, bool_t need_checking){
  //type = 0 store the fw chunk
  //       1 store the log chunk
  //       2 update the history read address
  //       3 update the history read address before history logs are overflows
  bool_t res = TRUE;
  //_turn_on_flash();
  uint32_t next_write_addr;
  if(type == 0){
   next_write_addr = update_location + data_offset + MAX_FIRMWARE_SIZE_BYTES_LENGTH;
  }else if(type == 1){
    next_write_addr = __get_32bit_cfg_data_from_storage(NXT_LOG_WRITE_ADDR, TRUE) + data_offset;

    if(rx_buff[2] != '$' && rx_buff[3] != ',' && need_checking == TRUE){
      DEVELOPER_PRINT("=================Log doesnt have $ and , so not storing...\n");
      DEVELOPER_PRINT("--> %s\n",rx_buff+2);
      return res;
    }

  }else if(type == 2){
    next_write_addr = __get_32bit_cfg_data_from_storage(NXT_LOG_WRITE_ADDR, TRUE) + data_offset;
    next_write_addr = next_write_addr -12; //to read the log addrs of next oldest log.
  }else{
    next_write_addr = MAX_LOG_WRITABLE_LOCATION - 12;
  }
  //DEVELOPER_PRINT("Log to be saved at: %ld with length: %ld\n",next_write_addr,data_length);
  uint16_t write_sector = next_write_addr / TOTAL_SECTORS;
  uint16_t write_sector_byte_offset = (next_write_addr % SECTOR_SIZE);
  uint8_t * sector_buff = (uint8_t *) pvPortMalloc(SECTOR_SIZE);
  if (sector_buff != NULL){
    uint16_t i;
    W25qxx_ReadSector(sector_buff, write_sector, 0, SECTOR_SIZE);
    for (i = 0; i < data_length; i++) {
      if (write_sector_byte_offset + i < SECTOR_SIZE){
        sector_buff[write_sector_byte_offset + i] = rx_buff;
      } else {
        break;
      }
    }
    W25qxx_EraseSector(write_sector);

    uint8_t try_count =0;
    bool_t is_successful = TRUE;
    while(TRUE){
      is_successful = FALSE;
      if(is_successful == TRUE){
        break;
      }else{
        try_count++;
        if(try_count == 2){
          break;
        }
      }
      W25qxx_WriteSector(sector_buff, write_sector, 0, SECTOR_SIZE);
      /* Verifying the data in the sector */
      W25qxx_ReadSector(sector_buff, write_sector, 0, SECTOR_SIZE);
      for (uint16_t j = 0; j < i; j++){
        if (sector_buff[write_sector_byte_offset + j] != rx_buff[j]){
          res = FALSE;
          is_successful = FALSE;
          DEVELOPER_PRINT("Flash saving failed-----------------\n");
          break;
        }
      }

    }
    vPortFree(sector_buff);
    if (res == TRUE){
      if (i < data_length){
        res = save_chunk_to_storage(rx_buff + i, data_length - i, bit_number, data_start, update_location, data_offset + i, type, FALSE);
      } else {
        if(type == 0){
          save_fw_chunk_addr_to_storage(bit_number, data_start, data_offset + data_length);
        }else if(type == 1){
          __save_32bit_cfg_data_to_external_storage(NXT_LOG_WRITE_ADDR, next_write_addr + data_length, FALSE, FALSE);
            //USER_PRINT("----------> Next Log storage address after %d\n--------------------->\n",__get_32bit_cfg_data_from_storage(NXT_LOG_WRITE_ADDR, TRUE));

          //DEVELOPER_PRINT("------Will store the external_flash config... Comment this as it will happen every 10 mins.");
          //_save_config_to_external_flash(); //will be stored every 10 min
        }
      }
    }
  }
  //_turn_off_flash();
  return res;
}

bool_t is_factory_default_firmware_present() {
  uint8_t data;
  _read_bytes_from_ext_flash(&data, 1, FIRMWARE_FACTORY_START_ADDR, 1);
  return (data == FACTORY_DEFAULT_FW_INSTALLED_FLAG) ? TRUE : FALSE;
}

bool_t set_factory_default_firmware_present_value() {
  //_turn_on_flash();
  uint16_t write_sector = FIRMWARE_FACTORY_START_ADDR / TOTAL_SECTORS;
  uint16_t write_sector_byte_offset = (FIRMWARE_FACTORY_START_ADDR % SECTOR_SIZE);
  uint8_t * sector_buff = (uint8_t *) pvPortMalloc(SECTOR_SIZE);
  if (sector_buff != NULL){
    W25qxx_ReadSector(sector_buff, write_sector, 0, SECTOR_SIZE);
    sector_buff[write_sector_byte_offset] = FACTORY_DEFAULT_FW_INSTALLED_FLAG;
    W25qxx_EraseSector(write_sector);
    W25qxx_WriteSector(sector_buff, write_sector, 0, SECTOR_SIZE);
    vPortFree(sector_buff);
  }
  //_turn_off_flash();
  return is_factory_default_firmware_present();
}

bool_t erase_ext_flash_sector(uint32_t address) {
  uint16_t erase_sector_num = address / TOTAL_SECTORS;
  //_turn_on_flash();
  W25qxx_EraseSector(erase_sector_num);
  //_turn_off_flash();
  return TRUE;
}

void read_update_data(uint8_t * buff, uint16_t max_len, uint32_t addr) {
  //_turn_on_flash();
  int32_t tmp_length = (max_len > SECTOR_SIZE) ? SECTOR_SIZE : max_len;
  int32_t bytes_cnt = 0;
  while (bytes_cnt < max_len){
    _read_bytes_from_ext_flash(buff + bytes_cnt, max_len - bytes_cnt, addr + bytes_cnt, tmp_length);
    bytes_cnt += tmp_length;
    if (bytes_cnt + SECTOR_SIZE > max_len){
      tmp_length = max_len - bytes_cnt;
    } else {
      tmp_length = SECTOR_SIZE;
    }
  }
  //_turn_off_flash();
}

void save_configuration_to_storage(uint8_t * conf_buffer, uint16_t bytes_to_write,uint16_t sector_address)
{
  W25qxx_EraseSector(sector_address);
  W25qxx_WriteSector(conf_buffer,sector_address,0,bytes_to_write);
#ifdef BOOTLOADERPROJECT
  uint8_t sector_buff[2048];
#else
  uint8_t * sector_buff = (uint8_t *) pvPortMalloc(bytes_to_write);
#endif
  if (sector_buff != NULL){
    bool_t res = FALSE;
    W25qxx_ReadSector(sector_buff, sector_address, 0, bytes_to_write);
    for (uint16_t j = 0; j < bytes_to_write-1; j++){
      if (sector_buff[j] != conf_buffer[j]){
        res = TRUE;
        break;
      }
    }
    if(res == TRUE){
      DEVELOPER_PRINT("Flash Data mismatch, rewriting the same data...\n");
      W25qxx_EraseSector(sector_address);
      W25qxx_WriteSector(conf_buffer,sector_address,0,bytes_to_write);
    }else{
      //DEVELOPER_PRINT("Data written to flash successfully...\n");
    }
    // vPortFree(sector_buff);

#ifndef BOOTLOADERPROJECT
    vPortFree(sector_buff);
#endif
  }
}
void read_configuration_from_storage(uint8_t * conf_buffer, uint16_t bytes_to_read, uint16_t sector_address){
  W25qxx_ReadSector(conf_buffer,sector_address,0,bytes_to_read);
}

static void _turn_on_flash(){
  //HAL_GPIO_WritePin(Flash_Ctrl_GPIO_Port, Flash_Ctrl_Pin, GPIO_PIN_SET);
}

static void _turn_off_flash(){
  //HAL_GPIO_WritePin(Flash_Ctrl_GPIO_Port, Flash_Ctrl_Pin, GPIO_PIN_RESET);
}

static uint32_t _write_to_multiple_sectors(uint8_t * log_line, uint16_t log_length, uint32_t next_write_addr, bool_t from_beginning, uint8_t log_meta) {
  /* Multi sector write */
  uint32_t free_in_last_sector;
  uint32_t additional_sectors_needed;
  uint16_t remaining_data_length;
  uint16_t last_wrote_length = 0;

  free_in_last_sector = (SECTOR_SIZE - (next_write_addr % SECTOR_SIZE));
  if (free_in_last_sector > log_length + ((from_beginning == TRUE) ? 2 : 0)){
    free_in_last_sector = log_length + ((from_beginning == TRUE) ? 2 : 0);
  }
  if (free_in_last_sector > 2){
    next_write_addr = _write_to_single_sector(log_line, free_in_last_sector, next_write_addr, from_beginning, log_meta);
    last_wrote_length = free_in_last_sector - ((from_beginning == TRUE) ? 2 : 0);
    if (free_in_last_sector == log_length + ((from_beginning == TRUE) ? 2 : 0)){
      log_length = 0;
    } else {
      log_length -= (free_in_last_sector - ((from_beginning == TRUE) ? 2 : 0));
    }
    from_beginning = FALSE;
  } else if (free_in_last_sector == 2) {
    next_write_addr = _write_to_single_sector(log_line, 2, next_write_addr, from_beginning, log_meta);
    from_beginning = FALSE;
  }
  additional_sectors_needed = log_length / SECTOR_SIZE;
  remaining_data_length = log_length % SECTOR_SIZE;
  for (uint8_t i = 0; i < additional_sectors_needed; i++) {
    uint16_t tmp_length = 0;
    if (log_length > SECTOR_SIZE){
      tmp_length = log_length - SECTOR_SIZE;
    } else {
      tmp_length = SECTOR_SIZE - log_length;
      if (tmp_length > log_length){
        tmp_length = log_length;
      }
    }
    next_write_addr = _write_to_single_sector(log_line + last_wrote_length, tmp_length, next_write_addr, ((i == 0) ? from_beginning : FALSE), log_meta);
    last_wrote_length += tmp_length;
    log_length -= tmp_length;
    from_beginning = FALSE;
  }
  if (remaining_data_length > 0){
    next_write_addr = _write_to_single_sector(log_line + last_wrote_length, remaining_data_length, next_write_addr, from_beginning, log_meta);
  }
  return next_write_addr;
}

void test_read_flash(){
  uint8_t * sector_buff = (uint8_t *) pvPortMalloc(SECTOR_SIZE);
  if (sector_buff != NULL){
    //W25qxx_EraseSector(0);
    memset(sector_buff, 0, SECTOR_SIZE);
    printf("sector_buff before: %lx\n",sector_buff);
    memset(sector_buff, 0, SECTOR_SIZE);
    W25qxx_ReadSector(sector_buff, 0, 0, SECTOR_SIZE);
    printf("sector_buff after: %lx\n",sector_buff);
    vPortFree(sector_buff);
  }
}

static uint32_t _write_to_single_sector(uint8_t * log_line, uint16_t length_including_meta, uint32_t next_write_addr, bool_t is_first, uint8_t log_meta){
  //_turn_on_flash();
  uint8_t * sector_buff = (uint8_t *) pvPortMalloc(SECTOR_SIZE);
  if (sector_buff != NULL){
    uint16_t write_sector = next_write_addr / TOTAL_SECTORS;
    uint16_t write_sector_byte_offset = (next_write_addr % SECTOR_SIZE);
    uint8_t write_start_idx;
    uint16_t i = 0;
    memset(sector_buff, 0, SECTOR_SIZE);
    W25qxx_ReadSector(sector_buff, write_sector, 0, SECTOR_SIZE);
    //printf("sector_buff after: %lx\n",sector_buff);
    //printf("Data already in sector: %s\n",(char *) sector_buff);
    if (is_first == TRUE){
      sector_buff[write_sector_byte_offset] = START_OF_TEXT;
      sector_buff[write_sector_byte_offset + 1] = log_meta;
      write_start_idx = LOG_META_BYTES_LENGTH;
    } else {
      write_start_idx = 0;
    }
    for (i = write_start_idx; i < length_including_meta; i++) {
      sector_buff[write_sector_byte_offset + i] = log_line[i - write_start_idx];
    }
    //printf("Data appended to sector before: %s\n",(char *) sector_buff);
    next_write_addr += i;
    W25qxx_EraseSector(write_sector);
    W25qxx_WriteSector(sector_buff, write_sector, 0, SECTOR_SIZE);
    //printf("Data appended to sector after: %s\n",(char *) sector_buff);
    vPortFree(sector_buff);
    if (next_write_addr > MAX_LOG_WRITABLE_LOCATION){
      next_write_addr = 0;
    }
  }
  //_turn_off_flash();
  return next_write_addr;
}

static uint32_t _find_next_valid_read_start_addr(uint32_t current_write_addr){
  //_turn_on_flash();
  uint8_t * buff = (uint8_t *) pvPortMalloc(SPI_MAX_WRITE_PER_CALL);
  uint32_t new_read_addr = -1;
  if (buff != NULL){
    uint32_t read_bytes = 0;
    while (read_bytes < TOTAL_BYTES && new_read_addr == -1) {
      uint16_t temp_read_len = SPI_MAX_WRITE_PER_CALL;
      if (current_write_addr + SPI_MAX_WRITE_PER_CALL > MAX_LOG_WRITABLE_LOCATION) {
        temp_read_len = (current_write_addr + SPI_MAX_WRITE_PER_CALL) - MAX_LOG_WRITABLE_LOCATION;
      }
      _read_bytes_from_ext_flash(buff, SPI_MAX_WRITE_PER_CALL, current_write_addr, temp_read_len);
      for (uint16_t i = 0; i < SPI_MAX_WRITE_PER_CALL; i++){
        if (buff == START_OF_TEXT){
          new_read_addr = current_write_addr + i;
          break;
        }
      }
      read_bytes += temp_read_len;
      current_write_addr += SPI_MAX_WRITE_PER_CALL;
      if (current_write_addr > MAX_LOG_WRITABLE_LOCATION){
        current_write_addr = 0;
      }
    }
    if (new_read_addr == -1){
      new_read_addr = 0;
    }
    vPortFree(buff);
  }
  //_turn_off_flash();
  return new_read_addr;
}

static void _read_bytes_from_ext_flash(uint8_t * buff, uint16_t max_buff_len, uint32_t addr, uint16_t length) {
  HAL_Delay(100);
  uint16_t read_sector = addr / TOTAL_SECTORS;
  uint16_t read_sector_byte_offset = (addr % SECTOR_SIZE);
  configASSERT((length <= SECTOR_SIZE) && (length <= max_buff_len));
  if((read_sector_byte_offset + length) > SECTOR_SIZE) {
    uint16_t tmp_length = SECTOR_SIZE - read_sector_byte_offset;
    if (tmp_length > max_buff_len){
      tmp_length = max_buff_len;
    }
    printf("reading 1\n");
    W25qxx_ReadSector(buff, read_sector, read_sector_byte_offset, tmp_length);
    length -= tmp_length;
    configASSERT((tmp_length + length) <= max_buff_len);
    W25qxx_ReadSector(buff + tmp_length, read_sector + 1, 0, length);
  } else {
    printf("reading 2\n");
    W25qxx_ReadSector(buff, read_sector, read_sector_byte_offset, length);
  }
  printf("the flash data : %s \n",buff);
}

uint32_t flashWriteData(uint8_t *pBuffer, uint32_t writeAddress, uint32_t noOfBytes) {

  //W25qxx_WriteSector(pBuffer);
  uint32_t noOfBytesWrittenSoFar = 0;
  uint32_t tmpnoOfBytes = noOfBytes;
  //printf("write buff %s\n",pBuffer);
  while (noOfBytesWrittenSoFar < noOfBytes) {
    
    uint32_t write_sector = writeAddress / TOTAL_SECTORS;
    uint32_t write_offset = writeAddress % SECTOR_SIZE;

    uint32_t noOfBytesToWrite;

    if ((write_offset + tmpnoOfBytes) > SECTOR_SIZE) {
      noOfBytesToWrite = SECTOR_SIZE - write_offset;
    } else {
      noOfBytesToWrite = tmpnoOfBytes;
    }
    /*HAL_GPIO_WritePin(GPIOB, GPIO_PIN_13, GPIO_PIN_SET);
    HAL_Delay(500);*/
       /*printf("--------Writing------\n");
       printf("%d\n",write_sector);
       printf("%d\n",write_offset);
       printf("%d\n",noOfBytesToWrite);
       printf("------Wrote--------\n");*/
      

    W25qxx_WriteSector(pBuffer + noOfBytesWrittenSoFar    ,write_sector,write_offset,noOfBytesToWrite);
    /*HAL_GPIO_WritePin(GPIOB, GPIO_PIN_13, GPIO_PIN_RESET);
    HAL_Delay(500);*/
    noOfBytesWrittenSoFar += noOfBytesToWrite;
    writeAddress += noOfBytesToWrite;
    tmpnoOfBytes -= noOfBytesToWrite;
    //break;
  }
  return 0;
}

uint32_t storeLog(uint8_t *TxData, uint32_t currentLogStorageAddress)
{

    char buffer[45];
    memcpy(buffer, TxData, 45);
    //sprintf(buffer, "%s", TxData);
    printf("FLASH write DATA: %s\n",buffer);
    flashWriteData((uint8_t*)buffer, currentLogStorageAddress, 45);
    // Update the current log storage address
    char read_buffer[45];
    test_read_flash();
    printf("FLASH READ DATA: %s\n",read_buffer);
    currentLogStorageAddress += 45;
    
    return currentLogStorageAddress;
}
 

Thread Starter

sreekuttan143

Joined May 20, 2025
5
"In the attached code i am writing 123, but i am not able to read . Please help"
try describing hardware setup

btw. below is your code without double spacing. i find this to be much more readable.
also i only see bunch of primitives to access and manipulate something (esternal EEPROM) but... your code is missing. where is this "123" that you mentioned? do not understand what is it that you are trying to do. i searched for 123 and found nothing.
C:
#include "W25Qxx.h"
//#include "safe_string.h"
#include "ext_flash.h"
#include "w25qxxConfig.h"
#include <stdio.h>  // For printf
#include <stdbool.h> // For bool_t replacement
#include "FreeRTOS.h" // For pvPortMalloc/vPortFree
#include "task.h"    // For configASSERT
/*#include "crc32.h"
#include "internal_eeprom.h"*/

static uint32_t _write_to_single_sector(uint8_t * log_line, uint16_t length_including_meta, uint32_t next_write_addr, bool_t is_first, uint8_t log_meta);
static uint32_t _write_to_multiple_sectors(uint8_t * log_line, uint16_t length, uint32_t next_write_addr, bool_t from_beginning, uint8_t log_meta);
static uint32_t _find_next_valid_read_start_addr(uint32_t current_write_addr);
static void _turn_on_flash();
static void _turn_off_flash();
static void _read_bytes_from_ext_flash(uint8_t * buff, uint16_t max_buff_len, uint32_t addr, uint16_t length);

bool_t init_ext_flash (){
  bool_t res = FALSE;
  //_turn_on_flash();
  res = (W25qxx_Init() == true) ? TRUE : FALSE;
  //_turn_off_flash();
  return res;
}

void erase_ext_flash(){
  //TODO uncomment it after changing the conf storage to flash;
  W25qxx_EraseChip();
  //_handle_factory_reset();
  //_save_settings_file();
}

void save_fw_chunk_addr_to_storage(uint16_t bit_number, uint16_t data_start, uint32_t new_offset) {
  //if (unlock_flash(TRUE)){
    __set_offset_in_external_storage(bit_number, FALSE);
    __save_32bit_cfg_data_to_external_storage(data_start, new_offset, TRUE, FALSE);
    _save_config_to_external_flash();
    //lock_flash(TRUE);
  //}
}

bool_t save_chunk_to_storage(uint8_t * rx_buff, uint16_t data_length, uint16_t bit_number, uint16_t data_start, uint32_t update_location, uint32_t data_offset, uint8_t type, bool_t need_checking){
  //type = 0 store the fw chunk
  //       1 store the log chunk
  //       2 update the history read address
  //       3 update the history read address before history logs are overflows
  bool_t res = TRUE;
  //_turn_on_flash();
  uint32_t next_write_addr;
  if(type == 0){
   next_write_addr = update_location + data_offset + MAX_FIRMWARE_SIZE_BYTES_LENGTH;
  }else if(type == 1){
    next_write_addr = __get_32bit_cfg_data_from_storage(NXT_LOG_WRITE_ADDR, TRUE) + data_offset;

    if(rx_buff[2] != '$' && rx_buff[3] != ',' && need_checking == TRUE){
      DEVELOPER_PRINT("=================Log doesnt have $ and , so not storing...\n");
      DEVELOPER_PRINT("--> %s\n",rx_buff+2);
      return res;
    }

  }else if(type == 2){
    next_write_addr = __get_32bit_cfg_data_from_storage(NXT_LOG_WRITE_ADDR, TRUE) + data_offset;
    next_write_addr = next_write_addr -12; //to read the log addrs of next oldest log.
  }else{
    next_write_addr = MAX_LOG_WRITABLE_LOCATION - 12;
  }
  //DEVELOPER_PRINT("Log to be saved at: %ld with length: %ld\n",next_write_addr,data_length);
  uint16_t write_sector = next_write_addr / TOTAL_SECTORS;
  uint16_t write_sector_byte_offset = (next_write_addr % SECTOR_SIZE);
  uint8_t * sector_buff = (uint8_t *) pvPortMalloc(SECTOR_SIZE);
  if (sector_buff != NULL){
    uint16_t i;
    W25qxx_ReadSector(sector_buff, write_sector, 0, SECTOR_SIZE);
    for (i = 0; i < data_length; i++) {
      if (write_sector_byte_offset + i < SECTOR_SIZE){
        sector_buff[write_sector_byte_offset + i] = rx_buff;
      } else {
        break;
      }
    }
    W25qxx_EraseSector(write_sector);

    uint8_t try_count =0;
    bool_t is_successful = TRUE;
    while(TRUE){
      is_successful = FALSE;
      if(is_successful == TRUE){
        break;
      }else{
        try_count++;
        if(try_count == 2){
          break;
        }
      }
      W25qxx_WriteSector(sector_buff, write_sector, 0, SECTOR_SIZE);
      /* Verifying the data in the sector */
      W25qxx_ReadSector(sector_buff, write_sector, 0, SECTOR_SIZE);
      for (uint16_t j = 0; j < i; j++){
        if (sector_buff[write_sector_byte_offset + j] != rx_buff[j]){
          res = FALSE;
          is_successful = FALSE;
          DEVELOPER_PRINT("Flash saving failed-----------------\n");
          break;
        }
      }

    }
    vPortFree(sector_buff);
    if (res == TRUE){
      if (i < data_length){
        res = save_chunk_to_storage(rx_buff + i, data_length - i, bit_number, data_start, update_location, data_offset + i, type, FALSE);
      } else {
        if(type == 0){
          save_fw_chunk_addr_to_storage(bit_number, data_start, data_offset + data_length);
        }else if(type == 1){
          __save_32bit_cfg_data_to_external_storage(NXT_LOG_WRITE_ADDR, next_write_addr + data_length, FALSE, FALSE);
            //USER_PRINT("----------> Next Log storage address after %d\n--------------------->\n",__get_32bit_cfg_data_from_storage(NXT_LOG_WRITE_ADDR, TRUE));

          //DEVELOPER_PRINT("------Will store the external_flash config... Comment this as it will happen every 10 mins.");
          //_save_config_to_external_flash(); //will be stored every 10 min
        }
      }
    }
  }
  //_turn_off_flash();
  return res;
}

bool_t is_factory_default_firmware_present() {
  uint8_t data;
  _read_bytes_from_ext_flash(&data, 1, FIRMWARE_FACTORY_START_ADDR, 1);
  return (data == FACTORY_DEFAULT_FW_INSTALLED_FLAG) ? TRUE : FALSE;
}

bool_t set_factory_default_firmware_present_value() {
  //_turn_on_flash();
  uint16_t write_sector = FIRMWARE_FACTORY_START_ADDR / TOTAL_SECTORS;
  uint16_t write_sector_byte_offset = (FIRMWARE_FACTORY_START_ADDR % SECTOR_SIZE);
  uint8_t * sector_buff = (uint8_t *) pvPortMalloc(SECTOR_SIZE);
  if (sector_buff != NULL){
    W25qxx_ReadSector(sector_buff, write_sector, 0, SECTOR_SIZE);
    sector_buff[write_sector_byte_offset] = FACTORY_DEFAULT_FW_INSTALLED_FLAG;
    W25qxx_EraseSector(write_sector);
    W25qxx_WriteSector(sector_buff, write_sector, 0, SECTOR_SIZE);
    vPortFree(sector_buff);
  }
  //_turn_off_flash();
  return is_factory_default_firmware_present();
}

bool_t erase_ext_flash_sector(uint32_t address) {
  uint16_t erase_sector_num = address / TOTAL_SECTORS;
  //_turn_on_flash();
  W25qxx_EraseSector(erase_sector_num);
  //_turn_off_flash();
  return TRUE;
}

void read_update_data(uint8_t * buff, uint16_t max_len, uint32_t addr) {
  //_turn_on_flash();
  int32_t tmp_length = (max_len > SECTOR_SIZE) ? SECTOR_SIZE : max_len;
  int32_t bytes_cnt = 0;
  while (bytes_cnt < max_len){
    _read_bytes_from_ext_flash(buff + bytes_cnt, max_len - bytes_cnt, addr + bytes_cnt, tmp_length);
    bytes_cnt += tmp_length;
    if (bytes_cnt + SECTOR_SIZE > max_len){
      tmp_length = max_len - bytes_cnt;
    } else {
      tmp_length = SECTOR_SIZE;
    }
  }
  //_turn_off_flash();
}

void save_configuration_to_storage(uint8_t * conf_buffer, uint16_t bytes_to_write,uint16_t sector_address)
{
  W25qxx_EraseSector(sector_address);
  W25qxx_WriteSector(conf_buffer,sector_address,0,bytes_to_write);
#ifdef BOOTLOADERPROJECT
  uint8_t sector_buff[2048];
#else
  uint8_t * sector_buff = (uint8_t *) pvPortMalloc(bytes_to_write);
#endif
  if (sector_buff != NULL){
    bool_t res = FALSE;
    W25qxx_ReadSector(sector_buff, sector_address, 0, bytes_to_write);
    for (uint16_t j = 0; j < bytes_to_write-1; j++){
      if (sector_buff[j] != conf_buffer[j]){
        res = TRUE;
        break;
      }
    }
    if(res == TRUE){
      DEVELOPER_PRINT("Flash Data mismatch, rewriting the same data...\n");
      W25qxx_EraseSector(sector_address);
      W25qxx_WriteSector(conf_buffer,sector_address,0,bytes_to_write);
    }else{
      //DEVELOPER_PRINT("Data written to flash successfully...\n");
    }
    // vPortFree(sector_buff);

#ifndef BOOTLOADERPROJECT
    vPortFree(sector_buff);
#endif
  }
}
void read_configuration_from_storage(uint8_t * conf_buffer, uint16_t bytes_to_read, uint16_t sector_address){
  W25qxx_ReadSector(conf_buffer,sector_address,0,bytes_to_read);
}

static void _turn_on_flash(){
  //HAL_GPIO_WritePin(Flash_Ctrl_GPIO_Port, Flash_Ctrl_Pin, GPIO_PIN_SET);
}

static void _turn_off_flash(){
  //HAL_GPIO_WritePin(Flash_Ctrl_GPIO_Port, Flash_Ctrl_Pin, GPIO_PIN_RESET);
}

static uint32_t _write_to_multiple_sectors(uint8_t * log_line, uint16_t log_length, uint32_t next_write_addr, bool_t from_beginning, uint8_t log_meta) {
  /* Multi sector write */
  uint32_t free_in_last_sector;
  uint32_t additional_sectors_needed;
  uint16_t remaining_data_length;
  uint16_t last_wrote_length = 0;

  free_in_last_sector = (SECTOR_SIZE - (next_write_addr % SECTOR_SIZE));
  if (free_in_last_sector > log_length + ((from_beginning == TRUE) ? 2 : 0)){
    free_in_last_sector = log_length + ((from_beginning == TRUE) ? 2 : 0);
  }
  if (free_in_last_sector > 2){
    next_write_addr = _write_to_single_sector(log_line, free_in_last_sector, next_write_addr, from_beginning, log_meta);
    last_wrote_length = free_in_last_sector - ((from_beginning == TRUE) ? 2 : 0);
    if (free_in_last_sector == log_length + ((from_beginning == TRUE) ? 2 : 0)){
      log_length = 0;
    } else {
      log_length -= (free_in_last_sector - ((from_beginning == TRUE) ? 2 : 0));
    }
    from_beginning = FALSE;
  } else if (free_in_last_sector == 2) {
    next_write_addr = _write_to_single_sector(log_line, 2, next_write_addr, from_beginning, log_meta);
    from_beginning = FALSE;
  }
  additional_sectors_needed = log_length / SECTOR_SIZE;
  remaining_data_length = log_length % SECTOR_SIZE;
  for (uint8_t i = 0; i < additional_sectors_needed; i++) {
    uint16_t tmp_length = 0;
    if (log_length > SECTOR_SIZE){
      tmp_length = log_length - SECTOR_SIZE;
    } else {
      tmp_length = SECTOR_SIZE - log_length;
      if (tmp_length > log_length){
        tmp_length = log_length;
      }
    }
    next_write_addr = _write_to_single_sector(log_line + last_wrote_length, tmp_length, next_write_addr, ((i == 0) ? from_beginning : FALSE), log_meta);
    last_wrote_length += tmp_length;
    log_length -= tmp_length;
    from_beginning = FALSE;
  }
  if (remaining_data_length > 0){
    next_write_addr = _write_to_single_sector(log_line + last_wrote_length, remaining_data_length, next_write_addr, from_beginning, log_meta);
  }
  return next_write_addr;
}

void test_read_flash(){
  uint8_t * sector_buff = (uint8_t *) pvPortMalloc(SECTOR_SIZE);
  if (sector_buff != NULL){
    //W25qxx_EraseSector(0);
    memset(sector_buff, 0, SECTOR_SIZE);
    printf("sector_buff before: %lx\n",sector_buff);
    memset(sector_buff, 0, SECTOR_SIZE);
    W25qxx_ReadSector(sector_buff, 0, 0, SECTOR_SIZE);
    printf("sector_buff after: %lx\n",sector_buff);
    vPortFree(sector_buff);
  }
}

static uint32_t _write_to_single_sector(uint8_t * log_line, uint16_t length_including_meta, uint32_t next_write_addr, bool_t is_first, uint8_t log_meta){
  //_turn_on_flash();
  uint8_t * sector_buff = (uint8_t *) pvPortMalloc(SECTOR_SIZE);
  if (sector_buff != NULL){
    uint16_t write_sector = next_write_addr / TOTAL_SECTORS;
    uint16_t write_sector_byte_offset = (next_write_addr % SECTOR_SIZE);
    uint8_t write_start_idx;
    uint16_t i = 0;
    memset(sector_buff, 0, SECTOR_SIZE);
    W25qxx_ReadSector(sector_buff, write_sector, 0, SECTOR_SIZE);
    //printf("sector_buff after: %lx\n",sector_buff);
    //printf("Data already in sector: %s\n",(char *) sector_buff);
    if (is_first == TRUE){
      sector_buff[write_sector_byte_offset] = START_OF_TEXT;
      sector_buff[write_sector_byte_offset + 1] = log_meta;
      write_start_idx = LOG_META_BYTES_LENGTH;
    } else {
      write_start_idx = 0;
    }
    for (i = write_start_idx; i < length_including_meta; i++) {
      sector_buff[write_sector_byte_offset + i] = log_line[i - write_start_idx];
    }
    //printf("Data appended to sector before: %s\n",(char *) sector_buff);
    next_write_addr += i;
    W25qxx_EraseSector(write_sector);
    W25qxx_WriteSector(sector_buff, write_sector, 0, SECTOR_SIZE);
    //printf("Data appended to sector after: %s\n",(char *) sector_buff);
    vPortFree(sector_buff);
    if (next_write_addr > MAX_LOG_WRITABLE_LOCATION){
      next_write_addr = 0;
    }
  }
  //_turn_off_flash();
  return next_write_addr;
}

static uint32_t _find_next_valid_read_start_addr(uint32_t current_write_addr){
  //_turn_on_flash();
  uint8_t * buff = (uint8_t *) pvPortMalloc(SPI_MAX_WRITE_PER_CALL);
  uint32_t new_read_addr = -1;
  if (buff != NULL){
    uint32_t read_bytes = 0;
    while (read_bytes < TOTAL_BYTES && new_read_addr == -1) {
      uint16_t temp_read_len = SPI_MAX_WRITE_PER_CALL;
      if (current_write_addr + SPI_MAX_WRITE_PER_CALL > MAX_LOG_WRITABLE_LOCATION) {
        temp_read_len = (current_write_addr + SPI_MAX_WRITE_PER_CALL) - MAX_LOG_WRITABLE_LOCATION;
      }
      _read_bytes_from_ext_flash(buff, SPI_MAX_WRITE_PER_CALL, current_write_addr, temp_read_len);
      for (uint16_t i = 0; i < SPI_MAX_WRITE_PER_CALL; i++){
        if (buff == START_OF_TEXT){
          new_read_addr = current_write_addr + i;
          break;
        }
      }
      read_bytes += temp_read_len;
      current_write_addr += SPI_MAX_WRITE_PER_CALL;
      if (current_write_addr > MAX_LOG_WRITABLE_LOCATION){
        current_write_addr = 0;
      }
    }
    if (new_read_addr == -1){
      new_read_addr = 0;
    }
    vPortFree(buff);
  }
  //_turn_off_flash();
  return new_read_addr;
}

static void _read_bytes_from_ext_flash(uint8_t * buff, uint16_t max_buff_len, uint32_t addr, uint16_t length) {
  HAL_Delay(100);
  uint16_t read_sector = addr / TOTAL_SECTORS;
  uint16_t read_sector_byte_offset = (addr % SECTOR_SIZE);
  configASSERT((length <= SECTOR_SIZE) && (length <= max_buff_len));
  if((read_sector_byte_offset + length) > SECTOR_SIZE) {
    uint16_t tmp_length = SECTOR_SIZE - read_sector_byte_offset;
    if (tmp_length > max_buff_len){
      tmp_length = max_buff_len;
    }
    printf("reading 1\n");
    W25qxx_ReadSector(buff, read_sector, read_sector_byte_offset, tmp_length);
    length -= tmp_length;
    configASSERT((tmp_length + length) <= max_buff_len);
    W25qxx_ReadSector(buff + tmp_length, read_sector + 1, 0, length);
  } else {
    printf("reading 2\n");
    W25qxx_ReadSector(buff, read_sector, read_sector_byte_offset, length);
  }
  printf("the flash data : %s \n",buff);
}

uint32_t flashWriteData(uint8_t *pBuffer, uint32_t writeAddress, uint32_t noOfBytes) {

  //W25qxx_WriteSector(pBuffer);
  uint32_t noOfBytesWrittenSoFar = 0;
  uint32_t tmpnoOfBytes = noOfBytes;
  //printf("write buff %s\n",pBuffer);
  while (noOfBytesWrittenSoFar < noOfBytes) {

    uint32_t write_sector = writeAddress / TOTAL_SECTORS;
    uint32_t write_offset = writeAddress % SECTOR_SIZE;

    uint32_t noOfBytesToWrite;

    if ((write_offset + tmpnoOfBytes) > SECTOR_SIZE) {
      noOfBytesToWrite = SECTOR_SIZE - write_offset;
    } else {
      noOfBytesToWrite = tmpnoOfBytes;
    }
    /*HAL_GPIO_WritePin(GPIOB, GPIO_PIN_13, GPIO_PIN_SET);
    HAL_Delay(500);*/
       /*printf("--------Writing------\n");
       printf("%d\n",write_sector);
       printf("%d\n",write_offset);
       printf("%d\n",noOfBytesToWrite);
       printf("------Wrote--------\n");*/
  

    W25qxx_WriteSector(pBuffer + noOfBytesWrittenSoFar    ,write_sector,write_offset,noOfBytesToWrite);
    /*HAL_GPIO_WritePin(GPIOB, GPIO_PIN_13, GPIO_PIN_RESET);
    HAL_Delay(500);*/
    noOfBytesWrittenSoFar += noOfBytesToWrite;
    writeAddress += noOfBytesToWrite;
    tmpnoOfBytes -= noOfBytesToWrite;
    //break;
  }
  return 0;
}

uint32_t storeLog(uint8_t *TxData, uint32_t currentLogStorageAddress)
{

    char buffer[45];
    memcpy(buffer, TxData, 45);
    //sprintf(buffer, "%s", TxData);
    printf("FLASH write DATA: %s\n",buffer);
    flashWriteData((uint8_t*)buffer, currentLogStorageAddress, 45);
    // Update the current log storage address
    char read_buffer[45];
    test_read_flash();
    printf("FLASH READ DATA: %s\n",read_buffer);
    currentLogStorageAddress += 45;

    return currentLogStorageAddress;
}
C:
#include <string.h> //for memset
#include "W25Qxx.h"
//#include "safe_string.h"
#include "ext_flash.h"
#include "w25qxxConfig.h"
#include <stdio.h>  // For printf
#include <stdbool.h> // For bool_t replacement
#include "FreeRTOS.h" // For pvPortMalloc/vPortFree
#include "task.h"    // For configASSERT
/*#include "crc32.h"
#include "internal_eeprom.h"*/

static uint32_t _write_to_single_sector(uint8_t * log_line, uint16_t length_including_meta, uint32_t next_write_addr, bool_t is_first, uint8_t log_meta);
static uint32_t _write_to_multiple_sectors(uint8_t * log_line, uint16_t length, uint32_t next_write_addr, bool_t from_beginning, uint8_t log_meta);
static uint32_t _find_next_valid_read_start_addr(uint32_t current_write_addr);
static void _turn_on_flash();
static void _turn_off_flash();
static void _read_bytes_from_ext_flash(uint8_t * buff, uint16_t max_buff_len, uint32_t addr, uint16_t length);

bool_t init_ext_flash (){
  bool_t res = FALSE;
  //_turn_on_flash();
  res = (W25qxx_Init() == true) ? TRUE : FALSE;
  //_turn_off_flash();
  return res;
}

void erase_ext_flash(){
  //TODO uncomment it after changing the conf storage to flash;
  W25qxx_EraseChip();
  //_handle_factory_reset();
  //_save_settings_file();
}

void save_fw_chunk_addr_to_storage(uint16_t bit_number, uint16_t data_start, uint32_t new_offset) {
  //if (unlock_flash(TRUE)){
    __set_offset_in_external_storage(bit_number, FALSE);
    __save_32bit_cfg_data_to_external_storage(data_start, new_offset, TRUE, FALSE);
    _save_config_to_external_flash();
    //lock_flash(TRUE);
  //}
}


bool_t save_chunk_to_storage(uint8_t * rx_buff, uint16_t data_length, uint16_t bit_number, uint16_t data_start, uint32_t update_location, uint32_t data_offset, uint8_t type, bool_t need_checking){
  //type = 0 store the fw chunk
  //       1 store the log chunk
  //       2 update the history read address
  //       3 update the history read address before history logs are overflows
  bool_t res = TRUE;
  //_turn_on_flash();
  uint32_t next_write_addr;
  if(type == 0){
   next_write_addr = update_location + data_offset + MAX_FIRMWARE_SIZE_BYTES_LENGTH;
  }else if(type == 1){
    next_write_addr = __get_32bit_cfg_data_from_storage(NXT_LOG_WRITE_ADDR, TRUE) + data_offset;

    if(rx_buff[2] != '$' && rx_buff[3] != ',' && need_checking == TRUE){
      DEVELOPER_PRINT("=================Log doesnt have $ and , so not storing...\n");
      DEVELOPER_PRINT("--> %s\n",rx_buff+2);
      return res;
    }

  }else if(type == 2){
    next_write_addr = __get_32bit_cfg_data_from_storage(NXT_LOG_WRITE_ADDR, TRUE) + data_offset;
    next_write_addr = next_write_addr -12; //to read the log addrs of next oldest log.
  }else{
    next_write_addr = MAX_LOG_WRITABLE_LOCATION - 12;
  }
  //DEVELOPER_PRINT("Log to be saved at: %ld with length: %ld\n",next_write_addr,data_length);
  uint16_t write_sector = next_write_addr / TOTAL_SECTORS;
  uint16_t write_sector_byte_offset = (next_write_addr % SECTOR_SIZE);
  uint8_t * sector_buff = (uint8_t *) pvPortMalloc(SECTOR_SIZE);
  if (sector_buff != NULL){
    uint16_t i;
    W25qxx_ReadSector(sector_buff, write_sector, 0, SECTOR_SIZE);
    for (i = 0; i < data_length; i++) {
      if (write_sector_byte_offset + i < SECTOR_SIZE){
        sector_buff[write_sector_byte_offset + i] = rx_buff;
      } else {
        break;
      }
    }
    W25qxx_EraseSector(write_sector);

    uint8_t try_count =0;
    bool_t is_successful = TRUE;
    while(TRUE){
      is_successful = FALSE;
      if(is_successful == TRUE){
        break;
      }else{
        try_count++;
        if(try_count == 2){
          break;
        }
      }
      W25qxx_WriteSector(sector_buff, write_sector, 0, SECTOR_SIZE);
      /* Verifying the data in the sector */
      W25qxx_ReadSector(sector_buff, write_sector, 0, SECTOR_SIZE);
      for (uint16_t j = 0; j < i; j++){
        if (sector_buff[write_sector_byte_offset + j] != rx_buff[j]){
          res = FALSE;
          is_successful = FALSE;
          DEVELOPER_PRINT("Flash saving failed-----------------\n");
          break;
        }
      }

    }
    vPortFree(sector_buff);
    if (res == TRUE){
      if (i < data_length){
        res = save_chunk_to_storage(rx_buff + i, data_length - i, bit_number, data_start, update_location, data_offset + i, type, FALSE);
      } else {
        if(type == 0){
          save_fw_chunk_addr_to_storage(bit_number, data_start, data_offset + data_length);
        }else if(type == 1){
          __save_32bit_cfg_data_to_external_storage(NXT_LOG_WRITE_ADDR, next_write_addr + data_length, FALSE, FALSE);
            //USER_PRINT("----------> Next Log storage address after %d\n--------------------->\n",__get_32bit_cfg_data_from_storage(NXT_LOG_WRITE_ADDR, TRUE));

          //DEVELOPER_PRINT("------Will store the external_flash config... Comment this as it will happen every 10 mins.");
          //_save_config_to_external_flash(); //will be stored every 10 min
        }
      }
    }
  }
  //_turn_off_flash();
  return res;
}

bool_t is_factory_default_firmware_present() {
  uint8_t data;
  _read_bytes_from_ext_flash(&data, 1, FIRMWARE_FACTORY_START_ADDR, 1);
  return (data == FACTORY_DEFAULT_FW_INSTALLED_FLAG) ? TRUE : FALSE;
}

bool_t set_factory_default_firmware_present_value() {
  //_turn_on_flash();
  uint16_t write_sector = FIRMWARE_FACTORY_START_ADDR / TOTAL_SECTORS;
  uint16_t write_sector_byte_offset = (FIRMWARE_FACTORY_START_ADDR % SECTOR_SIZE);
  uint8_t * sector_buff = (uint8_t *) pvPortMalloc(SECTOR_SIZE);
  if (sector_buff != NULL){
    W25qxx_ReadSector(sector_buff, write_sector, 0, SECTOR_SIZE);
    sector_buff[write_sector_byte_offset] = FACTORY_DEFAULT_FW_INSTALLED_FLAG;
    W25qxx_EraseSector(write_sector);
    W25qxx_WriteSector(sector_buff, write_sector, 0, SECTOR_SIZE);
    vPortFree(sector_buff);
  }
  //_turn_off_flash();
  return is_factory_default_firmware_present();
}

bool_t erase_ext_flash_sector(uint32_t address) {
  uint16_t erase_sector_num = address / TOTAL_SECTORS;
  //_turn_on_flash();
  W25qxx_EraseSector(erase_sector_num);
  //_turn_off_flash();
  return TRUE;
}

void read_update_data(uint8_t * buff, uint16_t max_len, uint32_t addr) {
  //_turn_on_flash();
  int32_t tmp_length = (max_len > SECTOR_SIZE) ? SECTOR_SIZE : max_len;
  int32_t bytes_cnt = 0;
  while (bytes_cnt < max_len){
    _read_bytes_from_ext_flash(buff + bytes_cnt, max_len - bytes_cnt, addr + bytes_cnt, tmp_length);
    bytes_cnt += tmp_length;
    if (bytes_cnt + SECTOR_SIZE > max_len){
      tmp_length = max_len - bytes_cnt;
    } else {
      tmp_length = SECTOR_SIZE;
    }
  }
  //_turn_off_flash();
}

void save_configuration_to_storage(uint8_t * conf_buffer, uint16_t bytes_to_write,uint16_t sector_address)
{
  W25qxx_EraseSector(sector_address);
  W25qxx_WriteSector(conf_buffer,sector_address,0,bytes_to_write);
#ifdef BOOTLOADERPROJECT
  uint8_t sector_buff[2048];
#else
  uint8_t * sector_buff = (uint8_t *) pvPortMalloc(bytes_to_write);
#endif
  if (sector_buff != NULL){
    bool_t res = FALSE;
    W25qxx_ReadSector(sector_buff, sector_address, 0, bytes_to_write);
    for (uint16_t j = 0; j < bytes_to_write-1; j++){
      if (sector_buff[j] != conf_buffer[j]){
        res = TRUE;
        break;
      }
    }
    if(res == TRUE){
      DEVELOPER_PRINT("Flash Data mismatch, rewriting the same data...\n");
      W25qxx_EraseSector(sector_address);
      W25qxx_WriteSector(conf_buffer,sector_address,0,bytes_to_write);
    }else{
      //DEVELOPER_PRINT("Data written to flash successfully...\n");
    }
    // vPortFree(sector_buff);

#ifndef BOOTLOADERPROJECT
    vPortFree(sector_buff);
#endif
  }
}
void read_configuration_from_storage(uint8_t * conf_buffer, uint16_t bytes_to_read, uint16_t sector_address){
  W25qxx_ReadSector(conf_buffer,sector_address,0,bytes_to_read);
}

static void _turn_on_flash(){
  //HAL_GPIO_WritePin(Flash_Ctrl_GPIO_Port, Flash_Ctrl_Pin, GPIO_PIN_SET);
}

static void _turn_off_flash(){
  //HAL_GPIO_WritePin(Flash_Ctrl_GPIO_Port, Flash_Ctrl_Pin, GPIO_PIN_RESET);
}

static uint32_t _write_to_multiple_sectors(uint8_t * log_line, uint16_t log_length, uint32_t next_write_addr, bool_t from_beginning, uint8_t log_meta) {
  /* Multi sector write */
  uint32_t free_in_last_sector;
  uint32_t additional_sectors_needed;
  uint16_t remaining_data_length;
  uint16_t last_wrote_length = 0;

  free_in_last_sector = (SECTOR_SIZE - (next_write_addr % SECTOR_SIZE));
  if (free_in_last_sector > log_length + ((from_beginning == TRUE) ? 2 : 0)){
    free_in_last_sector = log_length + ((from_beginning == TRUE) ? 2 : 0);
  }
  if (free_in_last_sector > 2){
    next_write_addr = _write_to_single_sector(log_line, free_in_last_sector, next_write_addr, from_beginning, log_meta);
    last_wrote_length = free_in_last_sector - ((from_beginning == TRUE) ? 2 : 0);
    if (free_in_last_sector == log_length + ((from_beginning == TRUE) ? 2 : 0)){
      log_length = 0;
    } else {
      log_length -= (free_in_last_sector - ((from_beginning == TRUE) ? 2 : 0));
    }
    from_beginning = FALSE;
  } else if (free_in_last_sector == 2) {
    next_write_addr = _write_to_single_sector(log_line, 2, next_write_addr, from_beginning, log_meta);
    from_beginning = FALSE;
  }
  additional_sectors_needed = log_length / SECTOR_SIZE;
  remaining_data_length = log_length % SECTOR_SIZE;
  for (uint8_t i = 0; i < additional_sectors_needed; i++) {
    uint16_t tmp_length = 0;
    if (log_length > SECTOR_SIZE){
      tmp_length = log_length - SECTOR_SIZE;
    } else {
      tmp_length = SECTOR_SIZE - log_length;
      if (tmp_length > log_length){
        tmp_length = log_length;
      }
    }
    next_write_addr = _write_to_single_sector(log_line + last_wrote_length, tmp_length, next_write_addr, ((i == 0) ? from_beginning : FALSE), log_meta);
    last_wrote_length += tmp_length;
    log_length -= tmp_length;
    from_beginning = FALSE;
  }
  if (remaining_data_length > 0){
    next_write_addr = _write_to_single_sector(log_line + last_wrote_length, remaining_data_length, next_write_addr, from_beginning, log_meta);
  }
  return next_write_addr;
}

void test_read_flash(){
  uint8_t * sector_buff = (uint8_t *) pvPortMalloc(SECTOR_SIZE);
  if (sector_buff != NULL){
    //W25qxx_EraseSector(0);
    memset(sector_buff, 0, SECTOR_SIZE);
    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_13, GPIO_PIN_SET);
    HAL_Delay(500);
    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_13, GPIO_PIN_RESET);
    HAL_Delay(500);
    printf("sector_buff before: %lx\n",sector_buff);
    memset(sector_buff, 0, SECTOR_SIZE);
    W25qxx_ReadSector(sector_buff, 0, 0, SECTOR_SIZE);
    printf("sector_buff after: %lx\n",sector_buff);
    vPortFree(sector_buff);
  }
}

static uint32_t _write_to_single_sector(uint8_t * log_line, uint16_t length_including_meta, uint32_t next_write_addr, bool_t is_first, uint8_t log_meta){
  //_turn_on_flash();
  uint8_t * sector_buff = (uint8_t *) pvPortMalloc(SECTOR_SIZE);
  if (sector_buff != NULL){
    uint16_t write_sector = next_write_addr / TOTAL_SECTORS;
    uint16_t write_sector_byte_offset = (next_write_addr % SECTOR_SIZE);
    uint8_t write_start_idx;
    uint16_t i = 0;
    memset(sector_buff, 0, SECTOR_SIZE);
    W25qxx_ReadSector(sector_buff, write_sector, 0, SECTOR_SIZE);
    //printf("sector_buff after: %lx\n",sector_buff);
    //printf("Data already in sector: %s\n",(char *) sector_buff);
    if (is_first == TRUE){
      sector_buff[write_sector_byte_offset] = START_OF_TEXT;
      sector_buff[write_sector_byte_offset + 1] = log_meta;
      write_start_idx = LOG_META_BYTES_LENGTH;
    } else {
      write_start_idx = 0;
    }
    for (i = write_start_idx; i < length_including_meta; i++) {
      sector_buff[write_sector_byte_offset + i] = log_line[i - write_start_idx];
    }
    //printf("Data appended to sector before: %s\n",(char *) sector_buff);
    next_write_addr += i;
    W25qxx_EraseSector(write_sector);
    W25qxx_WriteSector(sector_buff, write_sector, 0, SECTOR_SIZE);
    //printf("Data appended to sector after: %s\n",(char *) sector_buff);
    vPortFree(sector_buff);
    if (next_write_addr > MAX_LOG_WRITABLE_LOCATION){
      next_write_addr = 0;
    }
  }
  //_turn_off_flash();
  return next_write_addr;
}

static uint32_t _find_next_valid_read_start_addr(uint32_t current_write_addr){
  //_turn_on_flash();
  uint8_t * buff = (uint8_t *) pvPortMalloc(SPI_MAX_WRITE_PER_CALL);
  uint32_t new_read_addr = -1;
  if (buff != NULL){
    uint32_t read_bytes = 0;
    while (read_bytes < TOTAL_BYTES && new_read_addr == -1) {
      uint16_t temp_read_len = SPI_MAX_WRITE_PER_CALL;
      if (current_write_addr + SPI_MAX_WRITE_PER_CALL > MAX_LOG_WRITABLE_LOCATION) {
        temp_read_len = (current_write_addr + SPI_MAX_WRITE_PER_CALL) - MAX_LOG_WRITABLE_LOCATION;
      }
      _read_bytes_from_ext_flash(buff, SPI_MAX_WRITE_PER_CALL, current_write_addr, temp_read_len);
      for (uint16_t i = 0; i < SPI_MAX_WRITE_PER_CALL; i++){
        if (buff == START_OF_TEXT){
          new_read_addr = current_write_addr + i;
          break;
        }
      }
      read_bytes += temp_read_len;
      current_write_addr += SPI_MAX_WRITE_PER_CALL;
      if (current_write_addr > MAX_LOG_WRITABLE_LOCATION){
        current_write_addr = 0;
      }
    }
    if (new_read_addr == -1){
      new_read_addr = 0;
    }
    vPortFree(buff);
  }
  //_turn_off_flash();
  return new_read_addr;
}

static void _read_bytes_from_ext_flash(uint8_t * buff, uint16_t max_buff_len, uint32_t addr, uint16_t length) {
  HAL_Delay(100);
  uint16_t read_sector = addr / TOTAL_SECTORS;
  uint16_t read_sector_byte_offset = (addr % SECTOR_SIZE);
  configASSERT((length <= SECTOR_SIZE) && (length <= max_buff_len));
  if((read_sector_byte_offset + length) > SECTOR_SIZE) {
    uint16_t tmp_length = SECTOR_SIZE - read_sector_byte_offset;
    if (tmp_length > max_buff_len){
      tmp_length = max_buff_len;
    }
    printf("reading 1\n");
    W25qxx_ReadSector(buff, read_sector, read_sector_byte_offset, tmp_length);
    length -= tmp_length;
    configASSERT((tmp_length + length) <= max_buff_len);
    W25qxx_ReadSector(buff + tmp_length, read_sector + 1, 0, length);
  } else {
    printf("reading 2\n");
    W25qxx_ReadSector(buff, read_sector, read_sector_byte_offset, length);
  }
  printf("the flash data : %s \n",buff);
}

uint32_t flashWriteData(uint8_t *pBuffer, uint32_t writeAddress, uint32_t noOfBytes) {

  //W25qxx_WriteSector(pBuffer);
  uint32_t noOfBytesWrittenSoFar = 0;
  uint32_t tmpnoOfBytes = noOfBytes;
  //printf("write buff %s\n",pBuffer);
  while (noOfBytesWrittenSoFar < noOfBytes) {
   
    uint32_t write_sector = writeAddress / TOTAL_SECTORS;
    uint32_t write_offset = writeAddress % SECTOR_SIZE;

    uint32_t noOfBytesToWrite;

    if ((write_offset + tmpnoOfBytes) > SECTOR_SIZE) {
      noOfBytesToWrite = SECTOR_SIZE - write_offset;
    } else {
      noOfBytesToWrite = tmpnoOfBytes;
    }
    /*HAL_GPIO_WritePin(GPIOB, GPIO_PIN_13, GPIO_PIN_SET);
    HAL_Delay(500);*/
       /*printf("--------Writing------\n");
       printf("%d\n",write_sector);
       printf("%d\n",write_offset);
       printf("%d\n",noOfBytesToWrite);
       printf("------Wrote--------\n");*/
      


    W25qxx_WriteSector(pBuffer + noOfBytesWrittenSoFar    ,write_sector,write_offset,noOfBytesToWrite);
    /*HAL_GPIO_WritePin(GPIOB, GPIO_PIN_13, GPIO_PIN_RESET);
    HAL_Delay(500);*/
    noOfBytesWrittenSoFar += noOfBytesToWrite;
    writeAddress += noOfBytesToWrite;
    tmpnoOfBytes -= noOfBytesToWrite;
    //break;
  }
  return 0;
}


uint32_t storeLog(uint8_t *TxData, uint32_t currentLogStorageAddress)
{

    char buffer[45];
   memcpy(buffer, "123", 45); 
    //sprintf(buffer, "%s", TxData);
    printf("FLASH write DATA: %s\n",buffer);
    flashWriteData((uint8_t*)buffer, currentLogStorageAddress, 45);
    // Update the current log storage address
    char read_buffer[45];
    test_read_flash();
    printf("FLASH READ DATA: %s\n",read_buffer);
    currentLogStorageAddress += 45;
   
    return currentLogStorageAddress;
}
Moderator edit: added CODE tags
 
Last edited by a moderator:

Thread Starter

sreekuttan143

Joined May 20, 2025
5
#include <string.h> //for memset
#include "W25Qxx.h"
//#include "safe_string.h"
#include "ext_flash.h"
#include "w25qxxConfig.h"
#include <stdio.h> // For printf
#include <stdbool.h> // For bool_t replacement
#include "FreeRTOS.h" // For pvPortMalloc/vPortFree
#include "task.h" // For configASSERT
/*#include "crc32.h"
#include "internal_eeprom.h"*/

static uint32_t _write_to_single_sector(uint8_t * log_line, uint16_t length_including_meta, uint32_t next_write_addr, bool_t is_first, uint8_t log_meta);
static uint32_t _write_to_multiple_sectors(uint8_t * log_line, uint16_t length, uint32_t next_write_addr, bool_t from_beginning, uint8_t log_meta);
static uint32_t _find_next_valid_read_start_addr(uint32_t current_write_addr);
static void _turn_on_flash();
static void _turn_off_flash();
static void _read_bytes_from_ext_flash(uint8_t * buff, uint16_t max_buff_len, uint32_t addr, uint16_t length);

bool_t init_ext_flash (){
bool_t res = FALSE;
//_turn_on_flash();
res = (W25qxx_Init() == true) ? TRUE : FALSE;
//_turn_off_flash();
return res;
}

void erase_ext_flash(){
//TODO uncomment it after changing the conf storage to flash;
W25qxx_EraseChip();
//_handle_factory_reset();
//_save_settings_file();
}

void save_fw_chunk_addr_to_storage(uint16_t bit_number, uint16_t data_start, uint32_t new_offset) {
//if (unlock_flash(TRUE)){
__set_offset_in_external_storage(bit_number, FALSE);
__save_32bit_cfg_data_to_external_storage(data_start, new_offset, TRUE, FALSE);
_save_config_to_external_flash();
//lock_flash(TRUE);
//}
}


bool_t save_chunk_to_storage(uint8_t * rx_buff, uint16_t data_length, uint16_t bit_number, uint16_t data_start, uint32_t update_location, uint32_t data_offset, uint8_t type, bool_t need_checking){
//type = 0 store the fw chunk
// 1 store the log chunk
// 2 update the history read address
// 3 update the history read address before history logs are overflows
bool_t res = TRUE;
//_turn_on_flash();
uint32_t next_write_addr;
if(type == 0){
next_write_addr = update_location + data_offset + MAX_FIRMWARE_SIZE_BYTES_LENGTH;
}else if(type == 1){
next_write_addr = __get_32bit_cfg_data_from_storage(NXT_LOG_WRITE_ADDR, TRUE) + data_offset;

if(rx_buff[2] != '$' && rx_buff[3] != ',' && need_checking == TRUE){
DEVELOPER_PRINT("=================Log doesnt have $ and , so not storing...\n");
DEVELOPER_PRINT("--> %s\n",rx_buff+2);
return res;
}

}else if(type == 2){
next_write_addr = __get_32bit_cfg_data_from_storage(NXT_LOG_WRITE_ADDR, TRUE) + data_offset;
next_write_addr = next_write_addr -12; //to read the log addrs of next oldest log.
}else{
next_write_addr = MAX_LOG_WRITABLE_LOCATION - 12;
}
//DEVELOPER_PRINT("Log to be saved at: %ld with length: %ld\n",next_write_addr,data_length);
uint16_t write_sector = next_write_addr / TOTAL_SECTORS;
uint16_t write_sector_byte_offset = (next_write_addr % SECTOR_SIZE);
uint8_t * sector_buff = (uint8_t *) pvPortMalloc(SECTOR_SIZE);
if (sector_buff != NULL){
uint16_t i;
W25qxx_ReadSector(sector_buff, write_sector, 0, SECTOR_SIZE);
for (i = 0; i < data_length; i++) {
if (write_sector_byte_offset + i < SECTOR_SIZE){
sector_buff[write_sector_byte_offset + i] = rx_buff;
} else {
break;
}
}
W25qxx_EraseSector(write_sector);

uint8_t try_count =0;
bool_t is_successful = TRUE;
while(TRUE){
is_successful = FALSE;
if(is_successful == TRUE){
break;
}else{
try_count++;
if(try_count == 2){
break;
}
}
W25qxx_WriteSector(sector_buff, write_sector, 0, SECTOR_SIZE);
/* Verifying the data in the sector */
W25qxx_ReadSector(sector_buff, write_sector, 0, SECTOR_SIZE);
for (uint16_t j = 0; j < i; j++){
if (sector_buff[write_sector_byte_offset + j] != rx_buff[j]){
res = FALSE;
is_successful = FALSE;
DEVELOPER_PRINT("Flash saving failed-----------------\n");
break;
}
}

}
vPortFree(sector_buff);
if (res == TRUE){
if (i < data_length){
res = save_chunk_to_storage(rx_buff + i, data_length - i, bit_number, data_start, update_location, data_offset + i, type, FALSE);
} else {
if(type == 0){
save_fw_chunk_addr_to_storage(bit_number, data_start, data_offset + data_length);
}else if(type == 1){
__save_32bit_cfg_data_to_external_storage(NXT_LOG_WRITE_ADDR, next_write_addr + data_length, FALSE, FALSE);
//USER_PRINT("----------> Next Log storage address after %d\n--------------------->\n",__get_32bit_cfg_data_from_storage(NXT_LOG_WRITE_ADDR, TRUE));

//DEVELOPER_PRINT("------Will store the external_flash config... Comment this as it will happen every 10 mins.");
//_save_config_to_external_flash(); //will be stored every 10 min
}
}
}
}
//_turn_off_flash();
return res;
}

bool_t is_factory_default_firmware_present() {
uint8_t data;
_read_bytes_from_ext_flash(&data, 1, FIRMWARE_FACTORY_START_ADDR, 1);
return (data == FACTORY_DEFAULT_FW_INSTALLED_FLAG) ? TRUE : FALSE;
}

bool_t set_factory_default_firmware_present_value() {
//_turn_on_flash();
uint16_t write_sector = FIRMWARE_FACTORY_START_ADDR / TOTAL_SECTORS;
uint16_t write_sector_byte_offset = (FIRMWARE_FACTORY_START_ADDR % SECTOR_SIZE);
uint8_t * sector_buff = (uint8_t *) pvPortMalloc(SECTOR_SIZE);
if (sector_buff != NULL){
W25qxx_ReadSector(sector_buff, write_sector, 0, SECTOR_SIZE);
sector_buff[write_sector_byte_offset] = FACTORY_DEFAULT_FW_INSTALLED_FLAG;
W25qxx_EraseSector(write_sector);
W25qxx_WriteSector(sector_buff, write_sector, 0, SECTOR_SIZE);
vPortFree(sector_buff);
}
//_turn_off_flash();
return is_factory_default_firmware_present();
}

bool_t erase_ext_flash_sector(uint32_t address) {
uint16_t erase_sector_num = address / TOTAL_SECTORS;
//_turn_on_flash();
W25qxx_EraseSector(erase_sector_num);
//_turn_off_flash();
return TRUE;
}

void read_update_data(uint8_t * buff, uint16_t max_len, uint32_t addr) {
//_turn_on_flash();
int32_t tmp_length = (max_len > SECTOR_SIZE) ? SECTOR_SIZE : max_len;
int32_t bytes_cnt = 0;
while (bytes_cnt < max_len){
_read_bytes_from_ext_flash(buff + bytes_cnt, max_len - bytes_cnt, addr + bytes_cnt, tmp_length);
bytes_cnt += tmp_length;
if (bytes_cnt + SECTOR_SIZE > max_len){
tmp_length = max_len - bytes_cnt;
} else {
tmp_length = SECTOR_SIZE;
}
}
//_turn_off_flash();
}

void save_configuration_to_storage(uint8_t * conf_buffer, uint16_t bytes_to_write,uint16_t sector_address)
{
W25qxx_EraseSector(sector_address);
W25qxx_WriteSector(conf_buffer,sector_address,0,bytes_to_write);
#ifdef BOOTLOADERPROJECT
uint8_t sector_buff[2048];
#else
uint8_t * sector_buff = (uint8_t *) pvPortMalloc(bytes_to_write);
#endif
if (sector_buff != NULL){
bool_t res = FALSE;
W25qxx_ReadSector(sector_buff, sector_address, 0, bytes_to_write);
for (uint16_t j = 0; j < bytes_to_write-1; j++){
if (sector_buff[j] != conf_buffer[j]){
res = TRUE;
break;
}
}
if(res == TRUE){
DEVELOPER_PRINT("Flash Data mismatch, rewriting the same data...\n");
W25qxx_EraseSector(sector_address);
W25qxx_WriteSector(conf_buffer,sector_address,0,bytes_to_write);
}else{
//DEVELOPER_PRINT("Data written to flash successfully...\n");
}
// vPortFree(sector_buff);

#ifndef BOOTLOADERPROJECT
vPortFree(sector_buff);
#endif
}
}
void read_configuration_from_storage(uint8_t * conf_buffer, uint16_t bytes_to_read, uint16_t sector_address){
W25qxx_ReadSector(conf_buffer,sector_address,0,bytes_to_read);
}

static void _turn_on_flash(){
//HAL_GPIO_WritePin(Flash_Ctrl_GPIO_Port, Flash_Ctrl_Pin, GPIO_PIN_SET);
}

static void _turn_off_flash(){
//HAL_GPIO_WritePin(Flash_Ctrl_GPIO_Port, Flash_Ctrl_Pin, GPIO_PIN_RESET);
}

static uint32_t _write_to_multiple_sectors(uint8_t * log_line, uint16_t log_length, uint32_t next_write_addr, bool_t from_beginning, uint8_t log_meta) {
/* Multi sector write */
uint32_t free_in_last_sector;
uint32_t additional_sectors_needed;
uint16_t remaining_data_length;
uint16_t last_wrote_length = 0;

free_in_last_sector = (SECTOR_SIZE - (next_write_addr % SECTOR_SIZE));
if (free_in_last_sector > log_length + ((from_beginning == TRUE) ? 2 : 0)){
free_in_last_sector = log_length + ((from_beginning == TRUE) ? 2 : 0);
}
if (free_in_last_sector > 2){
next_write_addr = _write_to_single_sector(log_line, free_in_last_sector, next_write_addr, from_beginning, log_meta);
last_wrote_length = free_in_last_sector - ((from_beginning == TRUE) ? 2 : 0);
if (free_in_last_sector == log_length + ((from_beginning == TRUE) ? 2 : 0)){
log_length = 0;
} else {
log_length -= (free_in_last_sector - ((from_beginning == TRUE) ? 2 : 0));
}
from_beginning = FALSE;
} else if (free_in_last_sector == 2) {
next_write_addr = _write_to_single_sector(log_line, 2, next_write_addr, from_beginning, log_meta);
from_beginning = FALSE;
}
additional_sectors_needed = log_length / SECTOR_SIZE;
remaining_data_length = log_length % SECTOR_SIZE;
for (uint8_t i = 0; i < additional_sectors_needed; i++) {
uint16_t tmp_length = 0;
if (log_length > SECTOR_SIZE){
tmp_length = log_length - SECTOR_SIZE;
} else {
tmp_length = SECTOR_SIZE - log_length;
if (tmp_length > log_length){
tmp_length = log_length;
}
}
next_write_addr = _write_to_single_sector(log_line + last_wrote_length, tmp_length, next_write_addr, ((i == 0) ? from_beginning : FALSE), log_meta);
last_wrote_length += tmp_length;
log_length -= tmp_length;
from_beginning = FALSE;
}
if (remaining_data_length > 0){
next_write_addr = _write_to_single_sector(log_line + last_wrote_length, remaining_data_length, next_write_addr, from_beginning, log_meta);
}
return next_write_addr;
}

void test_read_flash(){
uint8_t * sector_buff = (uint8_t *) pvPortMalloc(SECTOR_SIZE);
if (sector_buff != NULL){
//W25qxx_EraseSector(0);
memset(sector_buff, 0, SECTOR_SIZE);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_13, GPIO_PIN_SET);
HAL_Delay(500);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_13, GPIO_PIN_RESET);
HAL_Delay(500);
printf("sector_buff before: %lx\n",sector_buff);
memset(sector_buff, 0, SECTOR_SIZE);
W25qxx_ReadSector(sector_buff, 0, 0, SECTOR_SIZE);
printf("sector_buff after: %lx\n",sector_buff);
vPortFree(sector_buff);
}
}

static uint32_t _write_to_single_sector(uint8_t * log_line, uint16_t length_including_meta, uint32_t next_write_addr, bool_t is_first, uint8_t log_meta){
//_turn_on_flash();
uint8_t * sector_buff = (uint8_t *) pvPortMalloc(SECTOR_SIZE);
if (sector_buff != NULL){
uint16_t write_sector = next_write_addr / TOTAL_SECTORS;
uint16_t write_sector_byte_offset = (next_write_addr % SECTOR_SIZE);
uint8_t write_start_idx;
uint16_t i = 0;
memset(sector_buff, 0, SECTOR_SIZE);
W25qxx_ReadSector(sector_buff, write_sector, 0, SECTOR_SIZE);
//printf("sector_buff after: %lx\n",sector_buff);
//printf("Data already in sector: %s\n",(char *) sector_buff);
if (is_first == TRUE){
sector_buff[write_sector_byte_offset] = START_OF_TEXT;
sector_buff[write_sector_byte_offset + 1] = log_meta;
write_start_idx = LOG_META_BYTES_LENGTH;
} else {
write_start_idx = 0;
}
for (i = write_start_idx; i < length_including_meta; i++) {
sector_buff[write_sector_byte_offset + i] = log_line[i - write_start_idx];
}
//printf("Data appended to sector before: %s\n",(char *) sector_buff);
next_write_addr += i;
W25qxx_EraseSector(write_sector);
W25qxx_WriteSector(sector_buff, write_sector, 0, SECTOR_SIZE);
//printf("Data appended to sector after: %s\n",(char *) sector_buff);
vPortFree(sector_buff);
if (next_write_addr > MAX_LOG_WRITABLE_LOCATION){
next_write_addr = 0;
}
}
//_turn_off_flash();
return next_write_addr;
}

static uint32_t _find_next_valid_read_start_addr(uint32_t current_write_addr){
//_turn_on_flash();
uint8_t * buff = (uint8_t *) pvPortMalloc(SPI_MAX_WRITE_PER_CALL);
uint32_t new_read_addr = -1;
if (buff != NULL){
uint32_t read_bytes = 0;
while (read_bytes < TOTAL_BYTES && new_read_addr == -1) {
uint16_t temp_read_len = SPI_MAX_WRITE_PER_CALL;
if (current_write_addr + SPI_MAX_WRITE_PER_CALL > MAX_LOG_WRITABLE_LOCATION) {
temp_read_len = (current_write_addr + SPI_MAX_WRITE_PER_CALL) - MAX_LOG_WRITABLE_LOCATION;
}
_read_bytes_from_ext_flash(buff, SPI_MAX_WRITE_PER_CALL, current_write_addr, temp_read_len);
for (uint16_t i = 0; i < SPI_MAX_WRITE_PER_CALL; i++){
if (buff == START_OF_TEXT){
new_read_addr = current_write_addr + i;
break;
}
}
read_bytes += temp_read_len;
current_write_addr += SPI_MAX_WRITE_PER_CALL;
if (current_write_addr > MAX_LOG_WRITABLE_LOCATION){
current_write_addr = 0;
}
}
if (new_read_addr == -1){
new_read_addr = 0;
}
vPortFree(buff);
}
//_turn_off_flash();
return new_read_addr;
}

static void _read_bytes_from_ext_flash(uint8_t * buff, uint16_t max_buff_len, uint32_t addr, uint16_t length) {
HAL_Delay(100);
uint16_t read_sector = addr / TOTAL_SECTORS;
uint16_t read_sector_byte_offset = (addr % SECTOR_SIZE);
configASSERT((length <= SECTOR_SIZE) && (length <= max_buff_len));
if((read_sector_byte_offset + length) > SECTOR_SIZE) {
uint16_t tmp_length = SECTOR_SIZE - read_sector_byte_offset;
if (tmp_length > max_buff_len){
tmp_length = max_buff_len;
}
printf("reading 1\n");
W25qxx_ReadSector(buff, read_sector, read_sector_byte_offset, tmp_length);
length -= tmp_length;
configASSERT((tmp_length + length) <= max_buff_len);
W25qxx_ReadSector(buff + tmp_length, read_sector + 1, 0, length);
} else {
printf("reading 2\n");
W25qxx_ReadSector(buff, read_sector, read_sector_byte_offset, length);
}
printf("the flash data : %s \n",buff);
}

uint32_t flashWriteData(uint8_t *pBuffer, uint32_t writeAddress, uint32_t noOfBytes) {

//W25qxx_WriteSector(pBuffer);
uint32_t noOfBytesWrittenSoFar = 0;
uint32_t tmpnoOfBytes = noOfBytes;
//printf("write buff %s\n",pBuffer);
while (noOfBytesWrittenSoFar < noOfBytes) {

uint32_t write_sector = writeAddress / TOTAL_SECTORS;
uint32_t write_offset = writeAddress % SECTOR_SIZE;

uint32_t noOfBytesToWrite;

if ((write_offset + tmpnoOfBytes) > SECTOR_SIZE) {
noOfBytesToWrite = SECTOR_SIZE - write_offset;
} else {
noOfBytesToWrite = tmpnoOfBytes;
}
/*HAL_GPIO_WritePin(GPIOB, GPIO_PIN_13, GPIO_PIN_SET);
HAL_Delay(500);*/
/*printf("--------Writing------\n");
printf("%d\n",write_sector);
printf("%d\n",write_offset);
printf("%d\n",noOfBytesToWrite);
printf("------Wrote--------\n");*/



W25qxx_WriteSector(pBuffer + noOfBytesWrittenSoFar ,write_sector,write_offset,noOfBytesToWrite);
/*HAL_GPIO_WritePin(GPIOB, GPIO_PIN_13, GPIO_PIN_RESET);
HAL_Delay(500);*/
noOfBytesWrittenSoFar += noOfBytesToWrite;
writeAddress += noOfBytesToWrite;
tmpnoOfBytes -= noOfBytesToWrite;
//break;
}
return 0;
}


uint32_t storeLog(uint8_t *TxData, uint32_t currentLogStorageAddress)
{

char buffer[45];
memcpy(buffer, "123", 45);
//sprintf(buffer, "%s", TxData);
printf("FLASH write DATA: %s\n",buffer);
flashWriteData((uint8_t*)buffer, currentLogStorageAddress, 45);
// Update the current log storage address
char read_buffer[45];
test_read_flash();
printf("FLASH READ DATA: %s\n",read_buffer);
currentLogStorageAddress += 45;

return currentLogStorageAddress;
}
I have bolded the statement
 

panic mode

Joined Oct 10, 2011
4,864
if you want to use computers, specially if writing code, you may want to learn how to do it correctly. as suggested before surround your code by CODE tag... then it will be inside its own window with line numbers. CODE wrapper is applied similarly like QUOTE but it looks very different since it also includes line numbers and retains formatting. also much easier copy/paste from since CODE copy selects entire content of the CODE window, without scrolling many pages and selecting content manually.

1747751878058.png
 

Thread Starter

sreekuttan143

Joined May 20, 2025
5
are you sure you have correct parameters? what is the value of currentLogStorageAddress ?
Actually below is my main.c code. In that when RFID card detects the data packet will 1st store inside buffer and buffer data is copied to TxData. I need this TxData to write in flash each time in the available next free space and need to read data from flash .please help me

C:
//main.c code

/* USER CODE BEGIN Header */
/**
  **************************
  * @file           : main.c
  * @brief          : Main program body
  **************************
  * @attention
  *
  * Copyright (c) 2025 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  **************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "cmsis_os.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "RC522.h"
#include "W25Qxx.h"
#include "string.h"
#include "stdio.h"
#include "ext_flash.h"   
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

int i = 0;

char* location;

/* USER CODE END PTD */
typedef enum {
    POWER_ACTIVE,
    POWER_SOFT_POWERDOWN,
    POWER_HIBERNATE
} PowerMode;



/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#define LOG_COUNT_SECTOR 0  // First sector to store log count
#define LOGS_PER_PAGE (W25Q_PAGE_SIZE / BUFFER_LENGTH)  // ~5 logs per page (256/45)
#define RFID_RESET_DELAY 500 // ms - longer reset delay for more reliable reset
#define MAX_KNOWN_CARDS 10   // Maximum number of cards to store in the database
#define READER_ID "KL02BQ1908" // Identifier for this specific reader
#define LED_PIN GPIO_PIN_13   // LED pin (PB13)
#define LED_PORT GPIOB       // LED port (GPIOB)
#define CARD_PRESENT_TIMEOUT 500  // Time in ms to keep LED on after card is removed
#define DS1307_ADDRESS 0x68 << 1  // DS1307 I2C address (shifted for HAL API)
#define DS1307_REG_SECONDS 0x00   // Register address for seconds
// 1. Define W25Q Flash constants
#define W25Q_FLASH_SIZE (16*1024*1024) // 16MB flash size (adjust based on your actual W25Q chip)
#define MAX_FLASH_PAGES (W25Q_FLASH_SIZE / 256) // Assuming 256-byte pages
// 2. Avoid redefining FLASH_PAGE_SIZE
// Remove or comment out any line defining FLASH_PAGE_SIZE in your code
// Instead, create a different name for your flash page size
#define W25Q_PAGE_SIZE 256 // Use this instead of FLASH_PAGE_SIZE for W25Q



#define HISTORY_SIZE 30
#define BUFFER_LENGTH 45  // Adjust if your buffer is longer

char bufferHistory[HISTORY_SIZE][BUFFER_LENGTH];
int bufferHistoryIndex = 0;

volatile uint32_t totalLogsStored = 0;
volatile uint16_t currentBufferCount = 0;

uint8_t tx_data[5] = {1,2,3,4,5};
uint8_t rx_data[5];
uint8_t SPI_Interrupt = 0;

#define POWER_DOWN_CMD 0x16
uint8_t isInSleepMode = 0;

uint8_t lastHour = 0xFF;  // Track last hour to detect time change
uint8_t lastMinute = 0xFF;  // Track last minute to detect time change

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/
TIM_HandleTypeDef htim2;
SPI_HandleTypeDef hspi1;
SPI_HandleTypeDef hspi2;
UART_HandleTypeDef huart1;
UART_HandleTypeDef huart2;
I2C_HandleTypeDef hi2c1;
osThreadId defaultTaskHandle;
osThreadId task2Handler;
/* USER CODE BEGIN PV */

volatile uint32_t totalBytesWritten = 0;
const uint32_t totalFlashCapacity = W25Q_FLASH_SIZE; // 16MB in your case
volatile uint32_t totalLogsStoredInFlash = 0;  // Total logs in flash

#define RS485_TX_EN_PIN GPIO_PIN_5
#define RS485_TX_EN_PORT GPIOB
uint8_t status;
uint8_t str[16];
uint8_t sNum[4];
uint32_t inactivity_timer = 0;
PowerMode currentPowerMode = POWER_ACTIVE;
uint32_t lastCardDetectTime = 0; // Time when card was last detected
uint32_t last_detect_time = 0;
uint8_t rtcData[7];  // Array to store RTC data (seconds, minutes, hours, day, date, month, year)
char uartBuffer[100]; // Buffer for UART transmission
#define WAKE_UP_CMD 0x17
#define TIMEOUT_MS 5000
/* Add to your defines section */
#define INACTIVITY_TIMEOUT 10000 // 10 seconds in ms
#define SLEEP_MODE_DEBUG 1 // Set to 0 for production
volatile uint8_t wakeupFlag = 0;
uint32_t lastActivityTime = 0;
uint32_t ID=0;
#define history_size 20
#define buffer_length 45
#define h_size 1
#define b_length 45
char RxData[history_size][buffer_length];
uint8_t TxData[h_size][b_length];
//uint8_t * TxData = (uint8_t *) pvPortMalloc(SECTOR_SIZE);
uint32_t currentLogStartAddress = LOG_STORAGE_START_ADDRESS;
int indx = 0;
// Mode flags and variables for UART command processing
uint8_t writeMode = 0;      // Flag to indicate if in write mode (0=read, 1=write, 2=add card)
char vehicleReg[20] = {0};  // Buffer to store vehicle registration or card location

char buffer[45]; // Buffer for formatted messages

char *msg1 = "Reading from card\r\n";
char *msg2 = "Reading from TAG\r\n";
char *msg_reset = "RFID Reader Reset Complete\r\n";
/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_SPI1_Init(void);
static void MX_SPI2_Init(void);
static void MX_USART1_UART_Init(void);
static void MX_USART2_UART_Init(void);
static void RFID_HardReset(void);
static void MX_I2C1_Init(void);
static void MX_TIM2_Init(void);
void StartDefaultTask(void const * argument);
void task2_init (void const * argument);
/* USER CODE BEGIN PFP */
extern uint32_t W25qxx_WritePage(uint8_t *pBuffer, uint32_t Page_Address, uint32_t OffsetInByte, uint32_t NumByteToWrite_up_to_PageSize);
extern uint32_t W25qxx_ReadPage(uint8_t *pBuffer, uint32_t Page_Address, uint32_t OffsetInByte, uint32_t NumByteToRead_up_to_PageSize);
void Write_MFRC522(uint8_t addr, uint8_t val);
uint8_t Read_MFRC522(uint8_t addr);
uint32_t W25qxx_ReadID(void);
//void ProcessUSART1Command(void);
void FlushBufferToFlash(void);
uint8_t Read_MFRC522(uint8_t addr);
char* GetCardLocation(uint8_t* cardID);
void UpdateLedStatus(uint8_t cardDetected);
HAL_StatusTypeDef DS1307_ReadTime(void);
HAL_StatusTypeDef DS1307_SetTime(uint8_t hour, uint8_t min, uint8_t sec);
HAL_StatusTypeDef DS1307_SetDate(uint8_t day, uint8_t date, uint8_t month, uint8_t year);
uint8_t BCD_to_DEC(uint8_t bcd);
uint8_t DEC_to_BCD(uint8_t dec);
void HAL_TIM_MspPostInit(TIM_HandleTypeDef *htim);

uint32_t CountLogsInFlash(void)
{
    return totalLogsStoredInFlash;
}

float GetFlashStoragePercentage(void)
{
    if (totalFlashCapacity == 0) return 0.0f;
    return ((float)totalBytesWritten / (float)totalFlashCapacity) * 100.0f;
}

void RS485_EnableTx(void)
{
    HAL_GPIO_WritePin(RS485_TX_EN_PORT, RS485_TX_EN_PIN, GPIO_PIN_SET);
}

void RS485_EnableRx(void)
{
    HAL_GPIO_WritePin(RS485_TX_EN_PORT, RS485_TX_EN_PIN, GPIO_PIN_RESET);
}

void RS485_SendData(uint8_t *data, uint16_t size)
{
    RS485_EnableTx();
    HAL_UART_Transmit(&huart1, data, size, HAL_MAX_DELAY);
    HAL_UART_Transmit(&huart2, data, size, HAL_MAX_DELAY);
    RS485_EnableRx();
}

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/*void ProcessUSART1Command(void)
{
    static uint8_t usart1_rx_buffer[2] = {0};
    static HAL_StatusTypeDef status;
   
    // Start non-blocking receive
    status = HAL_UART_Receive_IT(&huart1, usart1_rx_buffer, 1);
   
    if (status == HAL_OK)
    {
        if (usart1_rx_buffer[0] == 'b')
        {
            // Read current time
            HAL_StatusTypeDef rtcStatus = DS1307_ReadTime();
            if (rtcStatus == HAL_OK)
            {
                uint8_t seconds = BCD_to_DEC(rtcData[0] & 0x7F);
                uint8_t minutes = BCD_to_DEC(rtcData[1]);
                uint8_t hours = BCD_to_DEC(rtcData[2] & 0x3F);
                uint8_t date = BCD_to_DEC(rtcData[4]);
                uint8_t month = BCD_to_DEC(rtcData[5]);
                uint8_t year = BCD_to_DEC(rtcData[6]);
               
                char info[100];
                snprintf(info, sizeof(info),
                         "\n%02d/%02d/20%02d %02d:%02d:%02d\n",
                         date, month, year, hours, minutes, seconds);
               
                // Send timestamp via RS485 to USART1
                RS485_SendData((uint8_t*)info, strlen(info));
            }
        }
        if (usart1_rx_buffer[0] == 's')
        {
          char flashinfo[100];
           float percentUsed = GetFlashStoragePercentage();
            uint32_t logCount = CountLogsInFlash();
            sprintf(flashinfo, "Flash: %.2f%% used (%lu/%lu bytes)\r\nLogs stored in flash memory: %lu\r\n",
                   percentUsed, totalBytesWritten, totalFlashCapacity, logCount);
            HAL_UART_Transmit(&huart1, (uint8_t*)flashinfo, strlen(flashinfo), HAL_MAX_DELAY);
            RS485_SendData((uint8_t*)flashinfo, strlen(flashinfo));
    }
  }
}*/

void MFRC522_SoftPowerDown(void)
{
    if (currentPowerMode != POWER_SOFT_POWERDOWN)
    {
        printf("Entering soft power mode\n");
        // Write to Command Register to enter Power Down mode
        Write_MFRC522(CommandReg, POWER_DOWN_CMD);
       
        currentPowerMode = POWER_SOFT_POWERDOWN;
    }
}

void MFRC522_WakeUp(void)
{
    if (currentPowerMode != POWER_ACTIVE)
    {
        printf("Entering wakeup mode\n");
       
        // Perform complete module reset and initialization sequence
        // 1. Reset the module
        HAL_GPIO_WritePin(MFRC522_RST_PORT, MFRC522_RST_PIN, GPIO_PIN_RESET);
        HAL_Delay(10);
        HAL_GPIO_WritePin(MFRC522_RST_PORT, MFRC522_RST_PIN, GPIO_PIN_SET);
        HAL_Delay(10);
       
        // 2. Soft reset via command register
        Write_MFRC522(CommandReg, 0x0F);  // Soft reset command
        HAL_Delay(10);
       
        // 3. Write wake-up command
        Write_MFRC522(CommandReg, WAKE_UP_CMD);
       
        // 4. Full re-initialization
        MFRC522_Init();
       
        // 5. Additional configuration to ensure active mode
        Write_MFRC522(TModeReg, 0x8D);      // Timer mode configuration
        Write_MFRC522(TPrescalerReg, 0x3E); // Timer prescaler
        Write_MFRC522(TReloadRegH, 0x03);   // Reload timer high bits
        Write_MFRC522(TReloadRegL, 0xE8);   // Reload timer low bits
       
        // 6. Antenna on
        Write_MFRC522(TxControlReg, 0x83);  // Tx2 and Tx1 antenna enabled
       
        currentPowerMode = POWER_ACTIVE;
       
        printf("MFRC522 Fully Reinitialized\n");
    }
}

// Convert Binary Coded Decimal (BCD) to Decimal
uint8_t BCD_to_DEC(uint8_t bcd)
{
    return ((bcd >> 4) * 10) + (bcd & 0x0F);
}

// Convert Decimal to BCD
uint8_t DEC_to_BCD(uint8_t dec)
{
    return ((dec / 10) << 4) | (dec % 10);
}

// Read time from DS1307
HAL_StatusTypeDef DS1307_ReadTime(void)
{
    uint8_t reg = DS1307_REG_SECONDS; // Start from seconds register
    HAL_StatusTypeDef status;
   
    // Set the register pointer to seconds register
    status = HAL_I2C_Master_Transmit(&hi2c1, DS1307_ADDRESS, &reg, 1, HAL_MAX_DELAY);
    if (status != HAL_OK)
    {
        //printf("Error setting register pointer: %d\r\n", status);
        return status;
    }
   
    // Read 7 bytes starting from seconds register
    status = HAL_I2C_Master_Receive(&hi2c1, DS1307_ADDRESS, rtcData, 7, HAL_MAX_DELAY);
    if (status != HAL_OK)
    {
        //printf("Error reading RTC data: %d\r\n", status);
        return status;
    }
   
    return HAL_OK;
}

// Set time in DS1307
HAL_StatusTypeDef DS1307_SetTime(uint8_t hour, uint8_t min, uint8_t sec)
{
    uint8_t data[4];
    HAL_StatusTypeDef status;
   
    data[0] = DS1307_REG_SECONDS; // Register address
    data[1] = DEC_to_BCD(sec) & 0x7F;  // Seconds - ensure CH bit (bit 7) is cleared to start oscillator
    data[2] = DEC_to_BCD(min);    // Minutes
    data[3] = DEC_to_BCD(hour);   // Hours (24-hour mode)
   
    status = HAL_I2C_Master_Transmit(&hi2c1, DS1307_ADDRESS, data, 4, HAL_MAX_DELAY);
    if (status != HAL_OK)
    {
        //printf("Error setting time: %d\r\n", status);
        return status;
    }
   
    return HAL_OK;
}

// Set date in DS1307
HAL_StatusTypeDef DS1307_SetDate(uint8_t day, uint8_t date, uint8_t month, uint8_t year)
{
    uint8_t data[5];
    HAL_StatusTypeDef status;
   
    data[0] = 0x03;               // Register address for day
    data[1] = DEC_to_BCD(day);    // Day (1-7)
    data[2] = DEC_to_BCD(date);   // Date (1-31)
    data[3] = DEC_to_BCD(month);  // Month (1-12)
    data[4] = DEC_to_BCD(year);   // Year (0-99)
   
    status = HAL_I2C_Master_Transmit(&hi2c1, DS1307_ADDRESS, data, 5, HAL_MAX_DELAY);
    if (status != HAL_OK)
    {
        //printf("Error setting date: %d\r\n", status);
        return status;
    }
   
    return HAL_OK;
}

// Read control register
HAL_StatusTypeDef DS1307_ReadControl(uint8_t *control)
{
    uint8_t reg = 0x07; // Control register address
    HAL_StatusTypeDef status;
   
    status = HAL_I2C_Master_Transmit(&hi2c1, DS1307_ADDRESS, &reg, 1, HAL_MAX_DELAY);
    if (status != HAL_OK)
        return status;
   
    status = HAL_I2C_Master_Receive(&hi2c1, DS1307_ADDRESS, control, 1, HAL_MAX_DELAY);
    return status;
}

// Start the DS1307 oscillator
HAL_StatusTypeDef DS1307_StartClock(void)
{
    uint8_t reg = DS1307_REG_SECONDS;
    uint8_t sec_value;
    HAL_StatusTypeDef status;
   
    // First read current seconds value
    status = HAL_I2C_Master_Transmit(&hi2c1, DS1307_ADDRESS, &reg, 1, HAL_MAX_DELAY);
    if (status != HAL_OK)
        return status;
   
    status = HAL_I2C_Master_Receive(&hi2c1, DS1307_ADDRESS, &sec_value, 1, HAL_MAX_DELAY);
    if (status != HAL_OK)
        return status;
   
    // Clear CH bit (bit 7) to start the clock
    sec_value &= 0x7F;
   
    // Write back the seconds value
    uint8_t data[2];
    data[0] = DS1307_REG_SECONDS;
    data[1] = sec_value;
   
    return HAL_I2C_Master_Transmit(&hi2c1, DS1307_ADDRESS, data, 2, HAL_MAX_DELAY);
}

// Redirect printf to UART
int _write(int file, char *ptr, int len)
{
    //HAL_UART_Transmit(&huart2, (uint8_t*)ptr, len, HAL_MAX_DELAY);
    RS485_SendData((uint8_t*)ptr, len);
    HAL_UART_Transmit(&huart2, (uint8_t*)ptr, len, HAL_MAX_DELAY);
    return len;
}

/* Function to perform a hardware reset of the RFID module */
static void RFID_HardReset(void)
{
  // Pull the reset pin low to reset the MFRC522
  HAL_GPIO_WritePin(MFRC522_RST_PORT, MFRC522_RST_PIN, GPIO_PIN_RESET);
  HAL_Delay(RFID_RESET_DELAY); // Wait for the reset to take effect
 
  // Pull the reset pin high to exit reset state
  HAL_GPIO_WritePin(MFRC522_RST_PORT, MFRC522_RST_PIN, GPIO_PIN_SET);
  HAL_Delay(RFID_RESET_DELAY); // Wait for the module to stabilize
 
  //printf("RFID hardware reset performed\n");
  HAL_UART_Transmit(&huart2, (uint8_t*)msg_reset, strlen(msg_reset), HAL_MAX_DELAY);
}

/* Function to determine card location based on ID lookup */
char* GetCardLocation(uint8_t* cardID)
{
    // Always return just the reader ID regardless of card lookup
    return READER_ID;
}

/* Function to update LED status based on card detection */
void UpdateLedStatus(uint8_t cardDetected)
{
    #define CARD_PRESENT_TIMEOUT 500 // ms

    // In UpdateLedStatus:
    if (cardDetected)
    {
     /*__HAL_TIM_SET_PRESCALER(&htim2, 290);
     HAL_Delay(500);
     __HAL_TIM_SET_PRESCALER(&htim2, 330);*/
     //__HAL_TIM_SET_PRESCALER(&htim2, 290);
     HAL_GPIO_WritePin(LED_PORT, LED_PIN, GPIO_PIN_SET);
     lastCardDetectTime = HAL_GetTick();
    }
    else if (HAL_GetTick() - lastCardDetectTime > CARD_PRESENT_TIMEOUT)
    {
     //__HAL_TIM_SET_PRESCALER(&htim2, 0);
     HAL_GPIO_WritePin(LED_PORT, LED_PIN, GPIO_PIN_RESET);
    }
}

HAL_StatusTypeDef DS1307_ReadTimeWithRetry(uint8_t retries)
{
    HAL_StatusTypeDef status;
    while (retries-- > 0)
    {
        status = DS1307_ReadTime();
        if (status == HAL_OK) return status;
        HAL_Delay(10);
    }
    return status;
}

void FlushBufferToFlash(void)
{
    // Count how many valid entries we have in bufferHistory
    uint8_t logsInThisBatch = 0;
    for (int i = 0; i < HISTORY_SIZE; i++) {
        if (bufferHistory[I][0] != '\0') {
            logsInThisBatch++;
        }
    }
    
    if (logsInThisBatch == 0) return;  
    // Prepare data for flash writing
    uint16_t txPos = 0;
    for (int i = 0; i < HISTORY_SIZE; i++) {
        if (bufferHistory[I][0] != '\0') { // Only copy non-empty entries
            strncpy((char*)TxData + txPos, bufferHistory[I], buffer_length);
            txPos += buffer_length;
        }
    }
    
    // Only write if we have data to write
    if (txPos > 0) {
        // Ensure we don't exceed flash capacity
        if (indx >= MAX_FLASH_PAGES) {
            indx = 0; // Wrap around or handle error
            totalBytesWritten = 0; // Reset counter if we wrapped around
        }
        // Calculate actual data size (not rounded up)
        uint16_t actualDataSize = txPos;
        // Clear RxData before reading back data
        //memset(RxData, 0, sizeof(RxData)); 
        totalLogsStoredInFlash += logsInThisBatch;
        // Write to flash (ensure txPos is multiple of 256 for page alignment)
        uint16_t writeSize = ((txPos + 255) / 256) * 256; // Round up to nearest page size
        //W25Q_Write_Page(indx, indx * FLASH_PAGE_SIZE, writeSize, (uint8_t*)TxData);
        currentLogStartAddress = storeLog((uint8_t*)TxData, currentLogStartAddress);
        
        // Wait for write completion (W25Q takes up to 5ms per page)
        osDelay(10);
        
        // Update total bytes written (count actual data, not padded)
        totalBytesWritten += actualDataSize;
        
        // Read back from the same location to verify

        
        // Clear the history after successful write
        memset(bufferHistory, 0, sizeof(bufferHistory));
        bufferHistoryIndex = 0;
        

    }
}

/* USER CODE END 0 


*/

int main(void)
{

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_SPI1_Init();
  MX_SPI2_Init();
  MX_USART1_UART_Init();
  MX_USART2_UART_Init();
  MX_I2C1_Init();
  MX_TIM2_Init();
  RS485_EnableRx();
  /* USER CODE BEGIN 2 */
  
  //__HAL_TIM_SET_PRESCALER(&htim2, 240);
  HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);
  
  // Perform hardware reset before initializing the MFRC522
  RFID_HardReset();
  HAL_Delay(500);
  
  ID = W25qxx_ReadID();
  // Check if DS1307 is connected and responding
  if (HAL_I2C_IsDeviceReady(&hi2c1, DS1307_ADDRESS, 3, 100) == HAL_OK)
  {
      //printf("DS1307 found on I2C bus!\r\n");
  } 
  else 
  {
      //printf("ERROR: DS1307 not found or not responding!\r\n");
  }
  // Start the DS1307 clock
  if (DS1307_StartClock() == HAL_OK) 
  {
      //printf("DS1307 clock started\r\n");
  } 
  else 
  {
      //printf("ERROR: Failed to start DS1307 clock\r\n");
  }
  
  // Initialize the DS1307 with current time (only needs to be done once)
  // Comment this out after first run to avoid resetting the time on each restart
  
  /*if (DS1307_SetTime(12, 7, 0) != HAL_OK)
  {
    printf("Error setting time\r\n");
  }
  else
  {
    printf("Time set successfully\r\n");
  }
  
  if (DS1307_SetDate(2, 19, 5, 25) != HAL_OK) // Wednesday, March 14, 2025
  {
    printf("Error setting date\r\n");
  }
  else
  {
    printf("Date set successfully\r\n");
  }*/
  
  //printf("DS1307 RTC initialized\r\n");
  // Initialize LED pin as OFF
  HAL_GPIO_WritePin(LED_PORT, LED_PIN, GPIO_PIN_RESET);

  uint8_t usart1_rx_buffer[1] = {0};
  HAL_UART_Receive_IT(&huart1, usart1_rx_buffer, 1);
  /* USER CODE END 2 */
  uint8_t version = Read_MFRC522(0x37);
  //printf("RC522 Version: 0x%02X\n", version);
  //printf("RFID Reader ID: %s\n", READER_ID);

  /* Infinite loop */
  MFRC522_Init();
  ID = W25qxx_ReadID();
  if (status != MI_OK)
  {  
   if(HAL_GetTick() - last_detect_time > TIMEOUT_MS)
   {
    if (!isInSleepMode) 
    {
     printf("Show card to wakeup...\n");
     isInSleepMode = 1;
    }
    // 1. Suspend SysTick (stops HAL timekeeping, but SPI remains active)
    HAL_SuspendTick();

    // 2. Ensure SPI peripheral and GPIOs stay active
    __HAL_RCC_SPI1_CLK_ENABLE();  // Replace `SPIx` with your SPI (e.g., SPI1, SPI2)
        

    // __HAL_RCC_PWR_CLK_ENABLE();
    HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI);
                 
    // 5. After wakeup, resume SysTick
    HAL_ResumeTick();
   }
   else 
   {
    isInSleepMode = 0;  // Clear flag if not in sleep mode
   }
   // No card detected
   inactivity_timer += 10;  // Assuming 10ms delay in the loop
        
   // Check if inactivity timeout reached
   if (inactivity_timer >= TIMEOUT_MS) 
   {
    // Enter soft power down mode if not already in it
    if (currentPowerMode != POWER_SOFT_POWERDOWN) 
    {
     MFRC522_SoftPowerDown();
    }
            
    // Reset timer
    inactivity_timer = 0;
   }
  } 
  
  /* Create the thread(s) */
  /* definition and creation of defaultTask */
  osThreadDef(defaultTask, StartDefaultTask, osPriorityAboveNormal, 0, 256);
  defaultTaskHandle = osThreadCreate(osThread(defaultTask), NULL);
  // define the thread
  osThreadDef (task2, task2_init, osPriorityNormal, 0, 128);
  // create thraed and assign ID
  task2Handler = osThreadCreate(osThread(task2), NULL);
  /* Start scheduler */
  osKernelStart();
  /* USER CODE BEGIN WHILE */
  while (1)
  { 
  }
}
/* USER CODE END 3 */

/**
  * @brief System Clock Configuration
  * @retval None
  */

void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Configure the main internal regulator output voltage
  */
  if (HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1) != HAL_OK)
  {
    Error_Handler();
  }

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
  RCC_OscInitStruct.PLL.PLLM = 1;
  RCC_OscInitStruct.PLL.PLLN = 10;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV7;
  RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;
  RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK)
  {
    Error_Handler();
  }
}

/**
  * @brief SPI1 Initialization Function
  * [USER=120004]@Param[/USER] None
  * @retval None
  */

static void MX_I2C1_Init(void)
{

  /* USER CODE BEGIN I2C1_Init 0 */

  /* USER CODE END I2C1_Init 0 */

  /* USER CODE BEGIN I2C1_Init 1 */

  /* USER CODE END I2C1_Init 1 */
  hi2c1.Instance = I2C1;
  hi2c1.Init.Timing = 0x10909CEC;
  hi2c1.Init.OwnAddress1 = 0;
  hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
  hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
  hi2c1.Init.OwnAddress2 = 0;
  hi2c1.Init.OwnAddress2Masks = I2C_OA2_NOMASK;
  hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
  hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
  if (HAL_I2C_Init(&hi2c1) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure Analogue filter
  */
  if (HAL_I2CEx_ConfigAnalogFilter(&hi2c1, I2C_ANALOGFILTER_ENABLE) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure Digital filter
  */
  if (HAL_I2CEx_ConfigDigitalFilter(&hi2c1, 0) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN I2C1_Init 2 */

  /* USER CODE END I2C1_Init 2 */
}

static void MX_SPI1_Init(void)
{

  /* USER CODE BEGIN SPI1_Init 0 */

  /* USER CODE END SPI1_Init 0 */

  /* USER CODE BEGIN SPI1_Init 1 */

  /* USER CODE END SPI1_Init 1 */
  /* SPI1 parameter configuration*/
  hspi1.Instance = SPI1;
  hspi1.Init.Mode = SPI_MODE_MASTER;
  hspi1.Init.Direction = SPI_DIRECTION_2LINES;
  hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
  hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
  hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
  hspi1.Init.NSS = SPI_NSS_SOFT;
  hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16;
  hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
  hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
  hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  hspi1.Init.CRCPolynomial = 7;
  hspi1.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;
  hspi1.Init.NSSPMode = SPI_NSS_PULSE_ENABLE;
  if (HAL_SPI_Init(&hspi1) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN SPI1_Init 2 */

  /* USER CODE END SPI1_Init 2 */
}

/* SPI2 init function */
void MX_SPI2_Init(void)
{

  /* USER CODE BEGIN SPI2_Init 0 */

  /* USER CODE END SPI2_Init 0 */

  /* USER CODE BEGIN SPI2_Init 1 */

  /* USER CODE END SPI2_Init 1 */
  hspi2.Instance = SPI2;
  hspi2.Init.Mode = SPI_MODE_MASTER;
  hspi2.Init.Direction = SPI_DIRECTION_2LINES;
  hspi2.Init.DataSize = SPI_DATASIZE_8BIT;
  hspi2.Init.CLKPolarity = SPI_POLARITY_LOW;
  hspi2.Init.CLKPhase = SPI_PHASE_1EDGE;
  hspi2.Init.NSS = SPI_NSS_SOFT;
  hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16;
  hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;
  hspi2.Init.TIMode = SPI_TIMODE_DISABLE;
  hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  hspi2.Init.CRCPolynomial = 7;
  hspi2.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;
  hspi2.Init.NSSPMode = SPI_NSS_PULSE_ENABLE;
  if (HAL_SPI_Init(&hspi2) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN SPI2_Init 2 */

  /* USER CODE END SPI2_Init 2 */
}

/**
  * @brief USART1 Initialization Function
  * [USER=120004]@Param[/USER] None
  * @retval None
*/

static void MX_USART1_UART_Init(void)
{
  huart1.Instance = USART1;
  huart1.Init.BaudRate = 115200;
  huart1.Init.WordLength = UART_WORDLENGTH_8B;
  huart1.Init.StopBits = UART_STOPBITS_1;
  huart1.Init.Parity = UART_PARITY_NONE;
  huart1.Init.Mode = UART_MODE_TX_RX;
  huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart1.Init.OverSampling = UART_OVERSAMPLING_16;
  huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
  huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
  if (HAL_UART_Init(&huart1) != HAL_OK)
  {
    Error_Handler();
  }
}

/**
  * @brief USART2 Initialization Function
  * [USER=120004]@Param[/USER] None
  * @retval None
*/

static void MX_USART2_UART_Init(void)
{

  /* USER CODE BEGIN USART2_Init 0 */

  /* USER CODE END USART2_Init 0 */

  /* USER CODE BEGIN USART2_Init 1 */

  /* USER CODE END USART2_Init 1 */
  huart2.Instance = USART2;
  huart2.Init.BaudRate = 115200;
  huart2.Init.WordLength = UART_WORDLENGTH_8B;
  huart2.Init.StopBits = UART_STOPBITS_1;
  huart2.Init.Parity = UART_PARITY_NONE;
  huart2.Init.Mode = UART_MODE_TX_RX;
  huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart2.Init.OverSampling = UART_OVERSAMPLING_16;
  huart2.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
  huart2.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
  if (HAL_UART_Init(&huart2) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN USART2_Init 2 */

  /* USER CODE END USART2_Init 2 */
}

static void MX_TIM2_Init(void)
{

  /* USER CODE BEGIN TIM2_Init 0 */

  /* USER CODE END TIM2_Init 0 */

  TIM_ClockConfigTypeDef sClockSourceConfig = {0};
  TIM_MasterConfigTypeDef sMasterConfig = {0};
  TIM_OC_InitTypeDef sConfigOC = {0};

  /* USER CODE BEGIN TIM2_Init 1 */

  /* USER CODE END TIM2_Init 1 */
  htim2.Instance = TIM2;
  htim2.Init.Prescaler = 0;
  htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim2.Init.Period = 1000;
  htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
  {
    Error_Handler();
  }
  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_TIM_PWM_Init(&htim2) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sConfigOC.OCMode = TIM_OCMODE_PWM1;
  sConfigOC.Pulse = 500;
  sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
  if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN TIM2_Init 2 */

  /* USER CODE END TIM2_Init 2 */
  HAL_TIM_MspPostInit(&htim2);
}

/**
  * @brief GPIO Initialization Function
  * [USER=120004]@Param[/USER] None
  * @retval None
*/

static void MX_GPIO_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};
/* USER CODE BEGIN MX_GPIO_Init_1 */
/* USER CODE END MX_GPIO_Init_1 */

  /* GPIO Ports Clock Enable */
  
  __HAL_RCC_GPIOH_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();
    __HAL_RCC_GPIOC_CLK_ENABLE();

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(MFRC522_RST_PORT, MFRC522_RST_PIN, GPIO_PIN_RESET);

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(MFRC522_CS_PORT, MFRC522_CS_PIN, GPIO_PIN_RESET);
  
  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(LED_PORT, LED_PIN, GPIO_PIN_RESET);

    /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_RESET);
  
  HAL_GPIO_WritePin(RS485_TX_EN_PORT, RS485_TX_EN_PIN, GPIO_PIN_RESET); 
  
  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_14|GPIO_PIN_8, GPIO_PIN_SET);

  /*Configure GPIO pins : PB14 PB8 */
  GPIO_InitStruct.Pin = GPIO_PIN_14|GPIO_PIN_8;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
  
  /*Configure GPIO pin : RST_Pin */
  GPIO_InitStruct.Pin = MFRC522_RST_PIN;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(MFRC522_RST_PORT, &GPIO_InitStruct);

  /*Configure GPIO pin : SS_Pin */
  GPIO_InitStruct.Pin = MFRC522_CS_PIN;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(MFRC522_CS_PORT, &GPIO_InitStruct);
  
  /*Configure GPIO pin : LED_Pin */
  GPIO_InitStruct.Pin = LED_PIN;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(LED_PORT, &GPIO_InitStruct);

    /*Configure GPIO pin : PA0 */
  GPIO_InitStruct.Pin = GPIO_PIN_0;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
  
    // Configure RS485 TX_EN pin
  GPIO_InitStruct.Pin = RS485_TX_EN_PIN;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(RS485_TX_EN_PORT, &GPIO_InitStruct);
/* USER CODE BEGIN MX_GPIO_Init_2 */
/* USER CODE END MX_GPIO_Init_2 */
}

void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi1)
{
    SPI_Interrupt++;
        SystemClock_Config();
        HAL_ResumeTick();
        MFRC522_WakeUp();

}

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
    if (huart->Instance == USART1) {
        // Process the received command from USART1
        //ProcessUSART1Command();
        void task2_init(void const * argument); 
    }
}
/* USER CODE END 4 */

/* USER CODE END Header_StartDefaultTask */
void StartDefaultTask(void const * argument)
{
    uint32_t lastActivityTime = HAL_GetTick();
    uint32_t currentTime;
    
    
    // Initialize the MFRC522 reader
    MFRC522_Init();
    
    /* Infinite loop */
    for(;;)
    {
        osDelay(500);  // Reduced delay for more responsive checking
        currentTime = HAL_GetTick();
          
       
        // Check for card presence
        status = MFRC522_Request(PICC_REQIDL, str);
        if (status == MI_OK) 
        {
            // Card detected - reset inactivity timer
            lastActivityTime = currentTime;
            isInSleepMode = 0;
            
            // Get anti-collision data
            status = MFRC522_Anticoll(str);
            if (status == MI_OK) 
            {
              
              HAL_GPIO_WritePin(LED_PORT, LED_PIN, GPIO_PIN_SET);
            
              __HAL_TIM_SET_PRESCALER(&htim2, 290);

                // Copy card ID
                memcpy(sNum, str, 4);
                
                // Read RTC time with retry
                HAL_StatusTypeDef rtcStatus = HAL_ERROR;
                uint8_t retryCount = 3;
                
                while (retryCount-- > 0 && rtcStatus != HAL_OK) {
                    rtcStatus = DS1307_ReadTime();
                    if (rtcStatus != HAL_OK) {
                        osDelay(10);
                    }
                }
                
                // Prepare timestamp string
                char timestamp[20];
                if (rtcStatus == HAL_OK) {
                    uint8_t seconds = BCD_to_DEC(rtcData[0] & 0x7F);
                    uint8_t minutes = BCD_to_DEC(rtcData[1]);
                    uint8_t hours = BCD_to_DEC(rtcData[2] & 0x3F);
                    uint8_t date = BCD_to_DEC(rtcData[4]);
                    uint8_t month = BCD_to_DEC(rtcData[5]);
                    uint8_t year = BCD_to_DEC(rtcData[6]);
                    
                    snprintf(timestamp, sizeof(timestamp), "%02d/%02d/20%02d %02d:%02d:%02d",
                            date, month, year, hours, minutes, seconds);

                    // Format the complete data packet
                    snprintf(buffer, sizeof(buffer),
                        "%s,%02X%02X%02X%02X,%02d/%02d/20%02d,%02d:%02d:%02d.\r\n",
                        READER_ID,
                        sNum[0], sNum[1], sNum[2], sNum[3],
                        date, month, year,
                        hours, minutes, seconds);
                } 
                else 
                {
                    strcpy(timestamp, "ERROR");
                    snprintf(buffer, sizeof(buffer),
                        "{\"reader\":\"%s\",\"card\":\"%02X%02X%02X%02X\","
                        "\"date\":\"ERROR\",\"time\":\"ERROR\"}\r\n",
                        READER_ID,
                        sNum[0], sNum[1], sNum[2], sNum[3]);
                }
               
                // Save current buffer to history
                strncpy(bufferHistory[bufferHistoryIndex], buffer, BUFFER_LENGTH - 1);
                bufferHistory[bufferHistoryIndex][BUFFER_LENGTH - 1] = '\0';
                bufferHistoryIndex = (bufferHistoryIndex + 1) % HISTORY_SIZE;
                
                // Send the data packet
                RS485_SendData((uint8_t*)buffer, strlen(buffer));
                
                
                // Clear the buffer after storing
                memset(buffer, 0, sizeof(buffer));

                FlushBufferToFlash();
                
                // Short delay
                osDelay(10);
                
                // Toggle LED to indicate successful read
                //HAL_GPIO_TogglePin(LD4_GPIO_Port, LD4_Pin);
                
                //__HAL_TIM_SET_PRESCALER(&htim2, 290);
                
                // Delay to prevent multiple reads of same card
                osDelay(200);
                
                // Reset the card - important to release the card properly
                MFRC522_Halt();
            }
        }
        else 
        {
            // No card detected
            HAL_GPIO_WritePin(LED_PORT, LED_PIN, GPIO_PIN_RESET);
            
            __HAL_TIM_SET_PRESCALER(&htim2, 0);
        }
    }
}

void task2_init(void const * argument)
{
  /* USER CODE BEGIN 5 */
  /* Infinite loop */
  for(;;)
  {   

    static uint8_t usart1_rx_buffer[2] = {0};
    static HAL_StatusTypeDef status;
    
    // Start non-blocking receive
    status = HAL_UART_Receive_IT(&huart1, usart1_rx_buffer, 1);
    
    if (status == HAL_OK) 
    {
        if (usart1_rx_buffer[0] == 'b') 
        {
            // Read current time
            HAL_StatusTypeDef rtcStatus = DS1307_ReadTime();
            if (rtcStatus == HAL_OK) 
            {
                uint8_t seconds = BCD_to_DEC(rtcData[0] & 0x7F);
                uint8_t minutes = BCD_to_DEC(rtcData[1]);
                uint8_t hours = BCD_to_DEC(rtcData[2] & 0x3F);
                uint8_t date = BCD_to_DEC(rtcData[4]);
                uint8_t month = BCD_to_DEC(rtcData[5]);
                uint8_t year = BCD_to_DEC(rtcData[6]);
                
                char info[100];
                snprintf(info, sizeof(info), 
                         "\n%02d/%02d/20%02d %02d:%02d:%02d\n",
                         date, month, year, hours, minutes, seconds);
                
                // Send timestamp via RS485 to USART1
                RS485_SendData((uint8_t*)info, strlen(info));
            }
        }
        if (usart1_rx_buffer[0] == 's') 
        {

          char flashinfo[100];
           float percentUsed = GetFlashStoragePercentage();
            uint32_t logCount = CountLogsInFlash();
            sprintf(flashinfo, "Flash: %.2f%% used (%lu/%lu bytes)\r\nLogs stored in flash memory: %lu\r\n",
                   percentUsed, totalBytesWritten, totalFlashCapacity, logCount);
            HAL_UART_Transmit(&huart1, (uint8_t*)flashinfo, strlen(flashinfo), HAL_MAX_DELAY);
            RS485_SendData((uint8_t*)flashinfo, strlen(flashinfo));
    }
  }
  }
  /* USER CODE END 5 */
}

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
  /* USER CODE BEGIN Callback 0 */

  /* USER CODE END Callback 0 */
  if (htim->Instance == TIM1) {
    HAL_IncTick();
  }
  /* USER CODE BEGIN Callback 1 */

  /* USER CODE END Callback 1 */
}
/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  __disable_irq();
  while (1)
  {
  }
  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * [USER=120004]@Param[/USER]  file: pointer to the source file name
  * [USER=120004]@Param[/USER]  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
Moderator edit: added code tags[/I][/I][/I]
 
Last edited by a moderator:

panic mode

Joined Oct 10, 2011
4,864
dude, you keep on spamming your own thread... how many times you should be told to use CODE tags around your code?
i'm not reading this mile long unformatted garbage... I am out....
 

MrChips

Joined Oct 2, 2009
34,627
Please stop posting code that is more than 20 lines of code.
No one is interested in reading your code.
Test simple short programs to fix your problem.
 
Top