Как я могу оптимизировать эту функцию копирования изображений для встроенной системы - PullRequest
3 голосов
/ 18 мая 2011

Функция ниже считывает изображение страницы за раз, используя read_page (pageIter, pageArr, PAGESIZE) и выводит данные на выводы DOUT AND CCLK.

Мне сказали, что это неэффективно, но я не могу найти способ сделать это быстрее.Это в основном канал, работающий на 64-контактном uProcessor, между двумя областями памяти.Один содержит изображение, а другой получает изображение.

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

Спасибо!

/*
Port C Pin Out
*/
#define     BIT0        0x01    // CCLK
#define     BIT1        0x02    // CS_B
#define     BIT2        0x04    // INIT_B
#define     BIT3        0x08    // PROG_B
#define     BIT4        0x10    // RDRW_B
#define     BIT5        0x20    // BUSY_OUT
#define     BIT6        0x40    // DONE
#define     BIT7        0x80    // DOUT (DIN)

/*
PAGE
*/

#define     PAGESIZE    1024    // Example

void copyImage(ulong startAddress, ulong endAddress)
  {
  ulong pageIter;
  uchar *eByte, *byteIter, pageArr[PAGESIZE];
  register uchar bitIter, portCvar;
  portCvar = PORTC;
  /* Loops through pages in an image using ulong type*/
  for(pageIter = startAddress ;  pageIter <= endAddress ; pageIter += PAGESIZE)
    {
    read_page(pageIter, pageArr, PAGESIZE);
    eByte = pageArr+PAGESIZE;
    /* Loops through bytes in a page using pointer to uchar (pointer to a byte)*/
    for(byteIter = pageArr; byteIter <= eByte; byteIter++)
      {
      /* Loops through bits in byte and writes to PORTC - DIN ANC CCLK  */
      for(bitIter = 0x01; bitIter != 0x00; bitIter = bitIter << 1)
        {
        PORTC = portCvar | BIT0;
        (bitIter & *byteIter) ? (PORTC = portCvar & ~BIT7) : (PORTC = portCvar | BIT7);
        PORTC = portCvar & ~BIT0;
        }
      }
    }
  }

Ответы [ 4 ]

5 голосов
/ 18 мая 2011

Вероятно, вы можете двигаться быстрее, развернув передачу каждого байта с помощью чего-то вроде

PORTC = clock_1; PORTC = (value & 0x01 ? data1 : data0); PORTC = clock_0;
PORTC = clock_1; PORTC = (value & 0x02 ? data1 : data0); PORTC = clock_0;
PORTC = clock_1; PORTC = (value & 0x04 ? data1 : data0); PORTC = clock_0;
PORTC = clock_1; PORTC = (value & 0x08 ? data1 : data0); PORTC = clock_0;
PORTC = clock_1; PORTC = (value & 0x10 ? data1 : data0); PORTC = clock_0;
PORTC = clock_1; PORTC = (value & 0x20 ? data1 : data0); PORTC = clock_0;
PORTC = clock_1; PORTC = (value & 0x40 ? data1 : data0); PORTC = clock_0;
PORTC = clock_1; PORTC = (value & 0x80 ? data1 : data0); PORTC = clock_0;

после предварительного вычисления за пределами цикла изображения

unsigned char clock_1 = portC | BIT0;
unsigned char clock_0 = portC & ~BIT0;
unsigned char data1 = portC | BIT7;
unsigned char data0 = portC & ~BIT7;
2 голосов
/ 18 мая 2011
/* Loops through bits in byte and writes to PORTC - DIN ANC CCLK  */
for(bitIter = 0x01; bitIter <= 0x80; bitIter = bitIter << 1)
{
    PORTC = portC | BIT0;
    (bitIter & byteIter) ? (PORTC = portC & ~BIT7) : (PORTC = portC | BIT7);
    PORTC = portC & ~BIT0;
}

Для начала этот цикл оборван.bitIter - это uchar (я предполагаю, что это 8-битный символ без знака).При смещении его влево он в конечном итоге получит значение 0x80 для предполагаемой последней итерации.После следующей смены он получит значение 0.

За эффективность.В зависимости от архитектуры выполнение операции PORTC = PORTC | BIT0 может привести к установке одного бита.Однако это также может привести к чтению, установке бита в регистре и сохранении.

Как уже упоминалось ранее, если возможно, попытайтесь установить BIT0 и BIT7 одновременно (если аппаратное обеспечение позволяетthis).

Я бы попробовал что-то вроде:

bitIter = 0x01;
do
{
  if (byteIter & bitIter)
  {
    PORTC = BIT0;
  }
  else
  {
    PORTC = (BIT0 | BIT7);
  }
  PORTC = 0;

  bitIter <<= 1;
} while (bitIter != 0x80);

Использование цикла do ... while устранит проблему, и вы избавитесь от ненужного сравнения теста цикла передпервая итерация (если ваш компилятор уже не оптимизировал ее).

Вы можете попытаться развернуть цикл вручную, восемь раз, по одному разу для каждого бита.

2 голосов
/ 18 мая 2011
/* Loops through bits in byte and writes to PORTC - DIN ANC CCLK  */
      for(bitIter = 0x01; bitIter <= 0x80; bitIter = bitIter << 1)
        {
    PORTC = portC | BIT0;
    (bitIter & byteIter) ? (PORTC = portC & ~BIT7) : (PORTC = portC | BIT7);
    PORTC = portC & ~BIT0;
    }

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

Если предположить, что мы можем идти как можно быстрее (и задержки в цикле не учитывают время удержания установки в приемнике),Я бы хотел сократить этот цикл до как можно меньшего числа инструкций.Можете ли вы установить BIT0, а также бит данных одновременно или это создает опасность для приемника?Если вы можете это сохранить инструкцию или два.Многие микрооптимизации будут опираться на конкретный набор инструкций.Если данные имеют много 0 или 0xFF, вы можете сделать специальные развернутые случаи, когда бит данных не изменяется и бит BIT0 переключается 8 раз.Вы можете сделать 16 развернутых случаев для одного nybble и переключаться на него дважды для каждого байта.

1 голос
/ 18 мая 2011

Я предполагаю, что PORTC находится в известном состоянии, когда вы входите в эту функцию: то есть строки данных и часов равны 0? (или Часы низки, а Данные высоки?)

Если это предположение верно, вы должны быть в состоянии даже избежать условий в ответе @ 6502, сначала установив value = ~(*byteIter);, а затем повторив это 8 раз:

 PORTC|=BIT0;PORTC|=(value<<7)&BIT7;PORTC&=~(BIT7|BIT0);value>>=1;

или если бит7 начинает высокий уровень -

 PORTC|=(BIT7|BIT0);PORTC&=(~BIT7|(value<<7));PORTC&=~BIT0;value>>=1;

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...