Добавить heartbeat и передачу CAN по изменению и таймеру
Для всех Mode передавать пакеты при обновлении данных и повторять каждый через 1300 мс от последнего CAN ACK. Отдельно отправлять heartbeat раз в секунду. Сохранить маски рассылки, отключение потоков нулевым периодом и неблокирующее восстановление после ошибок TX. Проверены границы периодов, все Mode, занятый mailbox, отмена без CANAA, отсутствие ACK, переполнение Timer1, первый снимок и справедливость потоков. Изменённые модули ecan.c и main.c скомпилированы компилятором TI C2000.
This commit is contained in:
+50
-71
@@ -1,8 +1,8 @@
|
||||
/* Команды и телеметрия eCAN. MBOX1 принимает кадры, MBOX0 передаёт
|
||||
* технологические регистры, MBOX2 выделен под ответы логгера.
|
||||
* Слово 127 проходит UMP_commands_write непосредственно в CAN ISR.
|
||||
* Запрос архива ISR лишь ставит на обслуживание; фрагментация
|
||||
* ответов выполняется UMP_CAN_service из фонового цикла.
|
||||
/* Команды и телеметрия 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"
|
||||
@@ -39,9 +39,9 @@ int CanTimeOutErrorTR = 0;
|
||||
|
||||
int wait=0;
|
||||
|
||||
/* MBOX2 выделен под ответы регистратора; штатный MBOX0 продолжает
|
||||
* передавать технологические данные независимо. ISR только ставит запрос,
|
||||
* а снимок и отправка короткими шагами выполняются в основном цикле. */
|
||||
/* 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];
|
||||
@@ -49,6 +49,8 @@ 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;
|
||||
|
||||
#include "can_telemetry_impl.h" /* Определяет heartbeat, подтверждённый кэш и повтор данных через 1,3 с после объявления состояния штатного TX. */
|
||||
|
||||
void InitCan(int Port, int DevNum)
|
||||
{
|
||||
struct ECAN_REGS ECanShadow;
|
||||
@@ -59,6 +61,7 @@ void InitCan(int Port, int DevNum)
|
||||
|
||||
long id = 0x80BA0000;
|
||||
|
||||
CAN_telemetry_init(); /* Сбрасывает кэш, очередь и секундный heartbeat до разрешения аппаратных прерываний. */
|
||||
DevNum--;
|
||||
if(DevNum<0)DevNum=0;
|
||||
if(DevNum>15)DevNum=15;
|
||||
@@ -86,17 +89,17 @@ void InitCan(int Port, int DevNum)
|
||||
// Required before writing the MSGIDs
|
||||
ECanRegs->CANME.all = 0;
|
||||
|
||||
// задаем адрес 0 ащикa на передачу
|
||||
// задаем адрес 0 ащикa на передачу
|
||||
ECanMboxes->MBOX0.MSGID.all = id + 0x10 + DevNum;
|
||||
|
||||
// задаем адрес 1 ащикa на прием
|
||||
ECanMboxes->MBOX1.MSGID.all = id + DevNum; //поменать!!!! 1 и 0!!!
|
||||
// задаем адрес 1 ащикa на прием
|
||||
ECanMboxes->MBOX1.MSGID.all = id + DevNum; //поменать!!!! 1 и 0!!!
|
||||
|
||||
// MBOX0 и MBOX2 передают данные; MBOX1 принимает команды.
|
||||
// MBOX0 и MBOX2 передают данные; MBOX1 принимает команды.
|
||||
ECanMboxes->MBOX2.MSGID.all = id + 0x20 + DevNum;
|
||||
ECanRegs->CANMD.all = 0xFFFFFFFA;
|
||||
|
||||
// Включаем три mailbox: телеметрия, команды и ответы логгера.
|
||||
// Включаем три mailbox: телеметрия, команды и ответы логгера.
|
||||
ECanRegs->CANME.all = 0x00000007;
|
||||
|
||||
// Clear all TAn bits
|
||||
@@ -121,7 +124,7 @@ void InitCan(int Port, int DevNum)
|
||||
ECanRegs->CANMC.all = ECanShadow.CANMC.all;
|
||||
while(!ECanRegs->CANES.bit.CCE); // Wait for CCE bit to be set..
|
||||
|
||||
// настриваем скорость CAN
|
||||
// настриваем скорость CAN
|
||||
ECanShadow.CANBTC.all = ECanRegs->CANBTC.all;
|
||||
ECanShadow.CANBTC.bit.SJWREG=1;
|
||||
|
||||
@@ -134,7 +137,7 @@ void InitCan(int Port, int DevNum)
|
||||
ECanRegs->CANMC.all = ECanShadow.CANMC.all;
|
||||
while(ECanRegs->CANES.bit.CCE); // Wait for CCE bit to be cleared..
|
||||
|
||||
// задаем таймауты дла ожиданиа отправки получениа посылки
|
||||
// задаем таймауты дла ожиданиа отправки получениа посылки
|
||||
ECanMOTORegs->MOTO0 = 550000;
|
||||
ECanMOTORegs->MOTO1 = 550000;
|
||||
|
||||
@@ -161,7 +164,7 @@ void InitCan(int Port, int DevNum)
|
||||
IER |= M_INT9; // Enable CPU INT
|
||||
EDIS;
|
||||
|
||||
// завершили настройку CAN ащиков
|
||||
// завершили настройку CAN ащиков
|
||||
|
||||
MessageReceivedCount = 0;
|
||||
ErrorCount = 0;
|
||||
@@ -169,43 +172,10 @@ void InitCan(int Port, int DevNum)
|
||||
MessageTransivedCount=0;
|
||||
}
|
||||
|
||||
/* При занятом MBOX0 возвращается без ожидания ACK в цикле.
|
||||
* Это отличается от блокирующих UART/EEPROM операций main.
|
||||
/* При занятом 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();
|
||||
}
|
||||
/* CAN_send определён общим для этой единицы трансляции блоком can_telemetry_impl.h выше. */
|
||||
|
||||
|
||||
void Handlai(volatile struct ECAN_MBOXES * ECanMboxes)
|
||||
@@ -220,9 +190,9 @@ void Handlai(volatile struct ECAN_MBOXES * ECanMboxes)
|
||||
hiword = ECanMboxes->MBOX1.MDH.all;
|
||||
loword = ECanMboxes->MBOX1.MDL.all;
|
||||
|
||||
/* Служебный запрос логгера не является командой УМП и сам не должен
|
||||
* заполнять журнал CAN-событиями при онлайн-чтении. Короткие кадры
|
||||
* отбрасываются: незаполненные байты mailbox могли остаться от прошлого. */
|
||||
/* Служебный запрос логгера не является командой УМП и сам не должен
|
||||
* заполнять журнал CAN-событиями при онлайн-чтении. Короткие кадры
|
||||
* отбрасываются: незаполненные байты mailbox могли остаться от прошлого. */
|
||||
if ((unsigned int)(hiword >> 16) == UMP_CAN_MARKER) {
|
||||
if (ECanMboxes->MBOX1.MSGCTRL.bit.DLC == 8) {
|
||||
ump_can_tag = (unsigned int)hiword;
|
||||
@@ -244,10 +214,10 @@ void Handlai(volatile struct ECAN_MBOXES * ECanMboxes)
|
||||
Data[1] = (loword>>16) & 0xffff;
|
||||
Data[2] = (loword ) & 0xffff;
|
||||
|
||||
/* Каждое разрешённое слово имеет собственный адрес. Не опрашиваем
|
||||
* Commands после кадра безусловно: пакет телеметрии не должен
|
||||
* превращать внутренний сброс параметров в командный фронт.
|
||||
* Адрес 127 проходит через единый обработчик полного слова. */
|
||||
/* Каждое разрешённое слово имеет собственный адрес. Не опрашиваем
|
||||
* Commands после кадра безусловно: пакет телеметрии не должен
|
||||
* превращать внутренний сброс параметров в командный фронт.
|
||||
* Адрес 127 проходит через единый обработчик полного слова. */
|
||||
{
|
||||
unsigned int i;
|
||||
for (i = 0; i < 3; i++, adr++) {
|
||||
@@ -258,7 +228,7 @@ void Handlai(volatile struct ECAN_MBOXES * ECanMboxes)
|
||||
}
|
||||
}
|
||||
|
||||
/* Фиксируем применённую команду до выхода из обработчика CAN. */
|
||||
/* Фиксируем применённую команду до выхода из обработчика CAN. */
|
||||
ump_log_can((unsigned int)(hiword >> 16), Data[0], Data[1], Data[2]);
|
||||
led2_toggle();
|
||||
}
|
||||
@@ -292,8 +262,17 @@ interrupt void CANa_reset_err(void)
|
||||
PieCtrlRegs.PIEACK.all = 0xFFFF; // Enable PIE interrupts
|
||||
EINT;
|
||||
|
||||
ECanaRegs.CANTRR.all = 1;
|
||||
CanTimeOutErrorTR++;
|
||||
/* Проверяет реальный тайм-аут mailbox 0: отложенное PIE-прерывание после успешного TX уже может не иметь причины. */
|
||||
if (ECanaRegs.CANTOS.all & 1UL)
|
||||
{ /* Обрабатывает только штатный передатчик; служебный mailbox 2 контролируется отдельно в UMP_CAN_service. */
|
||||
EALLOW; /* Разрешает изменение управляющего регистра eCAN перед снятием источника прерывания. */
|
||||
ECanaRegs.CANTOC.all &= ~1UL; /* Снимает timeout только mailbox 0, сохраняя контроль служебных передач. */ /* Сброс TOC снимает TOS и MTOF согласно SPRUI07, 13.8.18.3; одной отмены TX недостаточно. */
|
||||
EDIS; /* Восстанавливает защиту регистров до выхода из ветви обработки тайм-аута. */
|
||||
if (ECanaRegs.CANTRS.all & 1UL) /* Передача могла завершиться между чтением TOS и снятием контроля. */
|
||||
ECanaRegs.CANTRR.all = 1UL; /* Запрашивает отмену только ещё занятого mailbox 0, не задерживая прерывание ожиданием CANAA. */
|
||||
can_tx_failed = 1U; /* Не допускает записи повреждённого или отменённого кадра в подтверждённый кэш телеметрии. */
|
||||
CanTimeOutErrorTR++; /* Считает обнаруженный тайм-аут один раз, исключая фантомные повторные входы PIE. */
|
||||
} /* Следующая штатная передача сама заново включит TOC после сброса временного счётчика. */
|
||||
|
||||
PieCtrlRegs.PIEACK.bit.ACK9 |= 1;
|
||||
|
||||
@@ -307,10 +286,10 @@ interrupt void CANa_reset_err(void)
|
||||
//===========================================================================
|
||||
|
||||
|
||||
/* Один вызов обслуживает максимум один кадр и никогда не ждёт ACK в цикле.
|
||||
* Снимок фиксируется один раз на запрос: CAN-фрагменты не смешивают
|
||||
* значения до/после переключения кольцевого банка. Новые запросы забираем
|
||||
* после завершения предыдущего ответа. GUI держит только один запрос. */
|
||||
/* Один вызов обслуживает максимум один кадр и никогда не ждёт ACK в цикле.
|
||||
* Снимок фиксируется один раз на запрос: CAN-фрагменты не смешивают
|
||||
* значения до/после переключения кольцевого банка. Новые запросы забираем
|
||||
* после завершения предыдущего ответа. GUI держит только один запрос. */
|
||||
void UMP_CAN_service(void)
|
||||
{
|
||||
unsigned int saved, tag, address, value, error;
|
||||
@@ -321,11 +300,11 @@ void UMP_CAN_service(void)
|
||||
ump_can_waiting = 0;
|
||||
} else if ((ECanaRegs.CANAA.all & 4UL) ||
|
||||
((unsigned long)CpuTimer1.InterruptCount - ump_can_sent_at > 250UL)) {
|
||||
/* Нет подтверждения шины: отменяем только служебный mailbox.
|
||||
* GUI обнаружит неполный ответ по тайм-ауту; управление MBOX0
|
||||
* и приём команд MBOX1 продолжаются. */
|
||||
/* Нет подтверждения шины: отменяем только служебный mailbox.
|
||||
* GUI обнаружит неполный ответ по тайм-ауту; управление MBOX0
|
||||
* и приём команд MBOX1 продолжаются. */
|
||||
ECanaRegs.CANTRR.all = 4UL;
|
||||
/* До фактического завершения отмены mailbox не переиспользуем. */
|
||||
/* До фактического завершения отмены mailbox не переиспользуем. */
|
||||
if (!(ECanaRegs.CANAA.all & 4UL)) return;
|
||||
ECanaRegs.CANAA.all = 4UL;
|
||||
ump_can_waiting = 0;
|
||||
@@ -342,7 +321,7 @@ void UMP_CAN_service(void)
|
||||
__restore_interrupts(saved);
|
||||
}
|
||||
if (ump_can_index >= ump_can_length) return;
|
||||
/* Перед следующим фрагментом уступаем штатной телеметрии MBOX0. */
|
||||
/* Перед следующим фрагментом уступаем штатной телеметрии 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];
|
||||
|
||||
Reference in New Issue
Block a user