Page tree

Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Code Block
titleLibcanard initialization
CanardInstance g_canard;   					//The library instance
static uint8_t canard_memory_pool[1024]; 	//Arena for memory allocation, used by the library

static void sw_initswInit(void)
{
    int result = 0;
    CanardSTM32CANTimings timings;
    result = canardSTM32ComputeCANTimings(RCC_Clocks.PCLK1_Frequency, 1000000, &timings);
    if(result)
    {
        __ASM volatile("BKPT #01"); 
    }
    result = canardSTM32Init(&timings, CanardSTM32IfaceModeNormal);
    if(result)
    {
        __ASM volatile("BKPT #01"); 
    }
  
    canardInit(&g_canard,                           // Uninitialized library instance
               canard_memory_pool,                // Raw memory chunk used for dynamic allocation
               sizeof(canard_memory_pool),        // Size of the above, in bytes
               onTransferReceived,                // Callback, see CanardOnTransferReception
               shouldAcceptTransfer,              // Callback, see CanardShouldAcceptTransfer
               NULL); 
    
    canardSetLocalNodeID(&canard, 100);
}

...

Code Block
titlecanard_service
#define CANARD_SERVICESPIN_PERIOD    1000


void canard_service(void)
{
	static uint32_t service_time = 0;  
    if(get_uptime() < service_time + CANARD_SERVICESPIN_PERIOD) return; // to enter this function only once a period
    service_time = get_uptime();
    gpio_toggle(GPIOE, GPIO_Pin_8); //some indication 

    uint8_t buffer[UAVCAN_NODE_STATUS_MESSAGE_SIZE];
    uint8_t transfer_id = 0;

    makeNodeStatusMessage(buffer);

    canardBroadcast(&canard, 
                    UAVCAN_NODE_STATUS_DATA_TYPE_SIGNATURE,
	    			UAVCAN_NODE_STATUS_DATA_TYPE_ID,
        			&transfer_id,
        			CANARD_TRANSFER_PRIORITY_LOW,
	    			buffer, 
	    			UAVCAN_NODE_STATUS_MESSAGE_SIZE);
}

...

Code Block
titlemakeNodeStatusMessage

void makeNodeStatusMessage(uint8_t buffer[UAVCAN_NODE_STATUS_MESSAGE_SIZE])
{
	uint8_t node_health = UAVCAN_NODE_HEALTH_OK;
	uint8_t node_mode   = UAVCAN_NODE_MODE_OPERATIONAL;
 void makeNodeStatusMessage(uint8_t buffer[UAVCAN_NODE_STATUS_MESSAGE_SIZE]) {
    memset(buffer, 0, UAVCAN_NODE_STATUS_MESSAGE_SIZE);
    uint32_t uptime_sec = (get_uptime() / 1000);
    canardEncodeScalar(buffer,  0, 32, &uptime_sec);
    canardEncodeScalar(buffer, 32,  2, &node_health);
    canardEncodeScalar(buffer, 34,  3, &node_mode);
}

...

Code Block
titlecanard_get_node_info_handle
#define APP_VERSION_MAJOR   					99
#define APP_VERSION_MINOR   					99
#define APP_NODE_NAME   						"com.zubax.babel.demo"
#define GIT_HASH								0xBADC0FFE
#define UAVCAN_GET_NODE_INFO_RESPONSE_MAX_SIZE  ((3015 + 7) / 8)

uint16_t makeNodeInfoMessage(uint8_t buffer[UAVCAN_GET_NODE_INFO_RESPONSE_MAX_SIZE])
{
    memset(buffer, 0, UAVCAN_GET_NODE_INFO_RESPONSE_MAX_SIZE);
    makeNodeStatusMessage(buffer);

    buffer[7] = APP_VERSION_MAJOR;
    buffer[8] = APP_VERSION_MINOR;
    buffer[9] = 1;  // Optional field flags, VCS commit is set
    uint32_t u32 = GIT_HASH;
    canardEncodeScalar(buffer, 80, 32, &u32); 

    readUniqueID(&buffer[24]);
    const size_t name_len = strlen(APP_NODE_NAME);
    memcpy(&buffer[41], APP_NODE_NAME, name_len);
    return 41 + name_len ;
}

void canard_get_node_info_handlecanardGetNodeInfoHandle(CanardRxTransfer* transfer)
{
    uint8_t buffer[UAVCAN_GET_NODE_INFO_RESPONSE_MAX_SIZE];
    memset(buffer,0,UAVCAN_GET_NODE_INFO_RESPONSE_MAX_SIZE);
    uint16_t len = 0;
    len = makeNodeInfoMessage(buffer);
    int result = canardRequestOrRespond(&g_canard,
                                        transfer->source_node_id,
                                        UAVCAN_GET_NODE_INFO_DATA_TYPE_SIGNATURE,
                                        UAVCAN_GET_NODE_INFO_DATA_TYPE_ID,
                                        &transfer->transfer_id,
                                        transfer->priority,
                                        CanardResponse,
                                        &buffer[0],
                                        (uint16_t)len);
}

...

Code Block
titlemain
int main(void)
{ 
    /*!< At this stage the microcontrollers clock setting is already configured, 
       this is done through SystemInit() function which is called from startup
       file (startup_stm32f37x.s) before to branch to application main.
       To reconfigure the default setting of SystemInit() function, refer to
       system_stm32f37x.c file */
    RCC_GetClocksFreq(&RCC_Clocks); //To make sure RCC is initialised properly
    hw_inithwInit();
     sw_initswInit();  
    SysTick_Config(SystemCoreClock / 1000); //To make systick event happen every 1 mS
     while(1)
    {
        canard_sendcanardSend();
        canard_receivecanardReceive();
        canard_servicecanardSpin();
    }
}

The only interrupt used in the application is SysTick interrupt for uptime counter with 1 mS resolution.

Code Block
titlesystick_isr
void systick_isrsystickIsr(void);
void SysTick_Handleruint32_t getUptime(void)
{
    systick_isr();
}

static uint32_t  uptime = 0;
void
systickuint32_isrt getUptime(void)
{
    return uptime++;
}

uint32_t get_uptimevoid systickIsr(void)
{
    return uptime++;
}

As libcanard does not use any interrupts it is up to user when and how to receive and transmit UAVCAN messages. In this application we will constantly poll if any message was received by MCU CAN peripheral and process it. We will also poll if library has any new messages to transmit and manually extract them from the library and pass to CAN transmitter.

Code Block
titlecanard_sender
void canard_sendcanardSend(void)
{
    const CanardCANFrame* txf = canardPeekTxQueue(&g_canard); 
    while(txf)
    {
        const int tx_res = canardSTM32Transmit(txf);
        if (tx_res < 0)         // Failure - drop the frame and report
        {
            __ASM volatile("BKPT #01"); 
        }
        if(tx_res > 0)
        {
            canardPopTxQueue(&g_canard);
        }
        txf = canardPeekTxQueue(&g_canard); 
    }
}


Code Block
titlecanard_receive
void canard_receivecanardReceive(void)
{
    CanardCANFrame rx_frame;
    int res = canardSTM32Receive(&rx_frame);
    if(res)
    {
        canardHandleRxFrame(&canard, &rx_frame, get_uptime() * 1000);
    }    
}

...