Files
Balsam_167/Source/Internal/ecan.c
andrey eb2ff79932 Устранена зависимость дискретов СИФУ от основного цикла в 166
Фронты START/STOP обрабатываются при принятии командного слова CAN/RS,
а окончание импульса обслуживается таймером. STOP имеет приоритет,
перекрытие выходов исключено, сохранена защита от самопуска при включении.
Загрузка параметров больше не подменяет живые команды нагрузки.

Добавлены подробные русские комментарии во все собственные C-модули
и основные заголовки, описание поведения и host-тест автомата.
Обновлены файлы прошивки. Полная сборка TI 22.6.1.LTS и тесты пройдены;
проверка на физической плате не выполнялась.
2026-09-23 01:28:11 +03:00

357 lines
11 KiB
C

/* Êîìàíäû è òåëåìåòðèÿ eCAN. MBOX1 ïðèíèìàåò êàäðû, MBOX0 ïåðåäà¸ò
* òåõíîëîãè÷åñêèå ðåãèñòðû, MBOX2 âûäåëåí ïîä îòâåòû ëîããåðà.
* Ñëîâî 127 ïðîõîäèò UMP_commands_write íåïîñðåäñòâåííî â CAN ISR.
* Çàïðîñ àðõèâà ISR ëèøü ñòàâèò íà îáñëóæèâàíèå; ôðàãìåíòàöèÿ
* îòâåòîâ âûïîëíÿåòñÿ UMP_CAN_service èç ôîíîâîãî öèêëà.
*/
#include "DSP2833x_Device.h" // DSP2833x Headerfile Include File
#include "DSP2833x_SWPrioritizedIsrLevels.h"
#include "filter_bat2.h"
#include "measure.h"
#include "package.h" // DSP281x Headerfile Include File
#include "ecan.h" // DSP281x Headerfile Include File
#include "tools.h" // DSP281x Headerfile Include File
#include "RS485.h"
#include "message.h"
#include "peripher.h"
#include "log_to_mem.h"
#include "ump_can_protocol.h"
#include "DAC.h"
// Prototype statements for functions found within this file.
interrupt void CANa_handler(void);
interrupt void CANa_reset_err(void);
// Global variable for this example
Uint32 ErrorCount;
Uint32 MessageReceivedCount;
Uint32 MessageTransivedCount=0;
Uint32 TestMbox1 = 0;
Uint32 TestMbox2 = 0;
Uint32 TestMbox3 = 0;
int CanTimeOutErrorTR = 0;
int wait=0;
/* MBOX2 âûäåëåí ïîä îòâåòû ðåãèñòðàòîðà; øòàòíûé MBOX0 ïðîäîëæàåò
* ïåðåäàâàòü òåõíîëîãè÷åñêèå äàííûå íåçàâèñèìî. ISR òîëüêî ñòàâèò çàïðîñ,
* à ñíèìîê è îòïðàâêà êîðîòêèìè øàãàìè âûïîëíÿþòñÿ â îñíîâíîì öèêëå. */
static volatile unsigned int ump_can_pending;
static volatile unsigned int ump_can_tag, ump_can_address, ump_can_value;
static unsigned int ump_can_reply[UMP_CAN_MAX_WORDS];
static unsigned int ump_can_length, ump_can_index, ump_can_reply_tag;
static unsigned int ump_can_waiting;
static unsigned long ump_can_sent_at;
void InitCan(int Port, int DevNum)
{
struct ECAN_REGS ECanShadow;
volatile struct ECAN_REGS * ECanRegs;
volatile struct ECAN_MBOXES * ECanMboxes;
volatile struct MOTO_REGS * ECanMOTORegs;
long id = 0x80BA0000;
DevNum--;
if(DevNum<0)DevNum=0;
if(DevNum>15)DevNum=15;
// Configure CAN pins using GPIO regs here
EALLOW;
ECanRegs = &ECanaRegs;
ECanMboxes = &ECanaMboxes;
ECanMOTORegs = &ECanaMOTORegs;
GpioCtrlRegs.GPAMUX2.bit.GPIO30 = 1;
GpioCtrlRegs.GPAMUX2.bit.GPIO31 = 1;
// Configure the eCAN RX and TX pins for eCAN transmissions
ECanRegs->CANTIOC.all = 8; // only 3rd bit, TXFUNC, is significant
ECanRegs->CANRIOC.all = 8; // only 3rd bit, RXFUNC, is significant
// Specify that 8 bits will be sent/received
ECanMboxes->MBOX0.MSGCTRL.all = 0x00000008;
ECanMboxes->MBOX1.MSGCTRL.all = 0x00000008;
ECanMboxes->MBOX2.MSGCTRL.all = 0x00000008;
// Disable all Mailboxes
// Required before writing the MSGIDs
ECanRegs->CANME.all = 0;
// çàäàåì àäðåñ 0 àùèêa íà ïåðåäà÷ó
ECanMboxes->MBOX0.MSGID.all = id + 0x10 + DevNum;
// çàäàåì àäðåñ 1 àùèêa íà ïðèåì
ECanMboxes->MBOX1.MSGID.all = id + DevNum; //ïîìåíàòü!!!! 1 è 0!!!
// MBOX0 è MBOX2 ïåðåäàþò äàííûå; MBOX1 ïðèíèìàåò êîìàíäû.
ECanMboxes->MBOX2.MSGID.all = id + 0x20 + DevNum;
ECanRegs->CANMD.all = 0xFFFFFFFA;
// Âêëþ÷àåì òðè mailbox: òåëåìåòðèÿ, êîìàíäû è îòâåòû ëîããåðà.
ECanRegs->CANME.all = 0x00000007;
// Clear all TAn bits
ECanRegs->CANTA.all = 0xFFFFFFFF;
// Clear all RMPn bits
ECanRegs->CANRMP.all = 0xFFFFFFFF;
// Clear all interrupt flag bits
ECanRegs->CANGIF0.all = 0xFFFFFFFF;
ECanRegs->CANGIF1.all = 0xFFFFFFFF;
// Clear all error and status bits
ECanRegs->CANES.all=0xffffffff;
// Request permission to change the configuration registers
ECanShadow.CANMC.all = 0;
ECanShadow.CANMC.bit.MBCC = 1; // Mailbox timestamp counter clear bit
ECanShadow.CANMC.bit.TCC = 1; // Time stamp counter MSB clear bit
ECanShadow.CANMC.bit.SCB = 1; // eCAN mode (reqd to access 32 mailboxes)
ECanShadow.CANMC.bit.WUBA = 1; // Wake up on bus activity
ECanShadow.CANMC.bit.ABO = 1; // Auto bus on
ECanShadow.CANMC.bit.CCR = 1;
// ECanShadow.CANMC.bit.STM = 1; // self-test loop-back
ECanRegs->CANMC.all = ECanShadow.CANMC.all;
while(!ECanRegs->CANES.bit.CCE); // Wait for CCE bit to be set..
// íàñòðèâàåì ñêîðîñòü CAN
ECanShadow.CANBTC.all = ECanRegs->CANBTC.all;
ECanShadow.CANBTC.bit.SJWREG=1;
ECanShadow.CANBTC.bit.BRPREG = (CLKMULT * 3) - 1;
ECanShadow.CANBTC.bit.TSEG1REG = 15;
ECanShadow.CANBTC.bit.TSEG2REG = 2;
ECanRegs->CANBTC.all = ECanShadow.CANBTC.all;
ECanShadow.CANMC.bit.CCR = 0; // Set CCR = 0
ECanRegs->CANMC.all = ECanShadow.CANMC.all;
while(ECanRegs->CANES.bit.CCE); // Wait for CCE bit to be cleared..
// çàäàåì òàéìàóòû äëà îæèäàíèà îòïðàâêè ïîëó÷åíèà ïîñûëêè
ECanMOTORegs->MOTO0 = 550000;
ECanMOTORegs->MOTO1 = 550000;
ECanRegs->CANTOC.all = 1;
ECanRegs->CANTOS.all = 0; // clear all time-out flags
ECanRegs->CANTSC = 0; // clear time-out counter
ECanShadow.CANGIM.all = 0;
ECanRegs->CANMIM.all = 2; // Enable interrupts of box 1
ECanRegs->CANMIL.all = 0x00000000; // All mailbox interrupts are generated on interrupt line 0.
ECanShadow.CANGIM.bit.I0EN = 1;
ECanShadow.CANGIM.bit.MTOM = 1;
ECanShadow.CANGIM.bit.I1EN = 1;
ECanShadow.CANGIM.bit.GIL = 1;
ECanRegs->CANGIM.all = ECanShadow.CANGIM.all;
PieVectTable.ECAN0INTA = &CANa_handler;
PieCtrlRegs.PIEIER9.bit.INTx5=1; // PIE Group 9, INT6
PieVectTable.ECAN1INTA = &CANa_reset_err;
PieCtrlRegs.PIEIER9.bit.INTx6=1; // PIE Group 9, INT6
IER |= M_INT9; // Enable CPU INT
EDIS;
// çàâåðøèëè íàñòðîéêó CAN àùèêîâ
MessageReceivedCount = 0;
ErrorCount = 0;
CanTimeOutErrorTR=0;
MessageTransivedCount=0;
}
/* Ïðè çàíÿòîì MBOX0 âîçâðàùàåòñÿ áåç îæèäàíèÿ ACK â öèêëå.
* Ýòî îòëè÷àåòñÿ îò áëîêèðóþùèõ UART/EEPROM îïåðàöèé main.
*/
void CAN_send(int Port, int data[], int Addr)
{
unsigned long hiword,loword;
volatile struct ECAN_REGS * ECanRegs;
volatile struct ECAN_MBOXES * ECanMboxes;
ECanRegs = &ECanaRegs;
ECanMboxes = &ECanaMboxes;
if(wait)
if(!(ECanRegs->CANTA.all & 1))
if(!(ECanRegs->CANAA.all & 1))
return;
ECanRegs->CANTA.all = 1;
ECanRegs->CANAA.all = 1;
hiword= ((((Uint32) Addr ) & 0xffff)<<16)| 0xE0000000 |
((((Uint32)data[Addr ]) & 0xffff) );
loword= ((((Uint32)data[Addr+1]) & 0xffff)<<16)|
((((Uint32)data[Addr+2]) & 0xffff) );
ECanMboxes->MBOX0.MDH.all = hiword;
ECanMboxes->MBOX0.MDL.all = loword;
EALLOW;
ECanRegs->CANTSC = 0; // clear time-out counter
EDIS;
ECanRegs->CANTRS.all = 1; // çàïóñòèòü ïåðåäà÷ó
wait=1;
led1_toggle();
}
void Handlai(volatile struct ECAN_MBOXES * ECanMboxes)
{
unsigned int adr;
unsigned int bit[3];
unsigned long hiword,loword;
int Data[3];
Lonely=0;
hiword = ECanMboxes->MBOX1.MDH.all;
loword = ECanMboxes->MBOX1.MDL.all;
/* Ñëóæåáíûé çàïðîñ ëîããåðà íå ÿâëÿåòñÿ êîìàíäîé ÓÌÏ è ñàì íå äîëæåí
* çàïîëíÿòü æóðíàë CAN-ñîáûòèÿìè ïðè îíëàéí-÷òåíèè. Êîðîòêèå êàäðû
* îòáðàñûâàþòñÿ: íåçàïîëíåííûå áàéòû mailbox ìîãëè îñòàòüñÿ îò ïðîøëîãî. */
if ((unsigned int)(hiword >> 16) == UMP_CAN_MARKER) {
if (ECanMboxes->MBOX1.MSGCTRL.bit.DLC == 8) {
ump_can_tag = (unsigned int)hiword;
ump_can_address = (unsigned int)(loword >> 16);
ump_can_value = (unsigned int)loword;
ump_can_pending = 1;
}
return;
}
adr = (hiword >> 16);
bit[0] = adr & 0x8000;
bit[1] = adr & 0x4000;
bit[2] = adr & 0x2000;
adr &= 0x1fff;
Data[0] = (hiword ) & 0xffff;
Data[1] = (loword>>16) & 0xffff;
Data[2] = (loword ) & 0xffff;
/* Êàæäîå ðàçðåø¸ííîå ñëîâî èìååò ñîáñòâåííûé àäðåñ. Íå îïðàøèâàåì
* Commands ïîñëå êàäðà áåçóñëîâíî: ïàêåò òåëåìåòðèè íå äîëæåí
* ïðåâðàùàòü âíóòðåííèé ñáðîñ ïàðàìåòðîâ â êîìàíäíûé ôðîíò.
* Àäðåñ 127 ïðîõîäèò ÷åðåç åäèíûé îáðàáîò÷èê ïîëíîãî ñëîâà. */
{
unsigned int i;
for (i = 0; i < 3; i++, adr++) {
if (bit[i] && adr < ANSWER_LEN) {
if (adr == 127) UMP_commands_write((unsigned int)Data[i]);
else modbus[adr] = Data[i];
}
}
}
/* Ôèêñèðóåì ïðèìåí¸ííóþ êîìàíäó äî âûõîäà èç îáðàáîò÷èêà CAN. */
ump_log_can((unsigned int)(hiword >> 16), Data[0], Data[1], Data[2]);
led2_toggle();
}
interrupt void CANa_handler(void)
{
// Set interrupt priority:
volatile Uint16 TempPIEIER = PieCtrlRegs.PIEIER9.all;
IER |= M_INT9;
IER &= MINT9; // Set "global" priority
PieCtrlRegs.PIEIER9.all &= MG95; // Set "group" priority
PieCtrlRegs.PIEACK.all = 0xFFFF; // Enable PIE interrupts
EINT;
Handlai(&ECanaMboxes);
ECanaRegs.CANRMP.all = 2;
PieCtrlRegs.PIEACK.bit.ACK9 |= 1;
// Restore registers saved:
DINT;
PieCtrlRegs.PIEIER9.all = TempPIEIER;
}
interrupt void CANa_reset_err(void)
{
// Set interrupt priority:
volatile Uint16 TempPIEIER = PieCtrlRegs.PIEIER9.all;
IER |= M_INT9;
IER &= MINT9; // Set "global" priority
PieCtrlRegs.PIEIER9.all &= MG96; // Set "group" priority
PieCtrlRegs.PIEACK.all = 0xFFFF; // Enable PIE interrupts
EINT;
ECanaRegs.CANTRR.all = 1;
CanTimeOutErrorTR++;
PieCtrlRegs.PIEACK.bit.ACK9 |= 1;
// Restore registers saved:
DINT;
PieCtrlRegs.PIEIER9.all = TempPIEIER;
}
//===========================================================================
// No more.
//===========================================================================
/* Îäèí âûçîâ îáñëóæèâàåò ìàêñèìóì îäèí êàäð è íèêîãäà íå æä¸ò ACK â öèêëå.
* Ñíèìîê ôèêñèðóåòñÿ îäèí ðàç íà çàïðîñ: CAN-ôðàãìåíòû íå ñìåøèâàþò
* çíà÷åíèÿ äî/ïîñëå ïåðåêëþ÷åíèÿ êîëüöåâîãî áàíêà. Íîâûå çàïðîñû çàáèðàåì
* ïîñëå çàâåðøåíèÿ ïðåäûäóùåãî îòâåòà. GUI äåðæèò òîëüêî îäèí çàïðîñ. */
void UMP_CAN_service(void)
{
unsigned int saved, tag, address, value, error;
unsigned long hiword, loword;
if (ump_can_waiting) {
if (ECanaRegs.CANTA.all & 4UL) {
ECanaRegs.CANTA.all = 4UL;
ump_can_waiting = 0;
} else if ((ECanaRegs.CANAA.all & 4UL) ||
((unsigned long)CpuTimer1.InterruptCount - ump_can_sent_at > 250UL)) {
/* Íåò ïîäòâåðæäåíèÿ øèíû: îòìåíÿåì òîëüêî ñëóæåáíûé mailbox.
* GUI îáíàðóæèò íåïîëíûé îòâåò ïî òàéì-àóòó; óïðàâëåíèå MBOX0
* è ïðè¸ì êîìàíä MBOX1 ïðîäîëæàþòñÿ. */
ECanaRegs.CANTRR.all = 4UL;
/* Äî ôàêòè÷åñêîãî çàâåðøåíèÿ îòìåíû mailbox íå ïåðåèñïîëüçóåì. */
if (!(ECanaRegs.CANAA.all & 4UL)) return;
ECanaRegs.CANAA.all = 4UL;
ump_can_waiting = 0;
ump_can_length = 0;
} else return;
}
if (ump_can_index >= ump_can_length && ump_can_pending) {
saved = __disable_interrupts();
tag = ump_can_tag; address = ump_can_address; value = ump_can_value;
ump_can_pending = 0;
ump_can_length = ump_can_prepare(tag & 0xFF, address, value, ump_can_reply, &error);
ump_can_reply_tag = (tag & 0xFF00) | error;
ump_can_index = 0;
__restore_interrupts(saved);
}
if (ump_can_index >= ump_can_length) return;
/* Ïåðåä ñëåäóþùèì ôðàãìåíòîì óñòóïàåì øòàòíîé òåëåìåòðèè MBOX0. */
if (ECanaRegs.CANTRS.all & 1UL) return;
hiword = ((unsigned long)(UMP_CAN_MARKER + ump_can_index/2) << 16) | ump_can_reply_tag;
loword = ((unsigned long)ump_can_reply[ump_can_index] << 16) | ump_can_reply[ump_can_index+1];
ECanaRegs.CANTA.all = 4UL; ECanaRegs.CANAA.all = 4UL;
ECanaMboxes.MBOX2.MDH.all = hiword;
ECanaMboxes.MBOX2.MDL.all = loword;
ump_can_sent_at = CpuTimer1.InterruptCount;
ECanaRegs.CANTRS.all = 4UL;
ump_can_waiting = 1;
ump_can_index += 2;
}