Skip to content

stm32g0xx_fdcan example project updated with eeprom storage routines#109

Open
TheCitrusMan wants to merge 8 commits into
CANopenNode:masterfrom
TheCitrusMan:storage/eeprom
Open

stm32g0xx_fdcan example project updated with eeprom storage routines#109
TheCitrusMan wants to merge 8 commits into
CANopenNode:masterfrom
TheCitrusMan:storage/eeprom

Conversation

@TheCitrusMan

Copy link
Copy Markdown

Modified Canopen files:

CO_app_STM32.c :

updated include references
CO_storageBlank_init replaced by CO_storageEeprom_init
uint32_t storageInitError moved to global scope

CO_driver_target.h :

#undef CO_CONFIG_STORAGE_ENABLE commented out
CO_storage_entry_t added extra parameters

CO_eeprom_STM32.c and CO_eeprom_STM32.h added to project. These files contain the main eeprom storage routines and are based on the PIC32 example.

CO_storageBlank.c and CO_storageBlank.h removed from project.

eeprom.c and eeprom.h files added to project. These files contain the low level eeprom routines.

i2c.h in core project:

added a couple of defines

Modified Canopen files:

CO_app_STM32.c :
> updated include references
> CO_storageBlank_init replaced by CO_storageEeprom_init
> uint32_t storageInitError moved to global scope

CO_driver_target.h :
> #undef CO_CONFIG_STORAGE_ENABLE commented out
> CO_storage_entry_t added extra parameters

CO_eeprom_STM32.c and CO_eeprom_STM32.h added to project.
These files contain the main eeprom storage routines and are based on the PIC32 example.

CO_storageBlank.c and CO_storageBlank.h removed from project.

eeprom.c and eeprom.h files added to project. These files contain the low level eeprom routines.

i2c.h in core project:
> added a couple of defines
@MaJerle

MaJerle commented Jun 26, 2026

Copy link
Copy Markdown
Collaborator

@CANopenNode @HamedJafarzadeh is this OK to merge?

@TheCitrusMan

Copy link
Copy Markdown
Author

A little comment on function CO_eeprom_init() in CO_eeprom_STM32.c :

This funcion initializes the EEPROM storage. The chosen EEPROM types contain a fixed serial number. This number is placed in OD_PERSIST_COMM.x1018_identity.serialNumber.

What it also does is to check the status of a predefined I/O pin of the microcontroller. When this pin is active high (in this case), (part of) the eeprom storage is erased, invalidating the contents of PERSIST_COMM. I have found that such functionality can be very handy when a project is still under development and the number of parameters in PERSIST_COMM changes. It seems that, when parameters are added to or removed from PERSIST_COMM after parameters were successfully written to eeprom, the old eeprom storage is still considered valid by canopennode. I haven't put any time in figuring this out yet, I opted for a simple "config mode" option instead.

In this demo project I have connected this "config mode" to the "joystick down" button. The idea is to press this button during power up of the device.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the stm32g0xx_fdcan example integration to use EEPROM-backed CANopen Object Dictionary storage (via CO_storageEeprom) instead of the previous blank storage stub, adding STM32-specific EEPROM access routines.

Changes:

  • Switch CANopen app initialization from CO_storageBlank_* to CO_storageEeprom_* and enable storage configuration.
  • Add STM32 EEPROM discovery + low-level I2C EEPROM access (eeprom.c/.h) and a CANopen storage EEPROM adapter (CO_eeprom_STM32.c/.h).
  • Add example-level I2C helper defines used by the new EEPROM code.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
examples/stm32g0xx_fdcan/Core/Inc/i2c.h Adds I2C timeout + handle macro used by EEPROM routines
CANopenNode_STM32/eeprom.h Adds EEPROM public API + exported device/layout globals
CANopenNode_STM32/eeprom.c Adds EEPROM device detection (ST/Microchip) and layout setup
CANopenNode_STM32/CO_storageBlank.h Removes blank storage stub (header)
CANopenNode_STM32/CO_storageBlank.c Removes blank storage stub (implementation)
CANopenNode_STM32/CO_eeprom_STM32.h Adds STM32 EEPROM adapter header (currently minimal)
CANopenNode_STM32/CO_eeprom_STM32.c Adds CO_storageEeprom ↔ STM32 EEPROM adapter implementation
CANopenNode_STM32/CO_driver_target.h Enables storage config and extends CO_storage_entry_t with EEPROM fields
CANopenNode_STM32/CO_app_STM32.c Switches to CO_storageEeprom_init and adjusts storage init handling

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread CANopenNode_STM32/CO_eeprom_STM32.c
Comment thread CANopenNode_STM32/CO_eeprom_STM32.c
Comment thread CANopenNode_STM32/CO_eeprom_STM32.c
Comment thread CANopenNode_STM32/CO_eeprom_STM32.c
Comment thread CANopenNode_STM32/eeprom.c Outdated
Comment thread CANopenNode_STM32/eeprom.h Outdated
Comment thread CANopenNode_STM32/CO_app_STM32.c Outdated
@CANopenNode

CANopenNode commented Jun 26, 2026

Copy link
Copy Markdown
Owner

After a quick look it seems OK to me. I can't test the code.

I ran copilot AI review and it showed some suggestions. @TheCitrusMan, please check, if they make sense.

Then I suggest to merge.

the Github Copilot code review :

CO_eeprom_STM32.c :
> #include <string.h> added
> HAL_I2C_IsDeviceReady() timeout

eeprom.c :
> replaced size_t by uint32_t / uint16_t specifiers
> removed support for m24m01e-u and m24m02e-u eeprom types
>  as they cannot be fully adressed by 16-bit adresses

eeprom.h :
> adjusted type specifiers for external variables
> #include <stdbool.h> added

main.c :
> #include "eeprom.h" added
> Added missing Eeprom_Init()
@TheCitrusMan

Copy link
Copy Markdown
Author

After a quick look it seems OK to me. I can't test the code.

I ran copilot AI review and it showed some suggestions. @TheCitrusMan, please check, if they make sense.

Then I suggest to merge.

Made some changes. Eeprom initialisation in main() was still missing. Removed the support for the largest eeprom types as they cannot be simply addressed with 2-byte addresses and I don't plan adding code for that as 32Kbytes or 64KBytes eeproms are already plenty large.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 11 out of 11 changed files in this pull request and generated 7 comments.

Comment thread CANopenNode_STM32/eeprom.c
Comment thread CANopenNode_STM32/eeprom.c
Comment thread CANopenNode_STM32/CO_eeprom_STM32.c
Comment thread CANopenNode_STM32/CO_eeprom_STM32.c
Comment thread CANopenNode_STM32/CO_eeprom_STM32.c
Comment thread CANopenNode_STM32/CO_app_STM32.c
Comment thread CANopenNode_STM32/CO_app_STM32.c
@HamedJafarzadeh

HamedJafarzadeh commented Jun 29, 2026

Copy link
Copy Markdown
Collaborator

@TheCitrusMan Thanks for your contribution, I can see that you had a lot of progress and I don't want to get in the way. Copilot has some comments that some of them are actually good points. You can reply on those you agree/disagree. Let me know once you finished your changes and I'll do a final review before merging it.

@TheCitrusMan

Copy link
Copy Markdown
Author

I will check the copilot comments later today. It's good to have this tool to review the code as it revealed some real issues already, but I believe it also points out issues that aren't actually an issue. I have to add that some of the comments apply to code was taken over unchanged from the PIC32 implementation.

Using the EEPROM extension in this project:
===========================================

The eeprom extension provides support for following eeprom types:

ST Microelectronics:
- m24c32-u (4 kBytes)
- m24c64-u (8 kBytes)
- m24128-u (16 kBytes)
- m24256-u (32 kBytes)
- m24512-u (64 kBytes)

Microchip:
- 24AA256-UID (32 kBytes)

The eeprom interface software assumes the default I2C address 0x50 as defined in EEP_MEM_I2C_ADDR (eeprom.c). This value can
be changed as required. The same is valid for the UID address in case a ST eeprom is used, which is assumed 0x58 by default,
and is defined in EEP_UID_I2C_ADDR (eeprom.c).

These eeprom types were chosen because they contain a serial number. This serial number is used to fill in object
OD_PERSIST_COMM.x1018_identity.serialNumber

The first 8 kBytes (or 4 kBytes in case of the m24c32-u) of eeprom storage are reserved for CanOpenNode. If the project also
requires storage for the application, a 16kByte or larger eeprom should be selected. The starting address and storage size
for the user application storage can be found in variables data_storage_start and data_storage_size after initialization.
Both variables are defined in eeprom.c

When the application is first run, the EEPROM is uninitialized. CanOpenNode will remain in the pre-operational state in that case.
To initialize the EEPROM storage, write visible string "save" to object 0x1010 sub-object 0x01 using SDO write.
Next, reset the microcontroller. CanOpenNode can now be put in the "running" state.

When the application is still in the development stage, it often happens that the number or type of PERSIST_COMM objects
needs to be changed. I have found that it may be required to reinitialize the EEPROM storage in that case.
This demo application runs on a STM32G0C1E-EV board, which contains a 4 way controller.
The EEPROM can be invalidated by keeping the "down" key pressed during power-up, after which it can be initialized again.
@TheCitrusMan

Copy link
Copy Markdown
Author

I believe everything should be ok now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants