Может ли это сделать быстрее?

Вопрос:

У меня есть функция, которая принимает некоторые данные, полученные по SPI через DMA. Для скорости при передаче через SPI три 10-битных фрагмента данных упаковываются в одно 32-битное слово (с двумя битами заполнения). Получив, мне нужно распаковать его на три 16-битных слова (десять фактических бит данных и шесть битов заполнения).

Эта функция вызывается довольно часто, поэтому любая оптимизация скорости сделает значительное улучшение общего времени выполнения. Он работает на STMicro Cortex M3, используя IAR EWARM 7.10 в качестве компилятора, с оптимизацией, установленной на высокий, оптимизированный для скорости.

    /*******************************************************************************
* Function Name  : Unpack
* Description    : the previous adc sample has been
DMA'd into an array
unpack each 32 bit transfer into 3, 10bit samples
( low 16 spi word ) ( high 16 spi word )
{ p15 p14 ch1_9:0 ch2_9:0 ch3_9:0 } 32 bit packing

* Input          : output buf 16 bit word (10 bit adc, right justified)
input buf 32 bit data
count in 32 bit input words

* Output         : None.
* Return         : None.
*******************************************************************************/
void Unpack( u16* pDest, u16* pSrc, u16 packed32_count)
{
u16 i;
u32 n;
u16 dest_index = 0;
u16 src_index = 0;

for ( i = 0; i < packed32_count ; i++ )
{
n = pSrc[src_index]; //get high 16
n <<= 16;
n |= pSrc[src_index+1]; //get low 16
src_index+=2;

pDest[dest_index+2] = n & 0x3ff;
n >>= 10;
pDest[dest_index+1] = n & 0x3ff;
n >>= 10;
pDest[dest_index] = n & 0x3ff;
dest_index+=3;
}
}

Ответ №1

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

void Unpack( u16* pDest, u32* pSrc, u16 packed32_count)
{
int i;
u32 val;

for(i = 0; i < packed32_count; i++)
{
val = pSrc[i];
pDest[2] = val & 0x3ff;
pDest[1] = (val >> 10) & 0x3ff;
pDest[0] = val >> 20;
pDest += 3;
}
}

Ответ №2

это может быть немного быстрее

void Unpack( u16* pDest, u16* pSrc, u16 packed32_count)
{
u32 n;
u16* pSrcEnd = pSrc + 2 * packed32_count;

while (pSrc < pSrcEnd)
{
n = *pSrc++; //get high 16
n <<= 16;
n |= *pSrc++; //get low 16

*pDest++ = (n>>20) & 0x3ff;
*pDest++ = (n>>10) & 0x3ff;
*pDest++ = n & 0x3ff;
}
}

Ответ №3

Предполагая, что ваш процессор имеет большой эндиан (если вы не можете сортировать его в упаковке, делая упаковку/распаковывать симметрию), вы можете загрузить данные с помощью чего-то вроде:

n = ((u32*)pSrc)[src_index++];

Также может быть быстрее использовать индексы u32, чем u16. Использование 16-бит, если у вас 32-разрядные регистры, неэффективен.

Вы можете использовать register, но я подозреваю, что оптимизатор сделает это уже:

register u32 src_index;

Но если это используется очень часто, вы должны действительно посмотреть на сгенерированный код сборки (чтобы проверить, нет ли неэффективности при использовании 16-битных переменных, например).

Оцените статью
TechArks.Ru
Добавить комментарий