static char size_cmd15; /* Моделирует локальную настройку длины команды, которую заполняет create_uart_vars. */ /* Проверка rs232_fifo на модели ПК. Русские пояснения сохранены в UTF-8. */ /* Продолжает список аргументов, полей или выражение volatile struct SCI_REGS SciaRegs,ScibRegs;; порядок элементов сохраняется. */ volatile struct SCI_REGS SciaRegs,ScibRegs; long LSPCLK=60000000L; /* Моделирует частоту SCI 60 МГц из текущего проекта, чтобы проверять настоящий расчёт BRR. */ /* Описывает структуру ; порядок полей определяет расположение данных. */ struct { struct { struct { unsigned ACK9; } bit; } PIEACK; } PieCtrlRegs; /* Описывает структуру ; порядок полей определяет расположение данных. */ struct { struct { struct { unsigned GPIO34; } bit; } GPBDAT; } GpioDataRegs; /* Объявляет rs_a — данные rs_a; rs_b — данные rs_b. */ RS_DATA rs_a,rs_b; /* Объявляет RS_Len — таблица ожидаемых длин команд последовательного протокола; irq — данные irq. */ unsigned int RS_Len[70],irq; /* Объявляет load_memory — данные load_memory. */ static unsigned int load_memory[4100]; /* Начинает функцию __disable_interrupts; назначение модуля — проверка rs232_fifo на модели ПК. */ static unsigned int __disable_interrupts(void) { unsigned old=irq;irq=1;return old; } /* Начинает функцию __restore_interrupts; назначение модуля — проверка rs232_fifo на модели ПК. */ static void __restore_interrupts(unsigned state) { irq=state; } /* Начинает функцию RS_SetLineMode; назначение модуля — проверка rs232_fifo на модели ПК. */ void RS_SetLineMode(RS_DATA *p,int bits,char parity,int stop) /* Продолжает список аргументов, полей или выражение { (void)p;(void)bits;(void)parity;(void)stop; }; порядок элементов сохраняется. */ { (void)p;(void)bits;(void)parity;(void)stop; } /* Объявляет length — длина; wire_count — wire число. */ static unsigned int queue[2][16],length[2],wire[2][20000],wire_count[2]; /* Объявляет rx_count — rx число; rx_pos — данные rx_pos; shift_pending — данные shift_pending; shift_checks — данные shift_checks. */ static unsigned int rx[2][16],rx_count[2],rx_pos[2],shift_pending[2],shift_checks; /* Начинает функцию port; назначение модуля — проверка rs232_fifo на модели ПК. */ static unsigned int port(RS_DATA *p) {return p->commnumber-1;} /* Начинает функцию model_interrupts; назначение модуля — проверка rs232_fifo на модели ПК. */ static void model_interrupts(RS_DATA *p,unsigned tx) /* Записывает p->SciRegs->SCICTL2.bit.TXINTENA значением tx;p->SciRegs->SCICTL2.bit.RXBKINTENA=!tx; }; данные TXINTENA. */ { p->SciRegs->SCICTL2.bit.TXINTENA=tx;p->SciRegs->SCICTL2.bit.RXBKINTENA=!tx; } /* Начинает функцию model_flush; назначение модуля — проверка rs232_fifo на модели ПК. */ static void model_flush(RS_DATA *p) /* Записывает i значением port(p);rx_count[i]=rx_pos[i]=0;p->SciRegs->SCIFFRX.bit.RXFFST=0;p->SciRegs->SCIFFRX.bit.RXFFOVF=0; }; данные i. */ { unsigned i=port(p);rx_count[i]=rx_pos[i]=0;p->SciRegs->SCIFFRX.bit.RXFFST=0;p->SciRegs->SCIFFRX.bit.RXFFOVF=0; } /* Начинает функцию model_pop; назначение модуля — проверка rs232_fifo на модели ПК. */ static unsigned int model_pop(RS_DATA *p) /* Открывает составной блок или описание полей; следующие строки принадлежат этому уровню вложенности. */ { /* Записывает i значением port(p),v;assert(rx_pos[i]SciRegs->SCIFFRX.bit.RXFFST значением rx_count[i]-rx_pos[i]; данные RXFFST. */ p->SciRegs->SCIFFRX.bit.RXFFST=rx_count[i]-rx_pos[i]; /* Записывает p->SciRegs->SCIRXST.bit.RXRDY значением rx_pos[i]SciRegs->SCIRXST.bit.RXRDY=rx_pos[i]SciRegs->SCIFFTX.bit.TXFFST=length[i]; последующий оператор выполняется только при истинном условии. */ if(i==0)p->SciRegs->SCIFFTX.bit.TXFFST=length[i]; /* Записывает p->SciRegs->SCICTL2.bit.TXEMPTY значением 0; данные TXEMPTY. */ p->SciRegs->SCICTL2.bit.TXEMPTY=0; /* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ } /* Начинает функцию model_shift; назначение модуля — проверка rs232_fifo на модели ПК. */ static void model_shift(RS_DATA *p) /* Открывает составной блок или описание полей; следующие строки принадлежат этому уровню вложенности. */ { /* Записывает i значением port(p);assert(length[i]==0); данные i. */ unsigned i=port(p);assert(length[i]==0); if(i==0)assert(p->fifo_tx_active); /* last symbol cannot finish early */ /* Проверяет if(i==0)assert(p->fifo_tx_active); последующий оператор выполняется только при истинном условии. */ /* Записывает shift_pending[i] значением 0;p->SciRegs->SCICTL2.bit.TXEMPTY=1;shift_checks++; данные shift_pending. */ shift_pending[i]=0;p->SciRegs->SCICTL2.bit.TXEMPTY=1;shift_checks++; /* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ } /* Начинает функцию model_step; назначение модуля — проверка rs232_fifo на модели ПК. */ static void model_step(RS_DATA *p) /* Открывает составной блок или описание полей; следующие строки принадлежат этому уровню вложенности. */ { /* Записывает i значением port(p),j; данные i. */ unsigned i=port(p),j; /* Проверяет if(length[i]); последующий оператор выполняется только при истинном условии. */ if(length[i]) { /* Изменяет счётчик в выражении wire[i][wire_count[i]++]=queue[i][0]; на один для следующего шага. */ wire[i][wire_count[i]++]=queue[i][0]; /* Цикл for(j=1;jSciRegs->SCIFFTX.bit.TXFFST=length[i]; последующий оператор выполняется только при истинном условии. */ if(i==0)p->SciRegs->SCIFFTX.bit.TXFFST=length[i]; /* Проверяет else if(shift_pending[i]) model_shift(p); последующий оператор выполняется только при истинном условии. */ } else if(shift_pending[i]) model_shift(p); /* Проверяет if(i==0 и p->SciRegs->SCIFFTX.bit.TXFFIENA и; последующий оператор выполняется только при истинном условии. */ if(i==0 && p->SciRegs->SCIFFTX.bit.TXFFIENA && /* Продолжает список аргументов, полей или выражение length[i]<=p->SciRegs->SCIFFTX.bit.TXFFIL) RS_TX_Handler(p);; порядок элементов сохраняется. */ length[i]<=p->SciRegs->SCIFFTX.bit.TXFFIL) RS_TX_Handler(p); /* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ } /* Начинает функцию reset; назначение модуля — проверка rs232_fifo на модели ПК. */ static void reset(void) /* Открывает составной блок или описание полей; следующие строки принадлежат этому уровню вложенности. */ { /* Вызывает memset с аргументами (&rs_a,0,sizeof(rs_a));memset(&rs_b,0,sizeof(rs_b)) в текущей последовательности операций. */ memset(&rs_a,0,sizeof(rs_a));memset(&rs_b,0,sizeof(rs_b)); /* Вызывает memset с аргументами ((void *)&SciaRegs,0,sizeof(SciaRegs));memset((void *)&ScibRegs,0,sizeof(ScibRegs)) в текущей последовательности операций. */ memset((void *)&SciaRegs,0,sizeof(SciaRegs));memset((void *)&ScibRegs,0,sizeof(ScibRegs)); /* Вызывает memset с аргументами (length,0,sizeof(length));memset(wire_count,0,sizeof(wire_count)) в текущей последовательности операций. */ memset(length,0,sizeof(length));memset(wire_count,0,sizeof(wire_count)); /* Вызывает memset с аргументами (rx_count,0,sizeof(rx_count));memset(rx_pos,0,sizeof(rx_pos)) в текущей последовательности операций. */ memset(rx_count,0,sizeof(rx_count));memset(rx_pos,0,sizeof(rx_pos)); /* Вызывает memset с аргументами (shift_pending,0,sizeof(shift_pending)) в текущей последовательности операций. */ memset(shift_pending,0,sizeof(shift_pending)); /* Записывает rs_a.commnumber значением 1;rs_b.commnumber=2;rs_a.SciRegs=&SciaRegs;rs_b.SciRegs=&ScibRegs; данные commnumber. */ rs_a.commnumber=1;rs_b.commnumber=2;rs_a.SciRegs=&SciaRegs;rs_b.SciRegs=&ScibRegs; /* Записывает SciaRegs.SCICTL2.bit.TXEMPTY значением ScibRegs.SCICTL2.bit.TXEMPTY=1; данные TXEMPTY. */ SciaRegs.SCICTL2.bit.TXEMPTY=ScibRegs.SCICTL2.bit.TXEMPTY=1; SciaRegs.SCICTL1.bit.RXERRINTENA=1; /* Повторяет штатное разрешение ошибок SCI-A, чтобы проверить их фактическое отключение на время TX и последующее включение. */ /* Записывает rs_a.RS_Flag9bit значением rs_b.RS_Flag9bit=1; RS флаг 9 бит. */ rs_a.RS_Flag9bit=rs_b.RS_Flag9bit=1; /* Записывает RS_Len[3] значением 8;RS_Len[6]=8;RS_Len[16]=13;RS_Len[51]=12; таблица ожидаемых длин команд последовательного протокола. */ RS_Len[3]=8;RS_Len[6]=8;RS_Len[16]=13;RS_Len[51]=12; /* Записывает GpioDataRegs.GPBDAT.bit.GPIO34 значением 1;irq=0; аппаратная линия ввода/вывода GPIO34. */ GpioDataRegs.GPBDAT.bit.GPIO34=1;irq=0; /* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ } /* Начинает функцию feed; назначение модуля — проверка rs232_fifo на модели ПК. */ static void feed(RS_DATA *p,const unsigned *bytes,unsigned n) /* Открывает составной блок или описание полей; следующие строки принадлежат этому уровню вложенности. */ { /* Записывает i значением port(p),j;assert(n<=16);rx_pos[i]=0;rx_count[i]=n; данные i. */ unsigned i=port(p),j;assert(n<=16);rx_pos[i]=0;rx_count[i]=n; /* Цикл for(j=0;jSciRegs->SCIFFRX.bit.RXFFST значением n;p->SciRegs->SCIRXST.bit.RXRDY=n!=0; данные RXFFST. */ p->SciRegs->SCIFFRX.bit.RXFFST=n;p->SciRegs->SCIRXST.bit.RXRDY=n!=0; /* Вызывает RS_RX_Handler. Разбирает приём SCI; для COM_1 читает FIFO и проверяет ошибки, для COM_2 сохраняет штатный обмен RS485. */ RS_RX_Handler(p); /* Закрывает текущий блок или список полей; следующие операторы относятся к внешнему уровню. */ } /* HANDLERS */ /* Точка входа: настраивает периферию, загружает параметры и обслуживает команды в главном цикле. */ int main(void) /* Открывает составной блок или описание полей; следующие строки принадлежат этому уровню вложенности. */ { /* Продолжает список аргументов, полей или выражение unsigned data[4200],sizes[]={0,1,2,7,8,15,16,17,31,120,253,400,8194};; порядок элементов сохраняется. */ unsigned data[4200],sizes[]={0,1,2,7,8,15,16,17,31,120,253,400,8194}; /* Продолжает список аргументов, полей или выражение unsigned a,n,i,mode;unsigned request[]={16,3,0x10,0,0,16,0,0};; порядок элементов сохраняется. */ unsigned a,n,i,mode;unsigned request[]={16,3,0x10,0,0,16,0,0}; RS_DATA expected = {0}; /* Задаёт чистое состояние порта независимо от содержимого моделируемой RAM. */ memset(&rs_a, 0xA5, sizeof(rs_a)); /* Воспроизводит ненулевые длины, указатели и флаги SCI-A после загрузки COFF. */ memset(&rs_b, 0x5A, sizeof(rs_b)); /* Проверяет независимый сброс второго порта с другим рисунком мусора. */ create_uart_vars(17); /* Вызывает настоящую загрузочную инициализацию до разрешения IRQ. */ expected.commnumber = COM_1; /* Единственным ненулевым полем после общего сброса должен быть номер первого порта. */ assert(memcmp(&rs_a, &expected, sizeof(rs_a)) == 0); /* Проверяет все поля и оба буфера первого порта, включая флаги готовности. */ expected.commnumber = COM_2; /* Подготавливает ожидаемое состояние второго порта. */ assert(memcmp(&rs_b, &expected, sizeof(rs_b)) == 0 && size_cmd15 == 17); /* Проверяет второй порт и сохранение настройки длины команды. */ reset(); /* Назначает регистры портов после проверки полного сброса RAM. */ RS_SetLineSpeed(&rs_a,115200UL); /* Воспроизводит установку скорости RS232, на которой наблюдались ошибки приёма. */ assert(SciaRegs.SCIHBAUD==0 && SciaRegs.SCILBAUD==64 && rs_a.curr_baud==115200UL); /* Проверяет BRR=64 по формуле LSPCLK/(8*baud)-1; прежний код ошибочно записывал 65. */ RS_SetLineSpeed(&rs_b,9600UL); /* Проверяет общую функцию на выбранной пользователем скорости второго порта. */ assert(ScibRegs.SCIHBAUD==3 && ScibRegs.SCILBAUD==12 && rs_b.curr_baud==9600UL); /* Проверяет округлённый BRR=780=0x030C для 60 МГц и 9600 бод. */ RS_SetLineSpeed(&rs_a,57600UL); /* Проверяет альтернативную стандартную скорость без дробных операций. */ assert(SciaRegs.SCIHBAUD==0 && SciaRegs.SCILBAUD==129); /* Проверяет BRR=129, соответствующий отношению 130,2083, округлённому до 130. */ RS_SetLineSpeed(&rs_a,19200UL); /* Проверяет округление вверх при дробной части отношения 0,625. */ assert(SciaRegs.SCIHBAUD==1 && SciaRegs.SCILBAUD==134); /* Проверяет BRR=390=0x0186 после округления отношения 390,625 до 391. */ RS_SetLineSpeed(&rs_a,0UL); /* Передаёт ошибочную нулевую скорость для проверки защиты от деления на ноль. */ RS_SetLineSpeed(&rs_a,0xFFFFFFFFUL); /* Проверяет защиту 32-битного произведения baud*8 от переполнения. */ assert(SciaRegs.SCIHBAUD==1 && SciaRegs.SCILBAUD==134 && rs_a.curr_baud==19200UL); /* Неверные аргументы не должны изменять регистры и диагностическую скорость. */ RS_SetLineSpeed(&rs_a,1UL); /* Проверяет ограничение слишком большого делителя, не представимого в 16-битном BRR. */ assert(SciaRegs.SCIHBAUD==255 && SciaRegs.SCILBAUD==255); /* Ограничение должно дать BRR=65535, а не обёрнутое значение младших битов. */ RS_SetLineSpeed(&rs_a,4000000UL); /* Проверяет ограничение скорости выше аппаратного максимума LSPCLK/16=3750000 бод. */ assert(SciaRegs.SCIHBAUD==0 && SciaRegs.SCILBAUD==1); /* Проверяет минимальный обычный BRR=1, соответствующий аппаратному пределу. */ reset(); /* Подготавливает ошибку BREAK при пустом FIFO, которая не вызывает RX-прерывание по уровню. */ SciaRegs.SCIRXST.all=0xA0U; /* Устанавливает RXERROR в бите 7 и BRKDT в бите 5 по карте регистра TI SPRUI07. */ RS_RX_Handler(&rs_a); /* Вызывает настоящий обработчик общей ошибки без чтения отсутствующего байта. */ assert(rs_a.fifo_rx_errors==1 && rs_a.fifo_rx_bytes==0 && rs_a.fifo_rx_last_status==0xA0U); /* Подтверждает сохранение BREAK до SWRESET и отсутствие фиктивного чтения FIFO. */ assert(!SciaRegs.SCIRXST.all && !rs_a.fifo_rx_last_error_word); /* Подтверждает сброс аппаратного состояния и отсутствие повреждённого слова при пустом FIFO. */ for(i=0;i<4;i++) RS_FifoTick1ms(); /* Выдерживает защитную паузу 3–4 мс после ошибки перед новым адресом. */ feed(&rs_a,request,8); /* Передаёт корректную восьмибайтную команду после восстановления приёмника. */ assert(rs_a.RS_DataReady && rs_a.fifo_rx_bytes==8); /* Проверяет реальное восстановление обработки команд после BREAK. */ /* Цикл for(mode=0;mode<2;mode++)for(a=0;a4200)continue; последующий оператор выполняется только при истинном условии. */ if(mode==0 && n>4200)continue; /* Вызывает assert с аргументами ((mode ? RS_BSend(&rs_a,data,n):RS_Send(&rs_a,data,n))==0) в текущей последовательности операций. */ assert((mode ? RS_BSend(&rs_a,data,n):RS_Send(&rs_a,data,n))==0); if (rs_a.fifo_tx_active) assert(!SciaRegs.SCICTL1.bit.RXERRINTENA); /* Во время активной передачи шум RX не должен сбрасывать SCI через прерывание ошибки. */ /* Проверяет if(n и rs_a.fifo_tx_active)assert(rs_a.RS_Flag9bit==0); последующий оператор выполняется только при истинном условии. */ if(n && rs_a.fifo_tx_active)assert(rs_a.RS_Flag9bit==0); /* Вызывает RS_FifoWait. Ожидает завершения аппаратной передачи FIFO и сдвигового регистра SCI. */ RS_FifoWait(&rs_a);assert(!rs_a.fifo_tx_active && wire_count[0]==n); if (n) assert(SciaRegs.SCICTL1.bit.RXERRINTENA); /* После любого непустого блока защита от BREAK должна возвращаться вместе с приёмом FIFO. */ /* Цикл for(i=0;i0) в текущей последовательности операций. */ assert(shift_checks>0); /* Вызывает reset с аргументами ();feed(&rs_a,request,8);assert(rs_a.RS_DataReady && rs_a.RS_HeaderCnt==8) в текущей последовательности операций. */ reset();feed(&rs_a,request,8);assert(rs_a.RS_DataReady && rs_a.RS_HeaderCnt==8); /* Вызывает reset с аргументами ();feed(&rs_a,request,3);feed(&rs_a,request+3,5);assert(rs_a.RS_DataReady) в текущей последовательности операций. */ reset();feed(&rs_a,request,3);feed(&rs_a,request+3,5);assert(rs_a.RS_DataReady); /* LOAD payload, including a short final chunk: nothing waits for byte 8. */ /* Записывает rs_a.RS_PrevCmd значением CMD_INITLOAD;rs_a.RS_Length=8194; данные RS_PrevCmd. */ reset();rs_a.RS_PrevCmd=CMD_INITLOAD;rs_a.RS_Length=8194; /* Записывает rs_a.pRS_RecvPtr значением rs_a.pRecvPtr=load_memory; данные pRS_RecvPtr. */ rs_a.pRS_RecvPtr=rs_a.pRecvPtr=load_memory; /* Записывает data[0] значением 16;data[1]=CMD_LOAD;feed(&rs_a,data,2); данные. */ data[0]=16;data[1]=CMD_LOAD;feed(&rs_a,data,2); /* Цикл for(a=0;a<8194;a+=n) ; задаёт начальное значение, условие продолжения и шаг перебора. */ for(a=0;a<8194;a+=n) { /* Записывает n значением 8194-a;n=n<16?n:16; данные n. */ n=8194-a;n=n<16?n:16; /* Цикл for(i=0;i