mirror of
https://github.com/infiniteCable2/panda.git
synced 2026-02-18 17:23:52 +08:00
227 lines
4.9 KiB
C
227 lines
4.9 KiB
C
#include <stdint.h>
|
|
#include "config.h"
|
|
#include "can.h"
|
|
#include "uart.h"
|
|
#include "gpio.h"
|
|
#include "libc.h"
|
|
|
|
// assign CAN numbering
|
|
#ifdef PANDA
|
|
// panda: CAN1 = 0 CAN2 = 1 CAN3 = 2
|
|
can_port_desc can_ports[] = {
|
|
{.CAN=CAN1,
|
|
.forwarding=-1,
|
|
.bitrate=CAN_DEFAULT_BITRATE,
|
|
.gmlan_support=false,
|
|
.gmlan=false,
|
|
.safety_mode=0,
|
|
.pin={GPIOC, 1, 0}},
|
|
{.CAN=CAN2,
|
|
.forwarding=-1,
|
|
.bitrate=CAN_DEFAULT_BITRATE,
|
|
.gmlan_support=true,
|
|
.gmlan=false,
|
|
.safety_mode=0,
|
|
.pin={GPIOC, 13, 0}},
|
|
//TODO Make gmlan support correct for REV B
|
|
{.CAN=CAN3,
|
|
.forwarding=-1,
|
|
.bitrate=CAN_DEFAULT_BITRATE,
|
|
.gmlan_support=true,
|
|
.gmlan=false,
|
|
.safety_mode=0,
|
|
.pin={GPIOA, 0, 0}},
|
|
};
|
|
#else
|
|
// old: CAN1 = 1 CAN2 = 0
|
|
can_port_desc can_ports[] = {
|
|
{.CAN=CAN2,
|
|
.forwarding=-1,
|
|
.bitrate=CAN_DEFAULT_BITRATE,
|
|
.gmlan_support=false,
|
|
.gmlan=false,
|
|
.safety_mode=0,
|
|
.pin={GPIOB, 3, 1}},
|
|
{.CAN=CAN1,
|
|
.forwarding=-1,
|
|
.bitrate=CAN_DEFAULT_BITRATE,
|
|
.gmlan_support=false,
|
|
.gmlan=false,
|
|
.safety_mode=0,
|
|
.pin={GPIOB, 4, 1}},
|
|
};
|
|
#endif
|
|
|
|
int controls_allowed = 0;
|
|
|
|
int pop(can_ring *q, CAN_FIFOMailBox_TypeDef *elem) {
|
|
if (q->w_ptr != q->r_ptr) {
|
|
*elem = q->elems[q->r_ptr];
|
|
if ((q->r_ptr + 1) == q->fifo_size) q->r_ptr = 0;
|
|
else q->r_ptr += 1;
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int push(can_ring *q, CAN_FIFOMailBox_TypeDef *elem) {
|
|
uint32_t next_w_ptr;
|
|
if ((q->w_ptr + 1) == q->fifo_size) next_w_ptr = 0;
|
|
else next_w_ptr = q->w_ptr + 1;
|
|
if (next_w_ptr != q->r_ptr) {
|
|
q->elems[q->w_ptr] = *elem;
|
|
q->w_ptr = next_w_ptr;
|
|
return 1;
|
|
}
|
|
puts("push failed!\n");
|
|
return 0;
|
|
}
|
|
|
|
// ********************* CAN Functions *********************
|
|
|
|
void can_init(uint8_t canid) {
|
|
uint32_t bitrate;
|
|
CAN_TypeDef *CAN;
|
|
uint8_t quanta;
|
|
uint16_t prescaler;
|
|
uint8_t seq1, seq2;
|
|
|
|
puts("Can init: ");
|
|
puth(canid);
|
|
puts("\n");
|
|
|
|
if(canid >= CAN_MAX) return;
|
|
|
|
bitrate = can_ports[canid].bitrate;
|
|
CAN = can_ports[canid].CAN;
|
|
|
|
//MAX 1 Megabaud
|
|
if(bitrate > 1000000)
|
|
bitrate = 1000000;
|
|
|
|
//puts(" Speed req: ");
|
|
//puth(bitrate);
|
|
//puts("\n");
|
|
|
|
//TODO: Try doing both and find the more accurate values.
|
|
if(min((FREQ / 2) / bitrate, 16) == 16){
|
|
quanta = 16;
|
|
seq1 = 13;//roundf(quanta * 0.875f) - 1;
|
|
seq2 = 2;//roundf(quanta * 0.125f);
|
|
}else{
|
|
quanta = 8;
|
|
seq1 = 6;//roundf(quanta * 0.875f) - 1;
|
|
seq2 = 1;//roundf(quanta * 0.125f);
|
|
}
|
|
|
|
// TODO: Look into better accuracy with rounding.
|
|
prescaler = FREQ / quanta / bitrate;
|
|
|
|
//Check the prescaler is not larger than max
|
|
if(prescaler > 0x3FF)
|
|
prescaler = 0x3FF;
|
|
|
|
can_ports[canid].bitrate = FREQ/quanta/prescaler;
|
|
|
|
puts(" Speed: ");
|
|
puth(can_ports[canid].bitrate);
|
|
puts("\n");
|
|
if (controls_allowed)
|
|
puts(" Output Enabled\n");
|
|
else
|
|
puts(" Output Disabled\n");
|
|
|
|
set_can_enable(canid, 1);
|
|
|
|
// Move CAN to initialization mode and sync.
|
|
CAN->MCR = CAN_MCR_TTCM | CAN_MCR_INRQ;
|
|
while((CAN->MSR & CAN_MSR_INAK) != CAN_MSR_INAK);
|
|
|
|
// seg 1: 13 time quanta, seg 2: 2 time quanta
|
|
CAN->BTR = (CAN_BTR_TS1_0 * (seq1 - 1)) |
|
|
(CAN_BTR_TS2_0 * (seq2 - 1)) |
|
|
(prescaler - 1);
|
|
|
|
// silent loopback mode for debugging
|
|
#ifdef CAN_LOOPBACK_MODE
|
|
CAN->BTR |= CAN_BTR_SILM | CAN_BTR_LBKM;
|
|
#endif
|
|
|
|
if (!controls_allowed) {
|
|
CAN->BTR |= CAN_BTR_SILM;
|
|
}
|
|
|
|
// reset
|
|
CAN->MCR = CAN_MCR_TTCM;
|
|
|
|
int tmp = 0;
|
|
while((CAN->MSR & CAN_MSR_INAK) == CAN_MSR_INAK && tmp < CAN_TIMEOUT) tmp++;
|
|
|
|
if (tmp == CAN_TIMEOUT) {
|
|
set_led(LED_BLUE, 1);
|
|
puts(" init FAILED!!!!!\n");
|
|
} else {
|
|
puts(" init SUCCESS\n");
|
|
}
|
|
|
|
// accept all filter
|
|
CAN->FMR |= CAN_FMR_FINIT;
|
|
|
|
// no mask
|
|
CAN->sFilterRegister[0].FR1 = 0;
|
|
CAN->sFilterRegister[0].FR2 = 0;
|
|
CAN->sFilterRegister[14].FR1 = 0;
|
|
CAN->sFilterRegister[14].FR2 = 0;
|
|
CAN->FA1R |= 1 | (1 << 14);
|
|
|
|
CAN->FMR &= ~(CAN_FMR_FINIT);
|
|
|
|
// enable all CAN interrupts
|
|
CAN->IER = 0xFFFFFFFF;
|
|
//CAN->IER = CAN_IER_TMEIE | CAN_IER_FMPIE0 | CAN_IER_FMPIE1;
|
|
}
|
|
|
|
// CAN error
|
|
void can_sce(CAN_TypeDef *CAN) {
|
|
#ifdef DEBUG
|
|
if (CAN==CAN1) puts("CAN1: ");
|
|
if (CAN==CAN2) puts("CAN2: ");
|
|
#ifdef CAN3
|
|
if (CAN==CAN3) puts("CAN3: ");
|
|
#endif
|
|
puts("MSR:");
|
|
puth(CAN->MSR);
|
|
puts(" TSR:");
|
|
puth(CAN->TSR);
|
|
puts(" RF0R:");
|
|
puth(CAN->RF0R);
|
|
puts(" RF1R:");
|
|
puth(CAN->RF1R);
|
|
puts(" ESR:");
|
|
puth(CAN->ESR);
|
|
puts("\n");
|
|
#endif
|
|
|
|
// clear
|
|
//CAN->sTxMailBox[0].TIR &= ~(CAN_TI0R_TXRQ);
|
|
CAN->TSR |= CAN_TSR_ABRQ0;
|
|
//CAN->ESR |= CAN_ESR_LEC;
|
|
//CAN->MSR &= ~(CAN_MSR_ERRI);
|
|
CAN->MSR = CAN->MSR;
|
|
}
|
|
|
|
int can_cksum(uint8_t *dat, int len, int addr, int idx) {
|
|
int i;
|
|
int s = 0;
|
|
for (i = 0; i < len; i++) {
|
|
s += (dat[i] >> 4);
|
|
s += dat[i] & 0xF;
|
|
}
|
|
s += (addr>>0)&0xF;
|
|
s += (addr>>4)&0xF;
|
|
s += (addr>>8)&0xF;
|
|
s += idx;
|
|
s = 8-s;
|
|
return s&0xF;
|
|
}
|