2008-12-11 1 views
6

У меня есть микроконтроллер, который должен загрузить большой файл с последовательного порта ПК (115200 бод) и записать его в последовательную флеш-память через SPI (~ 2 МГц). Запись флэш-памяти должна быть в 256-байтовых блоках, которым предшествует команда записи и адрес страницы. Общая оперативная память, доступная в системе, составляет 1 кБ с размером в 80 байт.Как вы обрабатываете большие передачи данных по очень ограниченным объемам памяти, встроенным системам?

В настоящее время он работает, заполняя буфер с 256 байтами из UART, а затем пинг-понг в другой буфер с 256 байтами, заполняемый прерыванием по сигналу готовности буфера RX, в то время как флэш-запись записывается с записью с занятой записью. Перестановка буфера повторяется до завершения операции.

Я бы предпочел настроить обработчики прерываний TX/RX для портов SPI и UART, работающих на отдельных круговых буферах. Таким образом, вместо опроса для новых байтов и ожидания завершения операций я могу просто заполнить буферы TX и включить прерывание или проверить буферы для входящих данных. Это дало бы намного больше тактовых циклов для реальной работы, а не для ожидания на периферии.

После внедрения IRQ с 128-байтовыми круговыми буферами я опросу буфера UART RX для данных и немедленно поместил его в буфер SPI TX для передачи файла. Проблема, с которой я сталкиваюсь в этом подходе, заключается в том, что у меня недостаточно памяти для буферов, и буфер приема ПК заполняется быстрее, чем я получаю данные в буфере передачи Flash. Очевидно, что скорость передачи данных не является проблемой (115,2 кГц и 2 МГц), но после каждой 256-байтной страницы есть ожидание цикла записи.


Оказывается, частые прерывания SPI блокируют некоторые UART прерываний и вызывая байт будет хватать. Решение, которое я выбрал, состояло в том, чтобы использовать кольцевой буфер для прерывания приема UART и подавать данные в буфер с 256-байтовым страницей, который отправляется на последовательную вспышку путем опроса для передачи байтов и завершения записи. Буфер 128-буфера достаточно велик, чтобы предотвратить переполнение во время записи SPI.

ответ

3

Я бы сделал что-то вроде сбора рассеяния на ПК. Создать связанный список в структуры, как это:

typedef struct data_buffer { 
    char flags; 
    char[128] data; 
} 

Есть один из битов флага означает «ReadyToFlash» и один для «мигающий». Вы должны быть в состоянии настроить количество буферов в вашем связанном списке, чтобы Flash не мог поймать UART, как он пишет, или наоборот.

Если вспышка попала в буферный блок, который не является «ReadyToFlash», он остановится, и вам нужно будет запустить его IRQ IRART. Если UART попадает в блок ReadyToFlash или «Мигает», он заполняется слишком быстро, и вам, вероятно, нужен другой буфер, если у вас есть динамическая память, вы можете выполнить эту настройку во время выполнения и добавить буфера в список на лету , иначе вам просто нужно провести эмпирическое тестирование.

4

Поддерживает ли интерфейс UART и ПК приложение RS-232 (управление потоком)? Если это так, когда ваш буфер приема приближается к заполнению, ISR отбросит линию CTS - если сторона ПК настроена на управление аппаратным потоком, она должна прекратить отправку, когда увидит это условие. После того, как вы вылили (или почти разрядили) буфер приема, снова подтвердите CTS, и ПК снова начнет отправку.

Обратите внимание, что это делает программное обеспечение на встроенном устройстве значительно более сложным - будет ли это компромисс, который вы готовы сделать, - это анализ, выполненный вами и вашим менеджером &.

+0

Это фактически происходит через интерфейс USB, и эти сигналы недоступны. Это хороший совет. – 2008-12-11 15:57:36

4

Это именно то, для чего был создан контроль потока. Я знаю, что его огромная боль настроена, но если вы включите управление потоком на последовательной линии, ваши проблемы будут иметь историю.

Я предполагаю, что вы передаете двоичный файл, поэтому XON-XOFF не является лучшим решением, которое оставляет управление аппаратным потоком.

Другой вариант - использовать протокол со встроенным управлением потоком, например XModem. У меня есть аналогичный встроенный проект, в котором Flash написан на 128-битных страницах. Какое совпадение, что XModem отправляет данные в 128-битных фрагментах, затем ждет ACK перед отправкой следующего.

+0

Я использовал XModem в прошлом, и для этого есть код. Тем не менее, я прихожу к контракту и не могу изменить клиент ПК (он просто разрывает весь файл сразу). – 2008-12-11 15:56:57

1

Не уверен, что мне здесь не хватает, но если факт заключается в том, что средняя скорость данных, поступающих с ПК, выше, чем средняя скорость, которую вы можете записать на флеш, то вам либо понадобится много оперативной памяти, или вам потребуется управление потоком.

Но вы говорите, что это сработало, когда у вас были блокирующие буферы, но теперь, когда у вас есть байтовые буферы, это не так?

Можете ли вы придерживаться буферов блоков, которые заполняются прерыванием UART RX, и когда каждый буфер заполнен, передайте его в код SPI/Flash, чтобы освободить этот буфер с помощью прерывания SPI? Это позволит вам копировать каждый байт, и вместо того, чтобы дважды выполнять циклическую буферную логику для каждого байта, вам нужно будет сделать это только для каждого блока.

+0

Цикл ожидания для записи страницы после передачи является узким местом. Я добавил эту информацию к вопросу. – 2008-12-11 16:12:21

+0

Я могу заставить его работать с 128-байтным круговым буфером в UART и 256-байтовым промежуточным буфером с занятой записью/опросом в SPI. 128-байтовые буферы без 256 посредников не работают. – 2008-12-11 16:13:54

Смежные вопросы