-
Notifications
You must be signed in to change notification settings - Fork 122
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 #12 from HamedJafarzadeh/master
STM32 Library overhaul
- Loading branch information
Showing
960 changed files
with
635,290 additions
and
21,433 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
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -23,6 +23,7 @@ | |
*.__i | ||
*.i | ||
*.txt | ||
*.launch | ||
!docs/*.txt | ||
RTE/ | ||
|
||
|
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 |
---|---|---|
@@ -1,16 +1,13 @@ | ||
[submodule "libs/lwrb"] | ||
path = libs/lwrb | ||
[submodule "legacy/libs/lwmem"] | ||
path = legacy/libs/lwmem | ||
url = https://github.com/MaJerle/lwmem | ||
[submodule "legacy/libs/lwprintf"] | ||
path = legacy/libs/lwprintf | ||
url = https://github.com/MaJerle/lwprintf | ||
[submodule "legacy/libs/lwrb"] | ||
path = legacy/libs/lwrb | ||
url = https://github.com/MaJerle/lwrb | ||
branch = master | ||
[submodule "CANopenNode"] | ||
path = CANopenNode | ||
url = https://github.com/CANopenNode/CANopenNode | ||
branch = master | ||
[submodule "libs/lwprintf"] | ||
path = libs/lwprintf | ||
url = https://github.com/MaJerle/lwprintf | ||
branch = master | ||
[submodule "libs/lwmem"] | ||
path = libs/lwmem | ||
url = https://github.com/MaJerle/lwmem | ||
branch = master | ||
branch = master |
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,2 @@ | ||
OD.c | ||
OD.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,251 @@ | ||
/* | ||
* CANopen main program file. | ||
* | ||
* This file is a template for other microcontrollers. | ||
* | ||
* @file main_generic.c | ||
* @author Hamed Jafarzadeh 2022 | ||
* Janez Paternoster 2021 | ||
* @copyright 2021 Janez Paternoster | ||
* | ||
* This file is part of CANopenNode, an opensource CANopen Stack. | ||
* Project home page is <https://github.com/CANopenNode/CANopenNode>. | ||
* For more information on CANopen see <http://www.can-cia.org/>. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
#include "CO_app_STM32.h" | ||
#include "CANopen.h" | ||
#include "main.h" | ||
#include <stdio.h> | ||
|
||
#include "CO_storageBlank.h" | ||
#include "OD.h" | ||
|
||
CANopenNodeSTM32* | ||
canopenNodeSTM32; // It will be set by canopen_app_init and will be used across app to get access to CANOpen objects | ||
|
||
/* Printf function of CanOpen app */ | ||
#define log_printf(macropar_message, ...) printf(macropar_message, ##__VA_ARGS__) | ||
|
||
/* default values for CO_CANopenInit() */ | ||
#define NMT_CONTROL \ | ||
CO_NMT_STARTUP_TO_OPERATIONAL \ | ||
| CO_NMT_ERR_ON_ERR_REG | CO_ERR_REG_GENERIC_ERR | CO_ERR_REG_COMMUNICATION | ||
#define FIRST_HB_TIME 500 | ||
#define SDO_SRV_TIMEOUT_TIME 1000 | ||
#define SDO_CLI_TIMEOUT_TIME 500 | ||
#define SDO_CLI_BLOCK false | ||
#define OD_STATUS_BITS NULL | ||
|
||
/* Global variables and objects */ | ||
CO_t* CO = NULL; /* CANopen object */ | ||
|
||
// Global variables | ||
uint32_t time_old, time_current; | ||
CO_ReturnError_t err; | ||
|
||
/* This function will basically setup the CANopen node */ | ||
int | ||
canopen_app_init(CANopenNodeSTM32* _canopenNodeSTM32) { | ||
|
||
// Keep a copy global reference of canOpenSTM32 Object | ||
canopenNodeSTM32 = _canopenNodeSTM32; | ||
|
||
#if (CO_CONFIG_STORAGE) & CO_CONFIG_STORAGE_ENABLE | ||
CO_storage_t storage; | ||
CO_storage_entry_t storageEntries[] = {{.addr = &OD_PERSIST_COMM, | ||
.len = sizeof(OD_PERSIST_COMM), | ||
.subIndexOD = 2, | ||
.attr = CO_storage_cmd | CO_storage_restore, | ||
.addrNV = NULL}}; | ||
uint8_t storageEntriesCount = sizeof(storageEntries) / sizeof(storageEntries[0]); | ||
uint32_t storageInitError = 0; | ||
#endif | ||
|
||
/* Allocate memory */ | ||
CO_config_t* config_ptr = NULL; | ||
#ifdef CO_MULTIPLE_OD | ||
/* example usage of CO_MULTIPLE_OD (but still single OD here) */ | ||
CO_config_t co_config = {0}; | ||
OD_INIT_CONFIG(co_config); /* helper macro from OD.h */ | ||
co_config.CNT_LEDS = 1; | ||
co_config.CNT_LSS_SLV = 1; | ||
config_ptr = &co_config; | ||
#endif /* CO_MULTIPLE_OD */ | ||
|
||
uint32_t heapMemoryUsed; | ||
CO = CO_new(config_ptr, &heapMemoryUsed); | ||
if (CO == NULL) { | ||
log_printf("Error: Can't allocate memory\n"); | ||
return 1; | ||
} else { | ||
log_printf("Allocated %u bytes for CANopen objects\n", heapMemoryUsed); | ||
} | ||
|
||
canopenNodeSTM32->canOpenStack = CO; | ||
|
||
#if (CO_CONFIG_STORAGE) & CO_CONFIG_STORAGE_ENABLE | ||
err = CO_storageBlank_init(&storage, CO->CANmodule, OD_ENTRY_H1010_storeParameters, | ||
OD_ENTRY_H1011_restoreDefaultParameters, storageEntries, storageEntriesCount, | ||
&storageInitError); | ||
|
||
if (err != CO_ERROR_NO && err != CO_ERROR_DATA_CORRUPT) { | ||
log_printf("Error: Storage %d\n", storageInitError); | ||
return 2; | ||
} | ||
#endif | ||
|
||
canopen_app_resetCommunication(); | ||
return 0; | ||
} | ||
|
||
int | ||
canopen_app_resetCommunication() { | ||
/* CANopen communication reset - initialize CANopen objects *******************/ | ||
log_printf("CANopenNode - Reset communication...\n"); | ||
|
||
/* Wait rt_thread. */ | ||
CO->CANmodule->CANnormal = false; | ||
|
||
/* Enter CAN configuration. */ | ||
CO_CANsetConfigurationMode((void*)canopenNodeSTM32); | ||
CO_CANmodule_disable(CO->CANmodule); | ||
|
||
/* initialize CANopen */ | ||
err = CO_CANinit(CO, canopenNodeSTM32, 0); // Bitrate for STM32 microcontroller is being set in MXCube Settings | ||
if (err != CO_ERROR_NO) { | ||
log_printf("Error: CAN initialization failed: %d\n", err); | ||
return 1; | ||
} | ||
|
||
CO_LSS_address_t lssAddress = {.identity = {.vendorID = OD_PERSIST_COMM.x1018_identity.vendor_ID, | ||
.productCode = OD_PERSIST_COMM.x1018_identity.productCode, | ||
.revisionNumber = OD_PERSIST_COMM.x1018_identity.revisionNumber, | ||
.serialNumber = OD_PERSIST_COMM.x1018_identity.serialNumber}}; | ||
err = CO_LSSinit(CO, &lssAddress, &canopenNodeSTM32->desiredNodeID, &canopenNodeSTM32->baudrate); | ||
if (err != CO_ERROR_NO) { | ||
log_printf("Error: LSS slave initialization failed: %d\n", err); | ||
return 2; | ||
} | ||
|
||
canopenNodeSTM32->activeNodeID = canopenNodeSTM32->desiredNodeID; | ||
uint32_t errInfo = 0; | ||
|
||
err = CO_CANopenInit(CO, /* CANopen object */ | ||
NULL, /* alternate NMT */ | ||
NULL, /* alternate em */ | ||
OD, /* Object dictionary */ | ||
OD_STATUS_BITS, /* Optional OD_statusBits */ | ||
NMT_CONTROL, /* CO_NMT_control_t */ | ||
FIRST_HB_TIME, /* firstHBTime_ms */ | ||
SDO_SRV_TIMEOUT_TIME, /* SDOserverTimeoutTime_ms */ | ||
SDO_CLI_TIMEOUT_TIME, /* SDOclientTimeoutTime_ms */ | ||
SDO_CLI_BLOCK, /* SDOclientBlockTransfer */ | ||
canopenNodeSTM32->activeNodeID, &errInfo); | ||
if (err != CO_ERROR_NO && err != CO_ERROR_NODE_ID_UNCONFIGURED_LSS) { | ||
if (err == CO_ERROR_OD_PARAMETERS) { | ||
log_printf("Error: Object Dictionary entry 0x%X\n", errInfo); | ||
} else { | ||
log_printf("Error: CANopen initialization failed: %d\n", err); | ||
} | ||
return 3; | ||
} | ||
|
||
err = CO_CANopenInitPDO(CO, CO->em, OD, canopenNodeSTM32->activeNodeID, &errInfo); | ||
if (err != CO_ERROR_NO) { | ||
if (err == CO_ERROR_OD_PARAMETERS) { | ||
log_printf("Error: Object Dictionary entry 0x%X\n", errInfo); | ||
} else { | ||
log_printf("Error: PDO initialization failed: %d\n", err); | ||
} | ||
return 4; | ||
} | ||
|
||
/* Configure Timer interrupt function for execution every 1 millisecond */ | ||
HAL_TIM_Base_Start_IT(canopenNodeSTM32->timerHandle); //1ms interrupt | ||
|
||
/* Configure CAN transmit and receive interrupt */ | ||
|
||
/* Configure CANopen callbacks, etc */ | ||
if (!CO->nodeIdUnconfigured) { | ||
|
||
#if (CO_CONFIG_STORAGE) & CO_CONFIG_STORAGE_ENABLE | ||
if (storageInitError != 0) { | ||
CO_errorReport(CO->em, CO_EM_NON_VOLATILE_MEMORY, CO_EMC_HARDWARE, storageInitError); | ||
} | ||
#endif | ||
} else { | ||
log_printf("CANopenNode - Node-id not initialized\n"); | ||
} | ||
|
||
/* start CAN */ | ||
CO_CANsetNormalMode(CO->CANmodule); | ||
|
||
log_printf("CANopenNode - Running...\n"); | ||
fflush(stdout); | ||
time_old = time_current = HAL_GetTick(); | ||
return 0; | ||
} | ||
|
||
void | ||
canopen_app_process() { | ||
/* loop for normal program execution ******************************************/ | ||
/* get time difference since last function call */ | ||
time_current = HAL_GetTick(); | ||
|
||
if ((time_current - time_old) > 0) { // Make sure more than 1ms elapsed | ||
/* CANopen process */ | ||
CO_NMT_reset_cmd_t reset_status; | ||
uint32_t timeDifference_us = (time_current - time_old) * 1000; | ||
time_old = time_current; | ||
reset_status = CO_process(CO, false, timeDifference_us, NULL); | ||
canopenNodeSTM32->outStatusLEDRed = CO_LED_RED(CO->LEDs, CO_LED_CANopen); | ||
canopenNodeSTM32->outStatusLEDGreen = CO_LED_GREEN(CO->LEDs, CO_LED_CANopen); | ||
|
||
if (reset_status == CO_RESET_COMM) { | ||
/* delete objects from memory */ | ||
CO_CANsetConfigurationMode((void*)canopenNodeSTM32); | ||
CO_delete(CO); | ||
log_printf("CANopenNode Reset Communication request\n"); | ||
canopen_app_resetCommunication(); // Reset Communication routine | ||
} else if (reset_status == CO_RESET_APP) { | ||
log_printf("CANopenNode Device Reset\n"); | ||
HAL_NVIC_SystemReset(); // Reset the STM32 Microcontroller | ||
} | ||
} | ||
} | ||
|
||
/* Thread function executes in constant intervals, this function can be called from FreeRTOS tasks or Timers ********/ | ||
void | ||
canopen_app_interrupt(void) { | ||
CO_LOCK_OD(CO->CANmodule); | ||
if (!CO->nodeIdUnconfigured && CO->CANmodule->CANnormal) { | ||
bool_t syncWas = false; | ||
/* get time difference since last function call */ | ||
uint32_t timeDifference_us = 1000; // 1ms second | ||
|
||
#if (CO_CONFIG_SYNC) & CO_CONFIG_SYNC_ENABLE | ||
syncWas = CO_process_SYNC(CO, timeDifference_us, NULL); | ||
#endif | ||
#if (CO_CONFIG_PDO) & CO_CONFIG_RPDO_ENABLE | ||
CO_process_RPDO(CO, syncWas, timeDifference_us, NULL); | ||
#endif | ||
#if (CO_CONFIG_PDO) & CO_CONFIG_TPDO_ENABLE | ||
CO_process_TPDO(CO, syncWas, timeDifference_us, NULL); | ||
#endif | ||
|
||
/* Further I/O or nonblocking application code may go here. */ | ||
} | ||
CO_UNLOCK_OD(CO->CANmodule); | ||
} |
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,74 @@ | ||
/* | ||
* CO_app_STM32.h | ||
* | ||
* Created on: Aug 7, 2022 | ||
* Author: hamed | ||
*/ | ||
|
||
#ifndef CANOPENSTM32_CO_APP_STM32_H_ | ||
#define CANOPENSTM32_CO_APP_STM32_H_ | ||
|
||
#include "CANopen.h" | ||
#include "main.h" | ||
|
||
/* CANHandle : Pass in the CAN Handle to this function and it wil be used for all CAN Communications. It can be FDCan or CAN | ||
* and CANOpenSTM32 Driver will take of care of handling that | ||
* HWInitFunction : Pass in the function that initialize the CAN peripheral, usually MX_CAN_Init | ||
* timerHandle : Pass in the timer that is going to be used for generating 1ms interrupt for tmrThread function, | ||
* please note that CANOpenSTM32 Library will override HAL_TIM_PeriodElapsedCallback function, if you also need this function | ||
* in your codes, please take required steps | ||
*/ | ||
|
||
#ifdef __cplusplus | ||
extern "C" { | ||
#endif | ||
|
||
|
||
typedef struct { | ||
uint8_t | ||
desiredNodeID; /*This is the Node ID that you ask the CANOpen stack to assign to your device, although it might not always | ||
* be the final NodeID, after calling canopen_app_init() you should check ActiveNodeID of CANopenNodeSTM32 structure for assigned Node ID. | ||
*/ | ||
uint8_t activeNodeID; /* Assigned Node ID */ | ||
uint8_t baudrate; /* This is the baudrate you've set in your CubeMX Configuration */ | ||
TIM_HandleTypeDef* | ||
timerHandle; /*Pass in the timer that is going to be used for generating 1ms interrupt for tmrThread function, | ||
* please note that CANOpenSTM32 Library will override HAL_TIM_PeriodElapsedCallback function, if you also need this function in your codes, please take required steps | ||
*/ | ||
|
||
/* Pass in the CAN Handle to this function and it wil be used for all CAN Communications. It can be FDCan or CAN | ||
* and CANOpenSTM32 Driver will take of care of handling that*/ | ||
#ifdef CO_STM32_FDCAN_Driver | ||
FDCAN_HandleTypeDef* CANHandle; | ||
#else | ||
CAN_HandleTypeDef* CANHandle; | ||
#endif | ||
|
||
void (*HWInitFunction)(); /* Pass in the function that initialize the CAN peripheral, usually MX_CAN_Init */ | ||
|
||
uint8_t outStatusLEDGreen; // This will be updated by the stack - Use them for the LED management | ||
uint8_t outStatusLEDRed; // This will be updated by the stack - Use them for the LED management | ||
CO_t* canOpenStack; | ||
|
||
} CANopenNodeSTM32; | ||
|
||
|
||
// In order to use CANOpenSTM32, you'll have it have a canopenNodeSTM32 structure somewhere in your codes, it is usually residing in CO_app_STM32.c | ||
extern CANopenNodeSTM32* canopenNodeSTM32; | ||
|
||
|
||
/* This function will initialize the required CANOpen Stack objects, allocate the memory and prepare stack for communication reset*/ | ||
int canopen_app_init(CANopenNodeSTM32* canopenSTM32); | ||
/* This function will reset the CAN communication periperhal and also the CANOpen stack variables */ | ||
int canopen_app_resetCommunication(); | ||
/* This function will check the input buffers and any outstanding tasks that are not time critical, this function should be called regurarly from your code (i.e from your while(1))*/ | ||
void canopen_app_process(); | ||
/* Thread function executes in constant intervals, this function can be called from FreeRTOS tasks or Timers ********/ | ||
void canopen_app_interrupt(void); | ||
|
||
#ifdef __cplusplus | ||
} | ||
#endif /* __cplusplus */ | ||
|
||
#endif /* CANOPENSTM32_CO_APP_STM32_H_ */ |
Oops, something went wrong.