CAN bus with FreeRTOS on SAMe54 Xplained Pro - gneidermeier/CANFDDemo_SAMe54_START GitHub Wiki
This guide covers a basic demonstration of the SAMe54 Xplained Pro eval board. This tutorial may also serve as a very superficial introduction to Atmel START web based graphical configuration tool.
Requirements:
- SAM E54 Xplained Pro eval board
- Micro USB cable (not supplied with the board)
- Computer with Atmel Studio installed
- Terminal emulator program installed on development computer
Generating starter project
- Open Atmel START web based graphical configuration tool and click BROWSE EXAMPLES
- Filter by Category: (e.g. I/O) and/or Board: (e.g. SAM E54 Xplained Pro)
- Select LED flasher and click Download Selected Example
- In Atmel Studio, [File | Import | Atmel Start Project] and select the downloaded project bundle LED flasher.atzip
- Build (F7) and Debug (F5)
Adding FreeRTOS component
After importing the tutorial project into Atmel Studio, the Atmel START configuration tool is available in the Studio IDE.
- Open [ Project | Update Atmel Start Project from Start file ]
- On the DASHBOARD tab, click Add software component
- In ADD SOFTWARE COMPONENTS dialog, expand Middleware, expand RTOS, select FreeRTOS V10.0.0 and click Add component(s)
- Click GENERATE PROJECT
In main.c add code to implement a FreeRTOS RTOS task:
#define TASK_LED_STACK_SIZE (108 / sizeof(portSTACK_TYPE))
#define TASK_LED_STACK_PRIORITY (tskIDLE_PRIORITY + 1)
static TaskHandle_t xCreatedLedTask;
static void task_led(void *p)
{
(void)p;
for (;;) {
gpio_toggle_pin_level(LED0);
os_sleep(500);
}
}
static void task_led_create(void)
{
/* Create task to make led blink */
if (xTaskCreate(task_led, "Led", TASK_LED_STACK_SIZE, NULL, TASK_LED_STACK_PRIORITY, &xCreatedLedTask) != pdPASS) {
while (1) {
;
}
}
}
Also in main.c, add code in main()
to create the RTOS task and start the FreeRTOS scheduler:
int main(void)
{
atmel_start_init();
task_led_create();
vTaskStartScheduler();
In main()
, execution will block at vTaskStartScheduler()
- the code following that call is superfluous and has been removed from the example.
Reconfigure clocks
Digital Phase Locked Loop (DPLL) component is essential for generating higher clock rate to the CPU, as well as various peripherals such as CAN bus which might require custom clock timing from a stable source.
- In Atmel Studio open the Atmel START configuration tool from [ Project | Update Atmel Start Project from Start file ] and select the CLOCKS tab
- Click the checkbox in Generic clock generator 1 (GCLK1).
- Click the gear icon on GCLK1 component - in the CLOCK SETTINGS dialog set Generic clock generator 1 source to XOSC1
- In the CLOCK SETTINGS dialog, the Generic clock generator 1 division should be changed to 12.
- Click Close on the CLOCK SETTINGS dialog (GCLK1 component label should indicate output frequency of 1 MHz)
- On the CLOCKS tab, click the checkbox in Digital Phase Locked Loop (DPLL0).
- Click the gear icon on DPLL0 component - in the CLOCK SETTINGS dialog set Reference Clock Source to Generic clock generator 1
- In the CLOCK SETTINGS dialog, set Loop Divider Ratio Fractional Part to 0
- Set Loop Divider Ratio Integer Part to 119
- Set Reference Clock Selection to GCLK clock reference
- Click Close on the CLOCK SETTINGS dialog (DPLL0 component label should indicate output frequency of 120 MHz)
With the DPLL configured, CPU frequency can be increased to 120 MHz:
- Click the gear icon on Generic clock generator 0 component - in the CLOCK SETTINGS dialog, set Generic clock generator 0 source to Digital Phase Locked Loop (DPLL0)
- Click Close on the CLOCK SETTINGS dialog (GCLK0 component label should indicate output frequency of 120 MHz)
- Click GENERATE PROJECT, click OK on Project Summary to accept the changes.
At this point, should be possible to compile/debug/run the project and observe LED0 flashing steadily - frequency of toggling LED0 can be changed faster or slower merely by adjusting parameter passed to os_sleep()
e.g.
static void task_led(void *p)
{
(void)p;
for (;;) {
gpio_toggle_pin_level(LED0);
os_sleep(100);
}
}
Adding CAN component
A CAN-bus peripheral driver component is available to be added by Atmel START. An RTOS task can be used to demonstrate transmission of a series of CAN messages from the SAMe54.
The CAN component configuration to be used will require a 40 MHz clock source. In the previous section, DPLL0 component was added and configured to provide such a clock reference, but it must be further divided down to provide 40 MHz to the CAN component.
Set up clock source for CAN component
- Change to CLOCKS tab of Atmel START, click enable checkbox in Generic clock generator 2 source (GCLK2)
- Click the gear icon on GCLK2 source
- In CLOCK SETTINGS, change Generic clock generator 2 source to DPLL0
- Uncheck Divide Selection, check Output Enable
- In Generic clock generator 2 division enter 3
- Click Close on the CLOCK SETTINGS dialog (CAN_0 component label should indicate output frequency of 40 MHz)
Add CAN component
- In Atmel START, switch to DASHBOARD tab, click Add software component
- In ADD SOFTWARE COMPONENTS dialog, expand Drivers, select CAN and click Add component(s)
- Click the gear icon on CAN_0 component
- Under CLOCKS set CAN to Generic clock generator 2
- Under COMPONENT SIGNALS set RX and TX to pins PB13 & PB12 respectively
- Driver Instance should indicate CAN1
- Under NORMAL BIT TIMING AND PRESCALER, enter the values 1, 59, 20, 15 for BRP, time segment before, time segment after and Synchronization Jump Width respectively
- Click GENERATE PROJECT (WARNING files modified will be overwritten)
NOTE: BIT TIMINGs were copied from "CAN FD Example" and does not justify the actual timing register values being used.
A little more Copy-and-paste programming should have the CAN-bus completely working on the SAMe54 and should be possible to transmit CAN message from SAMe54 board.
Add the following GPIO pin definition to atmel_start_pins.h:
#define CAN_STDBY GPIO(GPIO_PORTC, 13)
Add the pin configuration to driver_init.c:
gpio_set_pin_level(CAN_STDBY, false);
// Set pin direction to output
gpio_set_pin_direction(CAN_STDBY, GPIO_DIRECTION_OUT);
gpio_set_pin_function(CAN_STDBY, GPIO_PIN_FUNCTION_OFF);
Please see the accompanying CAN FD guide for more detail how to setup CAN-bus and monitoring tool.
Monitoring CAN-bus on SAMe54
This part of the guide will setup the demo project on SAMe54 board to receive message from the CAN-bus.
From Atmel START window, adding the Target IO component:
- In Atmel START, switch to DASHBOARD tab, click Add software component
- Expand Middleware, expand Utilities, select STDIO Redirect, click Add component(s) (TARGET_IO driver dependency automatically added)
- Click gear icon on TARGET_IO component
- Change COMPONENT SIGNALS set RX and TX to PB24 and PB25 respectively
- Under COMPONENT SETTINGS, set Instance to SERCOM2
- Change Baud rate to 115200
- Switching over to the CLOCKS tab, click enable on Generic clock generator 3 (GCLK3)
- On GCLK3, and click gear icon, set source of GCLK3 to XOSC32K and set generic clock generator 3 division to 1
- Click close - output frequency of GCLK3 should be 32.768 kHz, thus sourcing the Slow clock to TARGET_IO component
- Click GENERATE PROJECT (WARNING files modified will be overwritten), then OK on Project Summary dialog
Finally, the CAN_0_rx_callback()
can be modified to show received CAN messages in the terminal window:
void CAN_0_rx_callback(struct can_async_descriptor *const descr)
{
...
can_async_read(descr, &msg);
struct io_descriptor *io;
usart_sync_get_io_descriptor(&TARGET_IO, &io);
usart_sync_enable(&TARGET_IO);
static char ccc = '0';
ccc = ++ccc <= '9' ? ccc : '0';
io_write(io, &ccc, 1);
io_write(io, (uint8_t *)msg.data, strlen(msg.data));
io_write(io, (uint8_t *)"\r", 1);
io_write(io, (uint8_t *)"\n", 1);
return;
}
Generating test messages from PCANView
Please see the accompanying CAN FD guide for more detail how to setup CAN-bus and monitoring tool to generate test messages onto CAN-bus from PCANView monitoring tool.