Если ваш вопрос не влез ни в одну из вышеперечисленных тем, вам сюда.
Ответить

CH32V103 запись пользовательских данных во Flash

Вс июн 04, 2023 21:18:51

Доброго времени суток!

Пытаюсь реализовать сохранение данных в область Flash на CH32V103C8T6, причем в конце флешки. Чтобы гарантировать это, и гарантировать, что:
- данные будут храниться именно в конце флешки, на последних страницах (2*128)
- сама программа не залезет на данные

Я включил эти области в скрипт линкера:
Код:
.....

MEMORY
{
     APP (rx) : ORIGIN = 0x00000000, LENGTH = 0x0FF00
     CREDENTIALS (rx) : ORIGIN = 0x0800FF00, LENGTH = 0x00080
     DATA (rwx) : ORIGIN = 0x0800FF80, LENGTH = 0x00080
   RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 20K
}

....

.device_credentials :
   {
      . = ALIGN(4);
      *(.device_credentials)
      . = ALIGN(4);
   } > CREDENTIALS

   .user_data :
   {
      . = ALIGN(4);
      *(.user_data)
      . = ALIGN(4);
   } > DATA


И так же делаю обращение к этой области через директиву:
Код:
__attribute__((__section__(".user_data")))          const uint8_t user_data[FAST_FLASH_USER_DATA_SIZE];


После прошивки и запуска в первое слово во flash должно быть 0x00C0FFEE, но вместо него абракадабра (0x1CC009BF, начало этой области по адресу 0x0800FF80)
Прошу помощи в данном вопросе

СпойлерКод main.c
Код:
int main(void)
{
    SystemLEDSInit();
    SystemInit();
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    SystemCoreClockUpdate();

    Delay_Init();
    USART_Printf_Init(115200);
    printf("SystemClk:%d\r\n", SystemCoreClock);

    printf("This is printf example\r\n");

    Delay_Ms(500);
    DMX2PWM_GPIO_Init();
    DMX2PWM_RS485_Init();
    user_data_ptr = get_user_data_union_ptr();

    flash_init();
    read_user_data();
    init_user_data_union();
    user_data_ptr->data_struct.intensity_r = 255;
    write_user_data();

    while(1)
    {
    }
}


flash_operations.c
Код:
#include "flash_operations.h"

__attribute__((__section__(".device_credentials"))) const uint8_t device_credentials[FAST_FLASH_DEVICE_CREDENTIALS_SIZE];
__attribute__((__section__(".user_data")))          const uint8_t user_data[FAST_FLASH_USER_DATA_SIZE];

user_data_union_t user_data_union;
device_credentials_union_t device_credentials_union;

user_data_union_t * get_user_data_union_ptr() {
    return &user_data_union;
}

device_credentials_union_t * get_device_credentials_union_ptr() {
    return &device_credentials_union;
}

void flash_init() {
    FLASH_HalfCycleAccessCmd(FLASH_HalfCycleAccess_Disable);
    FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
    FLASH_SetLatency(FLASH_Latency_2);
}

void init_user_data_union() {
    memset(user_data_union.data_bytes, 0, FAST_FLASH_DEVICE_CREDENTIALS_SIZE);
    user_data_union.data_struct.magic = USER_DATA_MAGIC;
}

void read_credentials() {
    memcpy(device_credentials_union.dc_bytes, device_credentials, FAST_FLASH_DEVICE_CREDENTIALS_SIZE);
}

void read_user_data() {
//    init_user_data_union();
    memcpy(user_data_union.data_bytes, user_data, FAST_FLASH_USER_DATA_SIZE);
//    memcpy(user_data_union.data_bytes, *(u32 *)(FAST_FLASH_USER_DATA_START_ADDR), FAST_FLASH_USER_DATA_SIZE);
//    user_data_union = *(__IO uint32_t*) FAST_FLASH_USER_DATA_START_ADDR;
}

void write_user_data() {
    FLASH_Unlock_Fast();

//    FLASH_ClearFlag(FLASH_FLAG_BSY | FLASH_FLAG_EOP |FLASH_FLAG_WRPRTERR);
    FLASH_ErasePage_Fast(FAST_FLASH_USER_DATA_START_ADDR);

    FLASH_BufReset();
    for (uint8_t i = 0x00; i <= 0x70; i=i+0x10) {
//        word_to_byte_union_t wtbs[4] = {0};
        uint32_t u0 = (u32)user_data_union.data_bytes[i] | (u32)(user_data_union.data_bytes[i+1]<<8) | (u32)(user_data_union.data_bytes[i+2]<<16) | (u32)(user_data_union.data_bytes[i+3]<<24);
        uint32_t u1 = (u32)user_data_union.data_bytes[i+0x04] | (u32)(user_data_union.data_bytes[i+0x04+1]<<8) | (u32)(user_data_union.data_bytes[i+0x04+2]<<16) | (u32)(user_data_union.data_bytes[i+0x04+3]<<24);
        uint32_t u2 = (u32)user_data_union.data_bytes[i+0x08] | (u32)(user_data_union.data_bytes[i+0x08+1]<<8) | (u32)(user_data_union.data_bytes[i+0x08+2]<<16) | (u32)(user_data_union.data_bytes[i+0x08+3]<<24);
        uint32_t u3 = (u32)user_data_union.data_bytes[i+0x0C] | (u32)(user_data_union.data_bytes[i+0x0C+1]<<8) | (u32)(user_data_union.data_bytes[i+0x0C+2]<<16) | (u32)(user_data_union.data_bytes[i+0x0C+3]<<24);

//        memcpy((u8 *)wtbs[0].bytes, (u8 *)(user_data_union.data_bytes+i), 4);
//        memcpy((u8 *)wtbs[1].bytes, (u8 *)(user_data_union.data_bytes+0x04+i), 4);
//        memcpy((u8 *)wtbs[2].bytes, (u8 *)(user_data_union.data_bytes+0x08+i), 4);
//        memcpy((u8 *)wtbs[3].bytes, (u8 *)(user_data_union.data_bytes+0x0C+i), 4);

//        FLASH_BufLoad((u32 *)(FAST_FLASH_USER_DATA_START_ADDR+i), (u32 *)wtbs[0].word, (u32 *)wtbs[1].word, (u32 *)wtbs[2].word, (u32 *)wtbs[3].word);
        FLASH_BufLoad(FAST_FLASH_USER_DATA_START_ADDR+i, (u32 *)u0, (u32 *)u1, (u32 *)u2, (u32 *)u3);
    }

    FLASH_ProgramPage_Fast(FAST_FLASH_USER_DATA_START_ADDR);

    FLASH_Lock_Fast();
}


flash_operations.h
Код:
#ifndef USER_FLASH_OPERATIONS_H_
#define USER_FLASH_OPERATIONS_H_

#include "ch32v10x.h"
#include "persistent_config.h"
#include "default_values.h"

/* Global define */
typedef enum
{
    FAILED = 0,
    PASSED = !FAILED
} TestStatus;

typedef union {
    uint32_t word;
    uint8_t bytes[4];
} word_to_byte_union_t;

//#define PAGE_WRITE_START_ADDR            ((uint32_t)0x0800F000) /* Start from 60K */
//#define PAGE_WRITE_END_ADDR              ((uint32_t)0x08010000) /* End at 63K */
//#define FLASH_PAGE_SIZE                  128
//#define FLASH_PAGES_TO_BE_PROTECTED      FLASH_WRProt_Pages60to63

/* Fast Mode define */
#define FAST_FLASH_PROGRAM_START_ADDR    ((uint32_t)0x0800FF80)
#define FAST_FLASH_PROGRAM_END_ADDR      ((uint32_t)0x08010000)
#define FAST_FLASH_SIZE                  128 //(64 * 1024)

void flash_init();
user_data_union_t * get_user_data_union_ptr();
device_credentials_union_t * get_device_credentials_union_ptr();
void read_credentials();
void read_user_data();
void write_user_data();

#endif /* USER_FLASH_OPERATIONS_H_ */


persistent_config.h
Код:
#ifndef USER_PERSISTENT_CONFIG_H_
#define USER_PERSISTENT_CONFIG_H_

#include "user_data_struct.h"
#include "device_credentials_struct.h"

#define FAST_FLASH_USER_DATA_START_ADDR             ((uint32_t)0x0800FF80)
#define FAST_FLASH_USER_DATA_END_ADDR               ((uint32_t)0x08010000)
#define FAST_FLASH_USER_DATA_SIZE                   128

#define FAST_FLASH_DEVICE_CREDENTIALS_START_ADDR    ((uint32_t)0x0800FF00)
#define FAST_FLASH_DEVICE_CREDENTIALS_END_ADDR      ((uint32_t)0x0800FF80)
#define FAST_FLASH_DEVICE_CREDENTIALS_SIZE          128

#endif /* USER_PERSISTENT_CONFIG_H_ */


user_data_struct.h
Код:
#ifndef USER_USER_DATA_STRUCT_H_
#define USER_USER_DATA_STRUCT_H_

#define DEVICE_LABEL_LEN            33
#define USER_DATA_STRUCT_SIZE       47

#define USER_DATA_AREA_SIZE         128
#define USER_DATA_STRUCT_RESERVED   USER_DATA_AREA_SIZE-USER_DATA_STRUCT_SIZE

typedef struct {
    uint32_t magic;
    uint8_t intensity_r;
    uint8_t intensity_g;
    uint8_t intensity_b;
    uint8_t intensity_w;
    uint16_t dmx_start_address;
    char device_label[DEVICE_LABEL_LEN];
    uint8_t reserved[USER_DATA_STRUCT_RESERVED];
    uint32_t crc32;
} user_data_t;

typedef union {
    user_data_t data_struct;
    uint8_t data_bytes[USER_DATA_AREA_SIZE];
} user_data_union_t;

#endif /* USER_USER_DATA_STRUCT_H_ */

Re: CH32V103 запись пользовательских данных во Flash

Пн июн 05, 2023 16:34:24

Попробовал записать фиксированные числа.
Числа отображались зеркально: здесь
Плюс, видимо, не надо ставить точки останова на участка, где происходит запись

Добавлено after 8 minutes 35 seconds:
Данные тоже записываются корректно, если не помещать точки останова в процессе формирования данных и записи
Ответить