Фронты START/STOP обрабатываются при принятии командного слова CAN/RS, а окончание импульса обслуживается таймером. STOP имеет приоритет, перекрытие выходов исключено, сохранена защита от самопуска при включении. Загрузка параметров больше не подменяет живые команды нагрузки. Добавлены подробные русские комментарии во все собственные C-модули и основные заголовки, описание поведения и host-тест автомата. Обновлены файлы прошивки. Полная сборка TI 22.6.1.LTS и тесты пройдены; проверка на физической плате не выполнялась.
357 lines
11 KiB
C
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;
|
|
}
|