-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #632 from rogerclarkmelbourne/Phonog-Phonog-patch-1
Added CAN functionality
- Loading branch information
Showing
14 changed files
with
2,570 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
53 changes: 53 additions & 0 deletions
53
STM32F1/libraries/HardwareCAN/examples/HardwareCANexample/Changes.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
#ifdef CHANGES_INCLUDE | ||
|
||
****** DETAILS OF THE CHANGES TO BE DONE TO THE CORE TO BE ABLE TO USE THE LIBRARY HardwareCAN ****** | ||
|
||
1) History | ||
The Hardware CAN library was originally published in the Maple Leaflabs forum by X893. | ||
I tested it, and found bugs, which I fixed in the code. My fixes are commented with the initials JMD. | ||
The most important things that missed was to connect the interrupt service routine to the CAN interrupt vector. | ||
The problem is that in the F1 family, this vector is shared with the USB vector, as is some of the memory. Thus, | ||
when one wants to use the CAN, the USB becomes unavailable. This is a severe drawback of this chip, but one has to cope with this. | ||
|
||
2) Changes performed | ||
|
||
2.1) In file C:\ArduinoForSTM32\arduino-1.6.9\hardware\Arduino_STM32-master\STM32F1\cores\maple\libmaple\rcc_f1.c | ||
inserted 1 line, position 96: | ||
[RCC_CAN] = { .clk_domain = APB1, .line_num = 25 }, //! JMD after X893 | ||
|
||
2.2) In file C:\ArduinoForSTM32\arduino-1.6.9\hardware\Arduino_STM32-master\STM32F1\system\libmaple\stm32f1\include\series\rcc.h | ||
inserted 1 line, position 442: | ||
RCC_CAN, //! JMD after X893 | ||
|
||
2.3) In file C:\ArduinoForSTM32\arduino-1.6.9\hardware\Arduino_STM32-master\STM32F1\cores\maple\libmaple\usb\stm32f1\usb.c | ||
2.3.1) inserted 12 lines, position 186 | ||
// JMD : default ISRs of CAN, to be overridden if HardwareCAN library is used in sketch | ||
void __attribute__((weak)) USB_HP_CAN_TX_IRQHandler(void) | ||
{ ; } // Dummy ISR | ||
|
||
void __irq_usb_hp_can_tx(void) | ||
{ | ||
USB_HP_CAN_TX_IRQHandler () ; | ||
} | ||
|
||
uint8 __attribute__((weak)) CAN_RX0_IRQ_Handler(void) | ||
{ return 1 ; } // Dummy ISR | ||
|
||
2.3.2) and altered function void __irq_usb_lp_can_rx0(void) | ||
Was | ||
|
||
void __irq_usb_lp_can_rx0(void) { | ||
uint16 istr = USB_BASE->ISTR; | ||
|
||
/* Use USB_ISR_MSK to only include code for bits we care about. */ | ||
|
||
Becomes | ||
|
||
void __irq_usb_lp_can_rx0(void) { | ||
uint16 istr = USB_BASE->ISTR; | ||
|
||
if (CAN_RX0_IRQ_Handler()) //! JMD : Call to CAN ISR, returns 1 CAN is active | ||
return; //! JMD | ||
|
||
/* Use USB_ISR_MSK to only include code for bits we care about. */ | ||
#endif |
181 changes: 181 additions & 0 deletions
181
STM32F1/libraries/HardwareCAN/examples/HardwareCANexample/HardwareCANexample.ino
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,181 @@ | ||
#include <HardwareCAN.h> | ||
#include "changes.h" | ||
/* | ||
* Example of use of the HardwareCAN library | ||
* This application receives two frames containing various data. It also produces data that are sent periodically using another two frames. | ||
* Please read the file changes.h to see the changes to be performed to the core in order to use this | ||
*/ | ||
// Define the values of the identifiers | ||
#define GYRO_ID 0x27 | ||
#define JOYSTICK_VALUES_ID 0x5A | ||
#define TANK_LEVEL_ID 0x78 | ||
#define MOTOR_CONTROL_ID 0x92 | ||
|
||
// Limit time to flag a CAN error | ||
#define CAN_TIMEOUT 100 | ||
#define CAN_DELAY 10 // ms between two processings of incoming messages | ||
#define CAN_SEND_RATE 200 // ms between two successive sendings | ||
|
||
// Message structures. Each message has its own identifier. As many such variables should be defined | ||
// as the number of different CAN frames the application has to send. Here, they are two. | ||
CanMsg msgGyroscope ; | ||
CanMsg msgMotorControl ; | ||
|
||
// Traffic handling data | ||
int CANquietTime ; // Quiet time counter to detect no activity on CAN bus | ||
bool CANError ; // Indicates that incoming CAN traffic is missing | ||
int CANsendDivider ; // Used to send frames once every so many times loop() is called | ||
|
||
// Applicaton variables | ||
int Contents[4] ; // Contents of the four tanks | ||
int JoystickX ; // Setting of the joystick, X axis | ||
int JoystickY ; // ... Y axis | ||
int AngularRate ; // Output of local gyroscope | ||
int Throttle ; // Motor control value, produced by some local processing | ||
bool ErreurGyroscope = false ; | ||
|
||
// Instanciation of CAN interface | ||
HardwareCAN canBus(CAN1_BASE); | ||
|
||
|
||
// Note : for the predefined identifiers, please have a look in file can.h | ||
|
||
void CANSetup(void) | ||
{ | ||
CAN_STATUS Stat ; | ||
|
||
// Initialize the message structures | ||
// A CAN structure includes the following fields: | ||
msgGyroscope.IDE = CAN_ID_STD; // Indicates a standard identifier ; CAN_ID_EXT would mean this frame uses an extended identifier | ||
msgGyroscope.RTR = CAN_RTR_DATA; // Indicated this is a data frame, as opposed to a remote frame (would then be CAN_RTR_REMOTE) | ||
msgGyroscope.ID = GYRO_ID ; // Identifier of the frame : 0-2047 (0-0x3ff) for standard idenfiers; 0-0x1fffffff for extended identifiers | ||
msgGyroscope.DLC = 3; // Number of data bytes to follow | ||
msgGyroscope.Data[0] = 0x0; // Data bytes, there can be 0 to 8 bytes. | ||
msgGyroscope.Data[1] = 0x0; | ||
msgGyroscope.Data[2] = 0x0; | ||
|
||
msgMotorControl.IDE = CAN_ID_STD; | ||
msgMotorControl.RTR = CAN_RTR_DATA; | ||
msgMotorControl.ID = MOTOR_CONTROL_ID ; | ||
msgMotorControl.DLC = 2; | ||
msgMotorControl.Data[0] = 0x0; | ||
msgMotorControl.Data[1] = 0x0; | ||
|
||
// Initialize CAN module | ||
canBus.map(CAN_GPIO_PB8_PB9); // This setting is already wired in the Olimexino-STM32 board | ||
Stat = canBus.begin(CAN_SPEED_125, CAN_MODE_NORMAL); // Other speeds go from 125 kbps to 1000 kbps. CAN allows even more choices. | ||
|
||
canBus.filter(0, 0, 0); | ||
canBus.set_irq_mode(); // Use irq mode (recommended), so the handling of incoming messages | ||
// will be performed at ease in a task or in the loop. The software fifo is 16 cells long, | ||
// allowing at least 15 ms before processing the fifo is needed at 125 kbps | ||
Stat = canBus.status(); | ||
if (Stat != CAN_OK) | ||
/* Your own error processing here */ ; // Initialization failed | ||
} | ||
|
||
// Send one frame. Parameter is a pointer to a frame structure (above), that has previously been updated with data. | ||
// If no mailbox is available, wait until one becomes empty. There are 3 mailboxes. | ||
CAN_TX_MBX CANsend(CanMsg *pmsg) | ||
{ | ||
CAN_TX_MBX mbx; | ||
|
||
do | ||
{ | ||
mbx = canBus.send(pmsg) ; | ||
#ifdef USE_MULTITASK | ||
vTaskDelay( 1 ) ; // Infinite loops are not multitasking-friendly | ||
#endif | ||
} | ||
while(mbx == CAN_TX_NO_MBX) ; // Waiting outbound frames will eventually be sent, unless there is a CAN bus failure. | ||
return mbx ; | ||
} | ||
|
||
// Process incoming messages | ||
// Note : frames are not fully checked for correctness: DLC value is not checked, neither are the IDE and RTR fields. However, the data is guaranteed to be corrrect. | ||
void ProcessMessages(void) | ||
{ | ||
int Pr = 0 ; | ||
int i ; | ||
|
||
CanMsg *r_msg; | ||
|
||
// Loop for every message in the fifo | ||
while ((r_msg = canBus.recv()) != NULL) | ||
{ | ||
CANquietTime = 0 ; // Reset at each received frame | ||
CANError = false ; // Clear CAN silence error | ||
switch ( r_msg->ID ) | ||
{ | ||
case TANK_LEVEL_ID : // This frame contains four 16-bit words, little endian coded | ||
for ( i = 0 ; i < 4 ; i++ ) | ||
Contents[i] = (int)r_msg->Data[2*i] | ((int)r_msg->Data[(2*i)+1]) << 8 ; | ||
break ; | ||
|
||
case JOYSTICK_VALUES_ID : // This frame contains two 16-bit words, little endian coded | ||
Pr = (int)r_msg->Data[0] ; | ||
Pr |= (int)r_msg->Data[1] << 8 ; | ||
JoystickX = Pr ; | ||
|
||
Pr = (int)r_msg->Data[2] ; | ||
Pr |= (int)r_msg->Data[3] << 8 ; | ||
JoystickY = Pr ; | ||
break ; | ||
|
||
default : // Any frame with a different identifier is ignored | ||
break ; | ||
} | ||
|
||
canBus.free(); // Remove processed message from buffer, whatever the identifier | ||
#ifdef USE_MULTITASK | ||
vTaskDelay( 1 ) ; // Infinite loops are not multitasking-friendly | ||
#endif | ||
} | ||
} | ||
|
||
// Send messages | ||
// Prepare and send 2 frames containing the value of process variables | ||
// Sending all frames at once is a choice; they could be sent separately, at different times and rates. | ||
void SendCANmessages(void) | ||
{ | ||
// Prepare Gyroscope frame : send angular rate | ||
msgGyroscope.Data[0] = AngularRate & 0xff ; | ||
msgGyroscope.Data[1] = ( AngularRate >> 8 ) & 0xff ; | ||
msgGyroscope.Data[2] = ErreurGyroscope ? 1 : 0 ; | ||
CANsend(&msgGyroscope) ; // Send this frame | ||
|
||
msgMotorControl.Data[0] = Throttle & 0xff ; | ||
msgMotorControl.Data[1] = ( Throttle >> 8 ) & 0xff ; | ||
CANsend(&msgMotorControl) ; | ||
} | ||
|
||
// The application program starts here | ||
void setup() { | ||
// put your setup code here, to run once: | ||
CANSetup() ; // Initialize the CAN module and prepare the message structures. | ||
} | ||
|
||
void loop() { | ||
// Process incoming messages periodically (should be often enough to avoid overflowing the fifo) | ||
ProcessMessages() ; // Process all incoming messages, update local variables accordingly | ||
|
||
// This is an example of timeout management. Here it is global to all received frames; | ||
// it could be on a frame by frame basis, with as many control variables as the number of frames. | ||
CANquietTime++ ; | ||
if ( CANquietTime > CAN_TIMEOUT ) | ||
{ | ||
CANquietTime = CAN_TIMEOUT + 1 ; // To prevent overflowing this variable if silence prolongs... | ||
CANError = true ; // Flag CAN silence error. Will be cleared at first frame received | ||
} | ||
|
||
// Send messages containing variables to publish. Sent less frequently than the processing of incoming frames (here, every 200 ms) | ||
CANsendDivider-- ; | ||
if ( CANsendDivider < 0 ) | ||
{ | ||
CANsendDivider = CAN_SEND_RATE / CAN_DELAY ; | ||
SendCANmessages() ; | ||
} | ||
delay(CAN_DELAY) ; // The delay must not be greater than the time to overflow the incoming fifo (here about 15 ms) | ||
} | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
####################################### | ||
# Syntax Coloring Map For HardwareCAN | ||
####################################### | ||
|
||
####################################### | ||
# Datatypes (KEYWORD1) | ||
####################################### | ||
HardwareCAN KEYWORD1 | ||
CanMsg KEYWORD1 | ||
CAN_TX_MBX KEYWORD1 | ||
|
||
####################################### | ||
# Methods and Functions (KEYWORD2) | ||
####################################### | ||
release KEYWORD2 CAN_Release | ||
send KEYWORD2 CAN_Send | ||
read KEYWORD2 CAN_Read | ||
recv KEYWORD2 CAN_Recieve | ||
set_pool_mode KEYWORD2 CAN_Set_Pool_Mode | ||
set_irq_mode KEYWORD2 CAN_Set_IRQ_Mode | ||
fifo_ready KEYWORD2 CAN_Fifo_Ready | ||
filter KEYWORD2 CAN_Filter | ||
free KEYWORD2 CAN_Free | ||
available KEYWORD2 CAN_Available | ||
|
||
####################################### | ||
# Constants (LITERAL1) | ||
####################################### | ||
CAN_GPIO_PD0_PD1 LITERAL1 | ||
CAN_GPIO_PB8_PB9 LITERAL1 | ||
CAN_FIFO0 LITERAL1 | ||
CAN_FIFO1 LITERAL1 | ||
CAN_SPEED_125 LITERAL1 | ||
CAN_SPEED_250 LITERAL1 | ||
CAN_SPEED_500 LITERAL1 | ||
CAN_SPEED_1000 LITERAL1 | ||
CAN1_BASE LITERAL1 | ||
CAN2_BASE LITERAL1 | ||
CAN_ID_STD LITERAL1 | ||
CAN_RTR_DATA LITERAL1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
name=HardwareCAN | ||
version=1.0.0 | ||
author=Maple Leaflabs fixed by JMD | ||
maintainer=JMD | ||
sentence=Enables managing CAN communication using the built-in CAN port of the OLIMEX STM32 board. | ||
paragraph=With this library you can use the built-in CAN port of the OLIMEX STM32. The library handles both standard and extended frames. | ||
category=Communication | ||
url= | ||
architectures=* |
Oops, something went wrong.