#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 из обработчика прерываний. Все, что я сказал, это то, что обработчик прерываний собирает данные в текущий буфер и, когда этот буфер заполнен, выполняет две вещи: а) переключается на другой буфер б) запускает фоновую функцию, которая фактически обрабатывает данные.