aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/stm32/can.c289
1 files changed, 143 insertions, 146 deletions
diff --git a/src/stm32/can.c b/src/stm32/can.c
index ff1e633e..e841a222 100644
--- a/src/stm32/can.c
+++ b/src/stm32/can.c
@@ -1,96 +1,90 @@
-/*
- * Serial over CAN emulation for STM32 boards.
- *
- * Copyright (C) 2019 Eug Krashtan <eug.krashtan@gmail.com>
- * Copyright (C) 2020 Pontus Borg <glpontus@gmail.com>
- * This file may be distributed under the terms of the GNU GPLv3 license.
- *
- */
+// Serial over CAN emulation for STM32 boards.
+//
+// Copyright (C) 2019 Eug Krashtan <eug.krashtan@gmail.com>
+// Copyright (C) 2020 Pontus Borg <glpontus@gmail.com>
+//
+// This file may be distributed under the terms of the GNU GPLv3 license.
-#include "autoconf.h" //
-#include "board/armcm_boot.h" // armcm_enable_irq
-#include "board/serial_irq.h" // serial_rx_byte
+#include <string.h> // memcpy
+#include "autoconf.h" // CONFIG_MACH_STM32F1
+#include "can.h" // SHORT_UUID_LEN
#include "command.h" // DECL_CONSTANT_STR
+#include "fasthash.h" // fasthash64
+#include "generic/armcm_boot.h" // armcm_enable_irq
+#include "generic/serial_irq.h" // serial_rx_byte
#include "internal.h" // enable_pclock
#include "sched.h" // DECL_INIT
-#include <string.h>
-#include "can.h"
-#include <fasthash.h>
-#if (CONFIG_CAN_PINS_PA11_PA12)
-DECL_CONSTANT_STR("RESERVE_PINS_CAN", "PA11,PA12");
-#define GPIO_Rx GPIO('A', 11)
-#define GPIO_Tx GPIO('A', 12)
+#if CONFIG_CAN_PINS_PA11_PA12
+ DECL_CONSTANT_STR("RESERVE_PINS_CAN", "PA11,PA12");
+ #define GPIO_Rx GPIO('A', 11)
+ #define GPIO_Tx GPIO('A', 12)
#endif
-#if (CONFIG_CAN_PINS_PB8_PB9)
-DECL_CONSTANT_STR("RESERVE_PINS_CAN", "PB8,PB9");
-#define GPIO_Rx GPIO('B', 8)
-#define GPIO_Tx GPIO('B', 9)
+#if CONFIG_CAN_PINS_PB8_PB9
+ DECL_CONSTANT_STR("RESERVE_PINS_CAN", "PB8,PB9");
+ #define GPIO_Rx GPIO('B', 8)
+ #define GPIO_Tx GPIO('B', 9)
#endif
-#if (CONFIG_CAN_PINS_PI8_PH13)
-DECL_CONSTANT_STR("RESERVE_PINS_CAN", "PI8,PH13");
-#define GPIO_Rx GPIO('I', 8)
-#define GPIO_Tx GPIO('H', 13)
+#if CONFIG_CAN_PINS_PI8_PH13
+ DECL_CONSTANT_STR("RESERVE_PINS_CAN", "PI8,PH13");
+ #define GPIO_Rx GPIO('I', 8)
+ #define GPIO_Tx GPIO('H', 13)
#endif
-#if (CONFIG_CAN_PINS_PB5_PB6)
-DECL_CONSTANT_STR("RESERVE_PINS_CAN", "PB5,PB6");
-#define GPIO_Rx GPIO('B', 5)
-#define GPIO_Tx GPIO('B', 6)
+#if CONFIG_CAN_PINS_PB5_PB6
+ DECL_CONSTANT_STR("RESERVE_PINS_CAN", "PB5,PB6");
+ #define GPIO_Rx GPIO('B', 5)
+ #define GPIO_Tx GPIO('B', 6)
#endif
-#if (CONFIG_CAN_PINS_PB12_PB13)
-DECL_CONSTANT_STR("RESERVE_PINS_CAN", "PB12,PB13");
-#define GPIO_Rx GPIO('B', 12)
-#define GPIO_Tx GPIO('B', 13)
+#if CONFIG_CAN_PINS_PB12_PB13
+ DECL_CONSTANT_STR("RESERVE_PINS_CAN", "PB12,PB13");
+ #define GPIO_Rx GPIO('B', 12)
+ #define GPIO_Tx GPIO('B', 13)
#endif
-#if (CONFIG_MACH_STM32F0)
-#define SOC_CAN CAN
-#define CAN_RX0_IRQn CEC_CAN_IRQn
-#define CAN_RX1_IRQn CEC_CAN_IRQn
-#define CAN_TX_IRQn CEC_CAN_IRQn
-#define CAN_SCE_IRQn CEC_CAN_IRQn
-#define CAN_FUNCTION GPIO_FUNCTION(4) // Alternative function mapping number
+#if CONFIG_MACH_STM32F0
+ #define SOC_CAN CAN
+ #define CAN_RX0_IRQn CEC_CAN_IRQn
+ #define CAN_RX1_IRQn CEC_CAN_IRQn
+ #define CAN_TX_IRQn CEC_CAN_IRQn
+ #define CAN_SCE_IRQn CEC_CAN_IRQn
+ #define CAN_FUNCTION GPIO_FUNCTION(4) // Alternative function mapping number
#endif
-#if (CONFIG_MACH_STM32F1)
-#define SOC_CAN CAN1
-#define CAN_RX0_IRQn CAN1_RX0_IRQn
-#define CAN_RX1_IRQn CAN1_RX1_IRQn
-#define CAN_TX_IRQn CAN1_TX_IRQn
-#define CAN_SCE_IRQn CAN1_SCE_IRQn
-#define CAN_FUNCTION GPIO_FUNCTION(9) // Alternative function mapping number
+#if CONFIG_MACH_STM32F1
+ #define SOC_CAN CAN1
+ #define CAN_RX0_IRQn CAN1_RX0_IRQn
+ #define CAN_RX1_IRQn CAN1_RX1_IRQn
+ #define CAN_TX_IRQn CAN1_TX_IRQn
+ #define CAN_SCE_IRQn CAN1_SCE_IRQn
+ #define CAN_FUNCTION GPIO_FUNCTION(9) // Alternative function mapping number
#endif
+#if CONFIG_MACH_STM32F4
+ #warning CAN on STM32F4 is untested
+ #if (CONFIG_CAN_PINS_PA11_PA12 || CONFIG_CAN_PINS_PB8_PB9 \
+ || CONFIG_CAN_PINS_PI8_PH13)
+ #define SOC_CAN CAN1
+ #define CAN_RX0_IRQn CAN1_RX0_IRQn
+ #define CAN_RX1_IRQn CAN1_RX1_IRQn
+ #define CAN_TX_IRQn CAN1_TX_IRQn
+ #define CAN_SCE_IRQn CAN1_SCE_IRQn
+ #elif CONFIG_CAN_PINS_PB5_PB6 || CONFIG_CAN_PINS_PB12_PB13
+ #define SOC_CAN CAN2
+ #define CAN_RX0_IRQn CAN2_RX0_IRQn
+ #define CAN_RX1_IRQn CAN2_RX1_IRQn
+ #define CAN_TX_IRQn CAN2_TX_IRQn
+ #define CAN_SCE_IRQn CAN2_SCE_IRQn
+ #else
+ #error Uknown pins for STMF32F4 CAN
+ #endif
-#if (CONFIG_MACH_STM32F4)
-#warning CAN on STM32F4 is untested
-#if (CONFIG_CAN_PINS_PA11_PA12 || \
- CONFIG_CAN_PINS_PB8_PB9 || \
- CONFIG_CAN_PINS_PI8_PH13)
-#define SOC_CAN CAN1
-#define CAN_RX0_IRQn CAN1_RX0_IRQn
-#define CAN_RX1_IRQn CAN1_RX1_IRQn
-#define CAN_TX_IRQn CAN1_TX_IRQn
-#define CAN_SCE_IRQn CAN1_SCE_IRQn
-#elif ((CONFIG_CAN_PINS_PB5_PB6 || CONFIG_CAN_PINS_PB12_PB13)
-#define SOC_CAN CAN2
-#define CAN_RX0_IRQn CAN2_RX0_IRQn
-#define CAN_RX1_IRQn CAN2_RX1_IRQn
-#define CAN_TX_IRQn CAN2_TX_IRQn
-#define CAN_SCE_IRQn CAN2_SCE_IRQn
-#else
-#error Uknown pins for STMF32F4 CAN
+ #define CAN_FUNCTION GPIO_FUNCTION(9) // Alternative function mapping number
#endif
-#define CAN_FUNCTION GPIO_FUNCTION(9) // Alternative function mapping number
-#endif
-
-
#ifndef SOC_CAN
-#error No known CAN device for configured MCU
+ #error No known CAN device for configured MCU
#endif
-
// TXFP makes packets posted to the TX mboxes transmit in chronologcal order
// ABOM makes the hardware automatically leave bus-off state
#define MCR_FLAGS (CAN_MCR_TXFP | CAN_MCR_ABOM)
@@ -99,17 +93,23 @@ DECL_CONSTANT_STR("RESERVE_PINS_CAN", "PB12,PB13");
static uint16_t MyCanId = 0;
-static int can_find_empty_tx_mbox(void) {
+static int
+can_find_empty_tx_mbox(void)
+{
uint32_t tsr = SOC_CAN->TSR;
- if(tsr & CAN_TSR_TME0) return 0;
- if(tsr & CAN_TSR_TME1) return 1;
- if(tsr & CAN_TSR_TME2) return 2;
+ if (tsr & CAN_TSR_TME0)
+ return 0;
+ if (tsr & CAN_TSR_TME1)
+ return 1;
+ if (tsr & CAN_TSR_TME2)
+ return 2;
return -1;
}
-static void can_transmit_mbox(uint32_t id, int mbox, uint32_t dlc, uint8_t *pkt)
+static void
+can_transmit_mbox(uint32_t id, int mbox, uint32_t dlc, uint8_t *pkt)
{
- CAN_TxMailBox_TypeDef *mb = &SOC_CAN->sTxMailBox[mbox];
+ CAN_TxMailBox_TypeDef *mb = &SOC_CAN->sTxMailBox[mbox];
/* Set up the Id */
mb->TIR &= CAN_TI0R_TXRQ;
mb->TIR |= (id << CAN_TI0R_STID_Pos);
@@ -119,51 +119,54 @@ static void can_transmit_mbox(uint32_t id, int mbox, uint32_t dlc, uint8_t *pkt)
mb->TDTR |= (dlc & 0xFU);
/* Set up the data field */
- if(pkt) {
- mb->TDLR = ((uint32_t)pkt[3] << 24) |
- ((uint32_t)pkt[2] << 16) |
- ((uint32_t)pkt[1] << 8) |
- ((uint32_t)pkt[0] << 0);
- mb->TDHR = ((uint32_t)pkt[7] << 24) |
- ((uint32_t)pkt[6] << 16) |
- ((uint32_t)pkt[5] << 8) |
- ((uint32_t)pkt[4] << 0);
+ if (pkt) {
+ mb->TDLR = (((uint32_t)pkt[3] << 24)
+ | ((uint32_t)pkt[2] << 16)
+ | ((uint32_t)pkt[1] << 8)
+ | ((uint32_t)pkt[0] << 0));
+ mb->TDHR = (((uint32_t)pkt[7] << 24)
+ | ((uint32_t)pkt[6] << 16)
+ | ((uint32_t)pkt[5] << 8)
+ | ((uint32_t)pkt[4] << 0));
}
- /* Request transmission */
+ /* Request transmission */
__sync_synchronize(); // disable write optimization
mb->TIR |= CAN_TI0R_TXRQ;
-
}
// Blocking transmit function, it can race with the IRQ driven TX handler.
// This should(tm) not happen
-static void can_transmit(uint32_t id, uint32_t dlc, uint8_t *pkt)
+static void
+can_transmit(uint32_t id, uint32_t dlc, uint8_t *pkt)
{
int mbox = -1;
do {
- mbox = can_find_empty_tx_mbox();
- } while(mbox < 0);
+ mbox = can_find_empty_tx_mbox();
+ } while (mbox < 0);
can_transmit_mbox(id, mbox, dlc, pkt);
}
// Convert Unique 96-bit value into 48 bit representation
-static void pack_uuid(uint8_t* u)
+static void
+pack_uuid(uint8_t *u)
{
uint64_t hash = fasthash64((uint8_t*)UID_BASE, 12, 0xA16231A7);
memcpy(u, &hash, SHORT_UUID_LEN);
}
-static void can_uuid_resp(void)
+static void
+can_uuid_resp(void)
{
uint8_t short_uuid[SHORT_UUID_LEN];
pack_uuid(short_uuid);
can_transmit(PKT_ID_UUID_RESP, SHORT_UUID_LEN, short_uuid);
}
-static void get_rx_data(uint8_t* buf, unsigned int mbox)
+static void
+get_rx_data(uint8_t *buf, unsigned int mbox)
{
uint32_t rdlr = SOC_CAN->sFIFOMailBox[mbox].RDLR;
buf[0] = (rdlr >> 0) & 0xff;
@@ -178,42 +181,44 @@ static void get_rx_data(uint8_t* buf, unsigned int mbox)
}
// Return true if more data is available to send or mailboxes are full
-int CAN_TxIrq(void) {
+static int
+CAN_TxIrq(void)
+{
int txdata = 1;
// TODO: We need some kind of error handling?
- while(txdata) {
+ while (txdata) {
int mbox = can_find_empty_tx_mbox();
- if(mbox < 0) {
+ if (mbox < 0) {
// All mboxes full, wait for next IRQ
return 1;
}
- int i=0;
+ int i;
uint8_t databuf[8];
- for (;i<8;i++)
- {
- if(serial_get_tx_byte(&(databuf[i])) == -1) {
+ for (i=0; i<8; i++) {
+ if (serial_get_tx_byte(&(databuf[i])) == -1) {
txdata = 0;
break;
}
}
- if (i>0) {
+ if (i > 0) {
can_transmit_mbox(MyCanId+1, mbox, i, databuf);
}
}
return txdata;
}
-void CAN_RxCpltCallback(unsigned int mbox)
+static void
+CAN_RxCpltCallback(unsigned int mbox)
{
- CAN_FIFOMailBox_TypeDef* mb = &SOC_CAN->sFIFOMailBox[mbox];
+ CAN_FIFOMailBox_TypeDef *mb = &SOC_CAN->sFIFOMailBox[mbox];
uint32_t id = (mb->RIR >> CAN_RI0R_STID_Pos) & 0x7FF;
uint8_t dlc = mb->RDTR & CAN_RDT0R_DLC;
uint8_t databuf[8];
- if(!MyCanId) { // If serial not assigned yet
- if(id==PKT_ID_UUID && dlc == 0) {
+ if (!MyCanId) { // If serial not assigned yet
+ if (id==PKT_ID_UUID && dlc == 0) {
// Just inform host about my UUID
can_uuid_resp();
} else if (id == PKT_ID_SET) {
@@ -239,24 +244,21 @@ void CAN_RxCpltCallback(unsigned int mbox)
SOC_CAN->FMR &= ~(CAN_FMR_FINIT);
}
}
- } else {
+ } else {
if (id == MyCanId) {
// compare my UUID with packet to check if this packet mine
- if(dlc == 0) {
+ if (dlc == 0) {
// empty packet == ping request
can_transmit(MyCanId+1, 0, NULL);
} else {
get_rx_data(databuf, mbox);
- for(int i=0; i < dlc; i++ ) {
+ for (int i=0; i < dlc; i++) {
serial_rx_byte(databuf[i]);
}
}
- }
- else if (id == PKT_ID_UUID && dlc > 0)
- {
+ } else if (id == PKT_ID_UUID && dlc > 0) {
get_rx_data(databuf, mbox);
- if (memcmp(databuf, &MyCanId, 2) == 0)
- {
+ if (memcmp(databuf, &MyCanId, 2) == 0) {
// Reset from host
NVIC_SystemReset();
}
@@ -264,45 +266,41 @@ void CAN_RxCpltCallback(unsigned int mbox)
}
}
-/**
- * @brief This function handles CAN global interrupts
- */
+// This function handles CAN global interrupts
void
CAN_IRQHandler(void)
{
// RX
if (SOC_CAN->RF0R & CAN_RF0R_FMP0) {
// Mailbox 0
- while(SOC_CAN->RF0R & CAN_RF0R_FMP0) {
+ while (SOC_CAN->RF0R & CAN_RF0R_FMP0) {
CAN_RxCpltCallback(0);
SOC_CAN->RF0R |= CAN_RF0R_RFOM0;
}
}
if (SOC_CAN->RF1R & CAN_RF1R_FMP1) {
// Mailbox 1
- while(SOC_CAN->RF1R & CAN_RF1R_FMP1) {
+ while (SOC_CAN->RF1R & CAN_RF1R_FMP1) {
CAN_RxCpltCallback(1);
SOC_CAN->RF1R |= CAN_RF1R_RFOM1;
}
}
/* Check Overrun flag for FIFO0 */
- if(SOC_CAN->RF0R & CAN_RF0R_FOVR0)
- {
+ if (SOC_CAN->RF0R & CAN_RF0R_FOVR0) {
/* Clear FIFO0 Overrun Flag */
SOC_CAN->RF0R |= CAN_RF0R_FOVR0;
}
/* Check Overrun flag for FIFO1 */
- if(SOC_CAN->RF1R & CAN_RF1R_FOVR1)
- {
+ if (SOC_CAN->RF1R & CAN_RF1R_FOVR1) {
/* Clear FIFO1 Overrun Flag */
SOC_CAN->RF1R |= CAN_RF1R_FOVR1;
}
// TX
- if(SOC_CAN->IER & CAN_IER_TMEIE) { // TX IRQ enabled
- if(!CAN_TxIrq())
- SOC_CAN->IER &= ~CAN_IER_TMEIE; // Disable TXIRQ
+ if (SOC_CAN->IER & CAN_IER_TMEIE) { // TX IRQ enabled
+ if (!CAN_TxIrq())
+ SOC_CAN->IER &= ~CAN_IER_TMEIE; // Disable TXIRQ
}
}
@@ -312,17 +310,15 @@ make_btr(uint32_t sjw, // Sync jump width, ... hmm
uint32_t time_seg2, // time segment after sample point, 1 .. 8
uint32_t brp) // Baud rate prescaler, 1 .. 1024
{
- return
- ((uint32_t)(sjw-1)) << CAN_BTR_SJW_Pos
- | ((uint32_t)(time_seg1-1)) << CAN_BTR_TS1_Pos
- | ((uint32_t)(time_seg2-1)) << CAN_BTR_TS2_Pos
- | ((uint32_t)(brp - 1)) << CAN_BTR_BRP_Pos;
+ return (((uint32_t)(sjw-1)) << CAN_BTR_SJW_Pos
+ | ((uint32_t)(time_seg1-1)) << CAN_BTR_TS1_Pos
+ | ((uint32_t)(time_seg2-1)) << CAN_BTR_TS2_Pos
+ | ((uint32_t)(brp - 1)) << CAN_BTR_BRP_Pos);
}
-
static inline const uint32_t
-compute_btr(uint32_t pclock, uint32_t bitrate) {
-
+compute_btr(uint32_t pclock, uint32_t bitrate)
+{
/*
Some equations:
Tpclock = 1 / pclock
@@ -343,10 +339,10 @@ compute_btr(uint32_t pclock, uint32_t bitrate) {
uint32_t sjw = 2;
uint32_t qs;
// Find number of time quantas that gives us the exact wanted bit time
- for(qs = 18; qs > 9; qs --) {
+ for (qs = 18; qs > 9; qs--) {
// check that bit_clocks / quantas is an integer
uint32_t brp_rem = bit_clocks % qs;
- if(brp_rem == 0)
+ if (brp_rem == 0)
break;
}
uint32_t brp = bit_clocks / qs;
@@ -375,7 +371,8 @@ can_init(void)
/* Request initialisation */
SOC_CAN->MCR |= CAN_MCR_INRQ;
/* Wait the acknowledge */
- while( !(SOC_CAN->MSR & CAN_MSR_INAK) );
+ while (!(SOC_CAN->MSR & CAN_MSR_INAK))
+ ;
SOC_CAN->MCR |= MCR_FLAGS;
SOC_CAN->BTR = btr;
@@ -383,7 +380,8 @@ can_init(void)
/* Request leave initialisation */
SOC_CAN->MCR &= ~(CAN_MCR_INRQ);
/* Wait the acknowledge */
- while( SOC_CAN->MSR & CAN_MSR_INAK );
+ while (SOC_CAN->MSR & CAN_MSR_INAK)
+ ;
/*##-2- Configure the CAN Filter #######################################*/
uint32_t filternbrbitpos = (1U) << CAN_FILTER_NUMBER;
@@ -398,7 +396,7 @@ can_init(void)
SOC_CAN->sFilterRegister[CAN_FILTER_NUMBER].FR2 =
((uint32_t)(PKT_ID_SET<<5) << 16U);
- /*Identifier list mode for the filter*/
+ /* Identifier list mode for the filter */
SOC_CAN->FM1R |= filternbrbitpos;
/* 32-bit scale for the filter */
SOC_CAN->FS1R |= filternbrbitpos;
@@ -416,13 +414,12 @@ can_init(void)
SOC_CAN->IER |= (CAN_IER_FMPIE0 | CAN_IER_FMPIE1); // RX mailbox IRQ
armcm_enable_irq(CAN_IRQHandler, CAN_RX0_IRQn, 0);
- if(CAN_RX0_IRQn != CAN_RX1_IRQn)
- armcm_enable_irq(CAN_IRQHandler, CAN_RX1_IRQn, 0);
- if(CAN_RX0_IRQn != CAN_TX_IRQn)
- armcm_enable_irq(CAN_IRQHandler, CAN_TX_IRQn, 0);
+ if (CAN_RX0_IRQn != CAN_RX1_IRQn)
+ armcm_enable_irq(CAN_IRQHandler, CAN_RX1_IRQn, 0);
+ if (CAN_RX0_IRQn != CAN_TX_IRQn)
+ armcm_enable_irq(CAN_IRQHandler, CAN_TX_IRQn, 0);
// TODO: CAN_SCE_IRQ?n
-
/*##-4- Say Hello #################################*/
can_uuid_resp();
}
@@ -431,7 +428,7 @@ DECL_INIT(can_init);
void
serial_enable_tx_irq(void)
{
- if(MyCanId == 0)
+ if (MyCanId == 0)
// Serial port not initialized
return;