использование индекса в адресах указателей приводит к нулевому адресу

#c #pointers #buffer

#c #указатели #буфер

Вопрос:

Я пишу приложение MCU, которое загружает последовательные данные из UART и записывает их во флэш-память. Я использую два буфера в методологии «хранить входящие данные в пустом буфере, пока мы очищаем полный» (он же «переключение буфера»). Прием UART был написан таким образом, что «сохранение входящих данных» должно храниться непосредственно в буфере в правильном месте байта. Буферы имеют длину 512 байт, поскольку каждый сектор флэш-памяти имеет длину 512 байт.

Я хотел использовать индексы: один индекс, указывающий, какой буфер загружается; массив с двумя индексами, содержащий адреса первого байта каждого буфера; и индекс, который имеет смещение в пределах буфера (0-511) от фактического целевого адреса хранилища для входящего байта. Код был разработан для использования индекса «какой буфер?» для получения адреса загружаемого буфера, затем добавьте к нему смещение в буфере, и это должно быть все, что нужно. Я пытаюсь сократить длину пути, чтобы сделать все возможное, чтобы избежать переполнения буфера.

Однако я в некотором роде n00b в C. Хотя проверка двух буферов AFLASHBUFFAH показывает мне правильные адреса двух буферов, bFlashBuffah0[512] и bFlashBuffah1[512], похоже, что приведенный ниже код приводит к тому, что указатель на буфер (aFlashBuffahInUse) равен нулю, и, следовательно, выражение *(aFlashBuffahInUse hBuffahByteInUse) является поддельным.

 uint32_t    fFlashEndingAddress     = 0x2765A6;
uint8_t     iBuffahInUse            = 0;
uint16_t    hBuffahByteInUse        = 0;
uint16_t    *aFlashBuffahInUse;
uint16_t    *aFlashBuffahs[2];
uint8_t     bFlashBuffah0[512];
uint8_t     bFlashBuffah1[512];

aFlashBuffahs[0] = amp;bFlashBuffah0;
aFlashBuffahs[1] = amp;bFlashBuffah1;

iBuffahInUse      = 0;
aFlashBuffahInUse = aFlashBuffahs[iBuffahInUse];
hBuffahByteInUse  = 0;

for (i = 0; i < fFlashEndingAddress; i  ) {
    *(aFlashBuffahInUse hBuffahByteInUse) = usart_getchar(UASRT_SERIAL);
 

Если кто-нибудь может порадовать lmk, где я допустил ошибку, я был бы признателен. Tia!

Комментарии:

1. при запросе о проблеме во время выполнения post-код, который чисто компилируется, является коротким и по-прежнему показывает проблему. Если проблема связана с данными, опубликуйте фактические входные данные (разумная выборка) и фактические выходные данные (разумная выборка).

2. Я не понимаю, как for (i = 0; i < fFlashEndingAddress; i ) может работать ваш цикл, если вы не меняете местами буферы каждые 512 байт.

3. Вы даже не использовали i ничего для индексации, что бы ни делал цикл, он записывает каждый входящий байт в одно и то же место.

4. типичный термин не buffer toggling является, а скорее double buffering

Ответ №1:

ПРИМЕЧАНИЕ: в C ссылка на имя массива уменьшается до адреса первого байта массива, поэтому строки, подобные этой: aFlashBuffahs[0] = amp;bFlashBuffah0; получают адрес адреса, строки должны быть больше похожи на это: aFlashBuffahs[0] = bFlashBuffah0; Обратите вниманиенет дополнительного оператора amp; .

Предложите написать код, аналогичный:

 uint32_t    fFlashEndingAddress     = 0x2765A6;
uint8_t     iBuffahInUse            = 0;
uint16_t    hBuffahByteInUse        = 0;
uint16_t    *aFlashBuffahInUse;
uint16_t    *aFlashBuffahs[2];
uint8_t     bFlashBuffah0[512];
uint8_t     bFlashBuffah1[512];

aFlashBuffahs[0] = bFlashBuffah0;  // <-- note change
aFlashBuffahs[1] = bFlashBuffah1;  // <-- note change

//iBuffahInUse      = 0;
//aFlashBuffahInUse = aFlashBuffahs[iBuffahInUse];
aFlashBuffahInUse = bFlashBuffah0; // <-- added
//hBuffahByteInUse  = 0;


for (i = 0; i < fFlashEndingAddress; i  ) {
    *(aFlashBuffahInUse hBuffahByteInUse) = usart_getchar(UASRT_SERIAL);
    hBuffahByteInUse  ;
    if( 512 == hBuffahByteInUse )
    {
        hBuffahByteInUse = 0;
        // initiate processing of buffer (but do not do processing here)
        ....
        // swap buffers
        (aFlashBuffahInUse == bFlashBuffah0)? bFlashBuffah1 : bFlashBuffah0;
    }
 

ТАКЖЕ:
Опубликованный код содержит несколько «магических» чисел. «магические» числа — это числа без основы.

Примерами являются: 0x2765A6, 2, 512

Предложите либо использовать enum оператор или #define операторы, чтобы присвоить этим «магическим» числам значимые имена, а затем использовать эти значимые имена во всем коде.

Можно также упомянуть, что опубликованный код не меняет буферы при заполнении буфера. Я добавил эту функцию в свой ответ.

Комментарии:

1. Предлагаю: написать обработчик прерываний, который выполняет код в блоке кода ‘for ()`. Это значительно улучшило бы общий поток и не потребляло бы циклов процессора в ожидании следующего символа, который будет доступен, как в функции ‘usart_getchar ()`

2. «… ссылка на имя массива ухудшается до адреса первого байта массива» — два неправильных утверждения в одном предложении (особенно, если мы предполагаем, что вы имеете в виду тип данных «ссылка» и не упоминаете имя — C не имеет ссылочного типа).

3. Запись во флэш-память MCU из обработчика прерываний, вероятно, является очень плохой идеей. В лучшем случае это останавливает выполнение, в худшем случае происходит сбой и повреждение содержимого Flash.

4. Спасибо за все входные данные — я ценю это. И мои извинения за публикацию «сокращенного» кода!

5. @Olaf, никто не сказал записывать во flash из обработчика прерываний. Все, что я сказал, это то, что обработчик прерываний собирает данные в текущий буфер и, когда этот буфер заполнен, выполняет две вещи: а) переключается на другой буфер б) запускает фоновую функцию, которая фактически обрабатывает данные.