diff options
| author | Sam Anthony <sam@samanthony.xyz> | 2025-10-24 09:42:49 -0400 |
|---|---|---|
| committer | Sam Anthony <sam@samanthony.xyz> | 2025-10-24 09:42:49 -0400 |
| commit | 32dafa1088e2f2428e9b67bf848faf2433216011 (patch) | |
| tree | d1ee08ceb3e16d80784680fbc6ac2a2df3b580ab /fw | |
| parent | 94cdc9ec4e75fc5e55deb394eda4820ba672e3e4 (diff) | |
| download | can-gauge-interface-32dafa1088e2f2428e9b67bf848faf2433216011.zip | |
CAN echo systest
Diffstat (limited to 'fw')
| -rw-r--r-- | fw/can.c | 78 | ||||
| -rw-r--r-- | fw/can.h | 10 | ||||
| -rw-r--r-- | fw/tests/system/can_echo_systest.c | 85 | ||||
| -rw-r--r-- | fw/tests/system/can_tx_systest.c | 4 |
4 files changed, 150 insertions, 27 deletions
@@ -113,7 +113,7 @@ enum { // TXBnDLC RTR = 0x40, - EXIDE = 0x08, // extended identifier enable bit in SIDL registers + IDE = 0x08, // extended identifier flag bit of SIDL registers }; // Instructions @@ -236,29 +236,65 @@ canIE(bool enable) { } } +// Pack ID register values into a struct. static void -readRxbnData(U8 n, U8 data[8u]) { +packId(CanId *id, U8 sidh, U8 sidl, U8 eid8, U8 eid0) { + if (sidl & IDE) { // extended ID + id->type = CAN_ID_EXT; + id->eid[0] = (U8)(sidh << 3u) | (U8)(sidl >> 5u); // sid[7:0] + id->eid[1] = (U8)(eid0 << 3u) | (U8)(sidh >> 5u); //eid[4:0], sid[10:8] + id->eid[2] = (U8)(eid8 << 3u) | (U8)(eid0 >> 5u); // eid[12:5] + id->eid[3] = (U8)((sidl & 0x3) << 3u) | (U8)(eid8 >> 5u); // eid[17:13] + } else { // standard ID + id->type = CAN_ID_STD; + id->sid.lo = (U8)(sidh << 3u) | (U8)(sidl >> 5u); // sid[7:0] + id->sid.hi = sidh >> 5u; // sid[10:8] + } +} + +static void +readRxbn(U8 n, CanFrame *frame) { + U8 sidh, sidl, eid8, eid0; + CAN_CS = 0; - n &= 0x01; // n in {0,1} - (void)spiTx(CMD_READ_RX | (U8)(n << 2u) | 0x02); // start at RXBnD0 - for (n = 0u; n < 8u; n++) { - data[n] = spiTx(0x00); + + // Start reading at RXBnSIDH + (void)spiTx(CMD_READ_RX | (U8)((n & 1u) << 2u)); + + // Read ID + sidh = spiTx(0u); + sidl = spiTx(0u); + eid8 = spiTx(0u); + eid0 = spiTx(0u); + packId(&frame->id, sidh, sidl, eid8, eid0); + + // Read RTR and DLC + frame->dlc = spiTx(0u); + frame->rtr = frame->dlc & RTR; + frame->dlc &= 0xF; + + // Read data + for (n = 0u; n < frame->dlc; n++) { + frame->data[n] = spiTx(0u); } + CAN_CS = 1; } void -canReadRxb0Data(U8 data[8u]) { - readRxbnData(0u, data); +canReadRxb0(CanFrame *frame) { + readRxbn(0u, frame); } void -canReadRxb1Data(U8 data[8u]) { - readRxbnData(1u, data); +canReadRxb1(CanFrame *frame) { + readRxbn(1u, frame); } +// Write an ID to a set of {xSIDH, xSIDL, xEID8, xEID0} registers, +// e.g., RXMnSIDH etc. static void -writeIdToRegs(const CanId *id, Reg sidh, Reg sidl, Reg eid8, Reg eid0) { +writeId(const CanId *id, Reg sidh, Reg sidl, Reg eid8, Reg eid0) { switch (id->type) { case CAN_ID_STD: // standard ID write(sidh, (U8)(id->sid.hi << 5u) | (U8)(id->sid.lo >> 3u)); @@ -268,7 +304,7 @@ writeIdToRegs(const CanId *id, Reg sidh, Reg sidl, Reg eid8, Reg eid0) { break; case CAN_ID_EXT: // extended ID write(sidh, (U8)(id->eid[1] << 5u) | (U8)(id->eid[0] >> 3u)); // sid[10:3] - write(sidl, (U8)(id->eid[0] << 5u) | EXIDE | (U8)((id->eid[3] >> 3u) & 0x03)); // sid[2:0], exide, eid[28:27] + write(sidl, (U8)(id->eid[0] << 5u) | IDE | (U8)((id->eid[3] >> 3u) & 0x03)); // sid[2:0], exide, eid[28:27] write(eid8, (U8)(id->eid[3] << 5u) | (U8)(id->eid[2] >> 3u)); // eid[26:19] write(eid0, (U8)(id->eid[2] << 5u) | (U8)(id->eid[1] >> 3u)); // eid[18:11] break; @@ -280,7 +316,7 @@ canTx(const CanFrame *frame) { U8 k, ctrl; // Set ID, DLC, and RTR - writeIdToRegs(&frame->id, REG_TXB0SIDH, REG_TXB0SIDL, REG_TXB0EID8, REG_TXB0EID0); + writeId(&frame->id, REG_TXB0SIDH, REG_TXB0SIDL, REG_TXB0EID8, REG_TXB0EID0); write(REG_TXB0DLC, (frame->dlc & 0x0F) | ((frame->rtr) ? RTR : 0)); // Copy data to registers @@ -305,40 +341,40 @@ canTx(const CanFrame *frame) { void canSetMask0(const CanId *mask) { - writeIdToRegs(mask, REG_RXM0SIDH, REG_RXM0SIDL, REG_RXM0EID8, REG_RXM0EID0); + writeId(mask, REG_RXM0SIDH, REG_RXM0SIDL, REG_RXM0EID8, REG_RXM0EID0); } void canSetMask1(const CanId *mask) { - writeIdToRegs(mask, REG_RXM1SIDH, REG_RXM1SIDL, REG_RXM1EID8, REG_RXM1EID0); + writeId(mask, REG_RXM1SIDH, REG_RXM1SIDL, REG_RXM1EID8, REG_RXM1EID0); } void canSetFilter0(const CanId *filter) { - writeIdToRegs(filter, REG_RXF0SIDH, REG_RXF0SIDL, REG_RXF0EID8, REG_RXF0EID0); + writeId(filter, REG_RXF0SIDH, REG_RXF0SIDL, REG_RXF0EID8, REG_RXF0EID0); } void canSetFilter1(const CanId *filter) { - writeIdToRegs(filter, REG_RXF1SIDH, REG_RXF1SIDL, REG_RXF1EID8, REG_RXF1EID0); + writeId(filter, REG_RXF1SIDH, REG_RXF1SIDL, REG_RXF1EID8, REG_RXF1EID0); } void canSetFilter2(const CanId *filter) { - writeIdToRegs(filter, REG_RXF2SIDH, REG_RXF2SIDL, REG_RXF2EID8, REG_RXF2EID0); + writeId(filter, REG_RXF2SIDH, REG_RXF2SIDL, REG_RXF2EID8, REG_RXF2EID0); } void canSetFilter3(const CanId *filter) { - writeIdToRegs(filter, REG_RXF3SIDH, REG_RXF3SIDL, REG_RXF3EID8, REG_RXF3EID0); + writeId(filter, REG_RXF3SIDH, REG_RXF3SIDL, REG_RXF3EID8, REG_RXF3EID0); } void canSetFilter4(const CanId *filter) { - writeIdToRegs(filter, REG_RXF4SIDH, REG_RXF4SIDL, REG_RXF4EID8, REG_RXF4EID0); + writeId(filter, REG_RXF4SIDH, REG_RXF4SIDL, REG_RXF4EID8, REG_RXF4EID0); } void canSetFilter5(const CanId *filter) { - writeIdToRegs(filter, REG_RXF5SIDH, REG_RXF5SIDL, REG_RXF5EID8, REG_RXF5EID0); + writeId(filter, REG_RXF5SIDH, REG_RXF5SIDL, REG_RXF5EID8, REG_RXF5EID0); } @@ -52,9 +52,9 @@ typedef struct { // CAN frame typedef struct { CanId id; + bool rtr; // remote transmission request U8 dlc; // data length code U8 data[8]; - bool rtr; // remote transmission request } CanFrame; // Initialize the MCP2515. @@ -75,11 +75,11 @@ void canIE(bool enable); // Read RX status with RX STATUS instruction. U8 canRxStatus(void); -// Read the DATA field of RXB0. -void canReadRxb0Data(U8 data[8u]); +// Read the frame in RXB0. +void canReadRxb0(CanFrame *frame); -// Read the DATA field of RXB1. -void canReadRxb1Data(U8 data[8u]); +// Read the frame in RXB1. +void canReadRxb1(CanFrame *frame); // Transmit a frame to the CAN bus Status canTx(const CanFrame *frame); diff --git a/fw/tests/system/can_echo_systest.c b/fw/tests/system/can_echo_systest.c new file mode 100644 index 0000000..798e45f --- /dev/null +++ b/fw/tests/system/can_echo_systest.c @@ -0,0 +1,85 @@ +/* Listen for a standard DATA FRAME with ID 123h; + * echo it back with each byte of the DATA FIELD incremented by 1. + */ + +#include <xc.h> + +#include <stdbool.h> +#include <stdint.h> + +#include "system.h" +#include "types.h" +#include "spi.h" +#include "can.h" + +void +main(void) { + sysInit(); + spiInit(); + canInit(); + + // Setup MCP2515 CAN controller + canSetBitTiming(CAN_TIMING_10K); + CanId id = { + .type=CAN_ID_STD, + .sid = {0xFF, 0xFF}, + }; + canSetMask0(&id); // set masks + canSetMask1(&id); + canSetFilter1(&id); // set unused filters + canSetFilter2(&id); + canSetFilter3(&id); + canSetFilter4(&id); + canSetFilter5(&id); + id.sid = (U16){0x01, 0x23}; // listen for message on filter 0 + canSetFilter0(&id); + canIE(true); // enable interrupts on INT pin + canSetMode(CAN_MODE_NORMAL); + + // Enable interrupts + INTCON = 0x00; // clear flags + OPTION_REGbits.INTEDG = 0; // interrupt on falling edge + INTCONbits.INTE = 1; // enable INT pin + INTCONbits.PEIE = 1; // enable peripheral interrupts + INTCONbits.GIE = 1; // enable global interrupts + + for (;;) { + + } +} + +// Add 1 to each data byte of a CAN frame and transmit it to the bus. +static void +echo(CanFrame *frame) { + U8 k; + + for (k = 0u; k < frame->dlc; k++) { + frame->data[k]++; + } + + canTx(frame); +} + +void +__interrupt() isr(void) { + U8 status; + CanFrame frame; + + if (INTCONbits.INTF) { + status = canRxStatus(); + switch (status & 0x7) { // check filter match + case 0u: // RXF0 + canReadRxb0(&frame); + echo(&frame); + break; + case 1u: // RXF1 + canReadRxb0(&frame); // clear interrupt flag + break; + default: + // Message in RXB1 + canReadRxb1(&frame); // clear interrupt flag + } + + INTCONbits.INTF = 0; + } +} diff --git a/fw/tests/system/can_tx_systest.c b/fw/tests/system/can_tx_systest.c index b1dec17..ef1d7b0 100644 --- a/fw/tests/system/can_tx_systest.c +++ b/fw/tests/system/can_tx_systest.c @@ -1,3 +1,5 @@ +/* Periodically transmit a frame to the CAN bus. */ + #include <xc.h> #include <stdbool.h> @@ -14,9 +16,9 @@ static const CanFrame frame = { .type = CAN_ID_STD, .sid = {0x01, 0x23}, }, + .rtr = false, .dlc = 8u, .data = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77}, - .rtr = false, }; static U8 ctr = 0u; // timer |