|
Логирование данных во внешнюю память. |
|
|
|
 |
Ответов
|
Feb 4 2015, 15:15
|
Профессионал
    
Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075

|
упрощенно, в первом приближении написал так. как минимум проверю живая ли память. Код uint32_t LOGGER_SaveData(uint32_t data) { uint32_t low_byte, high_byte; low_byte = data & 0xFF; high_byte = data >> 8; SPIEEPROM_WriteByte(current_address, low_byte); SPIEEPROM_WriteByte(current_address+1, high_byte); current_address += 2; if(current_address>=EEPROM_SIZE) current_address = 0;
return current_address; }
uint32_t LOGGER_GetData(uint32_t address) { uint32_t low_byte, high_byte; low_byte = SPIEEPROM_ReadByte(address); high_byte = SPIEEPROM_ReadByte(address+1); return (high_byte << 8) | low_byte; } Цитата(CrimsonPig @ Feb 4 2015, 20:20)  "...иногда лучше молчать, чем говорить" (с) Топикстартер явно упомянул многопоточность, а тут конструкции, типа "data[obuf_start++ & OBUF_MASK]". Треды, атомарность, синхронизация.. слышали про такое ?
Можно сделать закат солнца вручную, т.е. написать свою очередь. Это не сложно. Сложно сделать так, чтобы оно работало правильно. В самом тупом случае берутся примитивы синхронизации, типа мютексов, пишется тупая кольцевая очередь, где PutData() / GetData() обвешаны этими мютексами как новогодние елки. Тупо, примитивно, не сильно оптимально по быстродействию и требует наличия ОС.
Если ОС нет или нужно выжать производительность, пишется неблокирующая очередь (а потом еще полгода отлаживается). Тут уже в ход идут такие вещи, как intrinsic функции для атомарного инкремента/декремента, реализация CAS, спинлоки и memory barriers если хотим, шоб оно еще не глючило на многоядерных системах.. .. Это один из любимых вопросов на собеседованиях в конторах типа АРМа..
В промежуточном случае пишутся свои мютексы. Но тут опять же надо очень хорошо разбираться в том, что делаешь.
Можно положиться на факт, что присваивание 32-битных значений атомарное, но для многоядерных систем все сильно сложнее с чтением и записью в одну переменную с разных ядер. не горячитесь. вот есть приличный буфер. вопрос как увязать все вместе. Код typedef struct struct_cBuffer { unsigned char *dataptr; ///< the physical memory address where the buffer is stored unsigned short size; ///< the allocated size of the buffer unsigned short datalength; ///< the length of the data currently in the buffer unsigned short dataindex; ///< the index into the buffer where the data starts } cBuffer;
void bufferInit(cBuffer* buffer, unsigned char *start, unsigned short size) { // begin critical section CRITICAL_SECTION_START; // set start pointer of the buffer buffer->dataptr = start; buffer->size = size; // initialize index and length buffer->dataindex = 0; buffer->datalength = 0; // end critical section CRITICAL_SECTION_END; }
// access routines unsigned char bufferGetFromFront(cBuffer* buffer) { unsigned char data = 0; // begin critical section CRITICAL_SECTION_START; // check to see if there's data in the buffer if(buffer->datalength) { // get the first character from buffer data = buffer->dataptr[buffer->dataindex]; // move index down and decrement length buffer->dataindex++; if(buffer->dataindex >= buffer->size) { buffer->dataindex -= buffer->size; } buffer->datalength--; } // end critical section CRITICAL_SECTION_END; // return return data; }
void bufferDumpFromFront(cBuffer* buffer, unsigned short numbytes) { // begin critical section CRITICAL_SECTION_START; // dump numbytes from the front of the buffer // are we dumping less than the entire buffer? if(numbytes < buffer->datalength) { // move index down by numbytes and decrement length by numbytes buffer->dataindex += numbytes; if(buffer->dataindex >= buffer->size) { buffer->dataindex -= buffer->size; } buffer->datalength -= numbytes; } else { // flush the whole buffer buffer->datalength = 0; } // end critical section CRITICAL_SECTION_END; }
unsigned char bufferGetAtIndex(cBuffer* buffer, unsigned short index) { // begin critical section CRITICAL_SECTION_START; // return character at index in buffer unsigned char data = buffer->dataptr[(buffer->dataindex+index)%(buffer->size)]; // end critical section CRITICAL_SECTION_END; return data; }
unsigned char bufferAddToEnd(cBuffer* buffer, unsigned char data) { // begin critical section CRITICAL_SECTION_START; // make sure the buffer has room if(buffer->datalength < buffer->size) { // save data byte at end of buffer buffer->dataptr[(buffer->dataindex + buffer->datalength) % buffer->size] = data; // increment the length buffer->datalength++; // end critical section CRITICAL_SECTION_END; // return success return -1; } // end critical section CRITICAL_SECTION_END; // return failure return 0; }
unsigned short bufferIsNotFull(cBuffer* buffer) { // begin critical section CRITICAL_SECTION_START; // check to see if the buffer has room // return true if there is room unsigned short bytesleft = (buffer->size - buffer->datalength); // end critical section CRITICAL_SECTION_END; return bytesleft; }
void bufferFlush(cBuffer* buffer) { // begin critical section CRITICAL_SECTION_START; // flush contents of the buffer buffer->datalength = 0; // end critical section CRITICAL_SECTION_END; }
|
|
|
|
|
Feb 4 2015, 15:43
|

Местный
  
Группа: Участник
Сообщений: 329
Регистрация: 23-04-14
Пользователь №: 81 502

|
Цитата(Jenya7 @ Feb 4 2015, 15:15)  не горячитесь. вот есть приличный буфер. вопрос как увязать все вместе. То есть макросы CRITICAL_SECTION_START CRITICAL_SECTION_END уже есть и работают ? В чем вопрос-то тогда ? Берем лопату и заменяем char на свой тип данных (это если по тупому). Насчет "приличности" можно сильно поспорить. Это пример того, что я выше назвал "увешан мютексами" как новогодняя елка. Как указывалось выше, если сделать длину буфера (в единицах данных) равной степени двойки, то адресация по модулю очень сильно упрощается. Применение /, % для таких вещей заставляет меня вздрогнуть. Далее. Если немного подумать, то можно понять, что увешивать мютексами можно только место, где происходит работа с индексами в буфере. Копирование _данных_ в буфер и из буфера не требует блокировки. Т.е. при помещении данных в буфер сначала копируем данные на незанятое место, только потом обновляем индекс (атомарно). При вынимании данных - в обратном порядке. > нам бы под ембедед. оптимизированный по скорости. Гы-гы-гы, с операцией деления и взятия остатка вы далеко уйдете в этом направлении, особенно если данные в буфер будут класться в прерываниях
Сообщение отредактировал CrimsonPig - Feb 4 2015, 15:46
|
|
|
|
|
Feb 4 2015, 15:47
|
Профессионал
    
Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075

|
Цитата(CrimsonPig @ Feb 4 2015, 21:43)  То есть макросы CRITICAL_SECTION_START CRITICAL_SECTION_END уже есть и работают ? В чем вопрос-то тогда ? Берем лопату и заменяем char на свой тип данных (это если по тупому).
Насчет "приличности" можно сильно поспорить. Это пример того, что я выше назвал "увешан мютексами" как новогодняя елка. Как указывалось выше, если сделать длину буфера (в единицах данных) равной степени двойки, то адресация по модулю очень сильно упрощается. Применение /, % для таких вещей заставляет меня вздрогнуть. Далее. Если немного подумать, то можно понять, что увешивать мютексами можно только место, где происходит работа с индексами в буфере. Копирование _данных_ в буфер и из буфера не требует блокировки. Т.е. при помещении данных в буфер сначала копируем данные на незанятое место, только потом обновляем индекс (атомарно). При вынимании данных - в обратном порядке.
> нам бы под ембедед. оптимизированный по скорости.
Гы-гы-гы, с операцией деления и взятия остатка вы далеко уйдете в этом направлении, особенно если данные в буфер будут класться в прерываниях ок. а как передать структуру в буфер. или тупо нарезать ее на байты и посылать побайтово? а при принятии склеивать обратно? я не спорю буфер можно пооптимизировать. это так сказать скелет.
Сообщение отредактировал Jenya7 - Feb 4 2015, 15:50
|
|
|
|
|
Feb 4 2015, 15:57
|

Местный
  
Группа: Участник
Сообщений: 329
Регистрация: 23-04-14
Пользователь №: 81 502

|
Цитата(Jenya7 @ Feb 4 2015, 15:47)  ок. а как передать структуру в буфер. или тупо нарезать ее на байты и посылать побайтово? а при принятии склеивать обратно? я не спорю буфер можно пооптимизировать. это так сказать скелет. Ну, в самом простейшем случае можно и по байтам туда загонять. Это должно работать (если код рабочий), но будет жутко неэффективно по определению. Если хочется пихать свои данные то делается так: - сидим, смотрим в существующий код. Понимаем как оно работает - выкидываем существующий код - пишем свой код с блекджеком и шлюхами (void* и memcpy). - Материмся, отлаживаем, пишем тесты Ну или можно попытаться найти уже существующие имплементации поторкобезопасной очереди, которая работает с данными более-менее произвольных размеров. Где взять - не знаю
|
|
|
|
|
Feb 4 2015, 16:15
|

Местный
  
Группа: Участник
Сообщений: 329
Регистрация: 23-04-14
Пользователь №: 81 502

|
Цитата(Jenya7 @ Feb 4 2015, 16:07)  вот я и пытаюсь "смотреть". только пока некуда.  А как же реализация буфера из сообщений выше ? void bufferInit(cBuffer* buffer, unsigned char *start, unsigned short size) и товарищи ? Выглядит как рабочая (на первый взгляд)... ну, со своими заморочками и недостатками. Какая разница, что в абстрактный буфер копировать, байт или кусок данных ? Общий принцип-то тот же.
|
|
|
|
Сообщений в этой теме
Jenya7 Логирование данных во внешнюю память. Feb 4 2015, 09:25 toweroff Цитата(Jenya7 @ Feb 4 2015, 12:25) мне ну... Feb 4 2015, 13:32 Jenya7 Цитата(toweroff @ Feb 4 2015, 19:32) что-... Feb 4 2015, 14:14 CrimsonPig Цитата(toweroff @ Feb 4 2015, 13:32) что-... Feb 4 2015, 14:20  Kabdim Цитата(CrimsonPig @ Feb 4 2015, 17:20) Ес... Feb 4 2015, 15:18   Jenya7 Цитата(Kabdim @ Feb 4 2015, 21:18) А заче... Feb 4 2015, 15:30    Kabdim Цитата(Jenya7 @ Feb 4 2015, 18:30) мда...... Feb 5 2015, 10:53      Jenya7 Цитата(CrimsonPig @ Feb 4 2015, 22:15) А ... Feb 4 2015, 16:26 WitFed Я бы порекомендовал от вечных шлюх последнего врем... Feb 4 2015, 16:26 CrimsonPig Цитата(Jenya7 @ Feb 4 2015, 16:26) да вот... Feb 4 2015, 16:37  Jenya7 Цитата(CrimsonPig @ Feb 4 2015, 22:37) А,... Feb 4 2015, 16:45
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|