Napisałem funkcję obliczającą filtr FIR - 16 współczynników - w moim playerze mp3 na kontrolerze Atmel at91sam7s256. Wszystko działa super, ale po przepisaniu funkcji z C na assembler (kod w C oraz w asm poniżej) niestety nie działa poprawnie. pętla liczenia filtru dla kolejnych sampli smp_loop jest wykonywana bez przerwy, a nawet jeśli nie to i tak jedyne co słychać w sluchawkach to trzaski, zatem obliczanie filtru jest nieprawidłowe. W C natomiast działa bez zarzutu, ale jest dość powolne. Prosiłbym o informację co jest nie tak. Przyznam, że do tej pory nie pisałem jeszcze niczego na ARMach w assemblerze, zawsze wszystko w C.
__attribute__ ((section (".data"))) void fir_count (short *FIRCoef, unsigned int NofSample)
{
// static int FIRAcc1, FIRAcc2;
//
// for (unsigned short i = 0 ; i<NofSample ; i+=2)
// {
// FIRCount = ((FIRCount-1) & 0x0f);
// pFIRBuf1[FIRCount] = (short)DMASBuf[i];
// pFIRBuf2[FIRCount] = (short)DMASBuf[i+1];
// FIRAcc1 = 0;
// FIRAcc2 = 0;
// for (unsigned short j = 0 ; j<16 ; j++)
// {
// FIRAcc1 += (FIRCoef[j] * pFIRBuf1[FIRCount]);
// FIRAcc2 += (FIRCoef[j] * pFIRBuf2[FIRCount++]);
// FIRCount &= 0x0f;
// }
// DMASBuf[i] = (unsigned short)(FIRAcc1>>15);
// DMASBuf[i+1] = (unsigned short)(FIRAcc2>>15);
// }
//}
//
// %0 - FIRCount, %1 - DMASBuf, %2 - pFIRBuf1, %3 - pFIRBuf2, %4 - FIRCoef,%5 - NofSample
asm volatile (
" stmfd r13!,{r6-r11} ;"
" mov r6,#0 ;"
"smp_loop: sub %0,%0,#2 ;"
" and %0,%0,#0x1f ;"
" ldrh r7,[%1,r6] ;"
" strh r7,[%2,%0] ;"
" add r6,r6,#2 ;"
" ldrh r7,[%1,r6] ;"
" strh r7,[%3,%0] ;"
" sub r6,r6,#2 ;"
" ldrsh r10,[%4] ;"
" ldrsh r11,[%2,%0] ;"
" mul r8,r10,r11 ;"
" ldrsh r11,[%3,%0] ;"
" mul r9,r10,r11 ;"
" add %0,%0,#2 ;"
" and %0,%0,#0x1f ;"
" mov r7,#2 ;"
"fir_loop: ldrsh r10,[%4,r7] ;"
" ldrsh r11,[%2,%0] ;"
" mla r8,r10,r11,r8 ;"
" ldrsh r11,[%3,%0] ;"
" mla r9,r10,r11,r9 ;"
" add %0,%0,#2 ;"
" and %0,%0,#0x1f ;"
" add r7,r7,#2 ;"
" cmp r7,#32 ;"
" bne fir_loop ;"
" mov r8,r8,ASR #15 ;"
" strh r8,[%1,r6] ;"
" add r6,r6,#2 ;"
" mov r9,r9,ASR #15 ;"
" strh r9,[%1,r6] ;"
" add r6,r6,#2 ;"
" cmp r6,%5, LSL #1 ;"
" bne smp_loop ;"
" ldmfd r13!,{r6-r11} ;"
: "=r" (FIRCount)
: "0" (FIRCount), "r" (DMASBuf), "r" (pFIRBuf1), "r" (pFIRBuf2), "r" (FIRCoef), "r" (NofSample)
: "cc", "memory", "r6", "r7", "r8", "r9", "r10", "r11" );
}