La transmisión MSCAN Kinetis E06 no se inicia

0

Estoy intentando usar el controlador CAN en Kinetis E06 (FRDM-KE06Z). He basado mi código en "FRDM-KEXX Driver Library Package". Para empezar, trato de enviar (y luego recibir) un marco en modo loopback.

Este es mi código de inicialización ( obd_can_init se llama solo una vez en el inicio, FreeRTOS no tiene nada que ver con esto ya que solo se está ejecutando una tarea):

#include "obd_can.h"
#include <FreeRTOS/include/FreeRTOS.h>
#include <FreeRTOS/include/task.h>
#include <MKE06Z4.h>
#include <string.h>

#if DEFAULT_BUS_CLOCK == 20000000
//Values were calculated using the spreadsheet in dev_documentation directory
#define CANBTR0_500KBAUD 0xC3
#define CANBTR1_500KBAUD 0x34
#define CANBTR0_250KBAUD 0xC7
#define CANBTR1_250KBAUD 0x34
#else
#error "CAN baud registers not defined for this bus clock!"
#endif

#define DEBUG_TERMINAL 0
#include <debug.h>

static void obd_can_transmit(uint32_t identifier, const uint8_t *payload, uint8_t payload_length);

void obd_can_init(void){
    portENTER_CRITICAL();
    SIM->SCGC |= SIM_SCGC_MSCAN_MASK;

#ifndef BOARD_EVK //EVK uses CAN_TX PTC7 and CAN_RX PTC6, which is the default setting
    SIM->PINSEL1 |= SIM_PINSEL1_MSCANPS_MASK; //CAN_TX PTE7, CAN_RX PTH2
#endif
    portEXIT_CRITICAL();

    MSCAN->CANCTL1 = MSCAN_CANCTL1_CANE_MASK /*enable CAN module*/
            | MSCAN_CANCTL1_CLKSRC_MASK /*use bus clock*/;

    MSCAN->CANCTL0 |= MSCAN_CANCTL0_INITRQ_MASK; //enter controller initialization mode
    while (!(MSCAN->CANCTL1 & MSCAN_CANCTL1_INITAK_MASK)){
        //wait for the controller to enter initialization mode
        vTaskDelay(2);
    }

    //set baud
    MSCAN->CANBTR0 = CANBTR0_500KBAUD;
    MSCAN->CANBTR1 = CANBTR1_500KBAUD;

    MSCAN->CANCTL1 |= MSCAN_CANCTL1_LOOPB_MASK; //enable loopback for testing

    MSCAN->CANRIER = MSCAN_CANRIER_RXFIE_MASK; //enable RX interrupt

    //RX filter
    MSCAN->CANIDAR_BANK_1[0] = 0;
    MSCAN->CANIDAR_BANK_1[1] = 0;
    MSCAN->CANIDAR_BANK_1[2] = 0;
    MSCAN->CANIDAR_BANK_1[3] = 0;
    //RX filter mask - accept all identifiers
    MSCAN->CANIDMR_BANK_1[0] = 0xFF;
    MSCAN->CANIDMR_BANK_1[1] = 0xFF;
    MSCAN->CANIDMR_BANK_1[2] = 0xFF;
    MSCAN->CANIDMR_BANK_1[3] = 0xFF;

    MSCAN->CANIDAC = MSCAN_CANIDAC_IDAM(0); //use two 32-bit acceptance filters

    MSCAN->CANTIER = MSCAN_CANTIER_TXEIE_MASK; //enable TX interrupt
    NVIC_SetPriority(MSCAN_RX_IRQn, 5);
    NVIC_EnableIRQ(MSCAN_RX_IRQn);
    NVIC_SetPriority(MSCAN_TX_IRQn, 5);
    NVIC_EnableIRQ(MSCAN_TX_IRQn);

    MSCAN->CANCTL0 &= ~MSCAN_CANCTL0_INITRQ_MASK; //exit initialization mode

    while (MSCAN->CANCTL1 & MSCAN_CANCTL1_INITAK_MASK){
        //wait for the controller to exit initialization mode
        vTaskDelay(2);
    }

    debugf("OBD CAN initialized");

    uint8_t data[] = {1,2,3,4};
    obd_can_transmit(10, data, sizeof(data));
    obd_can_transmit(10, data, sizeof(data));
    obd_can_transmit(10, data, sizeof(data));
}

Este es mi código de transmisión:

static void obd_can_transmit(uint32_t identifier, const uint8_t *payload, uint8_t payload_length){
    uint8_t empty_buffer_index = MSCAN->CANTFLG & MSCAN_CANTFLG_TXE_MASK;
    if (!(empty_buffer_index)){
        debugf("TX busy, dropping frame");
        return;
    }
    debugf("Using buffer %d", empty_buffer_index);
    //select transmit buffer
    MSCAN->CANTBSEL = MSCAN_CANTBSEL_TX(empty_buffer_index);

    uint32_t* identifier_ptr = (uint32_t*)&MSCAN->TEIDR0; //assumes little endianness
    *identifier_ptr = identifier;

    memcpy((uint8_t*)&MSCAN->TEIDR0, payload, payload_length); //copy payload

    MSCAN->TDLR = payload_length;
    MSCAN->TBPR = 0; //priority of this buffer

    //enable transmission of this buffer
    MSCAN->CANTFLG = MSCAN->CANTBSEL & MSCAN_CANTBSEL_TX_MASK;
}

Mi terminal muestra:

9:obd_init: OBD initialization
74:obd_can_init: OBD CAN initialized
88:obd_can_transmit: Using buffer 7
88:obd_can_transmit: Using buffer 6
88:obd_can_transmit: Using buffer 4

Por lo tanto, parece que la transmisión nunca se inicia y el envío de llamadas solo coloca datos en los búferes posteriores. ¿Qué estoy haciendo mal que no active la transmisión?

    
pregunta filo

1 respuesta

0

El problema fue que algunos de los registros MSCAN se pueden escribir solo en el modo de inicialización, algunos solo fuera del modo de inicialización y otros en ambos modos.

TX & Los registros de activación de interrupción de RX (CANTIER, CANRIER) se tuvieron que escribir después de salir del modo de inicialización y todo funcionó bien después.

    
respondido por el filo

Lea otras preguntas en las etiquetas