Author Topic: SAMC / Bosch TTCAN controller  (Read 660 times)

0 Members and 1 Guest are viewing this topic.

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17817
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
SAMC / Bosch TTCAN controller
« on: February 12, 2024, 05:06:30 pm »
I have this very weird situation where I have CAN0 set up to send and receive 1 extended message and CAN1 to receive 1 standard message and send several. As soon as I enable an Rx filter the transmissions just stop, I think when the same amount of messages have been sent as there is space in the rx buffer. The transmission of a message triggers a response of 4 messages of which one is being filtered.

The code for the two channels is the same baring CAN0 replaced with CAN1

On pausing the device I find it in the void interrupt:

void Dummy_Handler(void)
{
        while (1) {
        }
}
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11262
  • Country: us
    • Personal site
Re: SAMC / Bosch TTCAN controller
« Reply #1 on: February 12, 2024, 05:17:40 pm »
This is just a generic interrupt/fault handler. Look in the IPSR register and check the index of the interrupt that caused that handler.

It is likely to be 3 for the Hard Fault or some value greater than 15  for the interrupts index.

If it is 3, then you will have to debug what causes that fault.
Alex
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17817
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: SAMC / Bosch TTCAN controller
« Reply #2 on: February 12, 2024, 05:56:10 pm »
It's very odd code is pretty much this. I guess I should have created one big structure for each and then arrayed them but more haste = less speed and duplicate code.

RAM buffers:
Code: [Select]
void *can_0_rx_variable_index[CAN_0_STD_MESSAGE_FILTER_NUM + CAN_0_EXD_MESSAGE_FILTER_NUM]  ;
void *can_1_rx_variable_index[CAN_1_STD_MESSAGE_FILTER_NUM + CAN_1_EXD_MESSAGE_FILTER_NUM]  ;

/********************************* RAM variables - buffers, FIFO's and filter elements ************************************/

CanMramXifde             can_0_rx_exd_filter[CAN_0_EXD_MESSAGE_FILTER_NUM] ; // extended id filter elements
can_std_filter_element_t can_0_rx_std_filter[CAN_0_STD_MESSAGE_FILTER_NUM] ; // standard id filter elements
can_fifo_t               can_0_rx_buffer[CAN_0_RX_FIFO_0_NUM]              ; // receive buffer
can_tx_data_t            can_0_tx_buffer[CAN_0_TX_FIFO_NUM]                ; // transmit buffer


CanMramXifde             can_1_rx_exd_filter[CAN_1_EXD_MESSAGE_FILTER_NUM] ; // extended id filter elements
can_std_filter_element_t can_1_rx_std_filter[CAN_1_STD_MESSAGE_FILTER_NUM] ; // standard id filter elements
can_fifo_t               can_1_rx_buffer[CAN_1_RX_FIFO_0_NUM]              ; // receive buffer
can_tx_data_t            can_1_tx_buffer[CAN_1_TX_FIFO_NUM]                ; // transmit buffer

setup:
Code: [Select]
void can_init(Can * instance )
{
uint8_t n = ret_can_port_n(instance) ;

connect_peripheral_to_clock((per_clock_channel_CAN0 + n), F_48MHz) ; // connect clock to CPU clock, bridge connection made in clock setup

instance->CCCR.bit.INIT = 1 ; // put the can peripheral into initialization mode
instance->CCCR.bit.CCE  = 1 ; // enable writing of registers while in initialization mode
instance->CCCR.bit.TXP  = 0 ; // Transmit pause enabled. The CAN pauses for two CAN bit times before starting the next transmission after itself has successfully transmitted a frame.
instance->CCCR.bit.DAR  = 0 ; // Automatic retransmission of messages not transmitted successfully disabled.

instance->NBTP.bit.NBRP = (can_clock[n] / (can_baudrate[n] * 16U) ) - 1 ; //prescaler to obtain the arbitration field quantization clock max 511, a 1 is added by the hardware preventing division by 0.....

instance->TSCC.bit.TCP = 0xF ; // time stamp counter prescaler, actual value is +1 as dividing by "0" is - "silly".
//instance->TSCC.bit.TSS = 0x1 ; // enable this internal time stamp counter use system time counter instead

// Global filter configuration
instance->GFC.reg = 0x2 << 4   // Accept Non-matching Frames Standard: 0 = into FIFO 0, 1 = into FIFO 1, 2 or 3 reject
  | 0x2 << 2   // Accept Non-matching Frames Extended: 0 = into FIFO 0, 1 = into FIFO 1, 2 or 3 reject
  | 0x1 << 1   // Reject Remote Frames Standard      : 0 = filter as normal, 1 = reject
  | 0x1 << 0 ; // Reject Remote Frames Extended      : 0 = filter as normal, 1 = reject
 
instance->MRCFG.bit.QOS = 0x3 ;

if (n == 0U)
{
// transmit FIFO0 settings
instance->TXBC.reg = (0xFFFF & ( (uint32_t) can_0_tx_buffer)) | CAN_TXBC_NDTB(CAN_0_TX_BUFFER_NUM) | CAN_TXBC_TFQS(CAN_0_TX_FIFO_NUM) ; // TFQM left out as left at "0"

// receive FIFO0 settings
instance->RXF0C.reg = CAN_RXF0C_F0SA( (uint32_t) (can_0_rx_buffer)) | CAN_RXF0C_F0S(CAN_0_RX_FIFO_0_NUM) ;

// rx standard filter settings
if (CAN_0_STD_MESSAGE_FILTER_NUM)
{
instance->SIDFC.reg = CAN_SIDFC_FLSSA( (uint32_t) can_0_rx_std_filter ) | CAN_SIDFC_LSS(CAN_0_STD_MESSAGE_FILTER_NUM) ;
}

// rx extended filter settings
if (CAN_0_EXD_MESSAGE_FILTER_NUM)
{
instance->XIDFC.reg = CAN_0_EXD_MESSAGE_FILTER_NUM << 16 | ( ( (uint32_t) can_0_rx_exd_filter ) & 0xFFFFUL ) ;
}

interrupt_enable(NVIC_INT_CAN0_CH) ;
}

if (n == 1U)
{

// transmit FIFO0 settings
instance->TXBC.reg = (0xFFFF & ( (uint32_t) can_1_tx_buffer)) | CAN_TXBC_NDTB(CAN_1_TX_BUFFER_NUM) | CAN_TXBC_TFQS(CAN_1_TX_FIFO_NUM) ; // TFQM left out as left at "0"

// receive FIFO0 settings
instance->RXF0C.reg = CAN_RXF0C_F0SA( (uint32_t) (can_1_rx_buffer)) | CAN_RXF0C_F0S(CAN_1_RX_FIFO_0_NUM) ;

// rx standard filter settings
if (CAN_1_STD_MESSAGE_FILTER_NUM)
{

instance->SIDFC.reg = CAN_1_STD_MESSAGE_FILTER_NUM << 16 | ( ( (uint32_t) can_1_rx_std_filter ) & 0xFFFFUL ) ;
}

if (CAN_1_EXD_MESSAGE_FILTER_NUM)
{
instance->XIDFC.reg = CAN_1_EXD_MESSAGE_FILTER_NUM << 16 | ( ( (uint32_t) can_1_rx_exd_filter ) & 0xFFFFUL ) ;
}

interrupt_enable(NVIC_INT_CAN1_CH) ;
}

// interrupts enable
instance->IE.bit.RF0NE = 0x1 ; // message received interrupt
instance->ILE.reg = 0x1 ; // enable interrupt line 0

instance->CCCR.bit.INIT = 0 ; // conclude can configuration
}

RX handlers
Code: [Select]
void CAN0_Handler_rx_by_id()
{

if (CAN0->IR.bit.RF0N)
{
static can_rx_data_t sorting_buffer ;

static uint8_t n ;

n = CAN0->RXF0S.bit.F0GI ; // make n the get index

CAN0->IR.reg = 0x1 << 0 ; // reset  RF0N Rx FIFO 0 New Message

sorting_buffer.time_stamp = ret_rtc_us() ;

// copy data bytes only from RX fifo into holding variable that has the same layout as can_rx_data_t data types.
memcpy(&sorting_buffer , &can_0_rx_buffer[n].CAN_BUFFER_DATA , 8) ;

uint8_t exd_id_bit = can_0_rx_buffer[n].XTD ; // check for extended frame

CAN0->RXF0A.bit.F0AI = n ; // acknowledge data read so that get index increases

// memcpy from the sorting buffer variable to the destination variable.
if (exd_id_bit)
{
sorting_buffer.id = can_0_rx_buffer[n].ID   ; // use exd_id_bit as shifting enabler to shift the std id down
memcpy(can_0_rx_variable_index[ can_0_rx_buffer[n].FIDX + CAN_0_STD_MESSAGE_FILTER_NUM - 1 ] , &sorting_buffer , 32 ) ;
}
else
{
sorting_buffer.id = can_0_rx_buffer[n].ID >> 18 ;
memcpy(can_0_rx_variable_index[ can_0_rx_buffer[n].FIDX ] , &sorting_buffer , 32 ) ;
}

}
}



void CAN1_Handler_rx_by_id()
{
if (CAN1->IR.bit.RF0N)
{
static can_rx_data_t sorting_buffer ;

static uint8_t can1_get_index ;

can1_get_index = CAN1->RXF0S.bit.F0GI ; // make n the get index

CAN1->IR.reg = 0x1 << 0 ; // reset  RF0N Rx FIFO 0 New Message

sorting_buffer.time_stamp = ret_rtc_us() ;

// copy data bytes only from RX fifo into holding variable that has the same layout as can_rx_data_t data types.
memcpy(&sorting_buffer , &can_1_rx_buffer[can1_get_index].CAN_BUFFER_DATA , can_1_rx_buffer[can1_get_index].DLC) ;

uint8_t exd_id_bit = can_1_rx_buffer[can1_get_index].XTD ; // check for extended frame

CAN1->RXF0A.bit.F0AI = can1_get_index ; // acknowledge data read so that get index increases

// memcpy from the sorting buffer variable to the destination variable.

if (exd_id_bit)
{
sorting_buffer.id = can_1_rx_buffer[can1_get_index].ID ;
memcpy(can_1_rx_variable_index[ can_1_rx_buffer[can1_get_index].FIDX + CAN_1_STD_MESSAGE_FILTER_NUM - 1 ] , &sorting_buffer , 32 ) ;
}
else
{
sorting_buffer.id = can_1_rx_buffer[can1_get_index].ID >> 18  ; // use exd_id_bit as shifting enabler to shift the std id down
memcpy(can_1_rx_variable_index[ can_1_rx_buffer[can1_get_index].FIDX ] , &sorting_buffer , 32 ) ;
}
}
}
[code]

RX filters setup
[code]
void can_std_filter_setup(Can * instance , uint16_t id , uint8_t filter_element_n , void * variable )
{
uint8_t n = ret_can_port_n(instance) ;

if (n == 0)
{
can_0_rx_variable_index[filter_element_n] = variable ; // add the address of the allocated variable to the to the array that points to variables by ID/ filter element number

// see MTTCAN 2.4.5

can_0_rx_std_filter[filter_element_n].bit.SFEC = 0x1 ; // store in FIFO 0
can_0_rx_std_filter[filter_element_n].bit.SFID1 = id ; // message id
can_0_rx_std_filter[filter_element_n].bit.SFID2 = id ; // message id
can_0_rx_std_filter[filter_element_n].bit.SFT = 0x1 ;  // dual id filter
}

if (n == 1)
{
can_1_rx_variable_index[filter_element_n] = variable ; // add the address of the allocated variable to the to the array that points to variables by ID/ filter element number

// see MTTCAN 2.4.5

can_1_rx_std_filter[filter_element_n].bit.SFEC = 0x1 ; // store in FIFO 0
can_1_rx_std_filter[filter_element_n].bit.SFID1 = id ; // message id
can_1_rx_std_filter[filter_element_n].bit.SFID2 = id ; // message id
can_1_rx_std_filter[filter_element_n].bit.SFT = 0x1 ;  // dual id filter
}
}



void can_exd_filter_setup(Can * instance , uint32_t id , uint8_t filter_element_n , void * variable )
{
uint8_t n = ret_can_port_n(instance) ;

if (n == 0)
{
can_0_rx_variable_index[filter_element_n + CAN_0_STD_MESSAGE_FILTER_NUM - 1U] = variable ; // add the address of the allocated variable to the to the array that points to variables by ID/ filter element number

// see MTTCAN
can_0_rx_exd_filter[filter_element_n].XIDFE_0.bit.EFEC = 0x1 ;
can_0_rx_exd_filter[filter_element_n].XIDFE_0.bit.EFID1 = id ;
can_0_rx_exd_filter[filter_element_n].XIDFE_1.bit.EFT  = 0x1 ;
can_0_rx_exd_filter[filter_element_n].XIDFE_1.bit.EFID2 = id ;
}

if (n == 1)
{
can_1_rx_variable_index[filter_element_n + CAN_1_STD_MESSAGE_FILTER_NUM - 1U] = variable ; // add the address of the allocated variable to the to the array that points to variables by ID/ filter element number

// see MTTCAN
can_1_rx_exd_filter[filter_element_n].XIDFE_0.bit.EFEC = 0x1 ;
can_1_rx_exd_filter[filter_element_n].XIDFE_0.bit.EFID1 = id ;
can_1_rx_exd_filter[filter_element_n].XIDFE_1.bit.EFT  = 0x1 ;
can_1_rx_exd_filter[filter_element_n].XIDFE_1.bit.EFID2 = id ;
}
}
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17817
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: SAMC / Bosch TTCAN controller
« Reply #3 on: February 12, 2024, 05:57:39 pm »
The received data is always identical in the buffer so it is going where it should and is not being written to random places.
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11262
  • Country: us
    • Personal site
Re: SAMC / Bosch TTCAN controller
« Reply #4 on: February 12, 2024, 06:08:22 pm »
Again, check the IPSR value first.
Alex
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17817
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: SAMC / Bosch TTCAN controller
« Reply #5 on: February 12, 2024, 06:26:08 pm »
right, will do in the morning when I am back in.
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17817
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: SAMC / Bosch TTCAN controller
« Reply #6 on: February 13, 2024, 09:05:27 am »
Right, there is no IPSR register that i can find. there is a register called ICSR (https://developer.arm.com/documentation/107706/0100/Exceptions-and-interrupts-overview/SCB-registers-for-system-exception-management/Interrupt-Control-and-State-Register--SCB--ICSR-?lang=en) which seems to do the same. and yes the vectactive value is 3.

What I also note is that this problem is not simply due to reception on CAN1 being enabled. the system works fine if CAN0 has stopped receiving messages.

I'll try increasing the stack.
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17817
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: SAMC / Bosch TTCAN controller
« Reply #7 on: February 13, 2024, 09:18:51 am »
Stack increase from what I assume was 4kB to 8kB did nothing. So in the ICSR the vector pending is 15, this is CAN0, which backs up what I just noticed that basically one CAN bus channel receiving is fine but not two.
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17817
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: SAMC / Bosch TTCAN controller
« Reply #8 on: February 13, 2024, 09:59:39 am »
Well i have it working. I am receiving and filtering one message on CAN0 and filtering one only on CAN1 although 5 arrive. The solution was to move the filter element i was using on CAN0 for the extended frame from element 0 to 1, not sure what is wrong here. Will look further.
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17817
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: SAMC / Bosch TTCAN controller
« Reply #9 on: February 13, 2024, 10:15:09 am »
Sorted, I have an array of memory address pointers so that each filter element can point to it's associated variable, when I added the extended ID's to the existing standard ID code I decided to use one array still and to offset the extended anes by the standard ones, I then stupidly got confused about the index starting at 0 and subtracted 1 from the number of standard ID's when adding there to the index of the extended ID, this meant that when I used extended filter element 0 with 0 standard filter elements I used index -1 and wrote to some random location.
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11262
  • Country: us
    • Personal site
Re: SAMC / Bosch TTCAN controller
« Reply #10 on: February 13, 2024, 04:42:24 pm »
And the way you solve those issues on the spot is by looking at the stack at the time exception happens. The stack would contain the following values:r0, r1, r2, r3, r12, lr, pc, psr. You are interested in PC, which would be the address of the instruction that caused the fault or close to it. Then you can match it to the source code location and know immediately what part of the  C code is doing that.

In more rare case, LR is also useful. Sometimes when the fault is caused by a jump to an incorrect location, PC will be that incorrect location. But LR would contain the address after the last successful branch and link  instruction. And those are usually not too far away from the real fault place.
« Last Edit: February 13, 2024, 04:44:10 pm by ataradov »
Alex
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf