feat(rs232): enable SCI-A FIFO on PM35 and preserve RS485
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -3,4 +3,7 @@
|
||||
/Bin/UKSSTMS320F28335_*.bin
|
||||
/Bin/LoggerFix/
|
||||
/Bin/LoggerEepromFix/
|
||||
/Bin/Rs232FifoTest/
|
||||
/Bin/Rs232NoFifoTest/
|
||||
/Bin/UartFifoTest/
|
||||
/Bin/*.pending
|
||||
|
||||
69
Doc/RS232_FIFO.md
Normal file
69
Doc/RS232_FIFO.md
Normal file
@@ -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.
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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" `
|
||||
|
||||
118
tests/rs232_fifo/model.inc
Normal file
118
tests/rs232_fifo/model.inc
Normal file
@@ -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]<rx_count[i]);v=rx[i][rx_pos[i]++];
|
||||
p->SciRegs->SCIFFRX.bit.RXFFST=rx_count[i]-rx_pos[i];
|
||||
p->SciRegs->SCIRXST.bit.RXRDY=rx_pos[i]<rx_count[i];return v;
|
||||
}
|
||||
static void model_push(RS_DATA *p,unsigned v)
|
||||
{
|
||||
unsigned i=port(p);assert(length[i]<16);queue[i][length[i]++]=v&255;
|
||||
if(i==0)p->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;j<length[i];j++)queue[i][j-1]=queue[i][j];
|
||||
length[i]--;shift_pending[i]=1;
|
||||
if(i==0)p->SciRegs->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;j<n;j++)rx[i][j]=bytes[j];
|
||||
p->SciRegs->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;a<sizeof(sizes)/sizeof(sizes[0]);a++) {
|
||||
reset();n=sizes[a];for(i=0;i<4200;i++)data[i]=(i*131U+17U)&65535;
|
||||
if(mode==0 && n>4200)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;i<n;i++)assert(wire[0][i]==(mode?((i&1)?LOBYTE(data[i/2]):HIBYTE(data[i/2])):LOBYTE(data[i])));
|
||||
assert(GpioDataRegs.GPBDAT.bit.GPIO34==1); /* RS232 never touches DE */
|
||||
assert(!irq);
|
||||
}
|
||||
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,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;i<n;i++)data[i]=(a+i)&255;
|
||||
feed(&rs_a,data,n);
|
||||
}
|
||||
assert(rs_a.RS_DataReady && rs_a.RS_RecvLen==8194);
|
||||
for(i=0;i<4097;i++)assert(load_memory[i]==(((2*i)&255)<<8 | ((2*i+1)&255)));
|
||||
reset();data[0]=1;data[1]=2;RS_Send(&rs_a,data,2);
|
||||
feed(&rs_b,request,8);assert(rs_b.RS_DataReady && rs_a.fifo_tx_active);
|
||||
RS_FifoWait(&rs_a);
|
||||
reset();request[3]=0xC000;feed(&rs_a,request,8);
|
||||
assert(!rs_a.RS_DataReady && rs_a.fifo_rx_errors==1 && rs_a.fifo_rx_guard);
|
||||
request[3]=0;feed(&rs_a,request,8);assert(!rs_a.RS_DataReady);
|
||||
for(i=0;i<4;i++)RS_FifoTick1ms();
|
||||
feed(&rs_a,request,8);assert(rs_a.RS_DataReady);
|
||||
reset();SciaRegs.SCIFFRX.bit.RXFFOVF=1;RS_RX_Handler(&rs_a);
|
||||
assert(rs_a.fifo_overflows==1 && !rs_a.BS_LoadOK);
|
||||
for(i=0;i<4;i++)RS_FifoTick1ms();feed(&rs_a,request,8);assert(rs_a.RS_DataReady);
|
||||
/* A spurious old threshold interrupt may not finish an occupied FIFO. */
|
||||
reset();RS_Send(&rs_a,data,8);RS_TX_Handler(&rs_a);assert(rs_a.fifo_tx_active);
|
||||
RS_FifoWait(&rs_a);assert(wire_count[0]==8);
|
||||
/* SCI-B keeps the original RX parser and IRQ/TX path, never FIFO state. */
|
||||
reset();feed(&rs_b,request,8);assert(rs_b.RS_DataReady);
|
||||
reset();RS_Send(&rs_b,data,2);assert(!rs_b.fifo_tx_active && length[1]==1);
|
||||
model_step(&rs_b);RS_TX_Handler(&rs_b); /* legacy RS_Wait drains final char */
|
||||
assert(GpioDataRegs.GPBDAT.bit.GPIO34==1);
|
||||
puts("PM35 RS232 FIFO: PASS (TX/RX/errors/recovery/SCI-B isolation)");return 0;
|
||||
}
|
||||
73
tests/rs232_fifo/run_test.py
Normal file
73
tests/rs232_fifo/run_test.py
Normal file
@@ -0,0 +1,73 @@
|
||||
"""Exercise production RS485.c functions with FIFO register side effects."""
|
||||
import argparse
|
||||
import os
|
||||
from pathlib import Path
|
||||
import re
|
||||
import subprocess
|
||||
import tempfile
|
||||
|
||||
root=Path(__file__).resolve().parents[2]
|
||||
def read(path):
|
||||
return re.sub(r'/\*.*?\*/|//[^\n]*','',path.read_bytes().decode('cp1251').replace('\r\n','\n'),flags=re.S)
|
||||
source=read(root/'Source/Internal/RS485.c')
|
||||
names=['RS_RX_Handler','RS_TX_Handler','RS_Send','RS_BSend','RS_SetBitMode',
|
||||
'RS_FifoWait','RS_FifoTx','RS_FifoStart','RS_FifoAbort','RS_FifoTick1ms']
|
||||
prototypes=[];functions=[]
|
||||
for name in names:
|
||||
match=re.search(r'(?:static\s+)?(?:void|int)\s+'+name+r'\([^;{}]*\)\s*\{',source)
|
||||
assert match,name
|
||||
begin=source.index('{',match.start());end=begin+1;depth=1
|
||||
while depth:
|
||||
depth+=(source[end]=='{')-(source[end]=='}');end+=1
|
||||
prototypes.append(source[match.start():begin]+';')
|
||||
functions.append(source[match.start():end])
|
||||
body='\n'.join(functions)
|
||||
# TI C28x char is 16 bits: 0x80..0xFF remain positive before word packing.
|
||||
body=re.sub(r'\bchar\s+Rc;', 'unsigned int Rc;', body)
|
||||
body=body.replace('received=rs_arr->SciRegs->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 <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
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)
|
||||
Reference in New Issue
Block a user