|
Запись структуры во флеш. |
|
|
|
Nov 14 2016, 14:01
|
Профессионал
    
Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075

|
Есть структура. Код typedef struct TEST_S { unsigned char start; unsigned int length; char *text; }TEST;
extern TEST tests[MAX_TESTS]; я инициализирую структуру и пытаюсь записать. Код unsigned int TESTER_SaveTest(unsigned int user_page) { unsigned int ret; unsigned int addr; tests[0].start = 0xDA; tests[0].length = 5; tests[0].text = "HELLO"; tests[1].start = 0xDA; tests[1].length = 6; tests[1].text = "WORLD!"; ret = FLASH_PageErase(user_page); if (ret) return ret; addr = 0; ret = FLASH_PageProgram(user_page, addr, (uint8_t *) &tests[0], BUFFER_SIZE_BYTE); if (ret) return ret; addr += (sizeof(tests[0])) + 1; ret = FLASH_PageProgram(user_page, addr, (uint8_t *) &tests[1], BUFFER_SIZE_BYTE); //тут я получаю ошибку - 32. if (ret) return ret; return ret; } Первая запись проходит нормально. Вторая со смещением 13 выдает ошибку 32 - Access error is set in the FSTAT register. Я что то упускаю в логике?
|
|
|
|
3 страниц
1 2 3 >
|
 |
Ответов
(1 - 38)
|
Nov 14 2016, 14:43
|
Профессионал
    
Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075

|
Цитата(aaarrr @ Nov 14 2016, 20:26)  Для сферической флеш в вакууме? Вангую, требования по выравниванию по строкам. Они в Kinetis так намутили с флеш драйвером! Запись такая. Код FlashProgram(&flashSSDConfig, dest, size, buffer, FlashCommandSequence); Логично предположить что size это размер записываемого массива buffer. Смотрим реализацию CODE uint32_t SIZE_OPTIMIZATION FlashProgram(PFLASH_SSD_CONFIG pSSDConfig, \ uint32_t dest, \ uint32_t size, \ uint8_t* pData, \ pFLASHCOMMANDSEQUENCE pFlashCommandSequence) { uint32_t ret = FTFx_OK; /* return code variable */ uint8_t i; uint32_t temp;
if (size & (PGM_SIZE_BYTE - 0x01U)) { ret = FTFx_ERR_SIZE; } else { /* convert to byte address */ dest = WORD2BYTE(dest); #if (DEBLOCK_SIZE) temp = WORD2BYTE(pSSDConfig->DFlashBlockBase); if((dest >= temp) && (dest < (temp + pSSDConfig->DFlashBlockSize))) { dest = dest - temp + 0x800000U; } else #endif { temp = WORD2BYTE(pSSDConfig->PFlashBlockBase); if((dest >= temp) && (dest < (temp + pSSDConfig->PFlashBlockSize))) { dest -= temp; } else { ret = FTFx_ERR_ACCERR; } } while((size > 0x0U) && (FTFx_OK == ret)) { /* clear RDCOLERR & ACCERR & FPVIOL flag in flash status register. Write 1 to clear*/ temp = pSSDConfig->ftfxRegBase + FTFx_SSD_FSTAT_OFFSET; REG_WRITE(temp, FTFx_SSD_FSTAT_ERROR_BITS); /* passing parameter to the command */ #if (PGM_SIZE_BYTE == FTFx_PHRASE_SIZE) temp = pSSDConfig->ftfxRegBase + FTFx_SSD_FCCOB0_OFFSET; REG_WRITE(temp, FTFx_PROGRAM_PHRASE); #else temp = pSSDConfig->ftfxRegBase + FTFx_SSD_FCCOB0_OFFSET; REG_WRITE(temp, FTFx_PROGRAM_LONGWORD); #endif temp = pSSDConfig->ftfxRegBase + FTFx_SSD_FCCOB1_OFFSET; REG_WRITE(temp, GET_BIT_16_23(dest)); temp = pSSDConfig->ftfxRegBase + FTFx_SSD_FCCOB2_OFFSET; REG_WRITE(temp, GET_BIT_8_15(dest)); temp = pSSDConfig->ftfxRegBase + FTFx_SSD_FCCOB3_OFFSET; REG_WRITE(temp, GET_BIT_0_7(dest));
for (i = 0x0U; i < PGM_SIZE_BYTE; i++) { temp = pSSDConfig->ftfxRegBase + i + 0x08U; REG_WRITE(temp, *(pData + i)); }
/* calling flash command sequence function to execute the command */ ret = pFlashCommandSequence(pSSDConfig);
/* update destination address for next iteration */ dest += PGM_SIZE_BYTE; /* update size for next iteration */ size -= PGM_SIZE_BYTE; /* increment the source address by 1 */ pData += PGM_SIZE_BYTE; } } #if C90TFS_ENABLE_DEBUG /* Enter Debug state if enabled */ if (TRUE == (pSSDConfig->DebugEnable)) { ENTER_DEBUG_MODE; } #endif
return(ret); }
Код /* update size for next iteration */ size -= PGM_SIZE_BYTE; это как? учитывая что Код #define PGM_SIZE_BYTE 0x0008U /* 8 bytes */ то есть размер моей структуры должен быть кратный 8?
Сообщение отредактировал Jenya7 - Nov 14 2016, 14:55
|
|
|
|
|
Nov 14 2016, 15:29
|
Профессионал
    
Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075

|
Цитата(aaarrr @ Nov 14 2016, 21:27)  Что-то вроде. а где вставить прагму? так вроде не ругается Код #pragma pack(8) typedef struct TEST_S { unsigned char start; unsigned int length; char *text; }TEST; я вообще не понимаю что за клоунада такая. в STM32 и EFM32 я писал любой размер и все были довольны и я и флеш.
|
|
|
|
|
Nov 14 2016, 15:35
|
Профессионал
    
Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075

|
Цитата(aaarrr @ Nov 14 2016, 21:33)  О, сколько нам открытий чудных... Надо было начинать с LPC. так не я это решаю. как по мне остался бы на STM32 там все уже написано. пробовал так Код #pragma pack(8) typedef struct TEST_S { unsigned char start; unsigned int length; char *text; }TEST; и так Код typedef #pragma pack(8) struct TEST_S { unsigned char start; unsigned int length; char *text; }TEST; uint32_t n = sizeof(tests[0]); возвращает 12. почему 12 непонятно. по моему я понял. три члена структуры компайлер выравнивает до 4 байт. получаем 12. чтобы получить реальную длину я должен прибавить длину строки? "HELLO" - еще 5 байт?
Сообщение отредактировал Jenya7 - Nov 14 2016, 16:26
|
|
|
|
|
Nov 15 2016, 07:22
|
Профессионал
    
Группа: Свой
Сообщений: 1 123
Регистрация: 8-03-09
Из: Днепр
Пользователь №: 45 848

|
Цитата(Jenya7 @ Nov 14 2016, 18:29)  . . . . я вообще не понимаю что за клоунада такая. в STM32 и EFM32 я писал любой размер и все были довольны и я и флеш. Не Вы первый ходите по этим граблям. Такой метод записи сильно "компиляторо-прагма"-зависим. Чтоб с этим не заморачиваться (раз и навсегда), почитайте за сериализацию.
|
|
|
|
|
Nov 15 2016, 11:21
|
Профессионал
    
Группа: Свой
Сообщений: 1 123
Регистрация: 8-03-09
Из: Днепр
Пользователь №: 45 848

|
Цитата(Jenya7 @ Nov 15 2016, 13:11)  сериализация очень широкое понятие. буду признателен если ткнете носом. ссылки, где это внятно расписано, под рукой нет. Если в двух словах - преобразование различных данных (в том числе структур, классов и чегоугодно) в последовательность байт (в нашем случае) для сохранения или передачи где-куда-либо. С целю последующего однозначного восстановления, напр. при приеме из канала связи. Одна из основных особенностей-достоинств - платформо и компиляторо-независимость. Вы сохраняете структуру "оптом", по сути в виде образа из памяти. При сериализации придется - брать каждое поле структуры, - определять его размер, - преобразовывать его в последовательность байт (исходя из размера поля/типа данных), - и затем их (поля) "цепочкой" записывать в флеш. При этом на выравнивание можно не обращать внимание. Единственный ньюанс - надо учитывать платформенный Big-Little Endian формат для чисел конкретного процессора.
|
|
|
|
|
Nov 15 2016, 11:58
|
Профессионал
    
Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075

|
Цитата(k155la3 @ Nov 15 2016, 17:21)  ссылки, где это внятно расписано, под рукой нет. Если в двух словах - преобразование различных данных (в том числе структур, классов и чегоугодно) в последовательность байт (в нашем случае) для сохранения или передачи где-куда-либо. С целю последующего однозначного восстановления, напр. при приеме из канала связи. Одна из основных особенностей-достоинств - платформо и компиляторо-независимость. Вы сохраняете структуру "оптом", по сути в виде образа из памяти. При сериализации придется - брать каждое поле структуры, - определять его размер, - преобразовывать его в последовательность байт (исходя из размера поля/типа данных), - и затем их (поля) "цепочкой" записывать в флеш.
При этом на выравнивание можно не обращать внимание. Единственный ньюанс - надо учитывать платформенный Big-Little Endian формат для чисел конкретного процессора. (uint8_t *) &MyStruct - прекрасная сериализация только речь тут о другом . ребята из NXP говорят надо делать падинг буферу до размера кратного 8.
|
|
|
|
|
Nov 15 2016, 13:43
|
Профессионал
    
Группа: Свой
Сообщений: 1 123
Регистрация: 8-03-09
Из: Днепр
Пользователь №: 45 848

|
Цитата(Jenya7 @ Nov 15 2016, 15:58)  (uint8_t *) &MyStruct - прекрасная сериализация только речь тут о другом . ребята из NXP говорят надо делать падинг буферу до размера кратного 8. Может и так. Вы вообще делали "гарантированное" чтение из флеш ее содержимого, в смысле, например, программатором ? Если нет, то ошибка может быть как на записи, так и на чтении инф. из нее. Причем даже не при работе процедуры RD/WR во флеш, а при "прокачке" в них данных. К примеру, если в параметре ф-ии указано fun( t_uint32 * ptr) то делать так fun( (t_uint32 *) &MyCharArr[0] ) - чревато боком, особенно когда в качестве параметра передается указатель, по адресу которого вызываемая ф-ия должна записать данные.
|
|
|
|
|
Nov 15 2016, 14:09
|
Профессионал
    
Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075

|
Цитата(k155la3 @ Nov 15 2016, 19:43)  Может и так.
Вы вообще делали "гарантированное" чтение из флеш ее содержимого, в смысле, например, программатором ?
Если нет, то ошибка может быть как на записи, так и на чтении инф. из нее. Причем даже не при работе процедуры RD/WR во флеш, а при "прокачке" в них данных.
К примеру, если в параметре ф-ии указано fun( t_uint32 * ptr) то делать так fun( (t_uint32 *) &MyCharArr[0] ) - чревато боком, особенно когда в качестве параметра передается указатель, по адресу которого вызываемая ф-ия должна записать данные. скажем так Код status = FLASH_Init(); status = FLASH_PageErase(250); status = FLASH_PageProgram(250, 0, "hello", BUFFER_SIZE_BYTE); uint8_t buff[5]; #define FLASH_PARAM_ADDR (0x00000000U + (250 * 0x00001000U)) memcpy(&buff, (uint8_t*)FLASH_PARAM_ADDR, 5); пишется и читается правильно. но если писать кусками надо будет дополнять буфер до кратного 8.
|
|
|
|
|
Nov 15 2016, 16:16
|
Профессионал
    
Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075

|
Цитата(HardEgor @ Nov 15 2016, 21:54)  Вы не правы. У вас получается структура отдельно, а строка отдельно. соответственно и сохранять надо и структуру и строку. А смысл? вот тут я кстати в раздумьях. я принимаю строки от пользователя по UART. Эти строки мне надо сохранить во флеш. поэтому я сделал структуру включающую строку, длину строки, начало пакета. Код typedef struct TEST_S { unsigned char start; unsigned int length; char *text; }TEST;
extern TEST tests[MAX_TESTS]; допустим я принял строку. Код void TESTER_AddTest(const char *test) { if (test_idx < MAX_TESTS) { memcpy (tests[test_idx].text, test, strlen(test)); test_idx++; } else test_idx = 0; } теперь мне надо вычислить общий размер дополнить до кратный 8 и записать во флеш.
|
|
|
|
|
Nov 16 2016, 10:22
|
Гуру
     
Группа: Свой
Сообщений: 3 123
Регистрация: 7-04-07
Из: Химки
Пользователь №: 26 847

|
Цитата(Jenya7 @ Nov 15 2016, 19:16)  допустим я принял строку. Код void TESTER_AddTest(const char *test) { if (test_idx < MAX_TESTS) { memcpy (tests[test_idx].text, test, strlen(test)); test_idx++; } else test_idx = 0; } Жесть  А память под строку кто выделять будет? Цитата я понял. то есть мне нужно записать в два приема? Я бы сказал в три приема (или даже в 4) - еще надо выделить память под строку, а потом ее вернуть обратно То, как вы пытаетесь записать принятую от пользователя строку, крайне неэффективно и в текущем виде не работоспособно. - Вам надо писать строки во флешь сразу при их поступлении, или можно с некоторой задержкой?
- Что еще кроме строк надо записать?
- Может ли в строках встречаться код 0?
|
|
|
|
|
Nov 16 2016, 12:49
|
Профессионал
    
Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075

|
Цитата(XVR @ Nov 16 2016, 15:22)  Жесть  А память под строку кто выделять будет? Я бы сказал в три приема (или даже в 4) - еще надо выделить память под строку, а потом ее вернуть обратно То, как вы пытаетесь записать принятую от пользователя строку, крайне неэффективно и в текущем виде не работоспособно. - Вам надо писать строки во флешь сразу при их поступлении, или можно с некоторой задержкой?
- Что еще кроме строк надо записать?
- Может ли в строках встречаться код 0?
надо записать: 1.стартовый маркер 2.длину строки 3.саму строку. писать во флеш сразу по принятии строки? я думаю не критично хотя наверно правильней всего. ломаю голову как выделить место под строку. Кроме как динамическое выделение памяти я придумать не смог. Код char *test_str = malloc(sizeof(char) * (strlen(str) + padding_size)); но мне это очень не нравиться.
|
|
|
|
|
Nov 16 2016, 13:06
|
Гуру
     
Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448

|
Цитата(Jenya7 @ Nov 16 2016, 15:49)  Кроме как динамическое выделение памяти я придумать не смог. Код char *test_str = malloc(sizeof(char) * (strlen(str) + padding_size)); но мне это очень не нравиться. Мне, например, тоже. И в чем смысл динамического выделения, если строка - str - уже есть?
|
|
|
|
|
Nov 16 2016, 13:26
|
Гуру
     
Группа: Свой
Сообщений: 3 123
Регистрация: 7-04-07
Из: Химки
Пользователь №: 26 847

|
Советую сделать так. Строки в FLASH упаковывать в такую структуру: Код typedef struct PackedStr { unsigned int length; unsigned char tag; char string[1]; } PackedStr; Реально ваша строка (string[1]) будет занимать столько места, сколько надо (после конца структуры). В памяти строки складывать в буфер достаточной длинны (что бы принять целиком строку) и длинны, кратной 8 Там же (в памяти) у вас будет 2 индекса в этом буфере: - Индекс последнего занятого байта
- Индекс (в пределах первых 8ми байтов) хвоста от предыдущей записи
При приеме новой строки записываете ее в память, увеличивая длинну. После приема смотрите, если индекс занятого места больше 8 - записываете целое количество страниц, а незаписанный хвост переносите в начало буфера (корректируя указатели). После приема всех данных записываете последний неполный блок (если он есть) Чтение из FLASH аналогично: читаете в память и перемещаетесь по ней Код #define BUF_SIZE 1024 char buffer[BUF_SIZE];
PackedStr* get_next(PackedStr* str) { int len = sizeof(str)-1+str->length; if (len&-sizeof(int)) len=(len&-sizeof(int))+sizeof(int); // Align for 'int' field return (PackedStr*)(len+(char*)str); }
PackedStr* start = (PackedStr*)buffer;
void write_string(char* your_string, char tag) { start->tag = tag; start->length = strlen(your_string); memcpy(start->string,your_string,start->length);
start = get_next(start);
int len = (char*)start - buffer; if ( len >= PGM_SIZE_BYTE) { int page_aligned = len&-PGM_SIZE_BYTE; WriteToFlash(buffer,page_aligned); len &= PGM_SIZE_BYTE-1; if (len) memcpy(buffer,buffer+page_aligned,len); start = (PackedStr*)(buffer+len); } }
void final_flush() { if ((char*)start != buffer) { ... pad buffer with 0 ... WriteToFlash(buffer,PGM_SIZE_BYTE); start = (PackedStr*)buffer; } } Чтение напишите сами (по аналогии)
|
|
|
|
|
Nov 16 2016, 13:37
|
Гуру
     
Группа: Свой
Сообщений: 2 223
Регистрация: 3-03-06
Из: Tomsk
Пользователь №: 14 925

|
Цитата(XVR @ Nov 16 2016, 20:26)  Код PackedStr* get_next(PackedStr* str) { int len = sizeof(str)-1+str->length; if (len&-sizeof(int)) len=(len&-sizeof(int))+sizeof(int); // Align for 'int' field return (PackedStr*)(len+(char*)str); } А почему-бы при выравнивании, длину не вычислить напрямую: len = (str->length/8+1)*8 два сдвига на 8 и сложение.
|
|
|
|
|
Nov 16 2016, 13:41
|
Профессионал
    
Группа: Свой
Сообщений: 1 123
Регистрация: 8-03-09
Из: Днепр
Пользователь №: 45 848

|
Цитата(Jenya7 @ Nov 16 2016, 16:49)  . . . . ломаю голову как выделить место под строку. . . . . Сколько в процессоре RAM ? И какой тип флеш ? (ответ требуется в формате исповеди) --- Смысл выделять динамически, если памяти достаточно. Размер стоки (максимальный) имеет какие-то приближенные к жизни размеры, илиже ОНО бескоечно, аки Вселенная ?
|
|
|
|
|
Nov 16 2016, 13:50
|
Профессионал
    
Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075

|
Цитата(k155la3 @ Nov 16 2016, 18:41)  Сколько в процессоре RAM ? И какой тип флеш ? (ответ требуется в формате исповеди) --- Смысл выделять динамически, если памяти достаточно. Размер стоки (максимальный) имеет какие-то приближенные к жизни размеры, илиже ОНО бескоечно, аки Вселенная ?  Посмотрел сейчас и был приятно удивлен - 64К RAM. Можно выделить кусок под строки и не париться. Какая максимальная длинна строки? да кто их знает. предположительно не более 1 К.
Сообщение отредактировал Jenya7 - Nov 16 2016, 13:51
|
|
|
|
|
Nov 17 2016, 08:14
|
Профессионал
    
Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075

|
Тестирую запись. Создал структуру. Код typedef struct TEST_S { unsigned int start; unsigned int length; unsigned int text_addr; unsigned int padding; //for padint to 8 bytes }TEST;
TEST test; Инициализирую Код uint32_t struct_size = sizeof(TEST); //16 bytes test.start = 0xDADA; test.length = total_len; test.text_ptr = 0; tests[test_idx].padding = 0; Пишу. Код flash_addr = 0; //from the start of the page -> 0x000FA000, USER_PAGE = 250 ret = FLASH_PageProgram(USER_PAGE, flash_addr, (uint8_t*) &test, struct_size); if (ret) return ret; Получаю ошибку (ret = 1) - Protection violation is set in FSTAT register. В дебагере вижу первые 8 байт записывает нормально. На второй восьмерке генерируется ошибка. Я понял. Или стирать страницу или держать в памяти текущий адрес чтоб знать куда писать.
Сообщение отредактировал Jenya7 - Nov 17 2016, 08:23
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|