From c6c91282387adc789a7ebbc6f7e763d02b549789 Mon Sep 17 00:00:00 2001 From: Andrey Date: Fri, 2 Oct 2026 07:23:08 +0300 Subject: [PATCH] feat(rs232): enable SCI-A FIFO on PM35 and preserve RS485 --- .gitignore | 3 + Doc/RS232_FIFO.md | 69 +++++++++++++ Source/Internal/Include/RS485.h | 14 +++ Source/Internal/RS485.c | 166 +++++++++++++++++++++++++++++++- Source/Internal/measure.c | 3 + build_logger.ps1 | 12 ++- tests/rs232_fifo/model.inc | 118 +++++++++++++++++++++++ tests/rs232_fifo/run_test.py | 73 ++++++++++++++ 8 files changed, 455 insertions(+), 3 deletions(-) create mode 100644 Doc/RS232_FIFO.md create mode 100644 tests/rs232_fifo/model.inc create mode 100644 tests/rs232_fifo/run_test.py diff --git a/.gitignore b/.gitignore index 126e432..6252007 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,7 @@ /Bin/UKSSTMS320F28335_*.bin /Bin/LoggerFix/ /Bin/LoggerEepromFix/ +/Bin/Rs232FifoTest/ +/Bin/Rs232NoFifoTest/ +/Bin/UartFifoTest/ /Bin/*.pending diff --git a/Doc/RS232_FIFO.md b/Doc/RS232_FIFO.md new file mode 100644 index 0000000..2e2849f --- /dev/null +++ b/Doc/RS232_FIFO.md @@ -0,0 +1,69 @@ +# RS232 FIFO для ПМ35 / TMS320F28335 + +Ветка `codex/pm35-uart-fifo`. FIFO включён **только SCI-A / COM_1 / RS232**. +SCI-B / COM_2 / RS485 сохраняет прежние настройки и обработчики без FIFO. +Скорости портов не менялись: RS232 115200; RS485 — прежние 57600/115200. + +`Source/Internal/Include/RS485.h`: `RS232_USE_FIFO=1` по умолчанию. +Для сборки прежнего пути передачи определить `RS232_USE_FIFO=0`. + +## Работа + +- TX заполняет до 16 байт, пополняет при остатке не более 8. +- После постановки последнего байта порог переключается на 0. Следующее + прерывание завершает передачу только после пустого FIFO и `TXEMPTY`. + Ожидание внутри завершающего ISR ограничено остатком последнего символа; + передача всего FIFO внутри ISR не ожидается. +- Первый блок ставится в FIFO до разрешения TX-прерывания, под короткой + IRQ-блокировкой с восстановлением прежнего состояния. +- Убраны программные задержки перед передачей именно для SCI-A. Данные + `BM_CHAR32` и упакованный поток `BM_PACKED` сохраняют прежний порядок байтов. + Нулевая длина не обращается к указателю и не включает передатчик. +- RX читает накопленные байты из FIFO. Порог 1 сохраняет немедленный приём + коротких команд и остатка блока. `SCIRXBUF` читается один раз вместе с FE/PE. +- Ошибка/переполнение аннулирует пакет и `BS_LoadOK`, очищает FIFO. После + 3–4 мс тишины обработчик таймера 1 мс возвращает SCI-A к ожиданию адреса. + Продолжающийся повреждённый поток продлевает ожидание. CMD_LOAD после + ошибки требует нового CMD_INITLOAD. Расчёт паузы предназначен для 115200. +- Счётчики отладчика: `rs_a.fifo_rx_errors`, `rs_a.fifo_overflows`. + +Это UART-оптимизация. Она не меняет команды/формат логгера УМП и не подключает +экспериментальный GAS-логгер. Размеры блоков чтения УМП остаются прежними. + +## Проверка + +```powershell +python tests/rs232_fifo/run_test.py --cc C:/msys64/mingw64/bin/gcc.exe +``` + +Тест извлекает рабочие функции из `RS485.c`; заменяется только поведение +аппаратных регистров, ожидание продвижения UART и модель 16-битного char C28x. +Проверены TX-длины 0/1/2/7/8/15/16/17/31/120/253/400, упакованный блок 8194, +приём короткого/разделённого пакета и LOAD 8194, FIFO overflow, FE/PE, +восстановление после тишины, остаток сдвигового регистра и независимость SCI-B. + +Полная сборка TI C2000 22.6.0.LTS: + +```powershell +./build_logger.ps1 -OptimizeForSize -Rs232Fifo 1 ` + -OutputDirectory "$PWD/Bin/Rs232FifoTest" -ImageName PM35_167_rs232_fifo +./build_logger.ps1 -OptimizeForSize -Rs232Fifo 0 ` + -OutputDirectory "$PWD/Bin/Rs232NoFifoTest" -ImageName PM35_167_rs232_no_fifo +``` + +| Образ | Размер | Запас до параметров EEPROM | +|---|---:|---:| +| FIFO, `-O2 --opt_for_speed=0` | 32158 байт | 350 байт | +| Без FIFO, те же параметры оптимизации | 31234 байта | 1274 байта | + +Оба BIN прошли проверку структуры SCI8 и лимита 32508 байт существующим +`check_firmware.ps1`. Старые `-O1 --opt_for_speed=3` с FIFO превышают лимит; +для этого варианта обязателен `-OptimizeForSize`. Проверка запрещает выпуск +слишком большого BIN и не даёт затронуть сохранённые параметры. +Оптимизация размера применяется ко всей сборке, поэтому временные +характеристики приложения нужно проверить на стенде. + +На плату образы не загружены. Пока подтверждены сборка и тесты модели; +ускорение чтения логгера и устойчивость физического RS232 не измерены. +Для стенда сравнить одно и то же чтение архива на двух образах, проверить +CMD_LOAD/UPLOAD и параллельный RS485. FIFO не увеличивает baud rate. diff --git a/Source/Internal/Include/RS485.h b/Source/Internal/Include/RS485.h index ff3a413..89bb137 100644 --- a/Source/Internal/Include/RS485.h +++ b/Source/Internal/Include/RS485.h @@ -10,6 +10,10 @@ //#include "cntrl_adr.h" //#include "params.h" +#ifndef RS232_USE_FIFO +#define RS232_USE_FIFO 1 +#endif + #define COM_1 1 #define COM_2 2 @@ -58,6 +62,10 @@ typedef struct int RS_FlagSkiping; unsigned long curr_baud; unsigned long time_wait_rs_out; +#if RS232_USE_FIFO + volatile unsigned int fifo_tx_active, fifo_rx_guard; + volatile unsigned long fifo_rx_errors, fifo_overflows; +#endif } RS_DATA; @@ -106,7 +114,13 @@ void RS_SetLineSpeed(RS_DATA *rs_arr, unsigned long speed); // Îæèäàíèå çàâåðøåíèà ïåðåäà÷è UART // wait for TRDY =1 for empty state +#if RS232_USE_FIFO +void RS_FifoWait(RS_DATA *rs_arr); +void RS_FifoTick1ms(void); +#define RS_Wait4OK(x) RS_FifoWait(x) +#else #define RS_Wait4OK(x) while(!(x->SciRegs->SCICTL2.bit.TXEMPTY)) +#endif /** Ïåðåêëþ÷åíèå ëèíèè íà ïðèåì */ #define RS_Line_to_receive(x) if(x->commnumber==COM_2) GpioDataRegs.GPBDAT.bit.GPIO34 = 1; diff --git a/Source/Internal/RS485.c b/Source/Internal/RS485.c index 425ed58..17686b7 100644 --- a/Source/Internal/RS485.c +++ b/Source/Internal/RS485.c @@ -21,6 +21,11 @@ static char size_cmd15=1; void RS_RX_Handler(RS_DATA *rs_arr); void RS_TX_Handler(RS_DATA *rs_arr); +#if RS232_USE_FIFO +static int RS_FifoStart(RS_DATA *, unsigned int *, unsigned long, int); +static void RS_FifoTx(RS_DATA *); +static void RS_FifoAbort(RS_DATA *); +#endif /** Îáðàáîò÷èê ïðåðûâàíèé UART - ïðèíàòî */ interrupt void RSA_RX_Handler(void) @@ -105,6 +110,24 @@ void RS_RX_Handler(RS_DATA *rs_arr) for(;;) // 'goto' ýòî íå îïåðàòîð àçûêà Ñ { +#if RS232_USE_FIFO + if (rs_arr->commnumber == COM_1) { + unsigned int received; + if (rs_arr->SciRegs->SCIFFRX.bit.RXFFOVF || rs_arr->SciRegs->SCIRXST.bit.RXERROR) { + RS_FifoAbort(rs_arr); return; + } + if (!rs_arr->SciRegs->SCIFFRX.bit.RXFFST) { + rs_arr->SciRegs->SCIFFRX.bit.RXFFINTCLR=1; + PieCtrlRegs.PIEACK.bit.ACK9 |= 1; + return; + } + received=rs_arr->SciRegs->SCIRXBUF.all; /* one pop, data + FE/PE */ + if (received & 0xC000U) { RS_FifoAbort(rs_arr); return; } + if (rs_arr->fifo_rx_guard) { rs_arr->fifo_rx_guard=4; continue; } + Rc=received & 255U; + } else +#endif + { if(!rs_arr->SciRegs->SCIRXST.bit.RXRDY) // Receiver ready flag { PieCtrlRegs.PIEACK.bit.ACK9 |= 1; @@ -122,6 +145,8 @@ void RS_RX_Handler(RS_DATA *rs_arr) continue; } + } + if(rs_arr->RS_DataReady) continue; // Íå çàáðàëè äàííûå if (rs_arr->RS_Flag9bit==1) // äëà RS485???????? @@ -234,6 +259,9 @@ void RS_RX_Handler(RS_DATA *rs_arr) /** Îáðàáîò÷èê ïðåðûâàíèé UART - ïîñëàíî */ void RS_TX_Handler(RS_DATA *rs_arr) { +#if RS232_USE_FIFO + if (rs_arr->commnumber == COM_1) { RS_FifoTx(rs_arr); return; } +#endif char RS_BytePtr; // unsigned int i; @@ -278,6 +306,7 @@ void RS_TX_Handler(RS_DATA *rs_arr) PieCtrlRegs.PIEACK.bit.ACK9 |= 1; // rs_arr->SciRegs->SCIFFTX.bit.TXINTCLR=1; // Clear INT flag + } /** Èíèöèàëèçàöèà ìàññèâà äëèí êîìàíä */ @@ -329,6 +358,9 @@ void RS_SetBitMode(RS_DATA *rs_arr,int n) @see RS_BSend, RS_TRANSMIT_INTR */ int RS_Send(RS_DATA *rs_arr,unsigned int *pBuf,unsigned long len) { +#if RS232_USE_FIFO + if (rs_arr->commnumber == COM_1) return RS_FifoStart(rs_arr,pBuf,len,BM_CHAR32); +#endif unsigned int i; for (i=0; i <= 30000; i++){} /* Ïàóçà äëà PC */ @@ -359,11 +391,15 @@ int RS_Send(RS_DATA *rs_arr,unsigned int *pBuf,unsigned long len) RS_Line_to_receive(rs_arr); /* ðåæèì ïðèåìà RS485 */ } return 0; + } // Ïîñûëêà áëîêà óïàêîâàííûõ áàéòîâ int RS_BSend(RS_DATA *rs_arr,unsigned int *pBuf, unsigned long len) { +#if RS232_USE_FIFO + if (rs_arr->commnumber == COM_1) return RS_FifoStart(rs_arr,pBuf,len,BM_PACKED); +#endif RS_Line_to_send(rs_arr); // ðåæèì ïåðåäà÷è RS485 @@ -381,6 +417,7 @@ int RS_BSend(RS_DATA *rs_arr,unsigned int *pBuf, unsigned long len) SCI_send(rs_arr,HIBYTE(*pBuf));// Ïåðåäàåì ïåðâûé áàéò return 0; + } /** Óñòàíàâëèâàåò ñêîðîñòü îáìåíà. @@ -474,7 +511,20 @@ void setup_uart(char commnumber, unsigned long speed_baud) SciRegs->SCICTL1.bit.TXENA=1; SciRegs->SCICTL1.bit.RXENA=1; - SciRegs->SCIFFTX.bit.SCIFFENA=0; // fifo off +#if RS232_USE_FIFO + if (commnumber == COM_1) { + SciRegs->SCIFFTX.all=0xC008U; /* enhancement, reset held, TX level 8, IRQ off */ + SciRegs->SCIFFRX.all=0x0061U; /* reset held, RX level 1, IRQ on */ + SciRegs->SCIFFCT.all=0; + SciRegs->SCIFFRX.bit.RXFFOVRCLR=1; + SciRegs->SCIFFTX.bit.TXFFINTCLR=1; + SciRegs->SCIFFTX.bit.TXFIFOXRESET=1; + SciRegs->SCIFFRX.bit.RXFIFORESET=1; + rs_arr->fifo_tx_active=rs_arr->fifo_rx_guard=0; + rs_arr->fifo_rx_errors=rs_arr->fifo_overflows=0; + } else +#endif + SciRegs->SCIFFTX.bit.SCIFFENA=0; // fifo off SciRegs->SCIFFRX.bit.RXFFIL=1; // Äëèíà íàèìåíüøåé êîìàíäû setup_arr_cmd_length(); @@ -547,3 +597,117 @@ void test_rs_live(RS_DATA *rs_arr) RS_Line_to_receive(rs_arr); // ðåæèì ïðèåìà RS485 RS_SetBitMode(rs_arr,9); }*/ } + +#if RS232_USE_FIFO +/* FIFO is exclusively SCI-A / RS232. SCI-B keeps the legacy path. */ +void RS_FifoWait(RS_DATA *rs_arr) +{ + if (rs_arr->commnumber != COM_1) { + while (!rs_arr->SciRegs->SCICTL2.bit.TXEMPTY) { } + return; + } + while (rs_arr->fifo_tx_active || rs_arr->SciRegs->SCIFFTX.bit.TXFFST || + !rs_arr->SciRegs->SCICTL2.bit.TXEMPTY) { } +} + +static void RS_FifoTx(RS_DATA *rs_arr) +{ + unsigned int data; + if (!rs_arr->fifo_tx_active) { + rs_arr->SciRegs->SCIFFTX.bit.TXFFIENA=0; + } else if (rs_arr->RS_SendLen == rs_arr->RS_SLength) { + /* Level 0 interrupt: FIFO drained, last symbol may still be shifting. + * Do not finish on TXFFST alone. At most one symbol remains. */ + if (rs_arr->SciRegs->SCIFFTX.bit.TXFFST) { + rs_arr->SciRegs->SCIFFTX.bit.TXFFINTCLR=1; + PieCtrlRegs.PIEACK.bit.ACK9 |= 1; + return; + } + rs_arr->SciRegs->SCIFFTX.bit.TXFFIENA=0; + while (!rs_arr->SciRegs->SCICTL2.bit.TXEMPTY) { } + if (rs_arr->RS_SendBlockMode == BM_CHAR32) { + RS_SetBitMode(rs_arr,9); + rs_arr->flag_TIMEOUT_to_Send=false; + } + rs_arr->SciRegs->SCIFFRX.bit.RXFIFORESET=0; + rs_arr->SciRegs->SCIFFRX.bit.RXFFOVRCLR=1; + rs_arr->SciRegs->SCIFFRX.bit.RXFFINTCLR=1; + rs_arr->SciRegs->SCIFFRX.bit.RXFIFORESET=1; + enableUARTInt(rs_arr); + rs_arr->SciRegs->SCIFFRX.bit.RXFFIENA=1; + rs_arr->fifo_tx_active=0; + } else { + while (rs_arr->RS_SendLen < rs_arr->RS_SLength && + rs_arr->SciRegs->SCIFFTX.bit.TXFFST < 16) { + if (rs_arr->RS_SendBlockMode == BM_CHAR32) + data=*rs_arr->pRS_SendPtr++; + else if (rs_arr->RS_SendLen & 1U) + data=LOBYTE(*rs_arr->pRS_SendPtr++); + else data=HIBYTE(*rs_arr->pRS_SendPtr); + SCI_send(rs_arr,data); + rs_arr->RS_SendLen++; + } + rs_arr->SciRegs->SCIFFTX.bit.TXFFIL= + rs_arr->RS_SendLen == rs_arr->RS_SLength ? 0 : 8; + } + rs_arr->SciRegs->SCIFFTX.bit.TXFFINTCLR=1; + PieCtrlRegs.PIEACK.bit.ACK9 |= 1; +} + +static int RS_FifoStart(RS_DATA *rs_arr,unsigned int *buffer,unsigned long count,int mode) +{ + unsigned int saved; + if (!count) return 0; + if (!buffer) return -1; + RS_FifoWait(rs_arr); /* before replacing the previous transfer's counters */ + saved=__disable_interrupts(); + rs_arr->SciRegs->SCIFFTX.bit.TXFFIENA=0; + rs_arr->SciRegs->SCIFFRX.bit.RXFFIENA=0; + enableUARTIntW(rs_arr); + RS_SetBitMode(rs_arr,8); + rs_arr->pRS_SendPtr=buffer; + rs_arr->RS_SLength=count; + rs_arr->RS_SendLen=0; + rs_arr->RS_SendBlockMode=mode; + rs_arr->fifo_tx_active=1; + RS_FifoTx(rs_arr); /* prime before enabling a possibly immediate TX IRQ */ + rs_arr->SciRegs->SCIFFTX.bit.TXFFIENA=1; + __restore_interrupts(saved); + if (count == 1 && mode == BM_CHAR32) RS_FifoWait(rs_arr); + return 0; +} + +static void RS_FifoAbort(RS_DATA *rs_arr) +{ + rs_arr->fifo_rx_errors++; + if (rs_arr->SciRegs->SCIFFRX.bit.RXFFOVF) rs_arr->fifo_overflows++; + rs_arr->RS_DataReady=0; rs_arr->BS_LoadOK=0; + rs_arr->RS_PrevCmd=0; rs_arr->RS_Cmd=0; + rs_arr->RS_Flag9bit=0; rs_arr->RS_FlagSkiping=1; + rs_arr->fifo_rx_guard=4; + rs_arr->SciRegs->SCIFFRX.bit.RXFIFORESET=0; + rs_arr->SciRegs->SCIFFRX.bit.RXFFOVRCLR=1; + rs_arr->SciRegs->SCIFFRX.bit.RXFFINTCLR=1; + if (rs_arr->SciRegs->SCIRXST.bit.RXERROR) { + rs_arr->SciRegs->SCICTL1.bit.SWRESET=0; + rs_arr->SciRegs->SCICTL1.bit.SWRESET=1; + } + rs_arr->SciRegs->SCIFFRX.bit.RXFIFORESET=1; + PieCtrlRegs.PIEACK.bit.ACK9 |= 1; +} + +void RS_FifoTick1ms(void) +{ + unsigned int saved=__disable_interrupts(); + RS_DATA *p=&rs_a; + if (p->SciRegs && p->fifo_rx_guard) { + if (p->SciRegs->SCIFFRX.bit.RXFFST) p->fifo_rx_guard=4; + else if (--p->fifo_rx_guard == 0) { + p->RS_HeaderCnt=0;p->RS_RecvLen=0; + p->RS_FlagBegin=1;p->RS_FlagSkiping=0; + RS_SetBitMode(p,9); /* fresh address after 3..4 ms of idle */ + } + } + __restore_interrupts(saved); +} +#endif diff --git a/Source/Internal/measure.c b/Source/Internal/measure.c index abd9ccf..b684925 100644 --- a/Source/Internal/measure.c +++ b/Source/Internal/measure.c @@ -130,6 +130,9 @@ interrupt void cpu_timer1_isr_SENS(void) EALLOW; CpuTimer1.InterruptCount++; +#if RS232_USE_FIFO + RS_FifoTick1ms(); +#endif IER |= M_INT13; // Set "global" priority IER &= MINT13; // Set "global" priority EINT; diff --git a/build_logger.ps1 b/build_logger.ps1 index 73d5bd7..112c437 100644 --- a/build_logger.ps1 +++ b/build_logger.ps1 @@ -1,7 +1,10 @@ param( [string]$TemplatesRoot = "$PSScriptRoot/../newProject/SETGUI/third_party/templates", [string]$CompilerRoot = 'C:/ti/ccs1230/ccs/tools/compiler/ti-cgt-c2000_22.6.0.LTS', - [string]$OutputDirectory = "$PSScriptRoot/Bin/LoggerEepromFix" + [string]$OutputDirectory = "$PSScriptRoot/Bin/LoggerEepromFix", + [switch]$OptimizeForSize, + [ValidateSet(0,1)][int]$Rs232Fifo = 1, + [string]$ImageName = "UKSSTMS320F28335_logger_eeprom_fix" ) $ErrorActionPreference = 'Stop' $protocol = Join-Path (Resolve-Path -LiteralPath $TemplatesRoot).Path 'c/set-protocol' @@ -20,6 +23,11 @@ $includes += @("--include_path=$CompilerRoot/include", "--include_path=$protocol # Match the CCS Debug configuration used for 34a95bc5. $flags = @('-v28', '-ml', '-mt', '--float_support=fpu32', '-O1', '--define=LARGE_MODEL', '--define=_DEBUG', '--symdebug:dwarf', '--abi=coffabi', '--opt_for_speed=3') +$flags += "--define=RS232_USE_FIFO=$Rs232Fifo" +if ($OptimizeForSize) { + $flags = @($flags | Where-Object { $_ -ne '-O1' -and $_ -ne '--opt_for_speed=3' }) + $flags += @('-O2', '--opt_for_speed=0') +} $external = @('DSP2833x_ADC_cal.asm', 'DSP2833x_Adc.c', 'DSP2833x_CpuTimers.c', 'DSP2833x_PieCtrl.c', 'DSP2833x_SWPrioritizedDefaultIsr.c', 'DSP2833x_SWPrioritizedPieVect.c', 'DSP2833x_SysCtrl.c', 'DSP2833x_Xintf.c', 'DSP2833x_usDelay.asm') @@ -32,7 +40,7 @@ foreach ($source in $sources) { if ($LASTEXITCODE -ne 0) { throw "Compilation failed: $source" } $objectFiles += Join-Path $objects ([IO.Path]::GetFileNameWithoutExtension($source) + '.obj') } -$name = 'UKSSTMS320F28335_logger_eeprom_fix' +$name = $ImageName & "$CompilerRoot/bin/cl2000.exe" @flags -z "--map_file=$output/$name.map" --stack_size=0x3f0 --warn_sections ` "--search_path=$CompilerRoot/lib" --reread_libs --entry_point=_c_int00 --rom_model ` "--output_file=$output/$name.out" @objectFiles "$PSScriptRoot/F28335.cmd" ` diff --git a/tests/rs232_fifo/model.inc b/tests/rs232_fifo/model.inc new file mode 100644 index 0000000..f12fe42 --- /dev/null +++ b/tests/rs232_fifo/model.inc @@ -0,0 +1,118 @@ + +volatile struct SCI_REGS SciaRegs,ScibRegs; +struct { struct { struct { unsigned ACK9; } bit; } PIEACK; } PieCtrlRegs; +struct { struct { struct { unsigned GPIO34; } bit; } GPBDAT; } GpioDataRegs; +RS_DATA rs_a,rs_b; +unsigned int RS_Len[70],irq; +static unsigned int load_memory[4100]; +static unsigned int __disable_interrupts(void) { unsigned old=irq;irq=1;return old; } +static void __restore_interrupts(unsigned state) { irq=state; } +void RS_SetLineMode(RS_DATA *p,int bits,char parity,int stop) +{ (void)p;(void)bits;(void)parity;(void)stop; } +static unsigned int queue[2][16],length[2],wire[2][20000],wire_count[2]; +static unsigned int rx[2][16],rx_count[2],rx_pos[2],shift_pending[2],shift_checks; +static unsigned int port(RS_DATA *p) {return p->commnumber-1;} +static void model_interrupts(RS_DATA *p,unsigned tx) +{ p->SciRegs->SCICTL2.bit.TXINTENA=tx;p->SciRegs->SCICTL2.bit.RXBKINTENA=!tx; } +static void model_flush(RS_DATA *p) +{ unsigned i=port(p);rx_count[i]=rx_pos[i]=0;p->SciRegs->SCIFFRX.bit.RXFFST=0;p->SciRegs->SCIFFRX.bit.RXFFOVF=0; } +static unsigned int model_pop(RS_DATA *p) +{ + unsigned i=port(p),v;assert(rx_pos[i]SciRegs->SCIFFRX.bit.RXFFST=rx_count[i]-rx_pos[i]; + p->SciRegs->SCIRXST.bit.RXRDY=rx_pos[i]SciRegs->SCIFFTX.bit.TXFFST=length[i]; + p->SciRegs->SCICTL2.bit.TXEMPTY=0; +} +static void model_shift(RS_DATA *p) +{ + unsigned i=port(p);assert(length[i]==0); + if(i==0)assert(p->fifo_tx_active); /* last symbol cannot finish early */ + shift_pending[i]=0;p->SciRegs->SCICTL2.bit.TXEMPTY=1;shift_checks++; +} +static void model_step(RS_DATA *p) +{ + unsigned i=port(p),j; + if(length[i]) { + wire[i][wire_count[i]++]=queue[i][0]; + for(j=1;jSciRegs->SCIFFTX.bit.TXFFST=length[i]; + } else if(shift_pending[i]) model_shift(p); + if(i==0 && p->SciRegs->SCIFFTX.bit.TXFFIENA && + length[i]<=p->SciRegs->SCIFFTX.bit.TXFFIL) RS_TX_Handler(p); +} +static void reset(void) +{ + 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(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(shift_pending,0,sizeof(shift_pending)); + 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; + 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; + GpioDataRegs.GPBDAT.bit.GPIO34=1;irq=0; +} +static void feed(RS_DATA *p,const unsigned *bytes,unsigned n) +{ + 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; + 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 a,n,i,mode;unsigned request[]={16,3,0x10,0,0,16,0,0}; + for(mode=0;mode<2;mode++)for(a=0;a4200)continue; + assert((mode ? RS_BSend(&rs_a,data,n):RS_Send(&rs_a,data,n))==0); + if(n && rs_a.fifo_tx_active)assert(rs_a.RS_Flag9bit==0); + RS_FifoWait(&rs_a);assert(!rs_a.fifo_tx_active && wire_count[0]==n); + for(i=0;i0); + 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); + /* LOAD payload, including a short final chunk: nothing waits for byte 8. */ + reset();rs_a.RS_PrevCmd=CMD_INITLOAD;rs_a.RS_Length=8194; + rs_a.pRS_RecvPtr=rs_a.pRecvPtr=load_memory; + data[0]=16;data[1]=CMD_LOAD;feed(&rs_a,data,2); + for(a=0;a<8194;a+=n) { + n=8194-a;n=n<16?n:16; + for(i=0;iSciRegs->SCIRXBUF.all;', 'received=model_pop(rs_arr);') +body=body.replace('Rc = rs_arr->SciRegs->SCIRXBUF.bit.RXDT;', 'Rc=model_pop(rs_arr);') +body=body.replace('rs_arr->SciRegs->SCIFFRX.bit.RXFIFORESET=0;', + 'model_flush(rs_arr);rs_arr->SciRegs->SCIFFRX.bit.RXFIFORESET=0;') +body=body.replace('rs_arr->SciRegs->SCICTL1.bit.SWRESET=1;', + 'rs_arr->SciRegs->SCIRXST.all=0;rs_arr->SciRegs->SCICTL1.bit.SWRESET=1;') +body=body.replace('while (!rs_arr->SciRegs->SCICTL2.bit.TXEMPTY) { }', + 'while (!rs_arr->SciRegs->SCICTL2.bit.TXEMPTY) { model_step(rs_arr); }',1) +body=body.replace('while (!rs_arr->SciRegs->SCICTL2.bit.TXEMPTY) { }', + 'while (!rs_arr->SciRegs->SCICTL2.bit.TXEMPTY) { model_shift(rs_arr); }') +body=body.replace('!rs_arr->SciRegs->SCICTL2.bit.TXEMPTY) { }', + '!rs_arr->SciRegs->SCICTL2.bit.TXEMPTY) { model_step(rs_arr); }') +header=read(root/'Source/Internal/Include/RS485.h') +header=re.sub(r'#define SCI_send\(x,y\)[^\n]*', '#define SCI_send(x,y) model_push(x,y)',header) +header=re.sub(r'#define enableUARTInt\(x\)[^\n]*', '#define enableUARTInt(x) model_interrupts(x,0)',header) +header=re.sub(r'#define enableUARTIntW\(x\)[^\n]*', '#define enableUARTIntW(x) model_interrupts(x,1)',header) +header=re.sub(r'#define Rec_Bloc_Begin[^\n]*', '#define Rec_Bloc_Begin ((uintptr_t)load_memory)',header) +header=re.sub(r'#define Rec_Bloc_End[^\n]*', '#define Rec_Bloc_End ((uintptr_t)(load_memory+4100))',header) +registers=read(root/'Source/External/v120/DSP2833x_headers/include/DSP2833x_Sci.h') +defines=''' +#include +#include +#include +#include +typedef unsigned short Uint16; +#define interrupt +#define true 1 +#define false 0 +#define BM_CHAR32 0 +#define BM_PACKED 1 +#define CNTRL_ADDR_UNIVERSAL 16 +#define CNTRL_ADDR 5 +#define ADDR_FOR_ALL 0 +#define LOBYTE(x) ((x)&255) +#define HIBYTE(x) (((x)>>8)&255) +enum {CMD_MODBUS_3=3,ANS_MODBUS_4=4,CMD_MODBUS_6=6,CMD_MODBUS_16=16, +CMD_LOAD=51,CMD_INITLOAD=58,CMD_STD_ANS=66}; +''' +harness=(Path(__file__).with_name('model.inc')).read_text() +before,after=harness.split('/* HANDLERS */') +parser=argparse.ArgumentParser();parser.add_argument('--cc',required=True);args=parser.parse_args() +env=dict(os.environ);env['PATH']=str(Path(args.cc).parent)+os.pathsep+env.get('PATH','') +with tempfile.TemporaryDirectory(prefix='pm35-fifo-') as directory: + path=Path(directory);c=path/'model.c';exe=path/'model.exe' + c.write_text(defines+registers+header+'\n'.join(prototypes)+before+body+after) + subprocess.run([args.cc,'-std=c99','-O1','-Werror=implicit-function-declaration',str(c),'-o',str(exe)],check=True,env=env) + subprocess.run([str(exe)],check=True,env=env,timeout=20)