├── .github
└── workflows
│ └── master.yml
├── .gitignore
├── .mbedignore
├── CANopenNode.lib
├── CONTRIBUTING.md
├── CO_OD.c
├── CO_OD.h
├── README.md
├── config.h
├── doc
└── wiring.jpg
├── main.cpp
├── mbed-os.lib
└── mbed_app.json
/.github/workflows/master.yml:
--------------------------------------------------------------------------------
1 | # This is a basic workflow to help you get started with Actions
2 |
3 | name: CI master
4 |
5 | # Controls when the action will run.
6 | on:
7 | # Triggers the workflow on push or pull request events but only for the master branch
8 | push:
9 | branches: [ master ]
10 |
11 | pull_request:
12 | branches: [ master ]
13 |
14 | # Allows you to run this workflow manually from the Actions tab
15 | workflow_dispatch:
16 |
17 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel
18 | jobs:
19 | # This workflow contains a single job called "build"
20 | build:
21 | # The type of runner that the job will run on
22 | runs-on: ubuntu-20.04
23 | env:
24 | TARGET_MACHINE: NUCLEO_F091RC
25 |
26 | # Steps represent a sequence of tasks that will be executed as part of the job
27 | steps:
28 |
29 | - name: Show TARGET
30 | run: |
31 | echo "Target is ${{ env.TARGET_MACHINE }}"
32 |
33 | # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
34 | - name: Checkout
35 | uses: actions/checkout@v2
36 |
37 | # Runs a single command using the runners shell
38 | - name: Run a one-line script
39 | run: echo Hello, world!
40 |
41 | - name: Install Python
42 | uses: actions/setup-python@v2.2.2
43 | with:
44 | # Version range or exact version of a Python version to use, using SemVer's version range syntax.
45 | python-version: 2.x
46 |
47 | - name: Install arm-none-eabi-gcc
48 | # You may pin to the exact commit or the version.
49 | # uses: fiam/arm-none-eabi-gcc@77f4527db18a17bf6def2cfeeea231f7bfa50902
50 | uses: fiam/arm-none-eabi-gcc@v1.0.2
51 | with:
52 | # GNU Embedded Toolchain for Arm release name, in the V-YYYY-qZ format (e.g. "9-2019-q4")
53 | release: "7-2018-q2"
54 | env:
55 | ACTIONS_ALLOW_UNSECURE_COMMANDS: "true"
56 |
57 | - name: Show Python/pip/git/gcc versions
58 | run: |
59 | echo "---------------------------------------------------"
60 | python --version
61 | echo "---------------------------------------------------"
62 | pip --version
63 | echo "---------------------------------------------------"
64 | git --version
65 | echo "---------------------------------------------------"
66 | arm-none-eabi-gcc --version
67 | echo "---------------------------------------------------"
68 | wget --version
69 |
70 | - name: Install python/mbed/gcc requirements
71 | run: |
72 | echo "Installing mbed cli"
73 | pip install mbed-cli==1.10.0
74 | echo "---------------------------------------------------"
75 | echo "Downloading mbed-os 5.15 requirements.txt"
76 | wget "https://raw.githubusercontent.com/ARMmbed/mbed-os/mbed-os-5.15/requirements.txt"
77 | echo "---------------------------------------------------"
78 | echo "Installing requirements using pip"
79 | pip install -r requirements.txt
80 | echo "---------------------------------------------------"
81 | mbed --version
82 | echo "---------------------------------------------------"
83 | GCC_BIN=$(which arm-none-eabi-gcc | awk -F'arm' '{print $1}')
84 | echo "GCC PATH = $GCC_BIN"
85 | mbed config -G GCC_ARM_PATH "$GCC_BIN"
86 |
87 | - name: Mbed deploy
88 | run: mbed deploy -v
89 |
90 | - name: Mbed compile
91 | run: mbed compile -t GCC_ARM -m ${{ env.TARGET_MACHINE }}
92 |
93 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .build
2 | .mbed
3 | projectfiles
4 | *.py*
5 | .vscode
6 | GettingStarted.html
--------------------------------------------------------------------------------
/.mbedignore:
--------------------------------------------------------------------------------
1 | CANopenNode/example/*
2 | CANopenNode/stack/drvTemplate/*
3 | CANopenNode/stack/dsPIC30F/*
4 | CANopenNode/stack/eCos/*
5 | CANopenNode/stack/LPC177x_8x/*
6 | CANopenNode/stack/LPC1768/*
7 | CANopenNode/stack/MCF5282/*
8 | CANopenNode/stack/neuberger-socketCAN/*
9 | CANopenNode/stack/PIC24_dsPIC33/*
10 | CANopenNode/stack/PIC32/*
11 | CANopenNode/stack/SAM3X/*
12 | CANopenNode/stack/socketCAN/*
13 | CANopenNode/stack/STM32/*
14 | CANopenNode/stack/STM32F3/*
15 | mbed-os/features/nanostack/sal-stack-nanostack/source/Service_Libs/utils/ns_crc*
--------------------------------------------------------------------------------
/CANopenNode.lib:
--------------------------------------------------------------------------------
1 | https://github.com/Alphatronics/CANopenNode/#14678019528726b8de2742249dafd2964421595b
2 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing to Mbed OS
2 |
3 | Mbed OS is an open-source, device software platform for the Internet of Things. Contributions are an important part of the platform, and our goal is to make it as simple as possible to become a contributor.
4 |
5 | To encourage productive collaboration, as well as robust, consistent and maintainable code, we have a set of guidelines for [contributing to Mbed OS](https://os.mbed.com/docs/latest/reference/contributing.html).
6 |
--------------------------------------------------------------------------------
/CO_OD.c:
--------------------------------------------------------------------------------
1 | /*
2 | * CANopen Object Dictionary.
3 | *
4 | * This file was automatically generated with CANopenNode Object
5 | * Dictionary Editor. DON'T EDIT THIS FILE MANUALLY !!!!
6 | * Object Dictionary Editor is currently an older, but functional web
7 | * application. For more info see See 'Object_Dictionary_Editor/about.html' in
8 | *
9 | * For more information on CANopen Object Dictionary see .
10 | *
11 | * @file CO_OD.c
12 | * @author Janez Paternoster
13 | * @copyright 2010 - 2016 Janez Paternoster
14 | *
15 | * This file is part of CANopenNode, an opensource CANopen Stack.
16 | * Project home page is .
17 | * For more information on CANopen see .
18 | *
19 | * CANopenNode is free and open source software: you can redistribute
20 | * it and/or modify it under the terms of the GNU General Public License
21 | * as published by the Free Software Foundation, either version 2 of the
22 | * License, or (at your option) any later version.
23 | *
24 | * This program is distributed in the hope that it will be useful,
25 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 | * GNU General Public License for more details.
28 | *
29 | * You should have received a copy of the GNU General Public License
30 | * along with this program. If not, see .
31 | *
32 | * Following clarification and special exception to the GNU General Public
33 | * License is included to the distribution terms of CANopenNode:
34 | *
35 | * Linking this library statically or dynamically with other modules is
36 | * making a combined work based on this library. Thus, the terms and
37 | * conditions of the GNU General Public License cover the whole combination.
38 | *
39 | * As a special exception, the copyright holders of this library give
40 | * you permission to link this library with independent modules to
41 | * produce an executable, regardless of the license terms of these
42 | * independent modules, and to copy and distribute the resulting
43 | * executable under terms of your choice, provided that you also meet,
44 | * for each linked independent module, the terms and conditions of the
45 | * license of that module. An independent module is a module which is
46 | * not derived from or based on this library. If you modify this
47 | * library, you may extend this exception to your version of the
48 | * library, but you are not obliged to do so. If you do not wish
49 | * to do so, delete this exception statement from your version.
50 | */
51 |
52 |
53 | #include "CO_driver.h"
54 | #include "CO_OD.h"
55 | #include "CO_SDO.h"
56 |
57 |
58 | /*******************************************************************************
59 | DEFINITION AND INITIALIZATION OF OBJECT DICTIONARY VARIABLES
60 | *******************************************************************************/
61 |
62 | /***** Definition for RAM variables *******************************************/
63 | struct sCO_OD_RAM CO_OD_RAM = {
64 | CO_OD_FIRST_LAST_WORD,
65 |
66 | /*1001*/ 0x0,
67 | /*1002*/ 0x0L,
68 | /*1003*/ {0x0L, 0x0L, 0x0L, 0x0L, 0x0L, 0x0L, 0x0L, 0x0L},
69 | /*1010*/ {0x3L},
70 | /*1011*/ {0x1L},
71 | /*2100*/ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
72 | /*2103*/ 0x0,
73 | /*2104*/ 0x0,
74 | /*2107*/ {0x3E8, 0x0, 0x0, 0x0, 0x0},
75 | /*2108*/ {0},
76 | /*2109*/ {0},
77 | /*2110*/ {0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L},
78 | /*2120*/ {0x5, 0x1234567890ABCDEFLL, 0x234567890ABCDEF1LL, 12.345, 456.789, 0},
79 | /*2130*/ {0x3, {'-', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '}, 0, 0x0L},
80 | /*6000*/ {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
81 | /*6200*/ {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
82 | /*6401*/ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
83 | /*6411*/ {0, 0, 0, 0, 0, 0, 0, 0},
84 |
85 | CO_OD_FIRST_LAST_WORD,
86 | };
87 |
88 |
89 | /***** Definition for EEPROM variables ****************************************/
90 | struct sCO_OD_EEPROM CO_OD_EEPROM = {
91 | CO_OD_FIRST_LAST_WORD,
92 |
93 | /*2106*/ 0x0L,
94 | /*2112*/ {1L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L},
95 |
96 | CO_OD_FIRST_LAST_WORD,
97 | };
98 |
99 |
100 | /***** Definition for ROM variables *******************************************/
101 | struct sCO_OD_ROM CO_OD_ROM = { //constant variables, stored in flash
102 | CO_OD_FIRST_LAST_WORD,
103 |
104 | /*1000*/ 0x0L,
105 | /*1005*/ 0x80L,
106 | /*1006*/ 0x0L,
107 | /*1007*/ 0x0L,
108 | /*1008*/ {'A', 'l', 'p', 'h', 't', 'r', 'o', 'n', 'i', 'c', 's'},
109 | /*1009*/ {'1', '.', '0', 'A'},
110 | /*100A*/ {'1', '9', '1', '0'},
111 | /*1014*/ 0x80L,
112 | /*1015*/ 0x64,
113 | /*1016*/ {0x0L, 0x0L, 0x0L, 0x0L},
114 | /*1017*/ 0x1F4, // 500 ms
115 | /*1018*/ {0x4, 0x0L, 0x0L, 0x0L, 0x0L},
116 | /*1019*/ 0x0,
117 | /*1029*/ {0x0, 0x0, 0x1, 0x0, 0x0, 0x0},
118 | /*1200*/{{0x2, 0x600L, 0x580L}},
119 | /*1400*/{{0x2, 0x200L, 0xFF},
120 | /*1401*/ {0x2, 0x300L, 0xFE},
121 | /*1402*/ {0x2, 0x400L, 0xFE},
122 | /*1403*/ {0x2, 0x500L, 0xFE}},
123 | /*1600*/{{0x2, 0x62000108L, 0x62000208L, 0x0L, 0x0L, 0x0L, 0x0L, 0x0L, 0x0L},
124 | /*1601*/ {0x0, 0x0L, 0x0L, 0x0L, 0x0L, 0x0L, 0x0L, 0x0L, 0x0L},
125 | /*1602*/ {0x0, 0x0L, 0x0L, 0x0L, 0x0L, 0x0L, 0x0L, 0x0L, 0x0L},
126 | /*1603*/ {0x0, 0x0L, 0x0L, 0x0L, 0x0L, 0x0L, 0x0L, 0x0L, 0x0L}},
127 | /*1800*/{{0x6, 0x180L, 0xFF, 0x64, 0x0, 0x0, 0x0},
128 | /*1801*/ {0x6, 0x280L, 0xFE, 0x0, 0x0, 0x0, 0x0},
129 | /*1802*/ {0x6, 0x380L, 0xFE, 0x0, 0x0, 0x0, 0x0},
130 | /*1803*/ {0x6, 0x480L, 0xFE, 0x0, 0x0, 0x0, 0x0}},
131 | /*1A00*/{{0x2, 0x60000108L, 0x60000208L, 0x0L, 0x0L, 0x0L, 0x0L, 0x0L, 0x0L},
132 | /*1A01*/ {0x0, 0x0L, 0x0L, 0x0L, 0x0L, 0x0L, 0x0L, 0x0L, 0x0L},
133 | /*1A02*/ {0x0, 0x0L, 0x0L, 0x0L, 0x0L, 0x0L, 0x0L, 0x0L, 0x0L},
134 | /*1A03*/ {0x0, 0x0L, 0x0L, 0x0L, 0x0L, 0x0L, 0x0L, 0x0L, 0x0L}},
135 | /*1F80*/ 0x0L,
136 | /*2101*/ CANOPEN_DEFAULT_NODE_ID,
137 | /*2102*/ 0xFA,
138 | /*2111*/ {1L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L},
139 |
140 | CO_OD_FIRST_LAST_WORD
141 | };
142 |
143 |
144 | /*******************************************************************************
145 | STRUCTURES FOR RECORD TYPE OBJECTS
146 | *******************************************************************************/
147 | /*0x1018*/ const CO_OD_entryRecord_t OD_record1018[5] = {
148 | {(void*)&CO_OD_ROM.identity.maxSubIndex, 0x05, 1},
149 | {(void*)&CO_OD_ROM.identity.vendorID, 0x85, 4},
150 | {(void*)&CO_OD_ROM.identity.productCode, 0x85, 4},
151 | {(void*)&CO_OD_ROM.identity.revisionNumber, 0x85, 4},
152 | {(void*)&CO_OD_ROM.identity.serialNumber, 0x85, 4}};
153 | /*0x1200*/ const CO_OD_entryRecord_t OD_record1200[3] = {
154 | {(void*)&CO_OD_ROM.SDOServerParameter[0].maxSubIndex, 0x05, 1},
155 | {(void*)&CO_OD_ROM.SDOServerParameter[0].COB_IDClientToServer, 0x85, 4},
156 | {(void*)&CO_OD_ROM.SDOServerParameter[0].COB_IDServerToClient, 0x85, 4}};
157 | /*0x1400*/ const CO_OD_entryRecord_t OD_record1400[3] = {
158 | {(void*)&CO_OD_ROM.RPDOCommunicationParameter[0].maxSubIndex, 0x05, 1},
159 | {(void*)&CO_OD_ROM.RPDOCommunicationParameter[0].COB_IDUsedByRPDO, 0x8D, 4},
160 | {(void*)&CO_OD_ROM.RPDOCommunicationParameter[0].transmissionType, 0x0D, 1}};
161 | /*0x1401*/ const CO_OD_entryRecord_t OD_record1401[3] = {
162 | {(void*)&CO_OD_ROM.RPDOCommunicationParameter[1].maxSubIndex, 0x05, 1},
163 | {(void*)&CO_OD_ROM.RPDOCommunicationParameter[1].COB_IDUsedByRPDO, 0x8D, 4},
164 | {(void*)&CO_OD_ROM.RPDOCommunicationParameter[1].transmissionType, 0x0D, 1}};
165 | /*0x1402*/ const CO_OD_entryRecord_t OD_record1402[3] = {
166 | {(void*)&CO_OD_ROM.RPDOCommunicationParameter[2].maxSubIndex, 0x05, 1},
167 | {(void*)&CO_OD_ROM.RPDOCommunicationParameter[2].COB_IDUsedByRPDO, 0x8D, 4},
168 | {(void*)&CO_OD_ROM.RPDOCommunicationParameter[2].transmissionType, 0x0D, 1}};
169 | /*0x1403*/ const CO_OD_entryRecord_t OD_record1403[3] = {
170 | {(void*)&CO_OD_ROM.RPDOCommunicationParameter[3].maxSubIndex, 0x05, 1},
171 | {(void*)&CO_OD_ROM.RPDOCommunicationParameter[3].COB_IDUsedByRPDO, 0x8D, 4},
172 | {(void*)&CO_OD_ROM.RPDOCommunicationParameter[3].transmissionType, 0x0D, 1}};
173 | /*0x1600*/ const CO_OD_entryRecord_t OD_record1600[9] = {
174 | {(void*)&CO_OD_ROM.RPDOMappingParameter[0].numberOfMappedObjects, 0x0D, 1},
175 | {(void*)&CO_OD_ROM.RPDOMappingParameter[0].mappedObject1, 0x8D, 4},
176 | {(void*)&CO_OD_ROM.RPDOMappingParameter[0].mappedObject2, 0x8D, 4},
177 | {(void*)&CO_OD_ROM.RPDOMappingParameter[0].mappedObject3, 0x8D, 4},
178 | {(void*)&CO_OD_ROM.RPDOMappingParameter[0].mappedObject4, 0x8D, 4},
179 | {(void*)&CO_OD_ROM.RPDOMappingParameter[0].mappedObject5, 0x8D, 4},
180 | {(void*)&CO_OD_ROM.RPDOMappingParameter[0].mappedObject6, 0x8D, 4},
181 | {(void*)&CO_OD_ROM.RPDOMappingParameter[0].mappedObject7, 0x8D, 4},
182 | {(void*)&CO_OD_ROM.RPDOMappingParameter[0].mappedObject8, 0x8D, 4}};
183 | /*0x1601*/ const CO_OD_entryRecord_t OD_record1601[9] = {
184 | {(void*)&CO_OD_ROM.RPDOMappingParameter[1].numberOfMappedObjects, 0x0D, 1},
185 | {(void*)&CO_OD_ROM.RPDOMappingParameter[1].mappedObject1, 0x8D, 4},
186 | {(void*)&CO_OD_ROM.RPDOMappingParameter[1].mappedObject2, 0x8D, 4},
187 | {(void*)&CO_OD_ROM.RPDOMappingParameter[1].mappedObject3, 0x8D, 4},
188 | {(void*)&CO_OD_ROM.RPDOMappingParameter[1].mappedObject4, 0x8D, 4},
189 | {(void*)&CO_OD_ROM.RPDOMappingParameter[1].mappedObject5, 0x8D, 4},
190 | {(void*)&CO_OD_ROM.RPDOMappingParameter[1].mappedObject6, 0x8D, 4},
191 | {(void*)&CO_OD_ROM.RPDOMappingParameter[1].mappedObject7, 0x8D, 4},
192 | {(void*)&CO_OD_ROM.RPDOMappingParameter[1].mappedObject8, 0x8D, 4}};
193 | /*0x1602*/ const CO_OD_entryRecord_t OD_record1602[9] = {
194 | {(void*)&CO_OD_ROM.RPDOMappingParameter[2].numberOfMappedObjects, 0x0D, 1},
195 | {(void*)&CO_OD_ROM.RPDOMappingParameter[2].mappedObject1, 0x8D, 4},
196 | {(void*)&CO_OD_ROM.RPDOMappingParameter[2].mappedObject2, 0x8D, 4},
197 | {(void*)&CO_OD_ROM.RPDOMappingParameter[2].mappedObject3, 0x8D, 4},
198 | {(void*)&CO_OD_ROM.RPDOMappingParameter[2].mappedObject4, 0x8D, 4},
199 | {(void*)&CO_OD_ROM.RPDOMappingParameter[2].mappedObject5, 0x8D, 4},
200 | {(void*)&CO_OD_ROM.RPDOMappingParameter[2].mappedObject6, 0x8D, 4},
201 | {(void*)&CO_OD_ROM.RPDOMappingParameter[2].mappedObject7, 0x8D, 4},
202 | {(void*)&CO_OD_ROM.RPDOMappingParameter[2].mappedObject8, 0x8D, 4}};
203 | /*0x1603*/ const CO_OD_entryRecord_t OD_record1603[9] = {
204 | {(void*)&CO_OD_ROM.RPDOMappingParameter[3].numberOfMappedObjects, 0x0D, 1},
205 | {(void*)&CO_OD_ROM.RPDOMappingParameter[3].mappedObject1, 0x8D, 4},
206 | {(void*)&CO_OD_ROM.RPDOMappingParameter[3].mappedObject2, 0x8D, 4},
207 | {(void*)&CO_OD_ROM.RPDOMappingParameter[3].mappedObject3, 0x8D, 4},
208 | {(void*)&CO_OD_ROM.RPDOMappingParameter[3].mappedObject4, 0x8D, 4},
209 | {(void*)&CO_OD_ROM.RPDOMappingParameter[3].mappedObject5, 0x8D, 4},
210 | {(void*)&CO_OD_ROM.RPDOMappingParameter[3].mappedObject6, 0x8D, 4},
211 | {(void*)&CO_OD_ROM.RPDOMappingParameter[3].mappedObject7, 0x8D, 4},
212 | {(void*)&CO_OD_ROM.RPDOMappingParameter[3].mappedObject8, 0x8D, 4}};
213 | /*0x1800*/ const CO_OD_entryRecord_t OD_record1800[7] = {
214 | {(void*)&CO_OD_ROM.TPDOCommunicationParameter[0].maxSubIndex, 0x05, 1},
215 | {(void*)&CO_OD_ROM.TPDOCommunicationParameter[0].COB_IDUsedByTPDO, 0x8D, 4},
216 | {(void*)&CO_OD_ROM.TPDOCommunicationParameter[0].transmissionType, 0x0D, 1},
217 | {(void*)&CO_OD_ROM.TPDOCommunicationParameter[0].inhibitTime, 0x8D, 2},
218 | {(void*)&CO_OD_ROM.TPDOCommunicationParameter[0].compatibilityEntry, 0x0D, 1},
219 | {(void*)&CO_OD_ROM.TPDOCommunicationParameter[0].eventTimer, 0x8D, 2},
220 | {(void*)&CO_OD_ROM.TPDOCommunicationParameter[0].SYNCStartValue, 0x0D, 1}};
221 | /*0x1801*/ const CO_OD_entryRecord_t OD_record1801[7] = {
222 | {(void*)&CO_OD_ROM.TPDOCommunicationParameter[1].maxSubIndex, 0x05, 1},
223 | {(void*)&CO_OD_ROM.TPDOCommunicationParameter[1].COB_IDUsedByTPDO, 0x8D, 4},
224 | {(void*)&CO_OD_ROM.TPDOCommunicationParameter[1].transmissionType, 0x0D, 1},
225 | {(void*)&CO_OD_ROM.TPDOCommunicationParameter[1].inhibitTime, 0x8D, 2},
226 | {(void*)&CO_OD_ROM.TPDOCommunicationParameter[1].compatibilityEntry, 0x0D, 1},
227 | {(void*)&CO_OD_ROM.TPDOCommunicationParameter[1].eventTimer, 0x8D, 2},
228 | {(void*)&CO_OD_ROM.TPDOCommunicationParameter[1].SYNCStartValue, 0x0D, 1}};
229 | /*0x1802*/ const CO_OD_entryRecord_t OD_record1802[7] = {
230 | {(void*)&CO_OD_ROM.TPDOCommunicationParameter[2].maxSubIndex, 0x05, 1},
231 | {(void*)&CO_OD_ROM.TPDOCommunicationParameter[2].COB_IDUsedByTPDO, 0x8D, 4},
232 | {(void*)&CO_OD_ROM.TPDOCommunicationParameter[2].transmissionType, 0x0D, 1},
233 | {(void*)&CO_OD_ROM.TPDOCommunicationParameter[2].inhibitTime, 0x8D, 2},
234 | {(void*)&CO_OD_ROM.TPDOCommunicationParameter[2].compatibilityEntry, 0x0D, 1},
235 | {(void*)&CO_OD_ROM.TPDOCommunicationParameter[2].eventTimer, 0x8D, 2},
236 | {(void*)&CO_OD_ROM.TPDOCommunicationParameter[2].SYNCStartValue, 0x0D, 1}};
237 | /*0x1803*/ const CO_OD_entryRecord_t OD_record1803[7] = {
238 | {(void*)&CO_OD_ROM.TPDOCommunicationParameter[3].maxSubIndex, 0x05, 1},
239 | {(void*)&CO_OD_ROM.TPDOCommunicationParameter[3].COB_IDUsedByTPDO, 0x8D, 4},
240 | {(void*)&CO_OD_ROM.TPDOCommunicationParameter[3].transmissionType, 0x0D, 1},
241 | {(void*)&CO_OD_ROM.TPDOCommunicationParameter[3].inhibitTime, 0x8D, 2},
242 | {(void*)&CO_OD_ROM.TPDOCommunicationParameter[3].compatibilityEntry, 0x0D, 1},
243 | {(void*)&CO_OD_ROM.TPDOCommunicationParameter[3].eventTimer, 0x8D, 2},
244 | {(void*)&CO_OD_ROM.TPDOCommunicationParameter[3].SYNCStartValue, 0x0D, 1}};
245 | /*0x1A00*/ const CO_OD_entryRecord_t OD_record1A00[9] = {
246 | {(void*)&CO_OD_ROM.TPDOMappingParameter[0].numberOfMappedObjects, 0x0D, 1},
247 | {(void*)&CO_OD_ROM.TPDOMappingParameter[0].mappedObject1, 0x8D, 4},
248 | {(void*)&CO_OD_ROM.TPDOMappingParameter[0].mappedObject2, 0x8D, 4},
249 | {(void*)&CO_OD_ROM.TPDOMappingParameter[0].mappedObject3, 0x8D, 4},
250 | {(void*)&CO_OD_ROM.TPDOMappingParameter[0].mappedObject4, 0x8D, 4},
251 | {(void*)&CO_OD_ROM.TPDOMappingParameter[0].mappedObject5, 0x8D, 4},
252 | {(void*)&CO_OD_ROM.TPDOMappingParameter[0].mappedObject6, 0x8D, 4},
253 | {(void*)&CO_OD_ROM.TPDOMappingParameter[0].mappedObject7, 0x8D, 4},
254 | {(void*)&CO_OD_ROM.TPDOMappingParameter[0].mappedObject8, 0x8D, 4}};
255 | /*0x1A01*/ const CO_OD_entryRecord_t OD_record1A01[9] = {
256 | {(void*)&CO_OD_ROM.TPDOMappingParameter[1].numberOfMappedObjects, 0x0D, 1},
257 | {(void*)&CO_OD_ROM.TPDOMappingParameter[1].mappedObject1, 0x8D, 4},
258 | {(void*)&CO_OD_ROM.TPDOMappingParameter[1].mappedObject2, 0x8D, 4},
259 | {(void*)&CO_OD_ROM.TPDOMappingParameter[1].mappedObject3, 0x8D, 4},
260 | {(void*)&CO_OD_ROM.TPDOMappingParameter[1].mappedObject4, 0x8D, 4},
261 | {(void*)&CO_OD_ROM.TPDOMappingParameter[1].mappedObject5, 0x8D, 4},
262 | {(void*)&CO_OD_ROM.TPDOMappingParameter[1].mappedObject6, 0x8D, 4},
263 | {(void*)&CO_OD_ROM.TPDOMappingParameter[1].mappedObject7, 0x8D, 4},
264 | {(void*)&CO_OD_ROM.TPDOMappingParameter[1].mappedObject8, 0x8D, 4}};
265 | /*0x1A02*/ const CO_OD_entryRecord_t OD_record1A02[9] = {
266 | {(void*)&CO_OD_ROM.TPDOMappingParameter[2].numberOfMappedObjects, 0x0D, 1},
267 | {(void*)&CO_OD_ROM.TPDOMappingParameter[2].mappedObject1, 0x8D, 4},
268 | {(void*)&CO_OD_ROM.TPDOMappingParameter[2].mappedObject2, 0x8D, 4},
269 | {(void*)&CO_OD_ROM.TPDOMappingParameter[2].mappedObject3, 0x8D, 4},
270 | {(void*)&CO_OD_ROM.TPDOMappingParameter[2].mappedObject4, 0x8D, 4},
271 | {(void*)&CO_OD_ROM.TPDOMappingParameter[2].mappedObject5, 0x8D, 4},
272 | {(void*)&CO_OD_ROM.TPDOMappingParameter[2].mappedObject6, 0x8D, 4},
273 | {(void*)&CO_OD_ROM.TPDOMappingParameter[2].mappedObject7, 0x8D, 4},
274 | {(void*)&CO_OD_ROM.TPDOMappingParameter[2].mappedObject8, 0x8D, 4}};
275 | /*0x1A03*/ const CO_OD_entryRecord_t OD_record1A03[9] = {
276 | {(void*)&CO_OD_ROM.TPDOMappingParameter[3].numberOfMappedObjects, 0x0D, 1},
277 | {(void*)&CO_OD_ROM.TPDOMappingParameter[3].mappedObject1, 0x8D, 4},
278 | {(void*)&CO_OD_ROM.TPDOMappingParameter[3].mappedObject2, 0x8D, 4},
279 | {(void*)&CO_OD_ROM.TPDOMappingParameter[3].mappedObject3, 0x8D, 4},
280 | {(void*)&CO_OD_ROM.TPDOMappingParameter[3].mappedObject4, 0x8D, 4},
281 | {(void*)&CO_OD_ROM.TPDOMappingParameter[3].mappedObject5, 0x8D, 4},
282 | {(void*)&CO_OD_ROM.TPDOMappingParameter[3].mappedObject6, 0x8D, 4},
283 | {(void*)&CO_OD_ROM.TPDOMappingParameter[3].mappedObject7, 0x8D, 4},
284 | {(void*)&CO_OD_ROM.TPDOMappingParameter[3].mappedObject8, 0x8D, 4}};
285 | /*0x2120*/ const CO_OD_entryRecord_t OD_record2120[6] = {
286 | {(void*)&CO_OD_RAM.testVar.maxSubIndex, 0x06, 1},
287 | {(void*)&CO_OD_RAM.testVar.I64, 0xBE, 8},
288 | {(void*)&CO_OD_RAM.testVar.U64, 0xBE, 8},
289 | {(void*)&CO_OD_RAM.testVar.R32, 0xBE, 4},
290 | {(void*)&CO_OD_RAM.testVar.R64, 0xBE, 8},
291 | {0, 0x0E, 0}};
292 | /*0x2130*/ const CO_OD_entryRecord_t OD_record2130[4] = {
293 | {(void*)&CO_OD_RAM.time.maxSubIndex, 0x06, 1},
294 | {(void*)&CO_OD_RAM.time.string[0], 0x06, 30},
295 | {(void*)&CO_OD_RAM.time.epochTimeBaseMs, 0x8E, 8},
296 | {(void*)&CO_OD_RAM.time.epochTimeOffsetMs, 0xBE, 4}};
297 |
298 |
299 | /*******************************************************************************
300 | OBJECT DICTIONARY
301 | *******************************************************************************/
302 | const CO_OD_entry_t CO_OD[CO_OD_NoOfElements] = {
303 | {0x1000, 0x00, 0x85, 4, (void*)&CO_OD_ROM.deviceType},
304 | {0x1001, 0x00, 0x36, 1, (void*)&CO_OD_RAM.errorRegister},
305 | {0x1002, 0x00, 0xB6, 4, (void*)&CO_OD_RAM.manufacturerStatusRegister},
306 | {0x1003, 0x08, 0x8E, 4, (void*)&CO_OD_RAM.preDefinedErrorField[0]},
307 | {0x1005, 0x00, 0x8D, 4, (void*)&CO_OD_ROM.COB_ID_SYNCMessage},
308 | {0x1006, 0x00, 0x8D, 4, (void*)&CO_OD_ROM.communicationCyclePeriod},
309 | {0x1007, 0x00, 0x8D, 4, (void*)&CO_OD_ROM.synchronousWindowLength},
310 | {0x1008, 0x00, 0x05, 11, (void*)&CO_OD_ROM.manufacturerDeviceName[0]},
311 | {0x1009, 0x00, 0x05, 4, (void*)&CO_OD_ROM.manufacturerHardwareVersion[0]},
312 | {0x100A, 0x00, 0x05, 4, (void*)&CO_OD_ROM.manufacturerSoftwareVersion[0]},
313 | {0x1010, 0x01, 0x8E, 4, (void*)&CO_OD_RAM.storeParameters[0]},
314 | {0x1011, 0x01, 0x8E, 4, (void*)&CO_OD_RAM.restoreDefaultParameters[0]},
315 | {0x1014, 0x00, 0x85, 4, (void*)&CO_OD_ROM.COB_ID_EMCY},
316 | {0x1015, 0x00, 0x8D, 2, (void*)&CO_OD_ROM.inhibitTimeEMCY},
317 | {0x1016, 0x04, 0x8D, 4, (void*)&CO_OD_ROM.consumerHeartbeatTime[0]},
318 | {0x1017, 0x00, 0x8D, 2, (void*)&CO_OD_ROM.producerHeartbeatTime},
319 | {0x1018, 0x04, 0x00, 0, (void*)&OD_record1018},
320 | {0x1019, 0x00, 0x0D, 1, (void*)&CO_OD_ROM.synchronousCounterOverflowValue},
321 | {0x1029, 0x06, 0x0D, 1, (void*)&CO_OD_ROM.errorBehavior[0]},
322 | {0x1200, 0x02, 0x00, 0, (void*)&OD_record1200},
323 | {0x1400, 0x02, 0x00, 0, (void*)&OD_record1400},
324 | {0x1401, 0x02, 0x00, 0, (void*)&OD_record1401},
325 | {0x1402, 0x02, 0x00, 0, (void*)&OD_record1402},
326 | {0x1403, 0x02, 0x00, 0, (void*)&OD_record1403},
327 | {0x1600, 0x08, 0x00, 0, (void*)&OD_record1600},
328 | {0x1601, 0x08, 0x00, 0, (void*)&OD_record1601},
329 | {0x1602, 0x08, 0x00, 0, (void*)&OD_record1602},
330 | {0x1603, 0x08, 0x00, 0, (void*)&OD_record1603},
331 | {0x1800, 0x06, 0x00, 0, (void*)&OD_record1800},
332 | {0x1801, 0x06, 0x00, 0, (void*)&OD_record1801},
333 | {0x1802, 0x06, 0x00, 0, (void*)&OD_record1802},
334 | {0x1803, 0x06, 0x00, 0, (void*)&OD_record1803},
335 | {0x1A00, 0x08, 0x00, 0, (void*)&OD_record1A00},
336 | {0x1A01, 0x08, 0x00, 0, (void*)&OD_record1A01},
337 | {0x1A02, 0x08, 0x00, 0, (void*)&OD_record1A02},
338 | {0x1A03, 0x08, 0x00, 0, (void*)&OD_record1A03},
339 | {0x1F80, 0x00, 0x8D, 4, (void*)&CO_OD_ROM.NMTStartup},
340 | {0x2100, 0x00, 0x36, 10, (void*)&CO_OD_RAM.errorStatusBits[0]},
341 | {0x2101, 0x00, 0x0D, 1, (void*)&CO_OD_ROM.CANNodeID},
342 | {0x2102, 0x00, 0x8D, 2, (void*)&CO_OD_ROM.CANBitRate},
343 | {0x2103, 0x00, 0x8E, 2, (void*)&CO_OD_RAM.SYNCCounter},
344 | {0x2104, 0x00, 0x86, 2, (void*)&CO_OD_RAM.SYNCTime},
345 | {0x2106, 0x00, 0x87, 4, (void*)&CO_OD_EEPROM.powerOnCounter},
346 | {0x2107, 0x05, 0xBE, 2, (void*)&CO_OD_RAM.performance[0]},
347 | {0x2108, 0x01, 0xB6, 2, (void*)&CO_OD_RAM.temperature[0]},
348 | {0x2109, 0x01, 0xB6, 2, (void*)&CO_OD_RAM.voltage[0]},
349 | {0x2110, 0x10, 0xFE, 4, (void*)&CO_OD_RAM.variableInt32[0]},
350 | {0x2111, 0x10, 0xFD, 4, (void*)&CO_OD_ROM.variableROMInt32[0]},
351 | {0x2112, 0x10, 0xFF, 4, (void*)&CO_OD_EEPROM.variableNVInt32[0]},
352 | {0x2120, 0x05, 0x00, 0, (void*)&OD_record2120},
353 | {0x2130, 0x03, 0x00, 0, (void*)&OD_record2130},
354 | {0x6000, 0x08, 0x76, 1, (void*)&CO_OD_RAM.readInput8Bit[0]},
355 | {0x6200, 0x08, 0x3E, 1, (void*)&CO_OD_RAM.writeOutput8Bit[0]},
356 | {0x6401, 0x0C, 0xB6, 2, (void*)&CO_OD_RAM.readAnalogueInput16Bit[0]},
357 | {0x6411, 0x08, 0xBE, 2, (void*)&CO_OD_RAM.writeAnalogueOutput16Bit[0]},
358 | };
359 |
360 |
--------------------------------------------------------------------------------
/CO_OD.h:
--------------------------------------------------------------------------------
1 | /*
2 | * CANopen Object Dictionary.
3 | *
4 | * This file was automatically generated with CANopenNode Object
5 | * Dictionary Editor. DON'T EDIT THIS FILE MANUALLY !!!!
6 | * Object Dictionary Editor is currently an older, but functional web
7 | * application. For more info see See 'Object_Dictionary_Editor/about.html' in
8 | *
9 | * For more information on CANopen Object Dictionary see .
10 | *
11 | * @file CO_OD.h
12 | * @author Janez Paternoster
13 | * @copyright 2010 - 2016 Janez Paternoster
14 | *
15 | * This file is part of CANopenNode, an opensource CANopen Stack.
16 | * Project home page is .
17 | * For more information on CANopen see .
18 | *
19 | * CANopenNode is free and open source software: you can redistribute
20 | * it and/or modify it under the terms of the GNU General Public License
21 | * as published by the Free Software Foundation, either version 2 of the
22 | * License, or (at your option) any later version.
23 | *
24 | * This program is distributed in the hope that it will be useful,
25 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 | * GNU General Public License for more details.
28 | *
29 | * You should have received a copy of the GNU General Public License
30 | * along with this program. If not, see .
31 | *
32 | * Following clarification and special exception to the GNU General Public
33 | * License is included to the distribution terms of CANopenNode:
34 | *
35 | * Linking this library statically or dynamically with other modules is
36 | * making a combined work based on this library. Thus, the terms and
37 | * conditions of the GNU General Public License cover the whole combination.
38 | *
39 | * As a special exception, the copyright holders of this library give
40 | * you permission to link this library with independent modules to
41 | * produce an executable, regardless of the license terms of these
42 | * independent modules, and to copy and distribute the resulting
43 | * executable under terms of your choice, provided that you also meet,
44 | * for each linked independent module, the terms and conditions of the
45 | * license of that module. An independent module is a module which is
46 | * not derived from or based on this library. If you modify this
47 | * library, you may extend this exception to your version of the
48 | * library, but you are not obliged to do so. If you do not wish
49 | * to do so, delete this exception statement from your version.
50 | */
51 |
52 |
53 | #ifndef CO_OD_H
54 | #define CO_OD_H
55 |
56 | #include "config.h"
57 |
58 |
59 | /*******************************************************************************
60 | FILE INFO:
61 | FileName: IO Example
62 | FileVersion: -
63 | CreationTime: 18:04:29
64 | CreationDate: 2016-03-25
65 | CreatedBy: JP
66 | *******************************************************************************/
67 |
68 |
69 | /*******************************************************************************
70 | DEVICE INFO:
71 | VendorName: CANopenNode
72 | VendorNumber: 0
73 | ProductName: CANopenNode
74 | ProductNumber: 0
75 | *******************************************************************************/
76 |
77 |
78 | /*******************************************************************************
79 | FEATURES
80 | *******************************************************************************/
81 | #define CO_NO_SYNC 1 //Associated objects: 1005, 1006, 1007, 2103, 2104
82 | #define CO_NO_TIME 0 //Associated objects: 1012-1013
83 | #define CO_NO_EMERGENCY 1 //Associated objects: 1014, 1015
84 | #define CO_NO_SDO_SERVER 1 //Associated objects: 1200
85 | #define CO_NO_SDO_CLIENT 0
86 | #define CO_NO_RPDO 4 //Associated objects: 1400, 1401, 1402, 1403, 1600, 1601, 1602, 1603
87 | #define CO_NO_TPDO 4 //Associated objects: 1800, 1801, 1802, 1803, 1A00, 1A01, 1A02, 1A03
88 | #define CO_NO_NMT_MASTER 0
89 | #define CO_NO_TRACE 0
90 | #define CO_NO_LSS_SERVER 0
91 | #define CO_NO_LSS_CLIENT 0
92 |
93 | /*******************************************************************************
94 | OBJECT DICTIONARY
95 | *******************************************************************************/
96 | #define CO_OD_NoOfElements 55
97 |
98 |
99 | /*******************************************************************************
100 | TYPE DEFINITIONS FOR RECORDS
101 | *******************************************************************************/
102 | /*1018 */ typedef struct{
103 | uint8_t maxSubIndex;
104 | uint32_t vendorID;
105 | uint32_t productCode;
106 | uint32_t revisionNumber;
107 | uint32_t serialNumber;
108 | } OD_identity_t;
109 |
110 | /*1200[1] */ typedef struct{
111 | uint8_t maxSubIndex;
112 | uint32_t COB_IDClientToServer;
113 | uint32_t COB_IDServerToClient;
114 | } OD_SDOServerParameter_t;
115 |
116 | /*1400[4] */ typedef struct{
117 | uint8_t maxSubIndex;
118 | uint32_t COB_IDUsedByRPDO;
119 | uint8_t transmissionType;
120 | } OD_RPDOCommunicationParameter_t;
121 |
122 | /*1600[4] */ typedef struct{
123 | uint8_t numberOfMappedObjects;
124 | uint32_t mappedObject1;
125 | uint32_t mappedObject2;
126 | uint32_t mappedObject3;
127 | uint32_t mappedObject4;
128 | uint32_t mappedObject5;
129 | uint32_t mappedObject6;
130 | uint32_t mappedObject7;
131 | uint32_t mappedObject8;
132 | } OD_RPDOMappingParameter_t;
133 |
134 | /*1800[4] */ typedef struct{
135 | uint8_t maxSubIndex;
136 | uint32_t COB_IDUsedByTPDO;
137 | uint8_t transmissionType;
138 | uint16_t inhibitTime;
139 | uint8_t compatibilityEntry;
140 | uint16_t eventTimer;
141 | uint8_t SYNCStartValue;
142 | } OD_TPDOCommunicationParameter_t;
143 |
144 | /*1A00[4] */ typedef struct{
145 | uint8_t numberOfMappedObjects;
146 | uint32_t mappedObject1;
147 | uint32_t mappedObject2;
148 | uint32_t mappedObject3;
149 | uint32_t mappedObject4;
150 | uint32_t mappedObject5;
151 | uint32_t mappedObject6;
152 | uint32_t mappedObject7;
153 | uint32_t mappedObject8;
154 | } OD_TPDOMappingParameter_t;
155 |
156 | /*2120 */ typedef struct{
157 | uint8_t maxSubIndex;
158 | int64_t I64;
159 | uint64_t U64;
160 | float32_t R32;
161 | float64_t R64;
162 | domain_t domain_t;
163 | } OD_testVar_t;
164 |
165 | /*2130 */ typedef struct{
166 | uint8_t maxSubIndex;
167 | char_t string[30];
168 | uint64_t epochTimeBaseMs;
169 | uint32_t epochTimeOffsetMs;
170 | } OD_time_t;
171 |
172 |
173 | /*******************************************************************************
174 | STRUCTURES FOR VARIABLES IN DIFFERENT MEMORY LOCATIONS
175 | *******************************************************************************/
176 | #define CO_OD_FIRST_LAST_WORD 0x55 //Any value from 0x01 to 0xFE. If changed, EEPROM will be reinitialized.
177 |
178 | /***** Structure for RAM variables ********************************************/
179 | struct sCO_OD_RAM{
180 | uint32_t FirstWord;
181 |
182 | /*1001 */ uint8_t errorRegister;
183 | /*1002 */ uint32_t manufacturerStatusRegister;
184 | /*1003 */ uint32_t preDefinedErrorField[8];
185 | /*1010 */ uint32_t storeParameters[1];
186 | /*1011 */ uint32_t restoreDefaultParameters[1];
187 | /*2100 */ oChar_t errorStatusBits[10];
188 | /*2103 */ uint16_t SYNCCounter;
189 | /*2104 */ uint16_t SYNCTime;
190 | /*2107 */ uint16_t performance[5];
191 | /*2108 */ int16_t temperature[1];
192 | /*2109 */ int16_t voltage[1];
193 | /*2110 */ int32_t variableInt32[16];
194 | /*2120 */ OD_testVar_t testVar;
195 | /*2130 */ OD_time_t time;
196 | /*6000 */ uint8_t readInput8Bit[8];
197 | /*6200 */ uint8_t writeOutput8Bit[8];
198 | /*6401 */ int16_t readAnalogueInput16Bit[12];
199 | /*6411 */ int16_t writeAnalogueOutput16Bit[8];
200 |
201 | uint32_t LastWord;
202 | };
203 |
204 | /***** Structure for EEPROM variables *****************************************/
205 | struct sCO_OD_EEPROM{
206 | uint32_t FirstWord;
207 |
208 | /*2106 */ uint32_t powerOnCounter;
209 | /*2112 */ int32_t variableNVInt32[16];
210 |
211 | uint32_t LastWord;
212 | };
213 |
214 |
215 | /***** Structure for ROM variables ********************************************/
216 | struct sCO_OD_ROM{
217 | uint32_t FirstWord;
218 |
219 | /*1000 */ uint32_t deviceType;
220 | /*1005 */ uint32_t COB_ID_SYNCMessage;
221 | /*1006 */ uint32_t communicationCyclePeriod;
222 | /*1007 */ uint32_t synchronousWindowLength;
223 | /*1008 */ char_t manufacturerDeviceName[11];
224 | /*1009 */ char_t manufacturerHardwareVersion[4];
225 | /*100A */ char_t manufacturerSoftwareVersion[4];
226 | /*1014 */ uint32_t COB_ID_EMCY;
227 | /*1015 */ uint16_t inhibitTimeEMCY;
228 | /*1016 */ uint32_t consumerHeartbeatTime[4];
229 | /*1017 */ uint16_t producerHeartbeatTime;
230 | /*1018 */ OD_identity_t identity;
231 | /*1019 */ uint8_t synchronousCounterOverflowValue;
232 | /*1029 */ uint8_t errorBehavior[6];
233 | /*1200[1] */ OD_SDOServerParameter_t SDOServerParameter[1];
234 | /*1400[4] */ OD_RPDOCommunicationParameter_t RPDOCommunicationParameter[4];
235 | /*1600[4] */ OD_RPDOMappingParameter_t RPDOMappingParameter[4];
236 | /*1800[4] */ OD_TPDOCommunicationParameter_t TPDOCommunicationParameter[4];
237 | /*1A00[4] */ OD_TPDOMappingParameter_t TPDOMappingParameter[4];
238 | /*1F80 */ uint32_t NMTStartup;
239 | /*2101 */ uint8_t CANNodeID;
240 | /*2102 */ uint16_t CANBitRate;
241 | /*2111 */ int32_t variableROMInt32[16];
242 |
243 | uint32_t LastWord;
244 | };
245 |
246 |
247 | /***** Declaration of Object Dictionary variables *****************************/
248 | extern struct sCO_OD_RAM CO_OD_RAM;
249 |
250 | extern struct sCO_OD_EEPROM CO_OD_EEPROM;
251 |
252 | extern struct sCO_OD_ROM CO_OD_ROM;
253 |
254 |
255 | /*******************************************************************************
256 | ALIASES FOR OBJECT DICTIONARY VARIABLES
257 | *******************************************************************************/
258 | /*1000, Data Type: uint32_t */
259 | #define OD_deviceType CO_OD_ROM.deviceType
260 |
261 | /*1001, Data Type: uint8_t */
262 | #define OD_errorRegister CO_OD_RAM.errorRegister
263 |
264 | /*1002, Data Type: uint32_t */
265 | #define OD_manufacturerStatusRegister CO_OD_RAM.manufacturerStatusRegister
266 |
267 | /*1003, Data Type: uint32_t, Array[8] */
268 | #define OD_preDefinedErrorField CO_OD_RAM.preDefinedErrorField
269 | #define ODL_preDefinedErrorField_arrayLength 8
270 |
271 | /*1005, Data Type: uint32_t */
272 | #define OD_COB_ID_SYNCMessage CO_OD_ROM.COB_ID_SYNCMessage
273 |
274 | /*1006, Data Type: uint32_t */
275 | #define OD_communicationCyclePeriod CO_OD_ROM.communicationCyclePeriod
276 |
277 | /*1007, Data Type: uint32_t */
278 | #define OD_synchronousWindowLength CO_OD_ROM.synchronousWindowLength
279 |
280 | /*1008, Data Type: char_t, Array[11] */
281 | #define OD_manufacturerDeviceName CO_OD_ROM.manufacturerDeviceName
282 | #define ODL_manufacturerDeviceName_stringLength 11
283 |
284 | /*1009, Data Type: char_t, Array[4] */
285 | #define OD_manufacturerHardwareVersion CO_OD_ROM.manufacturerHardwareVersion
286 | #define ODL_manufacturerHardwareVersion_stringLength 4
287 |
288 | /*100A, Data Type: char_t, Array[4] */
289 | #define OD_manufacturerSoftwareVersion CO_OD_ROM.manufacturerSoftwareVersion
290 | #define ODL_manufacturerSoftwareVersion_stringLength 4
291 |
292 | /*1010, Data Type: uint32_t, Array[1] */
293 | #define OD_storeParameters CO_OD_RAM.storeParameters
294 | #define ODL_storeParameters_arrayLength 1
295 | #define ODA_storeParameters_saveAllParameters 0
296 |
297 | /*1011, Data Type: uint32_t, Array[1] */
298 | #define OD_restoreDefaultParameters CO_OD_RAM.restoreDefaultParameters
299 | #define ODL_restoreDefaultParameters_arrayLength 1
300 | #define ODA_restoreDefaultParameters_restoreAllDefaultParameters 0
301 |
302 | /*1014, Data Type: uint32_t */
303 | #define OD_COB_ID_EMCY CO_OD_ROM.COB_ID_EMCY
304 |
305 | /*1015, Data Type: uint16_t */
306 | #define OD_inhibitTimeEMCY CO_OD_ROM.inhibitTimeEMCY
307 |
308 | /*1016, Data Type: uint32_t, Array[4] */
309 | #define OD_consumerHeartbeatTime CO_OD_ROM.consumerHeartbeatTime
310 | #define ODL_consumerHeartbeatTime_arrayLength 4
311 |
312 | /*1017, Data Type: uint16_t */
313 | #define OD_producerHeartbeatTime CO_OD_ROM.producerHeartbeatTime
314 |
315 | /*1018, Data Type: OD_identity_t */
316 | #define OD_identity CO_OD_ROM.identity
317 |
318 | /*1019, Data Type: uint8_t */
319 | #define OD_synchronousCounterOverflowValue CO_OD_ROM.synchronousCounterOverflowValue
320 |
321 | /*1029, Data Type: uint8_t, Array[6] */
322 | #define OD_errorBehavior CO_OD_ROM.errorBehavior
323 | #define ODL_errorBehavior_arrayLength 6
324 | #define ODA_errorBehavior_communication 0
325 | #define ODA_errorBehavior_communicationOther 1
326 | #define ODA_errorBehavior_communicationPassive 2
327 | #define ODA_errorBehavior_generic 3
328 | #define ODA_errorBehavior_deviceProfile 4
329 | #define ODA_errorBehavior_manufacturerSpecific 5
330 |
331 | /*1200[1], Data Type: OD_SDOServerParameter_t, Array[1] */
332 | #define OD_SDOServerParameter CO_OD_ROM.SDOServerParameter
333 |
334 | /*1400[4], Data Type: OD_RPDOCommunicationParameter_t, Array[4] */
335 | #define OD_RPDOCommunicationParameter CO_OD_ROM.RPDOCommunicationParameter
336 |
337 | /*1600[4], Data Type: OD_RPDOMappingParameter_t, Array[4] */
338 | #define OD_RPDOMappingParameter CO_OD_ROM.RPDOMappingParameter
339 |
340 | /*1800[4], Data Type: OD_TPDOCommunicationParameter_t, Array[4] */
341 | #define OD_TPDOCommunicationParameter CO_OD_ROM.TPDOCommunicationParameter
342 |
343 | /*1A00[4], Data Type: OD_TPDOMappingParameter_t, Array[4] */
344 | #define OD_TPDOMappingParameter CO_OD_ROM.TPDOMappingParameter
345 |
346 | /*1F80, Data Type: uint32_t */
347 | #define OD_NMTStartup CO_OD_ROM.NMTStartup
348 |
349 | /*2100, Data Type: oChar_t, Array[10] */
350 | #define OD_errorStatusBits CO_OD_RAM.errorStatusBits
351 | #define ODL_errorStatusBits_stringLength 10
352 |
353 | /*2101, Data Type: uint8_t */
354 | #define OD_CANNodeID CO_OD_ROM.CANNodeID
355 |
356 | /*2102, Data Type: uint16_t */
357 | #define OD_CANBitRate CO_OD_ROM.CANBitRate
358 |
359 | /*2103, Data Type: uint16_t */
360 | #define OD_SYNCCounter CO_OD_RAM.SYNCCounter
361 |
362 | /*2104, Data Type: uint16_t */
363 | #define OD_SYNCTime CO_OD_RAM.SYNCTime
364 |
365 | /*2106, Data Type: uint32_t */
366 | #define OD_powerOnCounter CO_OD_EEPROM.powerOnCounter
367 |
368 | /*2107, Data Type: uint16_t, Array[5] */
369 | #define OD_performance CO_OD_RAM.performance
370 | #define ODL_performance_arrayLength 5
371 | #define ODA_performance_cyclesPerSecond 0
372 | #define ODA_performance_timerCycleTime 1
373 | #define ODA_performance_timerCycleMaxTime 2
374 | #define ODA_performance_mainCycleTime 3
375 | #define ODA_performance_mainCycleMaxTime 4
376 |
377 | /*2108, Data Type: int16_t, Array[1] */
378 | #define OD_temperature CO_OD_RAM.temperature
379 | #define ODL_temperature_arrayLength 1
380 | #define ODA_temperature_mainPCB 0
381 |
382 | /*2109, Data Type: int16_t, Array[1] */
383 | #define OD_voltage CO_OD_RAM.voltage
384 | #define ODL_voltage_arrayLength 1
385 | #define ODA_voltage_mainPCBSupply 0
386 |
387 | /*2110, Data Type: int32_t, Array[16] */
388 | #define OD_variableInt32 CO_OD_RAM.variableInt32
389 | #define ODL_variableInt32_arrayLength 16
390 |
391 | /*2111, Data Type: int32_t, Array[16] */
392 | #define OD_variableROMInt32 CO_OD_ROM.variableROMInt32
393 | #define ODL_variableROMInt32_arrayLength 16
394 |
395 | /*2112, Data Type: int32_t, Array[16] */
396 | #define OD_variableNVInt32 CO_OD_EEPROM.variableNVInt32
397 | #define ODL_variableNVInt32_arrayLength 16
398 |
399 | /*2120, Data Type: OD_testVar_t */
400 | #define OD_testVar CO_OD_RAM.testVar
401 |
402 | /*2130, Data Type: OD_time_t */
403 | #define OD_time CO_OD_RAM.time
404 |
405 | /*6000, Data Type: uint8_t, Array[8] */
406 | #define OD_readInput8Bit CO_OD_RAM.readInput8Bit
407 | #define ODL_readInput8Bit_arrayLength 8
408 |
409 | /*6200, Data Type: uint8_t, Array[8] */
410 | #define OD_writeOutput8Bit CO_OD_RAM.writeOutput8Bit
411 | #define ODL_writeOutput8Bit_arrayLength 8
412 |
413 | /*6401, Data Type: int16_t, Array[12] */
414 | #define OD_readAnalogueInput16Bit CO_OD_RAM.readAnalogueInput16Bit
415 | #define ODL_readAnalogueInput16Bit_arrayLength 12
416 |
417 | /*6411, Data Type: int16_t, Array[8] */
418 | #define OD_writeAnalogueOutput16Bit CO_OD_RAM.writeAnalogueOutput16Bit
419 | #define ODL_writeAnalogueOutput16Bit_arrayLength 8
420 |
421 |
422 | #endif
423 |
424 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # CANopenNode example for Mbed OS
2 |
3 | [](https://github.com/Alphatronics/mbed-os-example-canopen/actions/workflows/master.yml)
4 |
5 | This guide reviews the steps required to get CANopenNode working on an Mbed OS platform.
6 |
7 | **CANopenNode** is free and open source CANopen Stack.
8 |
9 | CANopen is the internationally standardized (EN 50325-4)
10 | ([CiA301](http://can-cia.org/standardization/technical-documents))
11 | CAN-based higher-layer protocol for embedded control system. For more
12 | information on CANopen see http://www.can-cia.org/
13 |
14 | CANopenNode is written in ANSI C in object-oriented way. It runs on
15 | different microcontrollers, as standalone application or with RTOS.
16 | Stack includes master functionalities. For Linux implementation with
17 | CANopen master functionalities see
18 | https://github.com/CANopenNode/CANopenSocket.
19 |
20 | Variables (communication, device, custom) are ordered in CANopen Object
21 | Dictionary and are accessible from both: C code and from CAN network.
22 |
23 | CANopenNode homepage is https://github.com/CANopenNode/CANopenNode
24 |
25 | ## CANopen Features
26 |
27 | - NMT slave to start, stop, reset device. Simple NMT master.
28 | - Heartbeat producer/consumer error control.
29 | - PDO linking and dynamic mapping for fast exchange of process variables.
30 | - SDO expedited, segmented and block transfer for service access to all parameters.
31 | - SDO master.
32 | - Emergency message.
33 | - Sync producer/consumer.
34 | - Non-volatile storage.
35 |
36 | ## Usage of CANopenNode
37 |
38 | CANopenNode itself doesn't have complete working code for any microcontroller.
39 | It is only the library with the stack and drivers for different
40 | microcontrollers. It has example, which should compile on any system with
41 | template driver (drvTemplate), which actually doesn't access CAN hardware.
42 | CANopenNode should be used as a git submodule included in a project with
43 |
44 | ## Supported boards
45 |
46 | * STM32 Nucleo F091RC
47 | * STM32 Nucleo L496ZG
48 |
49 | ## Deploying the firmware
50 |
51 | ### Import the example application
52 |
53 | Please install [mbed CLI](https://github.com/ARMmbed/mbed-cli#installing-mbed-cli).
54 |
55 | From the command-line, import the example:
56 |
57 | ```
58 | mbed import mbed-os-example-canopen
59 | cd mbed-os-example-canopen
60 | ```
61 |
62 | ### Now compile
63 |
64 | Invoke `mbed compile`, and specify the name of your platform and your favorite toolchain (`GCC_ARM`, `ARM`, `IAR`). For example, for the ARM Compiler 5:
65 |
66 | ```
67 | mbed compile -m NUCLEO_F091RC -t GCC_ARM
68 | ```
69 |
70 | Your PC may take a few minutes to compile your code. At the end, you see the following result:
71 |
72 | ```
73 | [snip]
74 | +-----------------------+--------------+----------+-----------+
75 | | Module | .text | .data | .bss |
76 | |-----------------------|--------------|----------|-----------|
77 | | CANopenNode\CANopen.o | 3626(+0) | 0(+0) | 86(+0) |
78 | | CANopenNode\stack | 23056(-146) | 0(+0) | 276(+0) |
79 | | CO_OD.o | 0(+0) | 980(+0) | 0(+0) |
80 | | [fill] | 98(+2) | 12(+0) | 20(+0) |
81 | | [lib]\c.a | 25188(+0) | 2472(+0) | 89(+0) |
82 | | [lib]\gcc.a | 8464(+0) | 0(+0) | 0(+0) |
83 | | [lib]\misc | 192(+0) | 4(+0) | 28(+0) |
84 | | main.o | 1338(+0) | 0(+0) | 222(+0) |
85 | | mbed-os\components | 244(+0) | 0(+0) | 0(+0) |
86 | | mbed-os\drivers | 1804(+0) | 0(+0) | 0(+0) |
87 | | mbed-os\events | 3184(+0) | 0(+0) | 3108(+0) |
88 | | mbed-os\hal | 2970(+0) | 4(+0) | 66(+0) |
89 | | mbed-os\platform | 6008(+0) | 260(+0) | 364(+0) |
90 | | mbed-os\rtos | 18026(+0) | 168(+0) | 5973(+0) |
91 | | mbed-os\targets | 15318(+0) | 4(+0) | 1064(+0) |
92 | | Subtotals | 109516(-144) | 3904(+0) | 11296(+0) |
93 | Total Static RAM memory (data + bss): 15200(+0) bytes
94 | Total Flash memory (text + data): 113420(-144) bytes
95 |
96 | Image: .\BUILD\NUCLEO_F091RC\GCC_ARM-DEBUG\mbed-os-example-canopen.bin
97 | ```
98 |
99 | ### Program your board
100 |
101 | 1. Connect your mbed device to the computer over USB.
102 | 2. Copy the binary file to the mbed device.
103 | 3. Press the reset button to start the program.
104 |
105 | ## Wiring
106 |
107 | 
108 |
109 | ## Output
110 |
111 | To view the serial output you can use any terminal client of your choosing such as [PuTTY](http://www.putty.org/) or [CoolTerm](http://freeware.the-meiers.org/).
112 |
113 | The default baud rate for this application is set to `115200` and may be modified in the `mbed_app.json` file.
114 |
115 | You can find more information on the Mbed OS configuration tools and serial communication in Mbed OS in the related [related links section](#related-links).
116 |
117 |
118 | ## Troubleshooting
119 |
120 | If you have problems, you can review the [documentation](https://os.mbed.com/docs/latest/tutorials/debugging.html) for suggestions on what could be wrong and how to fix it.
121 |
122 | ## Related Links
123 |
124 | * [Mbed OS Configuration](https://os.mbed.com/docs/latest/reference/configuration.html)
125 | * [Mbed OS Serial Communication](https://os.mbed.com/docs/latest/tutorials/serial-communication.html)
126 |
127 | ### License and contributions
128 |
129 | The software is provided under Apache-2.0 license. Contributions to this project are accepted under the same license. Please see contributing.md for more info.
130 |
131 | This project contains code from other projects. The original license text is included in those source files. They must comply with our license guide.
132 |
--------------------------------------------------------------------------------
/config.h:
--------------------------------------------------------------------------------
1 | #ifndef CONFIG_H
2 | #define CONFIG_H
3 |
4 | #define CAN_MODULE_ADDRESS CAN_1 // the hardware address of the can bus, since our STM32F091 has only one CAN bus this param is of no use so any value is OK
5 | #define CANOPEN_DEFAULT_NODE_ID 0x0A // CANopen NODE ID
6 | #define CAN_BITRATE 250 // in kbps
7 |
8 | #endif //CONFIG_H
--------------------------------------------------------------------------------
/doc/wiring.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alphatronics/mbed-os-example-canopen/81941bf101cf413ddba24c25c8db61e313b8dc86/doc/wiring.jpg
--------------------------------------------------------------------------------
/main.cpp:
--------------------------------------------------------------------------------
1 | /* mbed Microcontroller Library
2 | * Copyright (c) 2018 ARM Limited
3 | * SPDX-License-Identifier: Apache-2.0
4 | */
5 |
6 | #include "mbed.h"
7 |
8 | #include "CANopen.h"
9 | #include "config.h"
10 |
11 | extern "C" {
12 | #include "CO_driver.h"
13 | }
14 | #include "CO_Indicators.h"
15 |
16 |
17 | // flag used to stop threads
18 | #define STOP_THREADS_FLAG 1
19 | // Interval of tmrTask thread in micros: should always be 1ms!
20 | static const int RTTHREAD_INTERVAL_1000US = 1000;
21 | // variable increments each millisecond
22 | volatile uint16_t CO_timer1ms = 0U;
23 | // thread object that holds the RT thread
24 | Thread* rtThread;
25 | // function executed by RT thread
26 | static void rtTask(void);
27 | // Timer used to measure performance of RT thread
28 | Timer rtPerfTimer;
29 |
30 |
31 |
32 | DigitalOut userLed(LED2, 1);
33 | DigitalIn userButton(USER_BUTTON);
34 |
35 |
36 |
37 |
38 | // main() runs in its own thread in the OS
39 | int main()
40 | {
41 | printf("######## CANOPEN DEMO (" __DATE__ ", " __TIME__ ") ##########\n");
42 | OD_powerOnCounter++; // increment boot counter
43 |
44 | CO_NMT_reset_cmd_t resetCmd = CO_RESET_NOT;
45 | while(resetCmd != CO_RESET_APP && resetCmd != CO_RESET_QUIT)
46 | {
47 | printf("####### start comms-loop #######\n");
48 |
49 | // initialize CANopen
50 | CO_ReturnError_t err = CO_init((void*)CAN_MODULE_ADDRESS, CANOPEN_DEFAULT_NODE_ID, CAN_BITRATE);
51 | if(err != CO_ERROR_NO){
52 | printf("ERROR: CO_init, code: %d\n", err);
53 | ThisThread::sleep_for(3000); // in ms
54 | break;
55 | }
56 |
57 | // allow rtThread to process SYNC, RPDO and TPDO
58 | printf("Enabling rtThread processing\n");
59 | rtThread = new Thread(osPriorityAboveNormal, 8 * 1024, NULL, "rtThread");
60 | osStatus threadstate = rtThread->start(callback(rtTask));
61 | if(threadstate != osOK) {
62 | printf("Failed starting rtThread\n");
63 | }
64 |
65 | CO_CANsetNormalMode(CO->CANmodule[0]);
66 |
67 | resetCmd = CO_RESET_NOT;
68 | uint16_t previousTicksMs = CO_timer1ms;
69 |
70 | printf("CANopen ready\n");
71 | while(resetCmd == CO_RESET_NOT)
72 | {
73 | // calc the amount of millis have passed since we last ran this loop
74 | uint16_t currentTicksMs = CO_timer1ms;
75 | uint16_t millisDiff = currentTicksMs - previousTicksMs;
76 | previousTicksMs = currentTicksMs;
77 |
78 | // CANopen process (note: millisDiff will typically be 0ms or 1ms since this code loops faster than the rtThread)
79 | resetCmd = CO_process(CO, millisDiff, NULL);
80 |
81 | // Nonblocking application code may go here.
82 | // ex: killing the watchdog may be a good idea
83 | // ex: process EEPROM
84 | }
85 |
86 | printf("CANopen communication reset\n");
87 | rtThread->flags_set(STOP_THREADS_FLAG);
88 | rtThread->join();
89 | delete(rtThread);
90 | rtThread = NULL;
91 |
92 | // delete objects from memory
93 | CO_delete((void*)CAN_MODULE_ADDRESS); // => may crash application if CO_init failed
94 |
95 | // STATE MACHINE: CANopen communication reset - cleanup and reinitialize CANopen objects
96 | CO_CANreset();
97 | }
98 |
99 | // program exit: stop threads
100 | printf("Program exit!!\n");
101 |
102 | // reset
103 | if(resetCmd != CO_RESET_QUIT)
104 | system_reset();
105 | return 0;
106 | }
107 |
108 |
109 | static void rtLoop(void)
110 | {
111 | // Process Sync and read RPDO
112 | bool_t syncWas = CO_process_SYNC(CO, RTTHREAD_INTERVAL_1000US);
113 | CO_process_RPDO(CO, syncWas);
114 |
115 | //apply RPDO value to DigitalOut(s)
116 | // note: userLed is first bit of RPDO-0
117 | uint8_t outputmap = OD_writeOutput8Bit[0];
118 | userLed.write(outputmap & 0x01);
119 |
120 | //apply DigitalIn(s) value to TPDO
121 | // note: userButton is first bit of TPDO-0 and is also inverted
122 | uint8_t inputmap = (userButton.read() == 0 ? 1 : 0) & 0x01;
123 | OD_readInput8Bit[0] = inputmap;
124 |
125 | // Process TPDO
126 | CO_process_TPDO(CO, syncWas, RTTHREAD_INTERVAL_1000US);
127 |
128 | //Update LED indicators
129 | CO_Indicators_process(CO->NMT);
130 | }
131 |
132 |
133 | // timer thread executes in constant intervals
134 | static void rtTask(void)
135 | {
136 | rtPerfTimer.start();
137 |
138 | // Sleep for exact 1ms.
139 | // It schedules this this thread inactive which allows the main thread
140 | // to continue execution. It would be better if we could sleep more precisely
141 | // using nanos instead, however mbed doesn't allow that. The benefit would
142 | // be that we could sleep only the time needed to fit exactly
143 | // 1 ms taking into account the time to execute the RT code below.
144 | while(!ThisThread::flags_wait_any_for(STOP_THREADS_FLAG, RTTHREAD_INTERVAL_1000US/1000)) {
145 |
146 | CO_timer1ms++;
147 |
148 | if(CO->CANmodule[0]->CANnormal) {
149 | // We use a Timer to measure the RT thread execution time.
150 | // In case of bad performance, an EMCY msg will be created later on.
151 | rtPerfTimer.reset();
152 | int begin = rtPerfTimer.read_us();
153 |
154 | // perform RT tasks
155 | // NOTE: DO NOT PERFORM ANY PRINTF ACTIONS IN THE RT_LOOP,
156 | // it's too slow and will trigger the bad performance timer
157 | // and hence put the device in pre-op mode until reset.
158 | rtLoop();
159 |
160 | //calculate time spend executing RT code, send EMCY in case of bad performance (>1ms)
161 | int timespan = rtPerfTimer.read_us() - begin;
162 | if(timespan > RTTHREAD_INTERVAL_1000US) {
163 | float tsMillis = static_cast(timespan) / 1000;
164 | printf("RT slow: %.3fms\n", tsMillis);
165 | CO_errorReport(CO->em, CO_EM_ISR_TIMER_OVERFLOW, CO_EMC_SOFTWARE_INTERNAL, 0U);
166 | // => device will enter pre-op and must be reset
167 | }
168 | }
169 | }
170 | }
--------------------------------------------------------------------------------
/mbed-os.lib:
--------------------------------------------------------------------------------
1 | https://github.com/ARMmbed/mbed-os/#0b7d9af4dd104e57907f526ff963aa09e7018ffa
2 |
--------------------------------------------------------------------------------
/mbed_app.json:
--------------------------------------------------------------------------------
1 | {
2 | "target_overrides": {
3 | "*": {
4 | "platform.stdio-baud-rate": 115200,
5 | "platform.default-serial-baud-rate": 115200,
6 | "platform.stdio-convert-newlines": true
7 | },
8 | "LPC1768": {
9 | "target.features_remove": ["NANOSTACK", "BLE", "LWIP"]
10 | },
11 | "NUCLEO_F091RC": {
12 | "target.features_remove": ["NANOSTACK", "BLE", "LWIP"]
13 | }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------