diff --git a/.metadata/.tirex/am243x.content.tirex.json b/.metadata/.tirex/am243x.content.tirex.json index 2940b44..1b39fcf 100644 --- a/.metadata/.tirex/am243x.content.tirex.json +++ b/.metadata/.tirex/am243x.content.tirex.json @@ -1,4 +1,100 @@ [ + { + "resourceType": "project.ccs", + "resourceClass": [ + "example" + ], + "resourceSubClass": [ + "example.gettingstarted" + ], + "description": "EtherCAT connected dual servo motor drive example CPU is R5FSS0-0 running NORTOS.", + "name": "single_chip_servo", + "location": "../../examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-0_nortos/ti-arm-clang/example.projectspec", + "devtools": [ + "AM243x_LAUNCHPAD" + ], + "kernel": [ + "nortos" + ], + "compiler": [ + "ticlang" + ], + "subCategories": [ + "tidep_01032_dual_motor_drive", + "single_chip_servo", + "r5fss0-0_nortos" + ], + "mainCategories": [ + [ + "Examples", + "Development Tools" + ] + ] + }, + { + "resourceType": "project.ccs", + "resourceClass": [ + "example" + ], + "resourceSubClass": [ + "example.gettingstarted" + ], + "description": "EtherCAT connected dual servo motor drive example CPU is R5FSS0-1 running NORTOS.", + "name": "single_chip_servo", + "location": "../../examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-1_nortos/ti-arm-clang/example.projectspec", + "devtools": [ + "AM243x_LAUNCHPAD" + ], + "kernel": [ + "nortos" + ], + "compiler": [ + "ticlang" + ], + "subCategories": [ + "tidep_01032_dual_motor_drive", + "single_chip_servo", + "r5fss0-1_nortos" + ], + "mainCategories": [ + [ + "Examples", + "Development Tools" + ] + ] + }, + { + "resourceType": "project.ccs", + "resourceClass": [ + "example" + ], + "resourceSubClass": [ + "example.gettingstarted" + ], + "description": "EtherCAT connected dual servo motor drive example CPU is R5FSS1-0 running FREERTOS.", + "name": "single_chip_servo", + "location": "../../examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss1-0_freertos/ti-arm-clang/example.projectspec", + "devtools": [ + "AM243x_LAUNCHPAD" + ], + "kernel": [ + "freertos" + ], + "compiler": [ + "ticlang" + ], + "subCategories": [ + "tidep_01032_dual_motor_drive", + "single_chip_servo", + "r5fss1-0_freertos" + ], + "mainCategories": [ + [ + "Examples", + "Development Tools" + ] + ] + }, { "resourceType": "project.ccs", "resourceClass": [ @@ -1360,6 +1456,35 @@ ] ] }, + { + "resourceType": "project.ccs", + "resourceClass": [ + "example" + ], + "resourceSubClass": [ + "example.gettingstarted" + ], + "description": "EtherCAT connected dual servo motor drive example System project.", + "name": "single_chip_servo", + "location": "../../examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/system_freertos_nortos/system.projectspec", + "devtools": [ + "AM243x_LAUNCHPAD" + ], + "kernel": [ + "nortos" + ], + "subCategories": [ + "tidep_01032_dual_motor_drive", + "single_chip_servo", + "system_freertos_nortos" + ], + "mainCategories": [ + [ + "Examples", + "Development Tools" + ] + ] + }, { "resourceType": "web.page", "resourceClass": [ @@ -1368,8 +1493,8 @@ "name": "User Guide", "location": "../../docs/api_guide_am243x/index.html", "devtools": [ - "AM243x_GP_EVM", - "AM243x_LAUNCHPAD" + "AM243x_LAUNCHPAD", + "AM243x_GP_EVM" ], "mainCategories": [ [ diff --git a/.project/device/project_am243x.js b/.project/device/project_am243x.js index bd94ae0..b967a72 100644 --- a/.project/device/project_am243x.js +++ b/.project/device/project_am243x.js @@ -16,6 +16,7 @@ const device_defines = { }; const example_file_list = [ + "examples/tidep_01032_dual_motor_drive/single_chip_servo/.project/mcsdk_project.js", "examples/dcl/dcl_df22/.project/mcsdk_project.js", "examples/dcl/dcl_pi/.project/mcsdk_project.js", "examples/transforms/transforms_test/.project/mcsdk_project.js", diff --git a/examples/tidep_01032_dual_motor_drive/single_chip_servo/.project/mcsdk_project.js b/examples/tidep_01032_dual_motor_drive/single_chip_servo/.project/mcsdk_project.js new file mode 100644 index 0000000..cd0aaf2 --- /dev/null +++ b/examples/tidep_01032_dual_motor_drive/single_chip_servo/.project/mcsdk_project.js @@ -0,0 +1,20 @@ +function getComponentProperty(device) +{ + return require(`./mcsdk_project_${device}`).getComponentProperty(); +}; + +function getComponentBuildProperty(buildOption) +{ + return require(`./mcsdk_project_${buildOption.device}`).getComponentBuildProperty(buildOption); +}; + +function getSystemProjects(device) +{ + return require(`./mcsdk_project_${device}`).getSystemProjects(device); +}; + +module.exports = { + getComponentProperty, + getComponentBuildProperty, + getSystemProjects, +}; diff --git a/examples/tidep_01032_dual_motor_drive/single_chip_servo/.project/mcsdk_project_am243x.js b/examples/tidep_01032_dual_motor_drive/single_chip_servo/.project/mcsdk_project_am243x.js new file mode 100644 index 0000000..ce10846 --- /dev/null +++ b/examples/tidep_01032_dual_motor_drive/single_chip_servo/.project/mcsdk_project_am243x.js @@ -0,0 +1,395 @@ +let path = require('path'); + +let device = "am243x"; + +const files_r5f_0_0 = { + common: [ + /* Project Files */ + "endat_periodic_trigger.c", + "epwm_drv_aux.c", + "mclk_iep_sync.c", + "pwm.c", + "sddf.c", + "ti_r5fmath_trig.c", + "single_chip_servo.c", + "main.c", + ], +}; + +const files_r5f_0_1 = { + common: [ + /* Project Files */ + "epwm_drv_aux.c", + "pwm.c", + "ti_r5fmath_trig.c", + "single_chip_servo.c", + "main.c", + ], +}; + +const files_r5f_1_0 = { + common: [ + /* Project Files */ + "ind_comms_sdk/examples/industrial_comms/ethercat_slave_demo/common/ESL_version.c", + "ind_comms_sdk/examples/industrial_comms/ethercat_slave_demo/common/os/freertos/ESL_OS_os.c", + "ind_comms_sdk/examples/industrial_comms/ethercat_slave_demo/common/os/freertos/ESL_eeprom.c", + "ind_comms_sdk/examples/industrial_comms/ethercat_slave_demo/common/os/freertos/ESL_fileHandling.c", + "ind_comms_sdk/examples/industrial_comms/ethercat_slave_demo/common/os/freertos/ESL_foeDemo.c", + "ind_comms_sdk/examples/industrial_comms/ethercat_slave_demo/common/os/freertos/ESL_soeDemo.c", + "ind_comms_sdk/examples/industrial_comms/ethercat_slave_demo/common/os/freertos/ESL_gpioHelper.c", + "ind_comms_sdk/examples/industrial_comms/custom_phy/src/CUST_PHY_base.c", + "ind_comms_sdk/examples/industrial_comms/custom_phy/src/CUST_PHY_dp83869.c", + "ind_comms_sdk/examples/industrial_comms/ethercat_slave_demo/device_profiles/402_cia/ecSlvCiA402.c", + "ind_comms_sdk/examples/industrial_comms/ethercat_slave_demo/device_profiles/402_cia/ESL_cia402Obd.c", + "ind_comms_sdk/examples/industrial_comms/ethercat_slave_demo/device_profiles/402_cia/EtherCAT_Slave_CiA402.c", + "ESL_cia402Demo.c", + "ESL_BOARD_OS_config.c", + ], +}; + +const projectspec_files_r5f_0_0 = { + common: [ + "../DRV8350_defs.h", + "../endat_periodic_trigger.h", + "../epwm_drv_aux.h", + "../mclk_iep_sync.h", + "../pwm.h", + "../sddf.h", + "../tisddf_pruss_intc_mapping.h", + "../settings.h", + "../ti_r5fmath_trig.h", + ], +}; + +const projectspec_files_r5f_0_1 = { + common: [ + "../epwm_drv_aux.h", + "../pwm.h", + "../tisddf_pruss_intc_mapping.h", + "../settings.h", + "../ti_r5fmath_trig.h", + ], +}; + +const projectspec_files_r5f_1_0 = { + common: [ + "../project.h", + "../version.h", + ], +}; + +/* Relative to where the makefile will be generated + * Typically at /// + */ +const filedirs_r5f_0_0 = { + common: [ + "..", /* core_os_combo base */ + "../../..", /* Example base */ + ] +}; + +const filedirs_r5f_0_1 = { + common: [ + "..", /* core_os_combo base */ + "../../..", /* Example base */ + ], +}; + +const filedirs_r5f_1_0 = { + common: [ + "..", /* core_os_combo base */ + "../../..", /* Example base */ + "../../../../../..", /* Motor Control SDK base */ + ], +}; + +const libdirs_r5f_0_0 = { + common: [ + "${CG_TOOL_ROOT}/lib", + "${MOTOR_CONTROL_SDK_PATH}/mcu_plus_sdk/source/kernel/nortos/lib", + "${MOTOR_CONTROL_SDK_PATH}/mcu_plus_sdk/source/drivers/lib", + "${MOTOR_CONTROL_SDK_PATH}/mcu_plus_sdk/source/board/lib", + "${MOTOR_CONTROL_SDK_PATH}/source/position_sense/endat/lib", + "${MOTOR_CONTROL_SDK_PATH}/source/current_sense/sdfm/lib", + "${MOTOR_CONTROL_SDK_PATH}/mcu_plus_sdk/source/cmsis/lib", + ], +}; + +const libdirs_r5f_0_1 = { + common: [ + "${CG_TOOL_ROOT}/lib", + "${MOTOR_CONTROL_SDK_PATH}/mcu_plus_sdk/source/kernel/nortos/lib", + "${MOTOR_CONTROL_SDK_PATH}/mcu_plus_sdk/source/drivers/lib", + "${MOTOR_CONTROL_SDK_PATH}/mcu_plus_sdk/source/board/lib", + "${MOTOR_CONTROL_SDK_PATH}/source/position_sense/endat/lib", + "${MOTOR_CONTROL_SDK_PATH}/source/current_sense/sdfm/lib", + "${MOTOR_CONTROL_SDK_PATH}/mcu_plus_sdk/source/cmsis/lib", + ], +}; + +const libdirs_r5f_1_0 = { + common: [ + "${CG_TOOL_ROOT}/lib", + "${MOTOR_CONTROL_SDK_PATH}/mcu_plus_sdk/source/kernel/freertos/lib", + "${MOTOR_CONTROL_SDK_PATH}/mcu_plus_sdk/source/drivers/lib", + "${MOTOR_CONTROL_SDK_PATH}/mcu_plus_sdk/source/board/lib", + "${MOTOR_CONTROL_SDK_PATH}/ind_comms_sdk/source/industrial_comms/ethercat_slave/stack/lib", + ], +}; + +const includes_r5f_0_0 = { + common: [ + "${CG_TOOL_ROOT}/include/c", + "${MOTOR_CONTROL_SDK_PATH}/mcu_plus_sdk/source/drivers", + "${MOTOR_CONTROL_SDK_PATH}/mcu_plus_sdk/source/board", + "${MOTOR_CONTROL_SDK_PATH}/mcu_plus_sdk/source/cmsis/DSP/Include", + "${MOTOR_CONTROL_SDK_PATH}/mcu_plus_sdk/source/cmsis/Core/Include", + "${MOTOR_CONTROL_SDK_PATH}/source/current_sense/sdfm/firmware", + "${MOTOR_CONTROL_SDK_PATH}/source/current_sense/sdfm/include", + "${MOTOR_CONTROL_SDK_PATH}/source/position_sense/endat/firmware", + "${MOTOR_CONTROL_SDK_PATH}/source/position_sense/endat/include", + "${MOTOR_CONTROL_SDK_PATH}/source/transforms/clarke", + "${MOTOR_CONTROL_SDK_PATH}/source/transforms/ipark", + "${MOTOR_CONTROL_SDK_PATH}/source/transforms/park", + "${MOTOR_CONTROL_SDK_PATH}/source/transforms/svgen", + ], +}; + +const includes_r5f_0_1 = { + common: [ + "${CG_TOOL_ROOT}/include/c", + "${MOTOR_CONTROL_SDK_PATH}/mcu_plus_sdk/source/drivers", + "${MOTOR_CONTROL_SDK_PATH}/mcu_plus_sdk/source/board", + "${MOTOR_CONTROL_SDK_PATH}/mcu_plus_sdk/source/cmsis/DSP/Include", + "${MOTOR_CONTROL_SDK_PATH}/mcu_plus_sdk/source/cmsis/Core/Include", + "${MOTOR_CONTROL_SDK_PATH}/source/current_sense/sdfm/firmware", + "${MOTOR_CONTROL_SDK_PATH}/source/current_sense/sdfm/include", + "${MOTOR_CONTROL_SDK_PATH}/source/position_sense/endat/firmware", + "${MOTOR_CONTROL_SDK_PATH}/source/position_sense/endat/include", + "${MOTOR_CONTROL_SDK_PATH}/source/transforms/clarke", + "${MOTOR_CONTROL_SDK_PATH}/source/transforms/ipark", + "${MOTOR_CONTROL_SDK_PATH}/source/transforms/park", + "${MOTOR_CONTROL_SDK_PATH}/source/transforms/svgen", + ], +}; + +const includes_r5f_1_0 = { + common: [ + "${CG_TOOL_ROOT}/include/c", + "${MOTOR_CONTROL_SDK_PATH}/mcu_plus_sdk/source", + "${MOTOR_CONTROL_SDK_PATH}/ind_comms_sdk/source", + "${MOTOR_CONTROL_SDK_PATH}/mcu_plus_sdk/source/kernel/freertos/FreeRTOS-Kernel/include", + "${MOTOR_CONTROL_SDK_PATH}/mcu_plus_sdk/source/kernel/freertos/portable/TI_ARM_CLANG/ARM_CR5F", + "${MOTOR_CONTROL_SDK_PATH}/mcu_plus_sdk/source/kernel/freertos/config/am243x/r5f", + "${MOTOR_CONTROL_SDK_PATH}/ind_comms_sdk/examples/industrial_comms/ethercat_slave_demo/device_profiles/402_cia", + "${MOTOR_CONTROL_SDK_PATH}/ind_comms_sdk/examples/industrial_comms/ethercat_slave_demo/common", + "${MOTOR_CONTROL_SDK_PATH}/ind_comms_sdk/examples/industrial_comms/ethercat_slave_demo/common/os", + "${MOTOR_CONTROL_SDK_PATH}/ind_comms_sdk/examples/industrial_comms/ethercat_slave_demo/common/os/freertos", + "${MOTOR_CONTROL_SDK_PATH}/ind_comms_sdk/examples/industrial_comms/ethercat_slave_demo/common/board/am243lp", + "${MOTOR_CONTROL_SDK_PATH}/ind_comms_sdk/examples/industrial_comms/ethercat_slave_demo/common/board/am243lp/freertos", + "${MOTOR_CONTROL_SDK_PATH}/ind_comms_sdk/examples/industrial_comms/custom_phy/inc", + "${MOTOR_CONTROL_SDK_PATH}/ind_comms_sdk/source/industrial_comms/ethercat_slave/stack/inc", + "${MOTOR_CONTROL_SDK_PATH}/ind_comms_sdk/source/industrial_comms/common/inc", + ], +}; + +const libs_r5f_0_0 = { + common: [ + "libc.a", + "nortos.am243x.r5f.ti-arm-clang.${ConfigName}.lib", + "drivers.am243x.r5f.ti-arm-clang.${ConfigName}.lib", + "board.am243x.r5f.ti-arm-clang.${ConfigName}.lib", + "motorcontrol_sdfm.am243x.r5f.ti-arm-clang.${ConfigName}.lib", + "motorcontrol_endat.am243x.r5f.ti-arm-clang.${ConfigName}.lib", + "cmsis.am243x.r5f.ti-arm-clang.${ConfigName}.lib", + ], +}; + +const libs_r5f_0_1 = { + common: [ + "libc.a", + "nortos.am243x.r5f.ti-arm-clang.${ConfigName}.lib", + "drivers.am243x.r5f.ti-arm-clang.${ConfigName}.lib", + "board.am243x.r5f.ti-arm-clang.${ConfigName}.lib", + "motorcontrol_sdfm.am243x.r5f.ti-arm-clang.${ConfigName}.lib", + "motorcontrol_endat.am243x.r5f.ti-arm-clang.${ConfigName}.lib", + "cmsis.am243x.r5f.ti-arm-clang.${ConfigName}.lib", + ], +}; + +const libs_r5f_1_0 = { + common: [ + "libc.a", + "libsysbm.a", + "freertos.am243x.r5f.ti-arm-clang.${ConfigName}.lib", + "drivers.am243x.r5f.ti-arm-clang.${ConfigName}.lib", + "board.am243x.r5f.ti-arm-clang.${ConfigName}.lib", + "ethercat_slave.am243x_lp.r5f.ti-arm-clang.${ConfigName}.lib", + "ethercat_slave_bkhfSsc.am243x_lp.r5f.ti-arm-clang.${ConfigName}.lib", + ], +}; + +const defines_r5f_1_0 = { + common: [ + + "SOC_AM243X=1", + "OSAL_FREERTOS=1", + "core0", + "am243x", + "am243x_lp", + "SSC_CHECKTIMER=1", + "USE_ECAT_TIMER=1", + + ], +}; + +const cflags_r5f_1_0 = { + common: [ + + "-Wno-unused-but-set-variable", + + ], + debug: [ + + "-O0", + + ], +}; + +const lflags_r5f_1_0 = { + common: [ + + "--use_memcpy=fast", + "--use_memset=fast", + + ], +}; +const lnkfiles_r5f = { + common: [ + "linker.cmd", + ], +}; + + +const syscfgfile = "../example.syscfg"; + +const readmeDoxygenPageTag = "EXAMPLES_DUAL_MOTOR_DRIVE"; + +const templates_r5f_0_0 = +[ + { + input: ".project/templates/am243x/nortos/main_nortos.c.xdt", + output: "../main.c", + options: { + entryFunction: "single_chip_servo_main", + }, + } +]; + +const templates_r5f_0_1 = +[ + { + input: ".project/templates/am243x/nortos/main_nortos.c.xdt", + output: "../main.c", + options: { + entryFunction: "single_chip_servo_main", + }, + } +]; + +const templates_r5f_1_0 = +[ +]; + +const buildOptionCombos = [ + { device: device, cpu: "r5fss0-0", cgt: "ti-arm-clang", board: "am243x-lp", os: "nortos", isPartOfSystemProject: true}, + { device: device, cpu: "r5fss0-1", cgt: "ti-arm-clang", board: "am243x-lp", os: "nortos", isPartOfSystemProject: true}, + { device: device, cpu: "r5fss1-0", cgt: "ti-arm-clang", board: "am243x-lp", os: "freertos", isPartOfSystemProject: true}, +]; + +const systemProjects = [ + { + name: "single_chip_servo", + tag: "freertos_nortos", + skipProjectSpec: false, + readmeDoxygenPageTag: readmeDoxygenPageTag, + board: "am243x-lp", + projects: [ + { device: device, cpu: "r5fss0-0", cgt: "ti-arm-clang", board: "am243x-lp", os: "nortos"}, + { device: device, cpu: "r5fss0-1", cgt: "ti-arm-clang", board: "am243x-lp", os: "nortos"}, + { device: device, cpu: "r5fss1-0", cgt: "ti-arm-clang", board: "am243x-lp", os: "freertos"}, + ], + }, +]; + +function getComponentProperty() { + let property = {}; + + property.dirPath = path.resolve(__dirname, ".."); + property.type = "executable"; + property.name = "single_chip_servo"; + property.isInternal = false; + property.tirexResourceSubClass = [ "example.gettingstarted" ]; + property.description = "EtherCAT connected dual servo motor drive example" + property.buildOptionCombos = buildOptionCombos; + + return property; +}; + +function getComponentBuildProperty(buildOption) { + let build_property = {}; + + /* The following build property has been modified for motor drive usage, + specifically - added different includes vars distinguishing no/free rtos + added different lnkfiles vars distinguishing cpu-specific lnkfiles + */ + build_property.syscfgfile = syscfgfile; + build_property.lnkfiles = lnkfiles_r5f; + build_property.readmeDoxygenPageTag = readmeDoxygenPageTag; + + if(buildOption.cpu.match(/r5fss0-0/)) { + build_property.files = files_r5f_0_0; + build_property.filedirs = filedirs_r5f_0_0; + build_property.projectspec_files = projectspec_files_r5f_0_0; + build_property.includes = includes_r5f_0_0; + build_property.libs = libs_r5f_0_0; + build_property.libdirs = libdirs_r5f_0_0; + build_property.templates = templates_r5f_0_0; + } + + if(buildOption.cpu.match(/r5fss0-1/)) { + build_property.files = files_r5f_0_1; + build_property.filedirs = filedirs_r5f_0_1; + build_property.projectspec_files = projectspec_files_r5f_0_1; + build_property.includes = includes_r5f_0_1; + build_property.libs = libs_r5f_0_1; + build_property.libdirs = libdirs_r5f_0_1; + build_property.templates = templates_r5f_0_1; + } + + if(buildOption.cpu.match(/r5fss1-0/)) { + build_property.files = files_r5f_1_0; + build_property.filedirs = filedirs_r5f_1_0; + build_property.projectspec_files = projectspec_files_r5f_1_0; + build_property.includes = includes_r5f_1_0; + build_property.libs = libs_r5f_1_0; + build_property.libdirs = libdirs_r5f_1_0; + build_property.templates = templates_r5f_1_0; + build_property.cflags = cflags_r5f_1_0; + build_property.lflags = lflags_r5f_1_0; + build_property.defines = defines_r5f_1_0; + } + + return build_property; +}; + +function getSystemProjects(device) +{ + return systemProjects; +}; + +module.exports = { + getComponentProperty, + getComponentBuildProperty, + getSystemProjects, +}; diff --git a/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-0_nortos/DRV8350_defs.h b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-0_nortos/DRV8350_defs.h new file mode 100644 index 0000000..d45051e --- /dev/null +++ b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-0_nortos/DRV8350_defs.h @@ -0,0 +1,443 @@ +/* + * Copyright (C) 2004-2021 Texas Instruments Incorporated + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * Neither the name of Texas Instruments Incorporated nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _DRV8350_DEFS_H +#define _DRV8350_DEFS_H + +#include + +/*****************************************************************************/ +// Register Addresses +/*****************************************************************************/ +//DRV8305 Register Addresses +#define DRV8350_FAULT_STATUS_1_ADDR 0x00 +#define DRV8350_VGS_STATUS_2_ADDR 0x01 +#define DRV8350_DRIVER_CONTROL_ADDR 0x02 +#define DRV8350_GATE_DRIVE_HS_ADDR 0x03 +#define DRV8350_GATE_DRIVE_LS_ADDR 0x04 +#define DRV8350_OCP_CONTROL_ADDR 0x05 +#define DRV8350_CSA_CONTROL_ADDR 0x06 +#define DRV8350_CAL_MODE_ADDR 0x07 + +#define DRV8350_READ 0x8000 +#define DRV8350_WRITE 0x0000 +#define DRV8350_ADDR_SHIFT 11 + + +//============================================================================= + +// DRV8305 Warning and Watchdog Register bit definitions: +struct DRV8350_FAULT_STATUS_1_REG_BITS +{ // bit description + uint16_t VDS_LC:1; // 0 Over temp warning + uint16_t VDS_HC:1; // 1 temp > 135degC + uint16_t VDS_LB:1; // 2 temp > 125degC + uint16_t VDS_HB:1; // 3 temp > 105degC + uint16_t VDS_LA:1; // 4 Charge pump UV flag warning + uint16_t VDS_HA:1; // 5 Real time status of VDS sensor + uint16_t OTSD:1; // 6 PVDD ov flag + uint16_t UVLO:1; // 7 PVDD uv flag + uint16_t GDF:1; // 8 temp > 175degC + uint16_t VDS_OCP:1; // 9 + uint16_t FAULT:1; // 10 Latched fault + uint16_t Reserved2:5; // 15-11 +}; + +typedef union { + uint16_t all; + struct DRV8350_FAULT_STATUS_1_REG_BITS bit; +} DRV8350_FAULT_STATUS_1_REG; +// ============================= +struct DRV8350_VGS_STATUS_2_REG_BITS +{ // bit description + uint16_t VGS_LC:1; // 0 Over temp warning + uint16_t VGS_HC:1; // 1 temp > 135degC + uint16_t VGS_LB:1; // 2 temp > 125degC + uint16_t VGS_HB:1; // 3 temp > 105degC + uint16_t VGS_LA:1; // 4 Charge pump UV flag warning + uint16_t VGS_HA:1; // 5 Real time status of VDS sensor + uint16_t OTSD:1; // 6 VDS monitor fault - high side FET C + uint16_t OTW:1; // 7 VDS monitor fault - low side FET B + uint16_t SC_OC:1; // 8 VDS monitor fault - high side FET B + uint16_t SB_OC:1; // 9 VDS monitor fault - low side FET A + uint16_t SA_OC:1; // 10 VDS monitor fault - high side FET A + uint16_t Reserved2:5; // 15-11 +}; + +typedef union { + uint16_t all; + struct DRV8350_VGS_STATUS_2_REG_BITS bit; +} DRV8350_VGS_STATUS_2_REG; +// ============================= +struct DRV8350_DRIVER_CONTROL_REG_BITS +{ // bit description + uint16_t CLR_FLT:1; // 0 charge pump high side OV ABS fault + uint16_t BRAKE:1; // 1 charge pump high side OV fault + uint16_t COAST:1; // 2 charge pump high side UV fault + uint16_t PWM1_DIR:1; // 3 + uint16_t PWM1_COM:1; // 4 charge pump low side gate driver fault + uint16_t PWM_MODE:2; // 5:6 AVDD uv fault + uint16_t OTW_REP:1; // 7 + uint16_t DIS_GDF:1; // 8 Over temp fault + uint16_t DIS_GDUV:1; // 9 Watchdog fault + uint16_t OCP_ACT:1; // 10 PVDD uvder uv 2 fault + uint16_t Reserved3:5; // 15-11 +}; + +typedef union { + uint16_t all; + struct DRV8350_DRIVER_CONTROL_REG_BITS bit; +} DRV8350_DRIVER_CONTROL_REG; + +enum { + DRV8350_OCP_disable_phase = 0, + DRV8350_OCP_disable_three_phases = 1 +}; + +enum { + DRV8350_VCP_VGLS_enable = 0, + DRV8350_VCP_VGLS_disable = 1 +}; + +enum { + DRV8350_gate_drive_fault_enable = 0, + DRV8350_gate_drive_fault_disable = 1 +}; + +enum { + DRV8350_OTW_rep_disable = 0, + DRV8350_OTW_rep_enable = 1 +}; + +enum { + DRV8350_PWM_mode_6 = 0, + DRV8350_PWM_mode_3 = 1, + DRV8350_PWM_mode_1 = 2 +}; + +enum { + DRV8350_1PWM_mode_sync = 0, + DRV8350_1PWM_mode_async = 1 +}; + +enum { + DRV8350_coast_disable = 0, + DRV8350_coast_enable = 1 +}; + +enum { + DRV8350_brake_disable = 0, + DRV8350_brake_enable = 1 +}; + +enum { + DRV8350_ClrFaults_No = 0, + DRV8350_ClrFaults_Yes = 1 +}; + +// ============================= + +struct DRV8350_GATE_DRIVE_HS_REG_BITS +{ // bit description + uint16_t IDRIVEN_HS:4; // 3:0 + uint16_t IDRIVEP_HS:4; // 4:7 VGS monitor fault low side FET C + uint16_t LOCK:3; // 8:10 VGS monitor fault high side FET C + uint16_t Reserved2:5; // 15-11 +}; + +typedef union { + uint16_t all; + struct DRV8350_GATE_DRIVE_HS_REG_BITS bit; +} DRV8350_GATE_DRIVE_HS_REG; +// ============================= + + + +struct DRV8350_GATE_DRIVE_LS_REG_BITS +{ // bit description + uint16_t IDRIVEN_LS:4; // 3:0 high side gate driver peak source current + uint16_t IDRIVEP_LS:4; // 7:4 high side gate driver peak sink current + uint16_t TDRIVE:2; // 9:8 high side gate driver peak source time + uint16_t CBC:1; // 10 + uint16_t Reserved2:5; // 15-11 +}; + +typedef union { + uint16_t all; + struct DRV8350_GATE_DRIVE_LS_REG_BITS bit; +} DRV8350_GATE_DRIVE_LS_REG; + +enum { + DRV8350_lock_enable = 6, + DRV8350_lock_disable = 3 +}; + +enum { + DRV8350_OCP_ClrFaults_Cycle_by_Cycle_No = 0, + DRV8350_OCP_ClrFaults_Cycle_by_Cycle_Yes = 1 +}; + +enum { + DRV8350_tdrive_500nS = 0, + DRV8350_tdrive_1000nS = 1, + DRV8350_tdrive_2000nS = 2, + DRV8350_tdrive_4000nS = 3 +}; + +enum { + DRV8350_idriveN_100mA = 0, + DRV8350_idriveN_100mA1 = 1, + DRV8350_idriveN_200mA = 2, + DRV8350_idriveN_300mA = 3, + DRV8350_idriveN_600mA = 4, + DRV8350_idriveN_700mA = 5, + DRV8350_idriveN_800mA = 6, + DRV8350_idriveN_900mA = 7, + DRV8350_idriveN_1100mA = 8, + DRV8350_idriveN_1200mA = 9, + DRV8350_idriveN_1300mA = 10, + DRV8350_idriveN_1400mA = 11, + DRV8350_idriveN_1700mA = 12, + DRV8350_idriveN_1800mA = 13, + DRV8350_idriveN_1900mA = 14, + DRV8350_idriveN_2000mA = 15 +}; + +enum { + DRV8350_idriveP_50mA = 0, + DRV8350_idriveP_50mA1 = 1, + DRV8350_idriveP_100mA = 2, + DRV8350_idriveP_150mA = 3, + DRV8350_idriveP_300mA = 4, + DRV8350_idriveP_350mA = 5, + DRV8350_idriveP_400mA = 6, + DRV8350_idriveP_450mA = 7, + DRV8350_idriveP_550mA = 8, + DRV8350_idriveP_600mA = 9, + DRV8350_idriveP_650mA = 10, + DRV8350_idriveP_700mA = 11, + DRV8350_idriveP_850mA = 12, + DRV8350_idriveP_900mA = 13, + DRV8350_idriveP_950mA = 14, + DRV8350_idriveP_1000mA = 15 +}; + +// ============================= +struct DRV8350_OCP_CONTROL_REG_BITS +{ // bit description + uint16_t VDS_LVL:4; // 3:0 low side gate driver peak source current + uint16_t OCP_DEG:2; // 5:4 low side gate driver peak sink current + uint16_t OCP_MODE:2; // 7:6 low side gate driver peak source time + uint16_t DEAD_TIME:2; // 9:8 + uint16_t TRETRY:2; // 10 + uint16_t Reserved2:5; // 15-11 +}; + +typedef union { + uint16_t all; + struct DRV8350_OCP_CONTROL_REG_BITS bit; +} DRV8350_OCP_CONTROL_REG; + +enum { + DRV8350_OCP_retry_time_8ms = 0, + DRV8350_OCP_retry_time_50us = 1 +}; + +enum { + DRV8350_deadTime_50nS = 0, + DRV8350_deadTime_100nS = 1, + DRV8350_deadTime_200nS = 2, + DRV8350_deadTime_400nS = 3, +}; + +enum { + DRV8350_OCP_Latch_Fault = 0, + DRV8350_OCP_RETRY_Fault = 1, + DRV8350_OCP_report_no_action = 2, + DRV8350_OCP_no_report_no_action = 3 +}; + +enum { + DRV8350_deglitch_1us = 0, + DRV8350_deglitch_2us = 1, + DRV8350_deglitch_4us = 2, + DRV8350_deglitch_8us = 3 +}; + +enum { + DRV8350_VDS_LVL_60mV = 0, + DRV8350_VDS_LVL_70mV = 1, + DRV8350_VDS_LVL_80mV = 2, + DRV8350_VDS_LVL_90mV = 3, + DRV8350_VDS_LVL_100mV = 4, + DRV8350_VDS_LVL_200mV = 5, + DRV8350_VDS_LVL_300mV = 6, + DRV8350_VDS_LVL_400mV = 7, + DRV8350_VDS_LVL_500mV = 8, + DRV8350_VDS_LVL_600mV = 9, + DRV8350_VDS_LVL_700mV = 10, + DRV8350_VDS_LVL_800mV = 11, + DRV8350_VDS_LVL_900mV = 12, + DRV8350_VDS_LVL_1000mV = 13, + DRV8350_VDS_LVL_1500mV = 14, + DRV8350_VDS_LVL_2000mV = 15 +}; + +// ============================= +struct DRV8350_CSA_CONTROL_REG_BITS +{ // bit description + uint16_t SEN_LVL:2; // 1:0 VDS sense deglitch + uint16_t CSA_CAL_C:1; // 2 VDS sense blanking + uint16_t CSA_CAL_B:1; // 3 VDS sense blanking + uint16_t CSA_CAL_A:1; // 4 VDS sense blanking + uint16_t DIS_SEN:1; // 5 Dead time + uint16_t CSA_GAIN:2; // 7:6 PWM mode + uint16_t LS_REF:1; // 8 Rectification control + uint16_t VREF_DIF:1; // 9 Rectification control + uint16_t CSA_FET:1; // 10 + uint16_t Reserved2:5; // 15-11 +}; + +typedef union { + uint16_t all; + struct DRV8350_CSA_CONTROL_REG_BITS bit; +} DRV8350_CSA_CONTROL_REG; + +enum { + DRV8350_amp_pos_SPx = 0, + DRV8350_amp_pos_SHx = 1 +}; + +enum { + DRV8350_vref_uni = 0, + DRV8350_vref_div_2 = 1 +}; + +enum { + DRV8350_VDS_measured_SHxtoSPx = 0, + DRV8350_VDS_measured_SHxtoSNx = 1 +}; + +enum { + DRV8350_gain_CS_5 = 0, + DRV8350_gain_CS_10 = 1, + DRV8350_gain_CS_20 = 2, + DRV8350_gain_CS_40 = 3 +}; + +enum { + DRV8350_enable_SnsOcp = 0, + DRV8350_disable_SnsOcp = 1 +}; + +enum { + DRV8350_Normal_operation_amp_A = 0, + DRV8350_Calibrate_amp_A = 1 +}; +enum { + DRV8350_Normal_operation_amp_B = 0, + DRV8350_Calibrate_amp_B = 1 +}; +enum { + DRV8350_Normal_operation_amp_C = 0, + DRV8350_Calibrate_amp_C = 1 +}; + +enum { + DRV8350_Snslvl_250mV = 0, + DRV8350_Snslvl_500mV = 1, + DRV8350_Snslvl_750mV = 2, + DRV8350_Snslvl_1000mV = 3 +}; + +// ============================= +struct DRV8350_CAL_MODE_REG_BITS +{ // bit description + uint16_t CAL_MODE:1; // 0 set charge pump uv threshold level + uint16_t Reserved1:10; // 10-1 + uint16_t Reserved2:5; // 15-11 +}; + +typedef union { + uint16_t all; + struct DRV8350_CAL_MODE_REG_BITS bit; +} DRV8350_CAL_MODE_REG; + + + +enum { + DRV8350_Cal_manual = 0, + DRV8350_Cal_auto = 1 +}; +//============================================================================= +typedef struct { + DRV8350_FAULT_STATUS_1_REG status1_fault; + DRV8350_VGS_STATUS_2_REG status2_vgs; + DRV8350_DRIVER_CONTROL_REG driver_control; + DRV8350_GATE_DRIVE_HS_REG gate_drive_hs; + DRV8350_GATE_DRIVE_LS_REG gate_drive_ls; + DRV8350_OCP_CONTROL_REG ocp_control; + DRV8350_CSA_CONTROL_REG csa_control; + DRV8350_CAL_MODE_REG cal_mode; + + // DRV8350 variables + uint16_t readCntrl2, + readCntrl3, + readCntrl4, + readCntrl5, + readCntrl6, + readCntrl7, + + DRV_fault; +} DRV8350_Vars; + +#define DRV8350_DEFAULTS { \ + 0, /* Rsvd0 */ \ + 0, /* status1_wwd */ \ + 0, /* status2_ov_vds */ \ + 0, /* status3_IC */ \ + 0, /* status4_gd_Vgs */ \ + 0, /* cntr5_hs_gd */ \ + 0, /* cntr6_ls_gd */ \ + 0, /* cntr7_gd */ \ + \ + 0, /* readCntrl2 */ \ + 0, /* readCntrl3 */ \ + 0, /* readCntrl4 */ \ + 0, /* readCntrl5 */ \ + 0, /* readCntrl6 */ \ + 0, /* readCntrl7 */ \ + 0, /* DRV_fault */ \ + &SpiaRegs, \ +} + +#endif diff --git a/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-0_nortos/endat_periodic_trigger.c b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-0_nortos/endat_periodic_trigger.c new file mode 100644 index 0000000..0e055bb --- /dev/null +++ b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-0_nortos/endat_periodic_trigger.c @@ -0,0 +1,311 @@ +/* + * Copyright (C) 2023 Texas Instruments Incorporated + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * Neither the name of Texas Instruments Incorporated nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#include +#include +#include + +#include +#include +#include +#include +#include "endat_periodic_trigger.h" +#include +#include +#include +#include + +HwiP_Params hwiPrms; +static HwiP_Object gIcssgEncoderHwiObject0; /* ICSSG EnDat PRU FW HWI */ +static HwiP_Object gIcssgEncoderHwiObject1; /* ICSSG EnDat PRU FW HWI */ +static HwiP_Object gIcssgEncoderHwiObject2; /* ICSSG EnDat PRU FW HWI */ + +/* ICSSG Interrupt settings */ +#define ICSSG_PRU_ENDAT_INT_NUM ( CSLR_R5FSS0_CORE0_INTR_PRU_ICSSG0_PR1_HOST_INTR_PEND_0 ) +uint32_t gPruEnDatIrqCnt0; +uint32_t gPruEnDatIrqCnt1; +uint32_t gPruEnDatIrqCnt2; + +/*global variable */ +void *gPruss_iep; + +PRUICSS_Handle gPruIcssXHandle; + +void endat_config_iep(struct endat_periodic_interface *endat_periodic_interface) +{ + /*reset iep timer*/ + void *pruss_iep = endat_periodic_interface->pruss_iep; + struct endat_pruss_xchg *pruss_xchg = endat_periodic_interface->pruss_dmem; + uint8_t temp; + uint8_t event; + uint32_t cmp_reg0; + uint32_t cmp_reg1; + uint32_t event_clear; + uint64_t cmp0 = 0; + + /*clear IEP*/ + temp = HW_RD_REG8((uint8_t*)pruss_iep + CSL_ICSS_G_PR1_IEP1_SLV_GLOBAL_CFG_REG ); + temp &= 0xFE; + HW_WR_REG8((uint8_t*)pruss_iep + CSL_ICSS_G_PR1_IEP1_SLV_GLOBAL_CFG_REG, temp); + + /* cmp cfg reg */ + event = HW_RD_REG8((uint8_t*)pruss_iep + CSL_ICSS_G_PR1_IEP1_SLV_CMP_CFG_REG); + event_clear = HW_RD_REG8((uint8_t*)pruss_iep + CSL_ICSS_G_PR1_IEP1_SLV_CMP_STATUS_REG); + + /*enable IEP reset by cmp0 event*/ + event |= IEP_CMP0_ENABLE; + event |= IEP_RST_CNT_EN; + event_clear |= 1; + + /*set IEP counter to ZERO*/ + HW_WR_REG32((uint8_t*)pruss_iep + CSL_ICSS_G_PR1_IEP1_SLV_COUNT_REG0, 0); + HW_WR_REG32((uint8_t*)pruss_iep + CSL_ICSS_G_PR1_IEP1_SLV_COUNT_REG1, 0); + + /*Clear all event & configure*/ + if(endat_periodic_interface->load_share) + { + event |= pruss_xchg->config[0].channel==1?(0x1 << 4 ):0; //CMP3 for ch0 + event |= pruss_xchg->config[1].channel==2?(0x1 << 6 ):0; //CMP5 for Ch1 + event |= pruss_xchg->config[2].channel==4?(0x1 << 7 ):0; //CMP6 for CH2 + + /*clear event*/ + event_clear |= pruss_xchg->config[0].channel==1?(0x1 << 3 ):0; //CMP3 for ch0 + event_clear |= pruss_xchg->config[1].channel==2?(0x1 << 5 ):0; //CMP5 for Ch1 + event_clear |= pruss_xchg->config[2].channel==4?(0x1 << 6 ):0; //CMP6 for CH2 + + if(pruss_xchg->config[0].channel) + { + cmp_reg0 = (endat_periodic_interface->cmp3 & 0xffffffff) - IEP_DEFAULT_INC; + cmp_reg1 = (endat_periodic_interface->cmp3>>32 & 0xffffffff); + + HW_WR_REG32((uint8_t*)pruss_iep + CSL_ICSS_G_PR1_IEP1_SLV_CMP3_REG0, cmp_reg0); + HW_WR_REG32((uint8_t*)pruss_iep + CSL_ICSS_G_PR1_IEP1_SLV_CMP3_REG1, cmp_reg1); + + cmp0 = cmp0 > endat_periodic_interface->cmp3 ? cmp0: endat_periodic_interface->cmp3; + } + + if(pruss_xchg->config[1].channel) + { + cmp_reg0 = (endat_periodic_interface->cmp5 & 0xffffffff) - IEP_DEFAULT_INC; + cmp_reg1 = (endat_periodic_interface->cmp5>>32 & 0xffffffff); + + HW_WR_REG32((uint8_t*)pruss_iep + CSL_ICSS_G_PR1_IEP1_SLV_CMP5_REG0, cmp_reg0); + HW_WR_REG32((uint8_t*)pruss_iep + CSL_ICSS_G_PR1_IEP1_SLV_CMP5_REG1, cmp_reg1); + + cmp0 = cmp0 > endat_periodic_interface->cmp5 ? cmp0: endat_periodic_interface->cmp5; + } + + if(pruss_xchg->config[2].channel) + { + cmp_reg0 = (endat_periodic_interface->cmp6 & 0xffffffff) - IEP_DEFAULT_INC; + cmp_reg1 = (endat_periodic_interface->cmp6>>32 & 0xffffffff); + + HW_WR_REG32((uint8_t*)pruss_iep + CSL_ICSS_G_PR1_IEP1_SLV_CMP6_REG0, cmp_reg0); + HW_WR_REG32((uint8_t*)pruss_iep + CSL_ICSS_G_PR1_IEP1_SLV_CMP6_REG1, cmp_reg1); + + cmp0 = cmp0 > endat_periodic_interface->cmp6 ? cmp0: endat_periodic_interface->cmp6; + } + + + } + else + { + event |= (0x1 << 4 ); + event_clear |= (0x1 << 3); + cmp_reg0 = (endat_periodic_interface->cmp3 & 0xffffffff) - IEP_DEFAULT_INC; + cmp_reg1 = (endat_periodic_interface->cmp3>>32 & 0xffffffff); + + HW_WR_REG32((uint8_t*)pruss_iep + CSL_ICSS_G_PR1_IEP1_SLV_CMP3_REG0, cmp_reg0); + HW_WR_REG32((uint8_t*)pruss_iep + CSL_ICSS_G_PR1_IEP1_SLV_CMP3_REG1, cmp_reg1); + + cmp0 = endat_periodic_interface->cmp3; + + } + /*clear event*/ + HW_WR_REG8((uint8_t*)pruss_iep + CSL_ICSS_G_PR1_IEP1_SLV_CMP_STATUS_REG, event_clear); + /*enable event*/ + HW_WR_REG8((uint8_t*)pruss_iep + CSL_ICSS_G_PR1_IEP1_SLV_CMP_CFG_REG, event); + + /*configure cmp0 registers*/ + cmp0 = 2*cmp0; + cmp_reg0 = (cmp0 & 0xffffffff) - IEP_DEFAULT_INC; + cmp_reg1 = (cmp0>>32 & 0xffffffff); + HW_WR_REG32((uint8_t*)pruss_iep + CSL_ICSS_G_PR1_IEP1_SLV_CMP0_REG0, cmp_reg0); + HW_WR_REG32((uint8_t*)pruss_iep + CSL_ICSS_G_PR1_IEP1_SLV_CMP0_REG1, cmp_reg1); + + + /*write IEP default increment & IEP start*/ + temp = HW_RD_REG8((uint8_t*)pruss_iep + CSL_ICSS_G_PR1_IEP1_SLV_GLOBAL_CFG_REG ); + temp &= 0x0F; + temp |= 0x10; + temp |= IEP_COUNTER_EN; + HW_WR_REG8((uint8_t*)pruss_iep + CSL_ICSS_G_PR1_IEP1_SLV_GLOBAL_CFG_REG, temp); +} + + +void endat_interrupt_config(struct endat_periodic_interface *endat_periodic_interface) +{ + struct endat_pruss_xchg *pruss_xchg = endat_periodic_interface->pruss_dmem; + int32_t status; + if(endat_periodic_interface->load_share) + { + if(pruss_xchg->config[0].channel) + { + /* Register & enable ICSSG EnDat PRU FW interrupt */ + HwiP_Params_init(&hwiPrms); + hwiPrms.intNum = ICSSG_PRU_ENDAT_INT_NUM; + hwiPrms.callback = &pruEnDatIrqHandler0; + hwiPrms.args = 0; + hwiPrms.isPulse = FALSE; + hwiPrms.isFIQ = FALSE; + status = HwiP_construct(&gIcssgEncoderHwiObject0, &hwiPrms); + DebugP_assert(status == SystemP_SUCCESS); + + } + if(pruss_xchg->config[1].channel) + { + /* Register & enable ICSSG EnDat PRU FW interrupt */ + HwiP_Params_init(&hwiPrms); + hwiPrms.intNum = ICSSG_PRU_ENDAT_INT_NUM + 1; + hwiPrms.callback = &pruEnDatIrqHandler1; + hwiPrms.args = 0; + hwiPrms.isPulse = FALSE; + hwiPrms.isFIQ = FALSE; + status = HwiP_construct(&gIcssgEncoderHwiObject1, &hwiPrms); + DebugP_assert(status == SystemP_SUCCESS); + + } + if(pruss_xchg->config[2].channel) + { + /* Register & enable ICSSG EnDat PRU FW interrupt */ + HwiP_Params_init(&hwiPrms); + hwiPrms.intNum = ICSSG_PRU_ENDAT_INT_NUM + 2; + hwiPrms.callback = &pruEnDatIrqHandler2; + hwiPrms.args = 0; + hwiPrms.isPulse = FALSE; + hwiPrms.isFIQ = FALSE; + status = HwiP_construct(&gIcssgEncoderHwiObject2, &hwiPrms); + DebugP_assert(status == SystemP_SUCCESS); + + } + } + else + { + /* Register & enable ICSSG EnDat PRU FW interrupt */ + HwiP_Params_init(&hwiPrms); + hwiPrms.intNum = ICSSG_PRU_ENDAT_INT_NUM; + hwiPrms.callback = &pruEnDatIrqHandler0; + hwiPrms.args = 0; + hwiPrms.isPulse = FALSE; + hwiPrms.isFIQ = FALSE; + status = HwiP_construct(&gIcssgEncoderHwiObject0, &hwiPrms); + DebugP_assert(status == SystemP_SUCCESS); + + } + +} +uint32_t endat_config_periodic_mode(struct endat_periodic_interface *endat_periodic_interface, PRUICSS_Handle handle) +{ + gPruIcssXHandle = handle; + gPruss_iep = endat_periodic_interface->pruss_iep; + /*configure IEP*/ + endat_config_iep(endat_periodic_interface); + /* Initialize ICSS INTC */ + ///status = PRUICSS_intcInit(gPruIcssXHandle, &gPruicssIntcInitdata); + /// if (status != SystemP_SUCCESS) + /// { + /// return 0; + /// } + /*config Interrupt*/ + ///endat_interrupt_config(endat_periodic_interface); + return 1; + +} + +void endat_stop_periodic_continuous_mode(struct endat_periodic_interface *endat_periodic_interface) +{ + /*reset iep timer*/ + void *pruss_iep = endat_periodic_interface->pruss_iep; + uint8_t temp; + /*clear IEP*/ + temp = HW_RD_REG8((uint8_t*)pruss_iep + CSL_ICSS_G_PR1_IEP1_SLV_GLOBAL_CFG_REG ); + temp &= 0xFE; + HW_WR_REG8((uint8_t*)pruss_iep + CSL_ICSS_G_PR1_IEP1_SLV_GLOBAL_CFG_REG, temp); +} + +/* PRU EnDat FW IRQ handler */ +void pruEnDatIrqHandler0(void *args) +{ + + /* debug, inncrement PRU SDFM IRQ count */ + gPruEnDatIrqCnt0++; + + /* Clear interrupt at source */ + /* Write 18 to ICSSG_STATUS_CLR_INDEX_REG + Firmware: TRIGGER_HOST_SDFM_IRQ defined as 18 + 18 = 16+2, 2 is Host Interrupt Number. See AM64x TRM. + */ + PRUICSS_clearEvent(gPruIcssXHandle, PRU_TRIGGER_HOST_SDFM_EVT0); + +} +/* PRU EnDat FW IRQ handler */ +void pruEnDatIrqHandler1(void *args) +{ + /* debug, inncrement PRU SDFM IRQ count */ + gPruEnDatIrqCnt1++; + + /* Clear interrupt at source */ + /* Write 18 to ICSSG_STATUS_CLR_INDEX_REG + Firmware: TRIGGER_HOST_SDFM_IRQ defined as 18 + 18 = 16+2, 2 is Host Interrupt Number. See AM64x TRM. + */ + + PRUICSS_clearEvent(gPruIcssXHandle, PRU_TRIGGER_HOST_SDFM_EVT1); + + +} +/* PRU EnDat FW IRQ handler */ +void pruEnDatIrqHandler2(void *args) +{ + /* debug, inncrement PRU SDFM IRQ count */ + gPruEnDatIrqCnt2++; + + /* Clear interrupt at source */ + /* Write 18 to ICSSG_STATUS_CLR_INDEX_REG + Firmware: TRIGGER_HOST_SDFM_IRQ defined as 18 + 18 = 16+2, 2 is Host Interrupt Number. See AM64x TRM. + */ + PRUICSS_clearEvent(gPruIcssXHandle, PRU_TRIGGER_HOST_SDFM_EVT2); + + +} diff --git a/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-0_nortos/endat_periodic_trigger.h b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-0_nortos/endat_periodic_trigger.h new file mode 100644 index 0000000..6a94aa8 --- /dev/null +++ b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-0_nortos/endat_periodic_trigger.h @@ -0,0 +1,222 @@ +/* + * Copyright (C) 2023 Texas Instruments Incorporated + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * Neither the name of Texas Instruments Incorporated nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _ENDAT_H_ +#define _ENDAT_H_ + +#include + +struct endat_periodic_interface +{ + void *pruss_iep; + void *pruss_dmem; + void *pruss_cfg; + uint8_t load_share; + uint64_t cmp3; + uint64_t cmp5; + uint64_t cmp6; +}; + +///#define IEP_DEFAULT_INC 0x1; +#define IEP_DEFAULT_INC_EN 0x4; +#define IEP_COUNTER_EN 0x1; +#define IEP_RST_CNT_EN 0x1; +#define IEP_CMP0_ENABLE 0x1 << 1; + +#define IEP_CMP3_EVNT (0x1 << 3 ) +#define IEP_CMP5_EVNT (0x1 << 5 ) +#define IEP_CMP6_EVNT (0x1 << 6 ) + +#define PRU_TRIGGER_HOST_SDFM_EVT0 ( 2+16 ) /* pr0_pru_mst_intr[2]_intr_req */ +#define PRU_TRIGGER_HOST_SDFM_EVT1 ( 3+16 ) /* pr0_pru_mst_intr[3]_intr_req */ +#define PRU_TRIGGER_HOST_SDFM_EVT2 ( 4+16 ) /* pr0_pru_mst_intr[4]_intr_req */ + + +uint32_t endat_config_periodic_mode(struct endat_periodic_interface *endat_periodic_interface, PRUICSS_Handle handle); + +void endat_stop_periodic_continuous_mode(struct endat_periodic_interface *endat_periodic_interface); + +static void pruEnDatIrqHandler0(void *handle); +static void pruEnDatIrqHandler1(void *handle); +static void pruEnDatIrqHandler2(void *handle); + + +#define IEP_TIM_CAP_CMP_EVENT 7 +#define SYNC1_OUT_EVENT 13 +#define SYNC0_OUT_EVENT 14 + +/* SYS_EVT_16-31 can be used for generating interrupts for IPC with hosts/prus etc */ +#define PRU_ARM_EVENT00 16 +#define PRU_ARM_EVENT01 17 +#define PRU_ARM_EVENT02 18 +#define PRU_ARM_EVENT03 19 +#define PRU_ARM_EVENT04 20 +#define PRU_ARM_EVENT05 21 +#define PRU_ARM_EVENT06 22 +#define PRU_ARM_EVENT07 23 +#define PRU_ARM_EVENT08 24 +#define PRU_ARM_EVENT09 25 +#define PRU_ARM_EVENT10 26 +#define PRU_ARM_EVENT11 27 +#define PRU_ARM_EVENT12 28 +#define PRU_ARM_EVENT13 29 +#define PRU_ARM_EVENT14 30 +#define PRU_ARM_EVENT15 31 + +#define PRU0_RX_ERR32_EVENT 33 +#define PORT1_TX_UNDERFLOW 39 +#define PORT1_TX_OVERFLOW 40 +#define MII_LINK0_EVENT 41 +#define PORT1_RX_EOF_EVENT 42 +#define PRU1_RX_ERR32_EVENT 45 +#define PORT2_TX_UNDERFLOW 51 +#define PORT2_TX_OVERFLOW 53 +#define PORT2_RX_EOF_EVENT 54 +#define MII_LINK1_EVENT 53 + +#define CHANNEL0 0 +#define CHANNEL1 1 +#define CHANNEL2 2 +#define CHANNEL3 3 +#define CHANNEL4 4 +#define CHANNEL5 5 +#define CHANNEL6 6 +#define CHANNEL7 7 +#define CHANNEL8 8 +#define CHANNEL9 9 + +#define PRU0 0 +#define PRU1 1 +#define PRU_EVTOUT0 2 +#define PRU_EVTOUT1 3 +#define PRU_EVTOUT2 4 +#define PRU_EVTOUT3 5 +#define PRU_EVTOUT4 6 +#define PRU_EVTOUT5 7 +#define PRU_EVTOUT6 8 +#define PRU_EVTOUT7 9 + +#define PRU0_HOSTEN_MASK ((uint32_t)0x0001) +#define PRU1_HOSTEN_MASK ((uint32_t)0x0002) +#define PRU_EVTOUT0_HOSTEN_MASK ((uint32_t)0x0004) +#define PRU_EVTOUT1_HOSTEN_MASK ((uint32_t)0x0008) +#define PRU_EVTOUT2_HOSTEN_MASK ((uint32_t)0x0010) +#define PRU_EVTOUT3_HOSTEN_MASK ((uint32_t)0x0020) +#define PRU_EVTOUT4_HOSTEN_MASK ((uint32_t)0x0040) +#define PRU_EVTOUT5_HOSTEN_MASK ((uint32_t)0x0080) +#define PRU_EVTOUT6_HOSTEN_MASK ((uint32_t)0x0100) +#define PRU_EVTOUT7_HOSTEN_MASK ((uint32_t)0x0200) + +#define SYS_EVT_POLARITY_LOW 0 +#define SYS_EVT_POLARITY_HIGH 1 + +#define SYS_EVT_TYPE_PULSE 0 +#define SYS_EVT_TYPE_EDGE 1 + +#define PRUICSS_INTC_INITDATA { \ +{ IEP_TIM_CAP_CMP_EVENT, PRU_ARM_EVENT02, PRU_ARM_EVENT03, PRU_ARM_EVENT04, PRU_ARM_EVENT05, PRU_ARM_EVENT06, \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* initializing member [6-15] for Misra C standards */ \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* initializing member [16-31] for Misra C standards */ \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* initializing member [32-47] for Misra C standards */ \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, /* initializing member [48-63] for Misra C standards */ \ +{ {IEP_TIM_CAP_CMP_EVENT, CHANNEL1, SYS_EVT_POLARITY_HIGH, SYS_EVT_TYPE_PULSE},\ + {PRU_ARM_EVENT02, CHANNEL2, SYS_EVT_POLARITY_HIGH, SYS_EVT_TYPE_PULSE},\ + {PRU_ARM_EVENT03, CHANNEL3, SYS_EVT_POLARITY_HIGH, SYS_EVT_TYPE_PULSE},\ + {PRU_ARM_EVENT04, CHANNEL4, SYS_EVT_POLARITY_HIGH, SYS_EVT_TYPE_PULSE},\ + {PRU_ARM_EVENT05, CHANNEL5, SYS_EVT_POLARITY_HIGH, SYS_EVT_TYPE_PULSE},\ + {PRU_ARM_EVENT06, CHANNEL6, SYS_EVT_POLARITY_HIGH, SYS_EVT_TYPE_PULSE},\ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [6] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [7] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [8] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [9] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [10] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [11] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [12] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [13] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [14] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [15] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [16] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [17] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [18] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [19] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [20] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [21] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [22] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [23] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [24] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [25] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [26] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [27] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [28] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [29] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [30] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [31] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [32] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [33] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [34] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [35] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [36] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [37] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [38] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [39] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [40] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [41] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [42] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [43] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [44] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [45] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [46] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [47] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [48] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [49] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [50] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [51] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [52] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [53] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [54] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [55] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [56] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [57] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [58] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [59] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [60] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [61] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [62] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}}, /* initializing member [63] for Misra C standards */ \ + { {CHANNEL1, PRU1}, {CHANNEL2, PRU_EVTOUT0}, {CHANNEL3, PRU_EVTOUT1},\ + {CHANNEL4, PRU_EVTOUT2}, {CHANNEL5, PRU_EVTOUT3}, {CHANNEL6, PRU_EVTOUT4}, \ + {0xFF, 0xFF}, {0xFF, 0xFF}, {0xFF, 0xFF}, {0xFF, 0xFF} }, /* Initializing members [6,7,8,9] of array for Misra C standards */ \ + (PRU1_HOSTEN_MASK | PRU_EVTOUT0_HOSTEN_MASK | PRU_EVTOUT1_HOSTEN_MASK | PRU_EVTOUT2_HOSTEN_MASK | PRU_EVTOUT3_HOSTEN_MASK | PRU_EVTOUT4_HOSTEN_MASK) /* PRU_EVTOUT0 */ \ +} + + +#endif /* _ENDAT_H_ */ diff --git a/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-0_nortos/epwm_drv_aux.c b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-0_nortos/epwm_drv_aux.c new file mode 100644 index 0000000..ac68f1c --- /dev/null +++ b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-0_nortos/epwm_drv_aux.c @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2021 Texas Instruments Incorporated + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * Neither the name of Texas Instruments Incorporated nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include "epwm_drv_aux.h" + +#include + +/* Configure PWM Time base counter Frequency/Period */ +void tbPwmFreqCfg( + uint32_t baseAddr, + uint32_t tbClk, + uint32_t pwmFreq, + uint32_t counterDir, + uint32_t enableShadowWrite, + uint32_t *pPeriodCount +) +{ + uint32_t tbPeriodCount; + float tbPeriodCount_f; + uint32_t regVal = 0U; + + regVal = HW_RD_REG16(baseAddr + PWMSS_EPWM_TBCTL); + HW_SET_FIELD32(regVal, PWMSS_EPWM_TBCTL_PRDLD, enableShadowWrite); + HW_SET_FIELD32(regVal, PWMSS_EPWM_TBCTL_CTRMODE, counterDir); + HW_WR_REG16((baseAddr + PWMSS_EPWM_TBCTL), + (uint16_t)regVal); + + /* compute period using floating point */ + tbPeriodCount_f = (float)tbClk / pwmFreq; + if (EPWM_TB_COUNTER_DIR_UP_DOWN == counterDir) { + tbPeriodCount_f = tbPeriodCount_f / 2.0; + } + tbPeriodCount_f = roundf(tbPeriodCount_f); + tbPeriodCount = (uint32_t)tbPeriodCount_f; + +#if 0 /* use this in case there is some reason not to use floating point */ + /* compute period using fixed point */ + tbPeriodCount = tbClk << 4; /* U32Q4 */ + tbPeriodCount /= pwmFreq; + if (EPWM_TB_COUNTER_DIR_UP_DOWN == counterDir) { + tbPeriodCount /= 2; + } + tbPeriodCount += 1<<3; /* biased rouding to 0.5 */ + tbPeriodCount >>= 4; /* U32Q0 */ +#endif + + regVal = (counterDir == EPWM_TB_COUNTER_DIR_UP_DOWN) ? + tbPeriodCount : tbPeriodCount-1; + HW_WR_REG16((baseAddr + PWMSS_EPWM_TBPRD), + (uint16_t)regVal); + + *pPeriodCount = tbPeriodCount; +} diff --git a/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-0_nortos/epwm_drv_aux.h b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-0_nortos/epwm_drv_aux.h new file mode 100644 index 0000000..adac419 --- /dev/null +++ b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-0_nortos/epwm_drv_aux.h @@ -0,0 +1,190 @@ +/* + * Copyright (C) 2021 Texas Instruments Incorporated + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * Neither the name of Texas Instruments Incorporated nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _EPWM_DRV_AUX_H_ +#define _EPWM_DRV_AUX_H_ + +#include +#include +#include + +/* Write EPWM CMPA */ +static inline void writeCmpA( + uint32_t baseAddr, + uint32_t cmpVal +) +{ + HW_WR_REG16((baseAddr + PWMSS_EPWM_CMPA), (uint16_t)cmpVal); +} + +/* Write EPWM CMPB */ +static inline void writeCmpB( + uint32_t baseAddr, + uint32_t cmpVal +) +{ + HW_WR_REG16((baseAddr + PWMSS_EPWM_CMPB), (uint16_t)cmpVal); +} + +/* Write EPWM CMPA/CMPB */ +static inline void writeCmpAB( + uint32_t baseAddr, + uint32_t cmpAVal, + uint32_t cmpBVal +) +{ + HW_WR_REG16((baseAddr + PWMSS_EPWM_CMPA), (uint16_t)cmpAVal); + HW_WR_REG16((baseAddr + PWMSS_EPWM_CMPB), (uint16_t)cmpBVal); +} + +/* Configure Output ChannelA AQ Zero */ +static inline void cfgOutChAAqZero( + uint32_t baseAddr, + uint32_t zeroAction +) +{ + uint32_t regVal = 0U; + + regVal = HW_RD_REG16(baseAddr + PWMSS_EPWM_AQCTLA); + HW_SET_FIELD32(regVal, PWMSS_EPWM_AQCTLA_ZRO, zeroAction); + HW_WR_REG16((baseAddr + PWMSS_EPWM_AQCTLA), (uint16_t)regVal); +} + +/* Configure Output ChannelA AQ CMPA Up */ +static inline void cfgOutChAAqCAU( + uint32_t baseAddr, + uint32_t cmpAUpAction +) +{ + uint32_t regVal = 0U; + + regVal = HW_RD_REG16(baseAddr + PWMSS_EPWM_AQCTLA); + HW_SET_FIELD32(regVal, PWMSS_EPWM_AQCTLA_CAU, cmpAUpAction); + HW_WR_REG16((baseAddr + PWMSS_EPWM_AQCTLA), (uint16_t)regVal); +}; + +/* Configure Output ChannelA AQ CMPA Down */ +static inline void cfgOutChAAqCAD( + uint32_t baseAddr, + uint32_t cmpADownAction +) +{ + uint32_t regVal = 0U; + + regVal = HW_RD_REG16(baseAddr + PWMSS_EPWM_AQCTLA); + HW_SET_FIELD32(regVal, PWMSS_EPWM_AQCTLA_CAD, cmpADownAction); + HW_WR_REG16((baseAddr + PWMSS_EPWM_AQCTLA), (uint16_t)regVal); +} + +/* Configure Output ChannelB AQ Zero */ +static inline void cfgOutChBAqZero( + uint32_t baseAddr, + uint32_t zeroAction +) +{ + uint32_t regVal = 0U; + + regVal = HW_RD_REG16(baseAddr + PWMSS_EPWM_AQCTLB); + HW_SET_FIELD32(regVal, PWMSS_EPWM_AQCTLB_ZRO, zeroAction); + HW_WR_REG16((baseAddr + PWMSS_EPWM_AQCTLB), (uint16_t)regVal); +} + +/* Configure Output ChannelA AQ CMPB Up */ +static inline void cfgOutChAAqCBU( + uint32_t baseAddr, + uint32_t cmpBUpAction +) +{ + uint32_t regVal = 0U; + + regVal = HW_RD_REG16(baseAddr + PWMSS_EPWM_AQCTLA); + HW_SET_FIELD32(regVal, PWMSS_EPWM_AQCTLA_CBU, cmpBUpAction); + HW_WR_REG16((baseAddr + PWMSS_EPWM_AQCTLA), (uint16_t)regVal); +} + +/* Write TB Period */ +static inline void writeTbPrd( + uint32_t baseAddr, + uint32_t tbPeriodCount +) +{ + HW_WR_REG16((baseAddr + PWMSS_EPWM_TBPRD), (uint16_t)tbPeriodCount); +} + +/* Write TB Phase */ +static inline void writeTbPhase( + uint32_t baseAddr, + uint32_t tbPhsValue +) +{ + HW_WR_REG16((baseAddr + PWMSS_EPWM_TBPHS), (uint16_t)tbPhsValue); +} + +/* Write TBCTL HSPDIV & CLKDIV */ +static inline void writeTbClkDiv( + uint32_t baseAddr, + uint32_t hspClkDiv, + uint32_t clkDiv +) +{ + uint32_t regVal = 0U; + + regVal = HW_RD_REG16(baseAddr + PWMSS_EPWM_TBCTL); + HW_SET_FIELD32(regVal, PWMSS_EPWM_TBCTL_CLKDIV, clkDiv); + HW_SET_FIELD32(regVal, PWMSS_EPWM_TBCTL_HSPCLKDIV, hspClkDiv); + HW_WR_REG16((baseAddr + PWMSS_EPWM_TBCTL), (uint16_t)regVal); +} + +/* Write TBCTL CTRMODE */ +static inline void writeTbCtrMode( + uint32_t baseAddr, + uint32_t ctrMode +) +{ + uint32_t regVal = 0U; + + regVal = HW_RD_REG16(baseAddr + PWMSS_EPWM_TBCTL); + HW_SET_FIELD32(regVal, PWMSS_EPWM_TBCTL_CTRMODE, ctrMode); + HW_WR_REG16((baseAddr + PWMSS_EPWM_TBCTL), (uint16_t)regVal); +} + +/* Configure PWM Time base counter Frequency/Period */ +void tbPwmFreqCfg( + uint32_t baseAddr, + uint32_t tbClk, + uint32_t pwmFreq, + uint32_t counterDir, + uint32_t enableShadowWrite, + uint32_t *pPeriodCount +); + +#endif /* _EPWM_DRV_AUX_H_ */ diff --git a/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-0_nortos/example.syscfg b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-0_nortos/example.syscfg new file mode 100644 index 0000000..a51b0a6 --- /dev/null +++ b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-0_nortos/example.syscfg @@ -0,0 +1,247 @@ +/** + * These arguments were used when this file was generated. They will be automatically applied on subsequent loads + * via the GUI or CLI. Run CLI with '--help' for additional information on how to override these arguments. + * @cliArgs --device "AM243x_ALX_beta" --package "ALX" --part "ALX" --context "r5fss0-0" --product "MOTOR_CONTROL_SDK_AM243x@09.01.00" + * @versions {"tool":"1.18.0+3266"} + */ + +/** + * Import the modules used in this configuration. + */ +const epwm = scripting.addModule("/drivers/epwm/epwm", {}, false); +const epwm1 = epwm.addInstance(); +const epwm2 = epwm.addInstance(); +const epwm3 = epwm.addInstance(); +const gpio = scripting.addModule("/drivers/gpio/gpio", {}, false); +const gpio1 = gpio.addInstance(); +const gpio2 = gpio.addInstance(); +const gpio3 = gpio.addInstance(); +const ipc = scripting.addModule("/drivers/ipc/ipc"); +const mcspi = scripting.addModule("/drivers/mcspi/mcspi", {}, false); +const mcspi1 = mcspi.addInstance(); +const pruicss = scripting.addModule("/drivers/pruicss/pruicss", {}, false); +const pruicss1 = pruicss.addInstance(); +const debug_log = scripting.addModule("/kernel/dpl/debug_log"); +const mpu_armv7 = scripting.addModule("/kernel/dpl/mpu_armv7", {}, false); +const mpu_armv71 = mpu_armv7.addInstance(); +const mpu_armv72 = mpu_armv7.addInstance(); +const mpu_armv73 = mpu_armv7.addInstance(); +const mpu_armv74 = mpu_armv7.addInstance(); +const mpu_armv75 = mpu_armv7.addInstance(); +const mpu_armv76 = mpu_armv7.addInstance(); +const mpu_armv77 = mpu_armv7.addInstance(); +const mpu_armv78 = mpu_armv7.addInstance(); +const mpu_armv79 = mpu_armv7.addInstance(); +const mpu_armv710 = mpu_armv7.addInstance(); +const mpu_armv711 = mpu_armv7.addInstance(); +const mpu_armv712 = mpu_armv7.addInstance(); +const mpu_armv713 = mpu_armv7.addInstance(); +const endat = scripting.addModule("/position_sense/endat", {}, false); +const endat1 = endat.addInstance(); +const pru_ipc = scripting.addModule("/pru_io/pru_ipc/pru_ipc", {}, false); +const pru_ipc1 = pru_ipc.addInstance(); + +/** + * Write custom configuration values to the imported modules. + */ +epwm1.$name = "EPWM0"; +epwm1.EPWM.$assign = "EHRPWM2"; +epwm1.EPWM.SYNCO.$used = false; +epwm1.EPWM.SYNCI.$used = false; + +epwm2.$name = "EPWM1"; +epwm2.EPWM.$assign = "EHRPWM1"; +epwm2.EPWM.SYNCO.$used = false; +epwm2.EPWM.SYNCI.$used = false; + +epwm3.$name = "EPWM2"; +epwm3.EPWM.$assign = "EHRPWM0"; +epwm3.EPWM.SYNCO.$used = false; +epwm3.EPWM.SYNCI.$used = false; + +gpio1.$name = "MTR_1_PWM_EN"; +gpio1.pinDir = "OUTPUT"; +gpio1.GPIO.gpioPin.$assign = "I2C0_SCL"; + +gpio2.$name = "MTR_2_PWM_EN"; +gpio2.pinDir = "OUTPUT"; +gpio2.GPIO.gpioPin.$assign = "I2C0_SDA"; + +gpio3.$name = "BP_MUX_SEL"; +gpio3.pinDir = "OUTPUT"; +gpio3.GPIO.gpioPin.$assign = "GPMC0_AD11"; + + +ipc.r5fss0_1 = "notify"; +ipc.r5fss1_0 = "notify"; +ipc.r5fss1_1 = "NONE"; +ipc.m4fss0_0 = "notify"; + +mcspi1.$name = "CONFIG_MCSPI0"; +mcspi1.pinMode = 3; +mcspi1.inputSelect = "0"; +mcspi1.dpe0 = "DISABLE"; +mcspi1.dpe1 = "ENABLE"; +mcspi1.intrEnable = "POLLED"; +mcspi1.SPI.$assign = "SPI0"; +mcspi1.mcspiChannel[0].$name = "CONFIG_MCSPI_CH0"; + +debug_log.enableCssLog = false; + +mpu_armv71.$name = "CONFIG_MPU_REGION0"; +mpu_armv71.size = 31; +mpu_armv71.attributes = "Device"; +mpu_armv71.accessPermissions = "Supervisor RD+WR, User RD"; +mpu_armv71.allowExecute = false; + +mpu_armv72.$name = "CONFIG_MPU_REGION1"; +mpu_armv72.accessPermissions = "Supervisor RD+WR, User RD"; +mpu_armv72.size = 16; +mpu_armv72.attributes = "NonCached"; + +mpu_armv73.$name = "CONFIG_MPU_REGION2"; +mpu_armv73.baseAddr = 0x41010000; +mpu_armv73.accessPermissions = "Supervisor RD+WR, User RD"; +mpu_armv73.size = 16; +mpu_armv73.attributes = "NonCached"; + +mpu_armv74.$name = "CONFIG_MPU_REGION3"; +mpu_armv74.accessPermissions = "Supervisor RD+WR, User RD"; +mpu_armv74.baseAddr = 0x70000000; +mpu_armv74.size = 21; + +mpu_armv75.$name = "CONFIG_MPU_REGION4"; +mpu_armv75.baseAddr = 0x60000000; +mpu_armv75.size = 28; +mpu_armv75.attributes = "Device"; +mpu_armv75.allowExecute = false; + +mpu_armv76.$name = "CONFIG_MPU_REGION5_GPIO"; +mpu_armv76.baseAddr = 0x600000; +mpu_armv76.size = 19; +mpu_armv76.attributes = "Device"; +mpu_armv76.allowExecute = false; + +mpu_armv77.$name = "CONFIG_MPU_REGION6_ICSSG0"; +mpu_armv77.baseAddr = 0x30000000; +mpu_armv77.size = 19; +mpu_armv77.allowExecute = false; +mpu_armv77.attributes = "NonCached"; + +mpu_armv78.$name = "CONFIG_MPU_REGION7_PWMs0_8"; +mpu_armv78.baseAddr = 0x23000000; +mpu_armv78.size = 19; +mpu_armv78.attributes = "NonCached"; +mpu_armv78.allowExecute = false; + +mpu_armv79.$name = "CONFIG_MPU_REGION8_PWM9"; +mpu_armv79.attributes = "NonCached"; +mpu_armv79.size = 16; +mpu_armv79.baseAddr = 0x23080000; + +mpu_armv710.$name = "CONFIG_MPU_REGION9_OTHER_R5F_TCMB"; +mpu_armv710.baseAddr = 0x78500000; +mpu_armv710.size = 15; +mpu_armv710.allowExecute = false; +mpu_armv710.attributes = "NonCached"; + +mpu_armv711.$name = "CONFIG_MPU_MSRAM_CTRLVARS"; +mpu_armv711.baseAddr = 0x701BFF00; +mpu_armv711.size = 8; +mpu_armv711.allowExecute = false; + +mpu_armv712.$name = "CONFIG_MPU_MSRAM_NOCACHE"; +mpu_armv712.size = 16; +mpu_armv712.attributes = "NonCached"; +mpu_armv712.allowExecute = false; +mpu_armv712.baseAddr = 0x701D0000; + +mpu_armv713.$name = "CONFIG_MPU_MSRAM_NOCACHE0"; +mpu_armv713.baseAddr = 0x701C0000; +mpu_armv713.size = 16; +mpu_armv713.attributes = "NonCached"; +mpu_armv713.allowExecute = false; + +endat1.$name = "CONFIG_ENDAT0"; +endat1.Channel_2 = true; +endat1.Booster_Pack = true; +endat1.Multi_Channel_Load_Share = true; +endat1.PRU_ICSSG0_PRU.$assign = "PRU_ICSSG0_PRU1"; +endat1.PRU_ICSSG0_PRU.GPO5.$used = false; +endat1.PRU_ICSSG0_PRU.GPO4.$used = false; +endat1.PRU_ICSSG0_PRU.GPO3.$used = false; +endat1.PRU_ICSSG0_PRU.GPI14.$used = false; + +endat1.ENC1_EN.GPIO.$assign = "GPIO1"; +endat1.ENC1_EN.$name = "ENC1_EN"; +endat1.ENC1_EN.GPIO.gpioPin.pu_pd = "pu"; +endat1.ENC1_EN.GPIO.gpioPin.rx = false; +endat1.ENC1_EN.GPIO.gpioPin.$assign = "MMC1_SDWP"; + +endat1.ENC2_EN.$name = "ENC2_EN"; +endat1.ENC2_EN.GPIO.gpioPin.pu_pd = "pu"; +endat1.ENC2_EN.GPIO.gpioPin.rx = false; +endat1.ENC2_EN.GPIO.$assign = "GPIO1"; +endat1.ENC2_EN.GPIO.gpioPin.$assign = "MMC1_SDCD"; + +pruicss1.$name = "CONFIG_PRU_ICSS0"; +endat1.pru = pruicss1; +pruicss1.coreClk = 300000000; +pruicss1.iepClk = 300000000; +pruicss1.AdditionalICSSSettings[0].$name = "CONFIG_PRU_ICSS_IO0"; +pruicss1.AdditionalICSSSettings[0].PruGPIO.create(1); +pruicss1.AdditionalICSSSettings[0].PruGPIO[0].$name = "CONFIG_PRU_ICSS_GPIO0"; +pruicss1.AdditionalICSSSettings[0].PruGPIO[0].PRU_ICSSG0_PRU.GPI1.$used = true; +pruicss1.AdditionalICSSSettings[0].PruGPIO[0].PRU_ICSSG0_PRU.GPI11.$used = true; +pruicss1.AdditionalICSSSettings[0].PruGPIO[0].PRU_ICSSG0_PRU.GPI16.$used = true; +pruicss1.AdditionalICSSSettings[0].PruGPIO[0].PRU_ICSSG0_PRU.GPI18.$used = true; +pruicss1.AdditionalICSSSettings[0].PruGPIO[0].PRU_ICSSG0_PRU.GPI19.rx = false; +pruicss1.AdditionalICSSSettings[0].PruGPIO[0].PRU_ICSSG0_PRU.GPI3.$used = true; +pruicss1.AdditionalICSSSettings[0].PruGPIO[0].PRU_ICSSG0_PRU.GPI5.$used = true; +pruicss1.AdditionalICSSSettings[0].PruGPIO[0].PRU_ICSSG0_PRU.GPI7.$used = true; +pruicss1.AdditionalICSSSettings[0].PruGPIO[0].PRU_ICSSG0_PRU.GPI8.$used = true; +pruicss1.AdditionalICSSSettings[0].PruIepIO.create(1); +pruicss1.AdditionalICSSSettings[0].PruIepIO[0].$name = "CONFIG_PRU_ICSS_IEP_IO0"; +pruicss1.AdditionalICSSSettings[0].PruIepIO[0].PRU_ICSSG0_IEP.EDC_SYNC_OUT0.$used = true; +pruicss1.AdditionalICSSSettings[0].PruIepIO[0].PRU_ICSSG0_IEP.EDC_SYNC_OUT1.$used = true; + +pru_ipc1.$name = "CONFIG_PRU_IPC0"; +pru_ipc1.rxIntcMapping.$name = "CONFIG_ICSS0_INTC_MAPPING0"; + +/** + * Pinmux solution for unlocked pins/peripherals. This ensures that minor changes to the automatic solver in a future + * version of the tool will not impact the pinmux you originally saw. These lines can be completely deleted in order to + * re-solve from scratch. + */ +epwm1.EPWM.A.$suggestSolution = "GPMC0_AD8"; +epwm1.EPWM.B.$suggestSolution = "GPMC0_AD9"; +epwm2.EPWM.A.$suggestSolution = "GPMC0_AD5"; +epwm2.EPWM.B.$suggestSolution = "GPMC0_AD6"; +epwm3.EPWM.A.$suggestSolution = "GPMC0_AD3"; +epwm3.EPWM.B.$suggestSolution = "GPMC0_AD4"; +gpio1.GPIO.$suggestSolution = "GPIO1"; +gpio2.GPIO.$suggestSolution = "GPIO1"; +gpio3.GPIO.$suggestSolution = "GPIO0"; +mcspi1.SPI.CLK.$suggestSolution = "SPI0_CLK"; +mcspi1.SPI.D0.$suggestSolution = "SPI0_D0"; +mcspi1.SPI.D1.$suggestSolution = "SPI0_D1"; +endat1.PRU_ICSSG0_PRU.GPO2.$suggestSolution = "PRG0_PRU1_GPO2"; +endat1.PRU_ICSSG0_PRU.GPO1.$suggestSolution = "PRG0_PRU1_GPO1"; +endat1.PRU_ICSSG0_PRU.GPO0.$suggestSolution = "PRG0_PRU1_GPO0"; +endat1.PRU_ICSSG0_PRU.GPI13.$suggestSolution = "PRG0_PRU1_GPO13"; +endat1.PRU_ICSSG0_PRU.GPO8.$suggestSolution = "PRG0_PRU1_GPO8"; +endat1.PRU_ICSSG0_PRU.GPO12.$suggestSolution = "PRG0_PRU1_GPO12"; +endat1.PRU_ICSSG0_PRU.GPO6.$suggestSolution = "PRG0_PRU1_GPO6"; +endat1.PRU_ICSSG0_PRU.GPI11.$suggestSolution = "PRG0_PRU1_GPO11"; +pruicss1.AdditionalICSSSettings[0].PruGPIO[0].PRU_ICSSG0_PRU.$suggestSolution = "PRU_ICSSG0_PRU0"; +pruicss1.AdditionalICSSSettings[0].PruGPIO[0].PRU_ICSSG0_PRU.GPI1.$suggestSolution = "PRG0_PRU0_GPO1"; +pruicss1.AdditionalICSSSettings[0].PruGPIO[0].PRU_ICSSG0_PRU.GPI11.$suggestSolution = "PRG0_PRU0_GPO11"; +pruicss1.AdditionalICSSSettings[0].PruGPIO[0].PRU_ICSSG0_PRU.GPI16.$suggestSolution = "PRG0_PRU0_GPO16"; +pruicss1.AdditionalICSSSettings[0].PruGPIO[0].PRU_ICSSG0_PRU.GPI18.$suggestSolution = "PRG0_PRU0_GPO18"; +pruicss1.AdditionalICSSSettings[0].PruGPIO[0].PRU_ICSSG0_PRU.GPI3.$suggestSolution = "PRG0_PRU0_GPO3"; +pruicss1.AdditionalICSSSettings[0].PruGPIO[0].PRU_ICSSG0_PRU.GPI5.$suggestSolution = "PRG0_PRU0_GPO5"; +pruicss1.AdditionalICSSSettings[0].PruGPIO[0].PRU_ICSSG0_PRU.GPI7.$suggestSolution = "PRG0_PRU0_GPO7"; +pruicss1.AdditionalICSSSettings[0].PruGPIO[0].PRU_ICSSG0_PRU.GPI8.$suggestSolution = "PRG0_PRU0_GPO8"; +pruicss1.AdditionalICSSSettings[0].PruIepIO[0].PRU_ICSSG0_IEP.$suggestSolution = "PRU_ICSSG0_IEP0"; +pruicss1.AdditionalICSSSettings[0].PruIepIO[0].PRU_ICSSG0_IEP.EDC_SYNC_OUT0.$suggestSolution = "PRG0_PRU0_GPO19"; +pruicss1.AdditionalICSSSettings[0].PruIepIO[0].PRU_ICSSG0_IEP.EDC_SYNC_OUT1.$suggestSolution = "PRG0_PRU0_GPO17"; diff --git a/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-0_nortos/main.c b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-0_nortos/main.c new file mode 100644 index 0000000..6ad1b9e --- /dev/null +++ b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-0_nortos/main.c @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2018-2021 Texas Instruments Incorporated + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * Neither the name of Texas Instruments Incorporated nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include "ti_drivers_config.h" +#include "ti_board_config.h" + +void single_chip_servo_main(void *args); + +int main(void) +{ + System_init(); + Board_init(); + + single_chip_servo_main(NULL); + + Board_deinit(); + System_deinit(); + + return 0; +} diff --git a/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-0_nortos/mclk_iep_sync.c b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-0_nortos/mclk_iep_sync.c new file mode 100644 index 0000000..8821fa9 --- /dev/null +++ b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-0_nortos/mclk_iep_sync.c @@ -0,0 +1,229 @@ +/* + * Copyright (C) 2023 Texas Instruments Incorporated + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * Neither the name of Texas Instruments Incorporated nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPgResS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#include "stdint.h" +#include "math.h" +#include "stdio.h" + +#include +#include +#include + +void init_IEP0_SYNC(void) +{ + +#if 0 // FL: move to R5 +// ************************************* padconfig ************************************* +// unlock PADMMR config register + +// partition 0 + HW_WR_REG32(0x000f1008, 0x68EF3490); // Kick 0 + HW_WR_REG32(0x000f100C, 0xD172BC5A); // Kick 1 + +// partition 1 + HW_WR_REG32(0x000f5008, 0x68EF3490); // Kick 0 + HW_WR_REG32(0x000f500C, 0xD172BC5A); // Kick 1 + +// ICSS_G0 +// IEP SYNC0 -> BP.45 + HW_WR_REG32(0x000F41AC, 0x00010000 + 2); // mode 2 = SYNC0 + +// IEP SYNC1 -> BP.18 + HW_WR_REG32(0x000F41A4, 0x00010000 + 2); // mode 2 = SYNC1 +#endif +#if 0 // FL: move to R5 +// ************************************* clock config ********************************** +// core clock options: +// ICSSG0_CLKMUX_SEL: bit 0 = 1 PLL0, bit 0 = 0 PLL2 +// MAIN_PLL0_HSDIV9: 2 (333 MHz), 3 (250 MHz) +// MAIN_PLL2_HSDIV2: 5 (300 MHz), 7 (225 MHz) +// ICSSG_CFG: iep_clk to follow core clock +// +// iep clock options +// ICSSG0_CLKMUX_SEL: bit 16-17: +// 0h - MAIN_PLL2_HSDIV5_CLKOUT +// 1h - MAIN_PLL0_HSDIV6_CLKOUT +// 7h - SYSCLK0 (500 MHz) - not recommended!!! +// recommend to run both clocks from same PLL0 +// e.g. PLL0 iep_clk = 500 MHz, core_clock = 333 MHz + +// configure ICSS clocks +// unlock CTRLMMR config register +// partition 2 + HW_WR_REG32(0x43009008, 0x68EF3490 ); // Kick 0 + HW_WR_REG32(0x4300900c, 0xD172BC5A ); // Kick 1 + +// ICSS_G1_CLKMUX_SEL: +// 1h - MAIN_PLL0_HSDIV9_CLKOUT, + HW_WR_REG32(0x43008044, 0x00000001 ); // Kick 1 + +/* .if(0) + ; run iep_clk with core clock + ldi32 r2, 0x00026030 + ldi32 r3, 0x00000001 + sbbo &r3, r2, 0, 4 + .endif +*/ + +// unlock PLL0 ctrl register + HW_WR_REG32(0x00680010, 0x68EF3490 ); // Kick 0 + HW_WR_REG32(0x00680014, 0xD172BC5A ); // Kick 1 + +// set MAIN_PLL0_HSDIV9 to 2 for core_clock =333MHz (3 for 250 MHz) + HW_WR_REG8(0x006800a4, 2); + +// set MAIN_PLL0_HSDIV6_CLKOUT iep_clock from PLL0 (1 = 500 MHz, 2 = 333 MHz, 3 = 250 MHz) + HW_WR_REG8(0x00680098, 2); + +// unlock PLL2 ctrl register + HW_WR_REG32(0x00682010, 0x68EF3490 ); // Kick 0 + HW_WR_REG32(0x00682014, 0xD172BC5A ); // Kick 1 + +// set core clock MAIN_PLL2_HSDIV0 to 5 for 300 MHz (7 for 225 MHz, 5 for 300 MHz) + HW_WR_REG8(0x00682080, 5); + +// set MAIN_PLL2_HSDIV5_CLKOUT iep_clock from PLL2 (5= 300 MHz) + HW_WR_REG8(0x00682094, 5); +#endif +// ************************************* iep config ********************************** +#if 0 // FL: PRU code +// reset iep0 timer + HW_WR_REG8(CSL_ICSS_G_PR1_IEP0_SLV_REGS_BASE+CSL_ICSS_G_PR1_IEP0_SLV_GLOBAL_CFG_REG, 0x20); + HW_WR_REG32(CSL_ICSS_G_PR1_IEP0_SLV_REGS_BASE+CSL_ICSS_G_PR1_IEP0_SLV_COUNT_REG0, 0xffffffff); + HW_WR_REG32(CSL_ICSS_G_PR1_IEP0_SLV_REGS_BASE+CSL_ICSS_G_PR1_IEP0_SLV_COUNT_REG1, 0xffffffff); + +// set CMP0 period - 64 kHZ 15625 ns, - cycle as we start from 0 + HW_WR_REG32(CSL_ICSS_G_PR1_IEP0_SLV_REGS_BASE+CSL_ICSS_G_PR1_IEP0_SLV_CMP0_REG0, 15625-3); + HW_WR_REG32(CSL_ICSS_G_PR1_IEP0_SLV_REGS_BASE+CSL_ICSS_G_PR1_IEP0_SLV_CMP0_REG1, 15625-3); + +// set CMP1 period - SYNC01 trigger + HW_WR_REG32(CSL_ICSS_G_PR1_IEP0_SLV_REGS_BASE+CSL_ICSS_G_PR1_IEP0_SLV_CMP1_REG0, 99); + +// set CMP2 period - SYNC1 trigger - with 6 ns delay - only used in independent mode + HW_WR_REG32(CSL_ICSS_G_PR1_IEP0_SLV_REGS_BASE+CSL_ICSS_G_PR1_IEP0_SLV_CMP2_REG0, 99); + +// Set sync ctrl register: SYNC1 dependent, cyclic generation , SYNC0 and SYNC1 enable, SYNC enable + HW_WR_REG32(CSL_ICSS_G_PR1_IEP0_SLV_REGS_BASE+CSL_ICSS_G_PR1_IEP0_SLV_SYNC_CTRL_REG, 0x00A7); + +// Set SYNC0/1 high pulse time in iep clok cycles ( 7 clocks for 20 MHz at 300 MHz iep clk) + HW_WR_REG32(CSL_ICSS_G_PR1_IEP0_SLV_REGS_BASE+CSL_ICSS_G_PR1_IEP0_SLV_SYNC_PWIDTH_REG, 0x0006); + +// Set SYNC0/1 period ( 15 clocks for 20 MHz at 300 MHz iep clk) + HW_WR_REG32(CSL_ICSS_G_PR1_IEP0_SLV_REGS_BASE+CSL_ICSS_G_PR1_IEP0_SLV_SYNC0_PERIOD_REG, 14); + +// Set delay between SYNC0 and SYNC1 in clock cycles 2 = 3 clock cycles + HW_WR_REG32(CSL_ICSS_G_PR1_IEP0_SLV_REGS_BASE+CSL_ICSS_G_PR1_IEP0_SLV_SYNC1_DELAY_REG, 2); + +// Set offset from cpm1 hit + HW_WR_REG32(CSL_ICSS_G_PR1_IEP0_SLV_REGS_BASE+CSL_ICSS_G_PR1_IEP0_SLV_SYNC_START_REG, 0); + +// set enable cmp1 and cmp2 for sync start trigger generation + HW_WR_REG32(CSL_ICSS_G_PR1_IEP0_SLV_REGS_BASE+CSL_ICSS_G_PR1_IEP0_SLV_CMP_CFG_REG, 0x000000c); + +// set enable cmp1 and cmp2 for sync start trigger generation + HW_WR_REG32(CSL_ICSS_G_PR1_IEP0_SLV_REGS_BASE+CSL_ICSS_G_PR1_IEP0_SLV_CMP_CFG_REG, 0x000000c); + +// start iep0_timer - increment by 1 , start + HW_WR_REG8(CSL_ICSS_G_PR1_IEP0_SLV_REGS_BASE+CSL_ICSS_G_PR1_IEP0_SLV_GLOBAL_CFG_REG, 0x0111); +#endif + // reset iep0 timer + HW_WR_REG8(CSL_PRU_ICSSG0_IEP0_BASE+CSL_ICSS_G_PR1_IEP0_SLV_GLOBAL_CFG_REG, 0x20); + HW_WR_REG32(CSL_PRU_ICSSG0_IEP0_BASE+CSL_ICSS_G_PR1_IEP0_SLV_COUNT_REG0, 0xffffffff); + HW_WR_REG32(CSL_PRU_ICSSG0_IEP0_BASE+CSL_ICSS_G_PR1_IEP0_SLV_COUNT_REG1, 0xffffffff); + + // set CMP0 period - 64 kHZ 15625 ns, - cycle as we start from 0 + HW_WR_REG32(CSL_PRU_ICSSG0_IEP0_BASE+CSL_ICSS_G_PR1_IEP0_SLV_CMP0_REG0, 15625-3); + HW_WR_REG32(CSL_PRU_ICSSG0_IEP0_BASE+CSL_ICSS_G_PR1_IEP0_SLV_CMP0_REG1, 15625-3); + + // set CMP1 period - SYNC01 trigger + HW_WR_REG32(CSL_PRU_ICSSG0_IEP0_BASE+CSL_ICSS_G_PR1_IEP0_SLV_CMP1_REG0, 99); + + // set CMP2 period - SYNC1 trigger - with 6 ns delay - only used in independent mode + HW_WR_REG32(CSL_PRU_ICSSG0_IEP0_BASE+CSL_ICSS_G_PR1_IEP0_SLV_CMP2_REG0, 99); + + // Set sync ctrl register: SYNC1 dependent, cyclic generation , SYNC0 and SYNC1 enable, SYNC enable + HW_WR_REG32(CSL_PRU_ICSSG0_IEP0_BASE+CSL_ICSS_G_PR1_IEP0_SLV_SYNC_CTRL_REG, 0x00A7); + + // Set SYNC0/1 high pulse time in iep clok cycles ( 7 clocks for 20 MHz at 300 MHz iep clk) + HW_WR_REG32(CSL_PRU_ICSSG0_IEP0_BASE+CSL_ICSS_G_PR1_IEP0_SLV_SYNC_PWIDTH_REG, 0x0006); + + // Set SYNC0/1 period ( 15 clocks for 20 MHz at 300 MHz iep clk) + HW_WR_REG32(CSL_PRU_ICSSG0_IEP0_BASE+CSL_ICSS_G_PR1_IEP0_SLV_SYNC0_PERIOD_REG, 14); + + // Set delay between SYNC0 and SYNC1 in clock cycles 2 = 3 clock cycles + HW_WR_REG32(CSL_PRU_ICSSG0_IEP0_BASE+CSL_ICSS_G_PR1_IEP0_SLV_SYNC1_DELAY_REG, 2); + + // Set offset from cpm1 hit + HW_WR_REG32(CSL_PRU_ICSSG0_IEP0_BASE+CSL_ICSS_G_PR1_IEP0_SLV_SYNC_START_REG, 0); + + // set enable cmp1 and cmp2 for sync start trigger generation + ///HW_WR_REG32(CSL_PRU_ICSSG0_IEP0_BASE+CSL_ICSS_G_PR1_IEP0_SLV_CMP_CFG_REG, 0x000000c); + + // set enable cmp1 and cmp2 for sync start trigger generation + HW_WR_REG32(CSL_PRU_ICSSG0_IEP0_BASE+CSL_ICSS_G_PR1_IEP0_SLV_CMP_CFG_REG, 0x00000Dc); + + // set default and compensation increment to 1 + HW_WR_REG8(CSL_PRU_ICSSG0_IEP0_BASE+CSL_ICSS_G_PR1_IEP0_SLV_GLOBAL_CFG_REG, 0x0110); + +// ************************************* task manager ************************************* +// + + + return; +} + +void start_IEP0(void) +{ + uint8_t regVal; + + // start iep0_timer + regVal = HW_RD_REG8(CSL_PRU_ICSSG0_IEP0_BASE+CSL_ICSS_G_PR1_IEP0_SLV_GLOBAL_CFG_REG); + regVal += 0x1; + HW_WR_REG8(CSL_PRU_ICSSG0_IEP0_BASE+CSL_ICSS_G_PR1_IEP0_SLV_GLOBAL_CFG_REG, regVal); +} + +#if 0 // FL: PRU code +/** + * main.c + */ +int main(void) +{ + + __asm(" tsen 0"); + init_IEP0_SYNC(); + + while (1){}; + + return 0; +} +#endif diff --git a/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-0_nortos/mclk_iep_sync.h b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-0_nortos/mclk_iep_sync.h new file mode 100644 index 0000000..a39e5b2 --- /dev/null +++ b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-0_nortos/mclk_iep_sync.h @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2022 Texas Instruments Incorporated + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * Neither the name of Texas Instruments Incorporated nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MCLK_IEP_SYNC_H_ +#define _MCLK_IEP_SYNC_H_ + +void init_IEP0_SYNC(void); +void start_IEP0(void); + +#endif /* _MCLK_IEP_SYNC_H_ */ diff --git a/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-0_nortos/pwm.c b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-0_nortos/pwm.c new file mode 100644 index 0000000..a4844bb --- /dev/null +++ b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-0_nortos/pwm.c @@ -0,0 +1,177 @@ +/* + * Copyright (C) 2023 Texas Instruments Incorporated + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * Neither the name of Texas Instruments Incorporated nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include "pwm.h" + +/* Compute Duty Cycle & CMPx given Vref & EPWM period */ +__attribute__((always_inline)) inline void computeCmpx( + float Vref, + uint32_t epwmPrdVal, + float *pEpwmDutyCycle, + uint16_t *pEpwmCmpVal +) +{ + float dc_f; + float cmp_f; + uint16_t cmp; + + if (Vref > VREF_MAX) { + /* 100% duty cycle */ + dc_f = 1.0; + cmp = 0; + } + else if (Vref < VREF_MIN) { + /* 0% duty cycle */ + dc_f = 0.0; + cmp = epwmPrdVal; + } + else { + /* compute Duty Cycle */ + dc_f = 0.5*(Vref + 1.0); + + /* compute CMPx */ + cmp_f = (1.0 - dc_f)*epwmPrdVal; /* up-down count */ + cmp = (uint16_t)cmp_f; + } + + *pEpwmDutyCycle = dc_f; + *pEpwmCmpVal = cmp; +} + +void App_epwmConfig( + AppEPwmCfg_t *pAppEPwmCfg, + uint32_t *pEpwmPrdVal, + uint32_t *pEpwmCmpAVal +) +{ + uint32_t epwmBaseAddr; /* EPWM base address */ + uint32_t epwmCh; /* EPWM output channel */ + uint32_t epwmFuncClk; /* EPWM functional clock */ + uint32_t epwmTbFreq; /* EPWM timebase clock */ + uint32_t epwmOutFreq; /* EPWM output frequency */ + uint32_t epwmDutyCycle; /* EPWM duty cycle */ + uint32_t epwmTbCounterDir; /* EPWM TB counter direction */ + uint32_t epwmPrdVal; + uint32_t epwmCmpAVal; + + /* Get configuration parameters */ + epwmBaseAddr = pAppEPwmCfg->epwmBaseAddr; + epwmCh = pAppEPwmCfg->epwmCh; + epwmFuncClk = pAppEPwmCfg->epwmFuncClk; + epwmTbFreq = pAppEPwmCfg->epwmTbFreq; + epwmOutFreq = pAppEPwmCfg->epwmOutFreq; + epwmDutyCycle = pAppEPwmCfg->epwmDutyCycle; + epwmTbCounterDir = pAppEPwmCfg->epwmTbCounterDir; + + /* Configure Time Base submodule */ + EPWM_tbTimebaseClkCfg(epwmBaseAddr, epwmTbFreq, epwmFuncClk); + EPWM_tbPwmFreqCfg(epwmBaseAddr, epwmTbFreq, epwmOutFreq, + epwmTbCounterDir, EPWM_SHADOW_REG_CTRL_ENABLE); + + /* Configure TB Sync In Mode */ + if (pAppEPwmCfg->cfgTbSyncIn == FALSE) { + EPWM_tbSyncDisable(epwmBaseAddr); + } + else { + EPWM_tbSyncEnable(epwmBaseAddr, pAppEPwmCfg->tbPhsValue, pAppEPwmCfg->tbSyncInCounterDir); + } + + /* Configure TB Sync Out Mode */ + if (pAppEPwmCfg->cfgTbSyncOut == FALSE) { + EPWM_tbSetSyncOutMode(epwmBaseAddr, EPWM_TB_SYNC_OUT_EVT_DISABLE ); + } + else { + EPWM_tbSetSyncOutMode(epwmBaseAddr, pAppEPwmCfg->tbSyncOutMode); + } + + EPWM_tbSetEmulationMode(epwmBaseAddr, EPWM_TB_EMU_MODE_FREE_RUN); + + /* + * PRD value - this determines the period + */ + /* PRD = (TBCLK/PWM FREQ) */ + epwmPrdVal = epwmTbFreq / epwmOutFreq; + if (epwmTbCounterDir == EPWM_TB_COUNTER_DIR_UP_DOWN) { + /* + * PRD = (TBCLK/PWM FREQ) / 2 + * /2 is added because up&down counter is selected. So period is 2 times. + */ + epwmPrdVal /= 2U; + } + + /* + * COMPA value - this determines the duty cycle + * COMPA = (PRD - ((dutycycle * PRD) / 100) + */ + epwmCmpAVal = (epwmPrdVal - ((epwmDutyCycle * epwmPrdVal) / 100U)); + + /* Configure counter compare submodule */ + EPWM_counterComparatorCfg(epwmBaseAddr, EPWM_CC_CMP_A, + epwmCmpAVal, EPWM_SHADOW_REG_CTRL_ENABLE, + EPWM_CC_CMP_LOAD_MODE_CNT_EQ_ZERO_OR_PRD, TRUE); + EPWM_counterComparatorCfg(epwmBaseAddr, EPWM_CC_CMP_B, + epwmCmpAVal, EPWM_SHADOW_REG_CTRL_ENABLE, + EPWM_CC_CMP_LOAD_MODE_CNT_EQ_ZERO_OR_PRD, TRUE); + + /* Configure Action Qualifier Submodule */ + EPWM_aqActionOnOutputCfg(epwmBaseAddr, epwmCh, &pAppEPwmCfg->aqCfg); + + if (pAppEPwmCfg->cfgDb == TRUE) { + /* Configure Dead Band Submodule */ + EPWM_deadbandCfg(epwmBaseAddr, &pAppEPwmCfg->dbCfg); + } + else { + /* Configure Dead Band Submodule */ + EPWM_deadbandBypass(epwmBaseAddr); + } + + /* Configure Chopper Submodule */ + EPWM_chopperEnable(epwmBaseAddr, FALSE); + + /* Configure trip zone Submodule */ + EPWM_tzTripEventDisable(epwmBaseAddr, EPWM_TZ_EVENT_ONE_SHOT, 0U); + EPWM_tzTripEventDisable(epwmBaseAddr, EPWM_TZ_EVENT_CYCLE_BY_CYCLE, 0U); + + if (pAppEPwmCfg->cfgEt == TRUE) { + /* Configure event trigger Submodule */ + EPWM_etIntrCfg(epwmBaseAddr, pAppEPwmCfg->intSel, + pAppEPwmCfg->intPrd); + EPWM_etIntrEnable(epwmBaseAddr); + } + + /* Set return values */ + *pEpwmPrdVal = epwmPrdVal; + *pEpwmCmpAVal = epwmCmpAVal; +} diff --git a/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-0_nortos/pwm.h b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-0_nortos/pwm.h new file mode 100644 index 0000000..1450d17 --- /dev/null +++ b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-0_nortos/pwm.h @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2021 Texas Instruments Incorporated + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * Neither the name of Texas Instruments Incorporated nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _PWM_H_ +#define _PWM_H_ + +#include +#include +#include +#include "epwm_drv_aux.h" + +/* Switching control for EPWM output frequency */ +#define SET_EPWM_OUT_FREQ8K_THR ( 4000 ) +#define SET_EPWM_OUT_FREQ16K_THR ( SET_EPWM_OUT_FREQ8K_THR + 8000 ) +#define SET_EPWM_OUT_FREQ4K_THR ( SET_EPWM_OUT_FREQ16K_THR + 16000 ) + +/* Frequency of PWM output signal in Hz */ +#define APP_EPWM_OUTPUT_FREQ_4K ( 1U * 4000U ) +#define APP_EPWM_OUTPUT_FREQ_8K ( 1U * 8000U ) +#define APP_EPWM_OUTPUT_FREQ_20K ( 1U * 20000U ) +#define APP_EPWM_OUTPUT_FREQ_50K ( 1U * 50000U ) +#define APP_EPWM_OUTPUT_FREQ ( APP_EPWM_OUTPUT_FREQ_50K ) /* init freq */ +/* Deadband RED/FED timer counts */ +#define APP_EPWM_DB_RED_COUNT ( 5 ) /* 20 nsec @ 250 MHz */ +#define APP_EPWM_DB_FED_COUNT ( 5 ) /* 20 nsec @ 250 MHz */ + +/* Min / max output amplitude. + Waveform amplitude values beyond these thresholds are saturated. */ +#define VREF_MAX ( 1.0f ) +#define VREF_MIN ( -1.0f ) + +/* Sinusoid parameters */ +#define SIN_FREQ ( 6 ) /* sinusoid frequency */ +#define SIN_AMP ( 0.0 ) /* sinusoid amplitude */ + +/* EPWM configuration */ +typedef struct _AppEPwmCfg_t +{ + uint32_t epwmBaseAddr; /* EPWM base address */ + uint32_t epwmCh; /* EPWM output channel */ + uint32_t epwmFuncClk; /* EPWM functional clock */ + uint32_t epwmTbFreq; /* EPWM timebase clock */ + uint32_t epwmOutFreq; /* EPWM output frequency */ + uint32_t epwmDutyCycle; /* EPWM duty cycle */ + uint32_t epwmTbCounterDir; /* EPWM counter direction (Up, Down, Up/Down) */ + /* TB sync in config */ + Bool cfgTbSyncIn; /* config TB sync in flag (true/false) */ + uint32_t tbPhsValue; /* cfgTbSyncIn==TRUE: timer phase value to load on Sync In event */ + uint32_t tbSyncInCounterDir; /* cfgTbSyncIn==TRUE: counter direction on Sync In event */ + /* TB sync out config */ + Bool cfgTbSyncOut; /* config TB sync output flag (true/false) */ + uint32_t tbSyncOutMode; /* cfgTbSyncOut==TRUE: Sync Out mode */ + /* AQ config */ + EPWM_AqActionCfg aqCfg; /* Action Qualifier config */ + /* DB config */ + Bool cfgDb; /* config DB flag (true/false) */ + EPWM_DeadbandCfg dbCfg; /* Deadband config */ + /* ET config */ + Bool cfgEt; /* config ET module */ + uint32_t intSel; /* ET interrupt select */ + uint32_t intPrd; /* ET interrupt period */ +} AppEPwmCfg_t; + +/* Application specific initial PWM configuration */ +void App_epwmConfig( + AppEPwmCfg_t *pAppEPwmCfg, + uint32_t *pEpwmPrdVal, + uint32_t *pEpwmCmpAVal +); + +/* Compute Duty Cycle & CMPx given Vref & EPWM period */ +void computeCmpx( + float Vref, + uint32_t epwmPrdVal, + float *pEpwmDutyCycle, + uint16_t *pEpwmCmpVal +); + +#endif /* _PWM_H_ */ diff --git a/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-0_nortos/sddf.c b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-0_nortos/sddf.c new file mode 100644 index 0000000..b33a6d6 --- /dev/null +++ b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-0_nortos/sddf.c @@ -0,0 +1,644 @@ +/* + * Copyright (C) 2023 Texas Instruments Incorporated + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * Neither the name of Texas Instruments Incorporated nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include "ti_drivers_config.h" +#include "ti_drivers_open_close.h" +#include "ti_board_open_close.h" + +#include +#include +#include +#include +#include + +#include "tisddf_pruss_intc_mapping.h" /* INTC configuration */ +#include "current_sense/sdfm/firmware/sdfm_pru_bin.h" /* SDDF image data */ +#include "current_sense/sdfm/firmware/sdfm_rtu_bin.h" +#include "sddf.h" +#include "current_sense/sdfm/include/sdfm_api.h" + +/* PRU SDDF FW image info */ +typedef struct PRUSDDF_PruFwImageInfo_s { + const uint32_t *pPruImemImg; + const uint32_t pruImemImgSz; +} PRUSDDF_PruFwImageInfo; + +/* TISCI ICSSG Core clock selection options */ +static uint32_t gIcssCoreClkSel[ICSSGn_CORE_CLK_SEL_NUMSEL] = { + TISCI_DEV_PRU_ICSSG0_CORE_CLK_PARENT_HSDIV4_16FFT_MAIN_2_HSDIVOUT0_CLK, + TISCI_DEV_PRU_ICSSG0_CORE_CLK_PARENT_POSTDIV4_16FF_MAIN_0_HSDIVOUT9_CLK +}; +/* TISCI ICSSG IEP clock selection options */ +static uint32_t gIcssIepClkSel[ICSSGn_IEP_CLK_SEL_NUMSEL] = { + TISCI_DEV_PRU_ICSSG0_IEP_CLK_PARENT_POSTDIV4_16FF_MAIN_2_HSDIVOUT5_CLK, + TISCI_DEV_PRU_ICSSG0_IEP_CLK_PARENT_POSTDIV4_16FF_MAIN_0_HSDIVOUT6_CLK, + TISCI_DEV_PRU_ICSSG0_IEP_CLK_PARENT_BOARD_0_CP_GEMAC_CPTS0_RFT_CLK_OUT, + TISCI_DEV_PRU_ICSSG0_IEP_CLK_PARENT_BOARD_0_CPTS0_RFT_CLK_OUT, + TISCI_DEV_PRU_ICSSG0_IEP_CLK_PARENT_BOARD_0_MCU_EXT_REFCLK0_OUT, + TISCI_DEV_PRU_ICSSG0_IEP_CLK_PARENT_BOARD_0_EXT_REFCLK1_OUT, + TISCI_DEV_PRU_ICSSG0_IEP_CLK_PARENT_WIZ16B2M4CT_MAIN_0_IP1_LN0_TXMCLK, + TISCI_DEV_PRU_ICSSG0_IEP_CLK_PARENT_K3_PLL_CTRL_WRAP_MAIN_0_CHIP_DIV1_CLK_CLK +}; + +/* Number of PRU images */ +#define PRU_SDDF_NUM_PRU_IMAGE ( 3 ) + +/* PRU SDDF image info */ +static PRUSDDF_PruFwImageInfo gPruFwImageInfo[PRU_SDDF_NUM_PRU_IMAGE] = +{ + {pru_SDFM_PRU0_image_0, sizeof(pru_SDFM_PRU0_image_0)}, /* PRU FW */ + {pru_SDFM_RTU0_image_0, sizeof(pru_SDFM_RTU0_image_0)}, /* RTU FW */ + {NULL, 0} +}; + +/* ICSS INTC configuration */ +static const PRUICSS_IntcInitData gPruicssIntcInitdata = PRUICSS_INTC_INITDATA; + + +/* + * ======== cfgIcssgClkCfg ======== + */ +/* Configure ICSSG clock selection */ +int32_t cfgIcssgClkCfg( + uint8_t icssInstId, + uint8_t coreClkSel, /* ICSSG internal Core clock source select, ICSSG_CORE_SYNC_REG:CORE_VBUSP_SYNC_EN */ + uint8_t icssCoreClkSel, /* ICSSG external Core clock source select, CTRLMMR_ICSSGn_CLKSEL:CORE_CLKSEL, (used if coreClkSel==0) */ + uint64_t icssCoreClkFreqHz, /* ICSSG external Core clock frequency, (used if !=0 && coreClkSel==0) */ + uint8_t iepClkSel, /* ICSSG internal IEP clock source select, ICSSG_IEPCLK_REG:IEP_OCP_CLK_EN */ + uint8_t icssIepClkSel, /* ICSSG internal IEP clock source select, CTRLMMR_ICSSGn_CLKSEL:IEP_CLKSEL, (used if iepClkSel==0) */ + uint64_t icssIepClkFreqHz /* ICSSG external IEP clock frequency, (used if !=0 && icssIepClkSel==0) */ +) +{ + const PRUICSS_HwAttrs *hwAttrs; + uint32_t instance; + CSL_IcssCfgRegs *pIcssCfgRegs; + uint64_t moduleId, clockId; + uint32_t numParents = 0U; + uint32_t parent; + uint32_t regVal; + uint32_t ret; + + hwAttrs = PRUICSS_getAttrs(icssInstId); + instance = hwAttrs->instance; + + if (instance == PRUICSS_INSTANCE_ONE) { + pIcssCfgRegs = (CSL_IcssCfgRegs *)CSL_PRU_ICSSG0_PR1_CFG_SLV_BASE; + + /* Select ICSSG external Core clock source */ + if (coreClkSel == CORE_CLK_SEL_ICSSGn_CORE_CLK) { + moduleId = TISCI_DEV_PRU_ICSSG0; + clockId = TISCI_DEV_PRU_ICSSG0_CORE_CLK; + ret = Sciclient_pmGetModuleClkNumParent(moduleId, + clockId, + &numParents, + SystemP_WAIT_FOREVER); + + if ((ret == CSL_PASS) && (numParents > 1U)) { + /* Get TISCI parent clock ID */ + if (icssCoreClkSel < ICSSGn_CORE_CLK_SEL_NUMSEL) { + parent = gIcssCoreClkSel[icssCoreClkSel]; + } + else { + return SDDF_ERR_CFG_ICSSG_CLKCFG; + } + + /* Configure Core clock mux */ + ret = Sciclient_pmSetModuleClkParent(moduleId, + clockId, + parent, + SystemP_WAIT_FOREVER); + if (ret != CSL_PASS) { + return SDDF_ERR_CFG_ICSSG_CLKCFG; + } + + if (icssCoreClkFreqHz != 0) { + /* Configure Clock frequency */ + ret = Sciclient_pmSetModuleClkFreq(moduleId, clockId, icssCoreClkFreqHz, TISCI_MSG_FLAG_CLOCK_ALLOW_FREQ_CHANGE, SystemP_WAIT_FOREVER); + if (ret != CSL_PASS) { + return SDDF_ERR_CFG_ICSSG_CLKCFG; + } + } + } + else { + return SDDF_ERR_CFG_ICSSG_CLKCFG; + } + } + + /* Select ICSSG internal Core clock source */ + regVal = HW_RD_REG32(&pIcssCfgRegs->CORE_SYNC_REG); + regVal &= ~CSL_ICSSCFG_CORE_SYNC_REG_CORE_VBUSP_SYNC_EN_MASK; + regVal |= (coreClkSel << CSL_ICSSCFG_CORE_SYNC_REG_CORE_VBUSP_SYNC_EN_SHIFT) & CSL_ICSSCFG_CORE_SYNC_REG_CORE_VBUSP_SYNC_EN_MASK; + HW_WR_REG32(&pIcssCfgRegs->CORE_SYNC_REG, regVal); + + /* Select ICSSG external IEP clock source */ + if (iepClkSel == IEP_CLK_SEL_ICSSGn_IEP_CLK) { + moduleId = TISCI_DEV_PRU_ICSSG0; + clockId = TISCI_DEV_PRU_ICSSG0_IEP_CLK; + ret = Sciclient_pmGetModuleClkNumParent(moduleId, + clockId, + &numParents, + SystemP_WAIT_FOREVER); + + if ((ret == CSL_PASS) && (numParents > 1U)) { + /* Get TISCI parent clock ID */ + if (icssIepClkSel < ICSSGn_IEP_CLK_SEL_NUMSEL) { + parent = gIcssIepClkSel[icssIepClkSel]; + } + else { + return SDDF_ERR_CFG_ICSSG_CLKCFG; + } + + /* Configure Core clock mux */ + ret = Sciclient_pmSetModuleClkParent(moduleId, + clockId, + parent, + SystemP_WAIT_FOREVER); + if (ret != CSL_PASS) { + return SDDF_ERR_CFG_ICSSG_CLKCFG; + } + + if (icssIepClkFreqHz != 0) { + /* Configure Clock frequency */ + ret = Sciclient_pmSetModuleClkFreq(moduleId, clockId, icssIepClkFreqHz, TISCI_MSG_FLAG_CLOCK_ALLOW_FREQ_CHANGE, SystemP_WAIT_FOREVER); + if (ret != CSL_PASS) { + return SDDF_ERR_CFG_ICSSG_CLKCFG; + } + } + } + else { + return SDDF_ERR_CFG_ICSSG_CLKCFG; + } + } + + /* Select ICSSG internal IEP clock source */ + regVal = HW_RD_REG32(&pIcssCfgRegs->IEPCLK); + regVal &= ~CSL_ICSSCFG_IEPCLK_OCP_EN_MASK; + regVal |= (iepClkSel << CSL_ICSSCFG_IEPCLK_OCP_EN_SHIFT) & CSL_ICSSCFG_IEPCLK_OCP_EN_MASK; + HW_WR_REG32(&pIcssCfgRegs->IEPCLK, regVal); + } + else if (instance == PRUICSS_INSTANCE_TWO) { + pIcssCfgRegs = (CSL_IcssCfgRegs *)CSL_PRU_ICSSG1_PR1_CFG_SLV_BASE; + + /* Select ICSSG external Core clock source */ + if (coreClkSel == CORE_CLK_SEL_ICSSGn_CORE_CLK) { + moduleId = TISCI_DEV_PRU_ICSSG1; + clockId = TISCI_DEV_PRU_ICSSG1_CORE_CLK; + ret = Sciclient_pmGetModuleClkNumParent(moduleId, + clockId, + &numParents, + SystemP_WAIT_FOREVER); + + if ((ret == CSL_PASS) && (numParents > 1U)) { + if (icssCoreClkSel == ICSSGn_CORE_CLK_SEL_MAIN_PLL2_HSDIV0_CLKOUT) { + parent = TISCI_DEV_PRU_ICSSG1_CORE_CLK_PARENT_HSDIV4_16FFT_MAIN_2_HSDIVOUT0_CLK; + } + else if (icssCoreClkSel == ICSSGn_CORE_CLK_SEL_MAIN_PLL0_HSDIV9_CLKOUT) { + parent = TISCI_DEV_PRU_ICSSG1_CORE_CLK_PARENT_POSTDIV4_16FF_MAIN_0_HSDIVOUT9_CLK; + } + else { + return SDDF_ERR_CFG_ICSSG_CLKCFG; + } + + ret = Sciclient_pmSetModuleClkParent(moduleId, + clockId, + parent, + SystemP_WAIT_FOREVER); + if (ret != CSL_PASS) { + return SDDF_ERR_CFG_ICSSG_CLKCFG; + } + } + else { + return SDDF_ERR_CFG_ICSSG_CLKCFG; + } + } + + /* Select ICSSG internal Core clock source */ + regVal = HW_RD_REG32(&pIcssCfgRegs->CORE_SYNC_REG); + regVal &= ~CSL_ICSSCFG_CORE_SYNC_REG_CORE_VBUSP_SYNC_EN_MASK; + regVal |= (coreClkSel << CSL_ICSSCFG_CORE_SYNC_REG_CORE_VBUSP_SYNC_EN_SHIFT) & CSL_ICSSCFG_CORE_SYNC_REG_CORE_VBUSP_SYNC_EN_MASK; + HW_WR_REG32(&pIcssCfgRegs->CORE_SYNC_REG, regVal); + + /* Select ICSSG external IEP clock source */ + if (iepClkSel == IEP_CLK_SEL_ICSSGn_IEP_CLK) { + moduleId = TISCI_DEV_PRU_ICSSG1; + clockId = TISCI_DEV_PRU_ICSSG1_IEP_CLK; + ret = Sciclient_pmGetModuleClkNumParent(moduleId, + clockId, + &numParents, + SystemP_WAIT_FOREVER); + + if ((ret == CSL_PASS) && (numParents > 1U)) { + if (icssIepClkSel == ICSSGn_IEP_CLK_SEL_MAIN_PLL2_HSDIV5_CLKOUT) { + parent = TISCI_DEV_PRU_ICSSG1_IEP_CLK_PARENT_POSTDIV4_16FF_MAIN_2_HSDIVOUT5_CLK; + } + else if (icssIepClkSel == ICSSGn_IEP_CLK_SEL_MAIN_PLL0_HSDIV6_CLKOUT) { + parent = TISCI_DEV_PRU_ICSSG1_IEP_CLK_PARENT_POSTDIV4_16FF_MAIN_0_HSDIVOUT6_CLK; + } + else { + return SDDF_ERR_CFG_ICSSG_CLKCFG; + } + + ret = Sciclient_pmSetModuleClkParent(moduleId, + clockId, + parent, + SystemP_WAIT_FOREVER); + if (ret != CSL_PASS) { + return SDDF_ERR_CFG_ICSSG_CLKCFG; + } + } + else { + return SDDF_ERR_CFG_ICSSG_CLKCFG; + } + } + + /* Select ICSSG internal IEP clock source */ + regVal = HW_RD_REG32(&pIcssCfgRegs->IEPCLK); + regVal &= ~CSL_ICSSCFG_IEPCLK_OCP_EN_MASK; + regVal |= (iepClkSel << CSL_ICSSCFG_IEPCLK_OCP_EN_SHIFT) & CSL_ICSSCFG_IEPCLK_OCP_EN_MASK; + HW_WR_REG32(&pIcssCfgRegs->IEPCLK, regVal); + } + else { + return SDDF_ERR_CFG_ICSSG_CLKCFG; + } + + return SDDF_ERR_NERR; +} + +/* + * ======== initIcss ======== + */ +/* Initialize ICSSG */ +int32_t initIcss( + uint8_t icssInstId, + uint8_t sliceId, + uint8_t saMuxMode, + PRUICSS_Handle *pPruIcssHandle +) +{ + PRUICSS_Handle pruIcssHandle; + int32_t size; + const PRUICSS_HwAttrs *hwAttrs; + CSL_IcssCfgRegs *pIcssCfgRegs; + uint32_t instance; + uint32_t regVal; + int32_t status; + + /* Open ICSS PRU instance */ + pruIcssHandle = PRUICSS_open(icssInstId); + if (pruIcssHandle == NULL) { + return SDDF_ERR_INIT_ICSSG; + } + + /* Disable slice PRU cores */ + if (sliceId == ICSSG_SLICE_ID_0) + { + status = PRUICSS_disableCore(pruIcssHandle, PRUICSS_PRU0); + if (status != SystemP_SUCCESS) { + return SDDF_ERR_INIT_ICSSG; + } + status = PRUICSS_disableCore(pruIcssHandle, PRUICSS_RTU_PRU0); + if (status != SystemP_SUCCESS) { + return SDDF_ERR_INIT_ICSSG; + } + } + else if (sliceId == ICSSG_SLICE_ID_1) + { + status = PRUICSS_disableCore(pruIcssHandle, PRUICSS_PRU1); + if (status != SystemP_SUCCESS) { + return SDDF_ERR_INIT_ICSSG; + } + status = PRUICSS_disableCore(pruIcssHandle, PRUICSS_RTU_PRU1); + if (status != SystemP_SUCCESS) { + return SDDF_ERR_INIT_ICSSG; + } + } + else + { + return SDDF_ERR_INIT_ICSSG; + } + + /* Reset slice memories */ + size = PRUICSS_initMemory(pruIcssHandle, PRUICSS_IRAM_PRU(sliceId)); + if (size == 0) + { + return SDDF_ERR_INIT_ICSSG; + } + size = PRUICSS_initMemory(pruIcssHandle, PRUICSS_IRAM_RTU_PRU(sliceId)); + if (size == 0) + { + return SDDF_ERR_INIT_ICSSG; + } + size = PRUICSS_initMemory(pruIcssHandle, PRUICSS_IRAM_TX_PRU(sliceId)); + if (size == 0) + { + return SDDF_ERR_INIT_ICSSG; + } + size = PRUICSS_initMemory(pruIcssHandle, PRUICSS_DATARAM(sliceId)); + if (size == 0) + { + return SDDF_ERR_INIT_ICSSG; + } + + /* Set ICSS pin mux */ + PRUICSS_setSaMuxMode(pruIcssHandle, saMuxMode); + + /* Initialize ICSS INTC */ + status = PRUICSS_intcInit(pruIcssHandle, &gPruicssIntcInitdata); + if (status != SystemP_SUCCESS) { + return SDDF_ERR_INIT_ICSSG; + } + + /* Enable SDDF load sharing */ + hwAttrs = PRUICSS_getAttrs(icssInstId); + instance = hwAttrs->instance; + + /* Determine ICSSG instance */ + if (icssInstId == PRUICSS_INSTANCE_ONE) + { + pIcssCfgRegs = (CSL_IcssCfgRegs *)CSL_PRU_ICSSG0_PR1_CFG_SLV_BASE; + } + else if (instance == PRUICSS_INSTANCE_TWO) + { + pIcssCfgRegs = (CSL_IcssCfgRegs *)CSL_PRU_ICSSG1_PR1_CFG_SLV_BASE; + } + else + { + return SDDF_ERR_INIT_ICSSG; + } + /* Configure selected ICSSG slice for SD load sharing */ + if (sliceId == ICSSG_SLICE_ID_0) + { + regVal = HW_RD_REG32(&pIcssCfgRegs->SDPRU0CLKDIV); + regVal |= CSL_ICSSCFG_SDPRU0CLKDIV_PRU0_SD_SHARE_EN_MASK; + HW_WR_REG32(&pIcssCfgRegs->SDPRU0CLKDIV, regVal); + } + else if (sliceId == ICSSG_SLICE_ID_1) + { + regVal = HW_RD_REG32(&pIcssCfgRegs->SDPRU1CLKDIV); + regVal |= CSL_ICSSCFG_SDPRU1CLKDIV_PRU1_SD_SHARE_EN_MASK; + HW_WR_REG32(&pIcssCfgRegs->SDPRU1CLKDIV, regVal); + } + else + { + return SDDF_ERR_INIT_ICSSG; + } + + *pPruIcssHandle = pruIcssHandle; + + return SDDF_ERR_NERR; +} + +/* + * ======== initPruSddf ======== + */ +/* Initialize PRU core for SDDF */ +int32_t initPruSddf( + PRUICSS_Handle pruIcssHandle, + uint8_t pruInstId, + SdfmPrms *pSddfPrms, + sdfm_handle *pHSddf +) +{ + uint8_t sliceId; + uint32_t pruIMem; + PRUSDDF_PruFwImageInfo *pPruFwImageInfo; + int32_t size; + const uint32_t *sourceMem; /* Source memory[ Array of uint32_t ] */ + uint32_t imemOffset; + uint32_t byteLen; /* Total number of bytes to be written */ + uint8_t pruId; // FL: remove Host FW init since FW changing + int32_t status; + + /* Reset PRU */ + status = PRUICSS_resetCore(pruIcssHandle, pruInstId); + if (status != SystemP_SUCCESS) { + return SDDF_ERR_INIT_PRU_SDDF; + } + + /* Calculate slice ID */ + sliceId = pruInstId - (uint8_t)pruInstId/ICSSG_NUM_SLICE * ICSSG_NUM_SLICE; + /* Determine PRU DMEM address */ + PRUICSS_DATARAM(sliceId); + /* Determine PRU FW image and PRU IMEM address */ + switch (pruInstId) + { + case PRUICSS_PRU0: + case PRUICSS_PRU1: + pPruFwImageInfo = &gPruFwImageInfo[0]; + pruIMem = PRUICSS_IRAM_PRU(sliceId); + // dmemOffset = PRU_ICSSG_SDDF_CTRL_BASE; + break; + case PRUICSS_RTU_PRU0: + case PRUICSS_RTU_PRU1: + pPruFwImageInfo = &gPruFwImageInfo[1]; + pruIMem = PRUICSS_IRAM_RTU_PRU(sliceId); + // dmemOffset = RTU_ICSSG_SDDF_CTRL_BASE; + break; + case PRUICSS_TX_PRU0: + case PRUICSS_TX_PRU1: + pPruFwImageInfo = NULL; + break; + default: + pPruFwImageInfo = NULL; + break; + } + + if ((pPruFwImageInfo == NULL) || + (pPruFwImageInfo->pPruImemImg == NULL)) + { + return SDDF_ERR_INIT_PRU_SDDF; + } + + /* Write DMEM */ + //sourceMem = (uint32_t *)pPruFwImageInfo->pPruDmemImg; + // byteLen = pPruFwImageInfo->pruDmemImgSz; + //size = PRUICSS_writeMemory(pruIcssHandle, pruDMem, dmemOffset, sourceMem, byteLen); + //if (size == 0) + // { + /// return SDDF_ERR_INIT_PRU_SDDF; + //} + + /* Write IMEM */ + imemOffset = 0; + sourceMem = (uint32_t *)pPruFwImageInfo->pPruImemImg; + byteLen = pPruFwImageInfo->pruImemImgSz; + size = PRUICSS_writeMemory(pruIcssHandle, pruIMem, imemOffset, sourceMem, byteLen); + if (size == 0) + { + return SDDF_ERR_INIT_PRU_SDDF; + } + + /* Enable PRU */ + status = PRUICSS_enableCore(pruIcssHandle, pruInstId); + if (status != SystemP_SUCCESS) { + return SDDF_ERR_INIT_PRU_SDDF; + } + + /* Translate PRU ID to SDFM API */ + if (sliceId == PRUICSS_PRU0) { + pruId = PRU_ID_0; + } + else if (sliceId == PRUICSS_PRU1) { + pruId = PRU_ID_1; + } + else { + return SDDF_ERR_INIT_PRU_SDDF; + } + + /* Initialize SDDF PRU FW */ + status = initSddf(pruId, pruInstId, pSddfPrms, pHSddf); + if (status != SDDF_ERR_NERR) { + return SDDF_ERR_INIT_PRU_SDDF; + } + return SDDF_ERR_NERR; +} + +/* Initialize SDDF PRU FW */ +int32_t initSddf( + uint8_t pruId, uint8_t pruInstId, + SdfmPrms *pSdfmPrms, + sdfm_handle *pHSdfm +) +{ + sdfm_handle hSdfm; + + /* Initialize SDFM instance */ + hSdfm = SDFM_init(pruId, pruInstId); + if (hSdfm == NULL) { + return SDDF_ERR_INIT_SDDF; + } + uint32_t i; + i = SDFM_getFirmwareVersion(hSdfm); + DebugP_log("\n\n\n"); + DebugP_log("SDFM firmware version \t: %x.%x.%x (%s)\n\n", (i >> 24) & 0x7F, + (i >> 16) & 0xFF, i & 0xFFFF, i & (1 << 31) ? "internal" : "release"); + if (hSdfm == NULL) + { + return SDDF_ERR_INIT_SDDF; + } + + uint8_t SDFM_CH; + hSdfm->iepClock = pSdfmPrms->iep_clock; + hSdfm->sdfmClock = pSdfmPrms->sd_clock; + hSdfm->sampleOutputInterface = (SDFM_SampleOutInterface *)(pSdfmPrms->samplesBaseAddress); + uint32_t sampleOutputInterfaceGlobalAddr = CPU0_BTCM_SOCVIEW(pSdfmPrms->samplesBaseAddress); + hSdfm->p_sdfm_interface->sampleBufferBaseAdd = sampleOutputInterfaceGlobalAddr; + hSdfm->iepInc = 1; /* Default IEP increment 1 */ + + + uint8_t acc_filter = 0; //SINC3 filter + uint8_t ecap_divider = 0x0F; //IEP at 300MHz: SD clock = 300/15=20Mhz + + /*configure IEP count for one epwm period*/ + SDFM_configIepCount(hSdfm, pSdfmPrms->epwm_out_freq); + + /*configure ecap as PWM code for generate 20 MHz sdfm clock*/ + SDFM_configEcap(hSdfm, ecap_divider); + + /*set Noraml current OSR */ + SDFM_setFilterOverSamplingRatio(hSdfm, pSdfmPrms->FilterOsr); + + + /*below configuration for all three channel*/ + switch (pruInstId) + { + case PRUICSS_PRU0: + case PRUICSS_PRU1: + SDFM_CH = 3; + break; + case PRUICSS_RTU_PRU0: + case PRUICSS_RTU_PRU1: + SDFM_CH = 0; + break; + case PRUICSS_TX_PRU0: + case PRUICSS_TX_PRU1: + SDFM_CH = 6; + break; + default: + SDFM_CH = 0; + break; + } + + for(int i = SDFM_CH; i< SDFM_CH + NUM_CH_SUPPORTED_PER_AXIS; i++) + { + SDFM_setEnableChannel(hSdfm, i); + } + + for(SDFM_CH = 0; SDFM_CH < NUM_CH_SUPPORTED_PER_AXIS; SDFM_CH++) + { + + + /*set comparator osr or Over current osr*/ + SDFM_setCompFilterOverSamplingRatio(hSdfm, SDFM_CH, pSdfmPrms->ComFilterOsr); + + /*set ACC source or filter type*/ + SDFM_configDataFilter(hSdfm, SDFM_CH, acc_filter); + + /*set clock inversion & clock source for all three channel*/ + SDFM_selectClockSource(hSdfm, SDFM_CH, pSdfmPrms->clkPrms[SDFM_CH]); + + /*set threshold values */ + SDFM_setCompFilterThresholds(hSdfm, SDFM_CH, pSdfmPrms->threshold_parms[SDFM_CH]); + + if(pSdfmPrms->en_com) + { + SDFM_enableComparator(hSdfm, SDFM_CH); + } + else + { + SDFM_disableComparator(hSdfm, SDFM_CH); + } + + } + + /*GPIO pin configuration for threshold measurment*/ + ///sdfm_configure_gpio_pin(hSdfm); + + SDFM_setSampleTriggerTime(hSdfm, pSdfmPrms->firstSampTrigTime); + if(pSdfmPrms->en_second_update) + { + SDFM_enableDoubleSampling(hSdfm, pSdfmPrms->secondSampTrigTime); + } + else + { + SDFM_disableDoubleSampling(hSdfm); + } + + /* Enable (global) SDFM */ + SDFM_enable(hSdfm); + + *pHSdfm = hSdfm; + + return SDDF_ERR_NERR; +} diff --git a/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-0_nortos/sddf.h b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-0_nortos/sddf.h new file mode 100644 index 0000000..f47103e --- /dev/null +++ b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-0_nortos/sddf.h @@ -0,0 +1,189 @@ +/* + * Copyright (C) 2021 Texas Instruments Incorporated + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * Neither the name of Texas Instruments Incorporated nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SDDF_H_ +#define _SDDF_H_ + +#include +#include +#include +#include "tisddf_pruss_intc_mapping.h" + +/* Status codes */ +#define SDDF_ERR_NERR ( 0 ) /* no error */ +#define SDDF_ERR_CFG_PIN_MUX ( -1 ) /* pin mux configuration error */ +#define SDDF_ERR_CFG_ICSSG_CLKCFG ( -2 ) /* ICSSG clock configuration error */ +#define SDDF_ERR_INIT_ICSSG ( -3 ) /* initialize ICSSG error */ +#define SDDF_ERR_CFG_MCU_INTR ( -4 ) /* interrupt configuration error */ +#define SDDF_ERR_INIT_PRU_SDDF ( -5 ) /* initialize PRU for SDDF error */ +#define SDDF_ERR_INIT_SDDF ( -6 ) /* initialize SDDF error */ + +/* Bit for SDDF configuration mask */ +#define SDDF_CFG_CLK ( 1<<0 ) +#define SDDF_CFG_OSR ( 1<<1 ) +#define SDDF_CFG_TRIG_SAMP_TIME ( 1<<2 ) +#define SDDF_CFG_TRIG_SAMP_CNT ( 1<<3 ) +#define SDDF_CFG_CH_EN ( 1<<4 ) +#define SDDF_CFG_FD ( 1<<5 ) +#define SDDF_CFG_TRIG_OUT_SAMP_BUF ( 1<<6 ) + +/* SDDF mode */ +#define SDDF_MODE_TRIG ( 0 ) +#define SDDF_MODE_CONT ( 1 ) + +/* ICSSG Core clock source selection options */ +#define CORE_CLK_SEL_ICSSGn_CORE_CLK ( 0 ) /* Mux Output */ +#define CORE_CLK_SEL_ICSSGn_ICLK ( 1 ) /* ICSSGn_ICLK = MAIN_SYSCLK0/2 = 250 MHz */ +/* ICSSG Core clock selections in case Mux Output selected */ +#define ICSSGn_CORE_CLK_SEL_MAIN_PLL2_HSDIV0_CLKOUT ( 0 ) /* 225 or 300 MHz, default 225 MHz */ +#define ICSSGn_CORE_CLK_SEL_MAIN_PLL0_HSDIV9_CLKOUT ( 1 ) /* 200, 250, or 333 MHz, default 200 MHz */ +#define ICSSGn_CORE_CLK_SEL_NUMSEL ( 2 ) +/* ICSSG Core clock frequency in case Mux Output selected. + Set to 0 in case clock frequency configuration not desired. */ +#define ICSSGn_CORE_CLK_FREQ_225MHZ ( 225000000UL ) /* MAIN PLL2 HSDIV0, 225 MHz */ +#define ICSSGn_CORE_CLK_FREQ_300MHZ ( 300000000UL ) /* MAIN PLL2 HSDIV0, 300 MHz */ +#define ICSSGn_CORE_CLK_FREQ_200MHZ ( 200000000UL ) /* MAIN PLL0 HSDIV9, 200 MHz */ +#define ICSSGn_CORE_CLK_FREQ_250MHZ ( 250000000UL ) /* MAIN PLL0 HSDIV9, 250 MHz */ +#define ICSSGn_CORE_CLK_FREQ_333MHZ ( 333333333UL ) /* MAIN PLL0 HSDIV9, 333 MHz */ +#define ICSSGn_CORE_CLK_FREQ_NOCFG ( 0UL ) /* No clock frequency reconfig */ +//#define ICSSGn_CORE_CLK_FREQ ( ICSSGn_CORE_CLK_FREQ_NOCFG ) +#define ICSSGn_CORE_CLK_FREQ ( ICSSGn_CORE_CLK_FREQ_300MHZ ) +//#define ICSSGn_CORE_CLK_FREQ ( ICSSGn_CORE_CLK_FREQ_333MHZ ) + +/* ICSSG IEP clock source selection options */ +#define IEP_CLK_SEL_ICSSGn_IEP_CLK ( 0 ) /* Mux Output */ +#define IEP_CLK_SEL_CORE_CLK ( 1 ) /* CORE_CLK */ +/* ICSSG IEP clock selections in case Mux output selected */ +#define ICSSGn_IEP_CLK_SEL_MAIN_PLL2_HSDIV5_CLKOUT ( 0 ) /* Default 225 MHz */ +#define ICSSGn_IEP_CLK_SEL_MAIN_PLL0_HSDIV6_CLKOUT ( 1 ) /* 200 or 250 MHz, default 200 MHz */ +#define ICSSGn_IEP_CLK_SEL_CPSW0_CPTS_RFT_CLK ( 2 ) +#define ICSSGn_IEP_CLK_SEL_CPTS_RFT_CLK ( 3 ) +#define ICSSGn_IEP_CLK_SEL_MCU_EXT_REFCLK0 ( 4 ) +#define ICSSGn_IEP_CLK_SEL_EXT_REFCLK1 ( 5 ) +#define ICSSGn_IEP_CLK_SEL_SERDES0_IP1_LN0_TXMCLK ( 6 ) +#define ICSSGn_IEP_CLK_SEL_SYSCLK0 ( 7 ) +#define ICSSGn_IEP_CLK_SEL_NUMSEL ( 8 ) +/* ICSSG IEP clock frequency in case Mux Output selected. + Set to 0 in case clock frequency configuration not desired. */ +#define ICSSGn_IEP_CLK_FREQ_200MHZ ( 200000000UL ) /* MAIN PLL0 HSDIV6, 200 MHz */ +#define ICSSGn_IEP_CLK_FREQ_250MHZ ( 250000000UL ) /* MAIN PLL0 HSDIV6, 250 MHz */ +#define ICSSGn_IEP_CLK_FREQ_NOCFG ( 0UL ) /* No clock frequency reconfig */ +#define ICSSGn_IEP_CLK_FREQ ( ICSSGn_IEP_CLK_FREQ_NOCFG ) + +/* Default ICSS pin mux setting */ +#define PRUICSS_G_MUX_EN_DEF ( 0x0 ) /* ICSSG_SA_MX_REG:G_MUX_EN */ + +/* Translate the TCM local view addr to SoC view addr */ +#define CPU0_ATCM_SOCVIEW(x) (CSL_R5FSS0_CORE0_ATCM_BASE+(x)) +#define CPU1_ATCM_SOCVIEW(x) (CSL_R5FSS1_CORE0_ATCM_BASE+(x)) +#define CPU0_BTCM_SOCVIEW(x) (CSL_R5FSS0_CORE0_BTCM_BASE+(x - CSL_R5FSS0_BTCM_BASE)) +#define CPU1_BTCM_SOCVIEW(x) (CSL_R5FSS1_CORE0_BTCM_BASE+(x - CSL_R5FSS1_BTCM_BASE)) + +#define ICSSG_SLICE_ID_0 ( 0 ) /* ICSSG slide ID 0 */ +#define ICSSG_SLICE_ID_1 ( 1 ) /* ICSSG slide ID 1 */ +#define ICSSG_NUM_SLICE ( 2 ) /* ICSSG number of slices */ + +/*! + * @brief PRUICSS Instance IDs + */ +typedef enum PRUICSS_MaxInstances_s +{ + PRUICSS_INSTANCE_ONE=0, + PRUICSS_INSTANCE_TWO=1, + PRUICSS_INSTANCE_MAX=2 +} PRUICSS_MaxInstances; + +/* SDFM configuration parameters */ +typedef struct SdfmPrms_s { + /**< IEP clock value */ + uint32_t iep_clock; + /**< Sigma delta input clock value */ + uint32_t sd_clock; + /**< double update enable field */ + uint8_t en_second_update; + /**< First normal current sample trigger time */ + float firstSampTrigTime; + /**< First normal current sample trigger time */ + float secondSampTrigTime; + /**< output freq. of EPWM0 */ + uint32_t epwm_out_freq; + /**< Over current threshold parameters */ + SDFM_ThresholdParms threshold_parms[NUM_CH_SUPPORTED_PER_AXIS]; + /**< SD clock source and clock inversion */ + SDFM_ClkSourceParms clkPrms[3]; + /**< Over current OSR */ + uint16_t ComFilterOsr; + /**< Normal current OSR */ + uint16_t FilterOsr; + /**< over current enable field */ + uint8_t en_com; + /**< output samples base address*/ + uint32_t samplesBaseAddress; +} SdfmPrms; + + +/* Configure ICSSG clock selection */ +int32_t cfgIcssgClkCfg( + uint8_t icssInstId, + uint8_t coreClkSel, /* ICSSG internal Core clock source select, ICSSG_CORE_SYNC_REG:CORE_VBUSP_SYNC_EN */ + uint8_t icssCoreClkSel, /* ICSSG external Core clock source select, CTRLMMR_ICSSGn_CLKSEL:CORE_CLKSEL, (used if coreClkSel==0) */ + uint64_t icssCoreClkFreqHz, /* ICSSG external Core clock frequency, (used if !=0 && coreClkSel==0) */ + uint8_t iepClkSel, /* ICSSG internal IEP clock source select, ICSSG_IEPCLK_REG:IEP_OCP_CLK_EN */ + uint8_t icssIepClkSel, /* ICSSG internal IEP clock source select, CTRLMMR_ICSSGn_CLKSEL:IEP_CLKSEL, (used if iepClkSel==0) */ + uint64_t icssIepClkFreqHz /* ICSSG external IEP clock frequency, (used if !=0 && icssIepClkSel==0) */ +); + +/* Initialize ICSSG */ +int32_t initIcss( + uint8_t icssInstId, + uint8_t sliceId, + uint8_t saMuxMode, + PRUICSS_Handle *pPruIcssHandle +); + +/* Initialize PRU core for SDDF */ +int32_t initPruSddf( + PRUICSS_Handle pruIcssHandle, + uint8_t pruInstId, + SdfmPrms *pSddfPrms, + sdfm_handle *pHSddf +); + +/* Initialize SDDF PRU FW */ +int32_t initSddf( + uint8_t pruId, uint8_t pruInstId, + SdfmPrms *pSddfPrms, + sdfm_handle *pHSddf +); + + +#endif /* _SDDF_H_ */ diff --git a/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-0_nortos/settings.h b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-0_nortos/settings.h new file mode 100644 index 0000000..4f4c80f --- /dev/null +++ b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-0_nortos/settings.h @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2023 Texas Instruments Incorporated + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * Neither the name of Texas Instruments Incorporated nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* Following is the list of the Build Level choices */ +#define OPEN_LOOP_IQ_ID 1 /* Open loop Iq, Id */ +#define CLOSED_LOOP_IQ_ID 2 /* Closed loop Iq with reference array, Id closed loop to 0.0 */ +#define CLOSED_LOOP_SPEED 3 /* Closed loop Speed */ +#define CLOSED_LOOP_POSITION 4 /* Closed loop Position */ +#define CLOSED_LOOP_CIA402 5 /* Closed loop Iq, Speed, or Position based on EtherCAT CiA402 */ + +#define PID_TUNING 1 /* Enable the runtime PID tuning code */ +#define NO_TUNING 2 /* Disabe the runtime PID tuning, tuning has already occurred */ + +#define DEBUG_BUFFERS_ON 1 /* Log data into the debug buffers */ +#define DEBUG_BUFFERS_OFF 2 /* No data logging */ + +#define DEBUG_BUFFER_WRAP 1 /* Wrap the debug buffer continuously */ +#define DEBUG_BUFFER_SINGLE 2 /* Fill the debug buffer once to focus on startup conditions */ + +#define PRECOMPUTE_CLARKE 1 /* Use the SDDF ISR to convert/scale phase currents and compute Clarke Transform */ +#define NO_PRECOMPUTE 2 /* Convert/scale and compute Clarke Transform in the EnDat ISR along with the FOC loop */ + +#define BUILDLEVEL CLOSED_LOOP_SPEED ///CLOSED_LOOP_CIA402 ///CLOSED_LOOP_SPEED ///CLOSED_LOOP_IQ_ID ///OPEN_LOOP_IQ_ID +#define PID_TUNE_LEVEL NO_TUNING +#define DEBUG_LEVEL DEBUG_BUFFERS_OFF +#define DEBUG_WRAP_TYPE DEBUG_BUFFER_WRAP +#define PRECOMPUTE_LEVEL NO_PRECOMPUTE + +/* The number of ISR cycles to use the same target from the list of 8 targets */ +#define CYCLES_PER_TARGET 600 +#define TARGET_BUFF_SIZE CYCLES_PER_TARGET * 8 /* This value needs to be less than DEBUG_BUFF_SZ (65536) if DEBUG_BUFFERS_ON */ + +/* Iq testing value for open loop */ +#define INIT_PWM_DIFF 0.05 ///0.1 +#define IQ_TESTING 0.3 ///0.2 +#define ID_TESTING 0.0 + +/* Max speed change request allowed between updates */ +#define MAX_SPD_CHANGE 0.12 ///0.12 +/* Max position change request allowed between updates */ +#define MAX_POS_CHANGE 0.06 /* 500RPMs max speed movement between positions at 100KHz update rate */ + +#define MAX_SPD_RPM 120 ///500 + +#define ISR_PRD_IN_SECONDS 0.00002 /* 50KHz @ 1x update is 20us */ +#define ISR_PRD_IN_MINUTES (ISR_PRD_IN_SECONDS / 60.0) + +/* PRU event to clear for the EnDat interrupt */ +#define ENDAT_EVENT ( 18 ) /* 18 (EVT) for 120 (INT#) pr0_pru_mst_intr[4]_intr_req */ + +/* Sigma Delta definitions for SINC3 OSR64 - 0 - 2^18 */ +#define SDDF_FULL_SCALE 262144 +#define SDDF_HALF_SCALE 131072 +#define SDDF_HALF_SCALE_FLT 131072.0 + +/* Intial settling counts for SDDF and Electrical Angle offset calculations */ +#define SETTLING_COUNT 8192.0 +#define OFFSET_FINISHED (uint32_t) (SETTLING_COUNT * 2.0) + +#define CYCLIC_SYNC_POSITION_MODE 8 /**< \brief Cyclic Synchronous Position mode*/ +#define CYCLIC_SYNC_VELOCITY_MODE 9 /**< \brief Cyclic Synchronous Velocity mode*/ +#define CYCLIC_SYNC_TORQUE_MODE 10/**< \brief Cyclic Synchronous Torque mode*/ + +#define SINGLE_AXLE_USE_M1 /* for R5F_0_0, it controls the M1 */ +#define DUAL_AXIS_USE_M1_M2 /* for R5F_0_0, it controls the M1. for R5F_0_1, it controls the M2 */ + +///#define SINGLE_AXLE_USE_M2 /* for R5F_0_1, it controls the M2 */ + +#define CORE_R5F_0_0 + +#define SDDF_HW_EVM_ADAPTER_BP +///#define AM243X_ALV +#define AM243X_ALX + +///#define USE_PURE_OPEN_LOOP +///#define USE_OPEN_LOOP_WITH_SDDF + +///#define USE_RTLIB_FOC + diff --git a/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-0_nortos/single_chip_servo.c b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-0_nortos/single_chip_servo.c new file mode 100644 index 0000000..15abd33 --- /dev/null +++ b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-0_nortos/single_chip_servo.c @@ -0,0 +1,2833 @@ +/* + * Copyright (C) 2023 Texas Instruments Incorporated + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * Neither the name of Texas Instruments Incorporated nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ti_drivers_open_close.h" +#include "ti_board_open_close.h" +#include "DRV8350_defs.h" +#include "pwm.h" +#include "settings.h" +#include "ti_r5fmath_trig.h" +#include + +#include "tisddf_pruss_intc_mapping.h" +#include "mclk_iep_sync.h" +#include "sddf.h" +#include +#include "endat_periodic_trigger.h" + +#include + +#if defined(USE_RTLIB_FOC) +#include "clarke.h" +#include "park.h" +#include "ipark.h" +#include "svgen.h" +#endif + +#if PRU_ICSSGx_PRU_SLICE +#define PRUICSS_PRUx PRUICSS_PRU1 +#define PRUICSS_TXPRUx PRUICSS_TX_PRU1 +#define PRUICSS_RTUPRUx PRUICSS_RTU_PRU1 +#else +#define PRUICSS_PRUx PRUICSS_PRU0 +#define PRUICSS_TXPRUx PRUICSS_TX_PRU0 +#define PRUICSS_RTUPRUx PRUICSS_RTU_PRU0 +#endif +#define PRUICSS_SLICEx PRU_ICSSGx_PRU_SLICE + +#if CONFIG_ENDAT0_MODE == ENDAT_MODE_MULTI_CHANNEL_SINGLE_PRU +#include +#endif + +#if (CONFIG_ENDAT0_MODE == ENDAT_MODE_MULTI_CHANNEL_MULTI_PRU) +#include +#endif + +#if (CONFIG_ENDAT0_MODE == ENDAT_MODE_MULTI_CHANNEL_MULTI_PRU) +#include +#endif + +#if (CONFIG_ENDAT0_MODE == ENDAT_MODE_MULTI_CHANNEL_MULTI_PRU) +#include +#endif + +#if CONFIG_ENDAT0_MODE == ENDAT_MODE_SINGLE_CHANNEL_SINGLE_PRU +#include +#endif + +#define WAIT_5_SECOND (5000) +#define TASK_STACK_SIZE (4096) +#define TASK_PRIORITY (6) + +#define ENDAT_RX_SAMPLE_SIZE 7 +#define ENDAT_RX_SESQUI_DIV (1 << 15) + +#define MRS_POS_VAL2_WORD1 0x42 +#define MRS_POS_VAL2_WORD2 0x43 +#define MRS_POS_VAL2_WORD3 0x44 + +/* Translate the TCM local view addr to SoC view addr */ +#define CPU0_ATCM_SOCVIEW(x) (CSL_R5FSS0_CORE0_ATCM_BASE+(x)) +#define CPU1_ATCM_SOCVIEW(x) (CSL_R5FSS1_CORE0_ATCM_BASE+(x)) +#define CPU0_BTCM_SOCVIEW(x) (CSL_R5FSS0_CORE0_BTCM_BASE+(x - CSL_R5FSS0_BTCM_BASE)) +#define CPU1_BTCM_SOCVIEW(x) (CSL_R5FSS1_CORE0_BTCM_BASE+(x - CSL_R5FSS1_BTCM_BASE)) + +#define NUM_CH_SUPPORTED ( 3 ) + +/* EPWM ISR information */ +typedef struct _AppEPwmIsrInfo_t +{ + uint32_t epwmBaseAddr; + SemaphoreP_Object *pEpwmSyncSemObject; +} AppEPwmIsrInfo_t; +/* Interrupt globals */ +static HwiP_Object gEpwm0HwiObject; +static SemaphoreP_Object gEpwm0SyncSemObject; +static SemaphoreP_Object gEpwm0SyncSemObject2; +/* variable to hold EPWM base address and semaphore address for ISR */ +AppEPwmIsrInfo_t gAppEPwm0Info; +AppEPwmIsrInfo_t gAppEPwm0Info2; + +/* variables to hold EPWM base addresses */ +uint32_t gEpwm0BaseAddr; +uint32_t gEpwm1BaseAddr; +uint32_t gEpwm2BaseAddr; + +uint32_t gEpwm0BaseAddr2A; +uint32_t gEpwm0BaseAddr2B; +uint32_t gEpwm1BaseAddr2; +uint32_t gEpwm2BaseAddr2; + +/* EPWM output frequency */ +volatile uint32_t gEpwmOutFreq = APP_EPWM_OUTPUT_FREQ; +/* EPWM output frequency set value */ +volatile uint32_t gEpwmOutFreqSet = APP_EPWM_OUTPUT_FREQ; +/* EPWM Rising Edge Delay */ +uint32_t gDbRisingEdgeDelay = APP_EPWM_DB_RED_COUNT; +/* EPWM Falling Edge Delay */ +uint32_t gDbFallingEdgeDelay = APP_EPWM_DB_FED_COUNT; + +volatile Bool gSetEPwmOutFreq8K = TRUE; +volatile Bool gSetEPwmOutFreq16K = TRUE; +volatile Bool gSetEPwmOutFreq4K = TRUE; + +// debug, mainloop count +uint32_t gLoopCnt = 0; + +// debug, ISR counts +volatile uint32_t gEpwmIsrCnt = 0; +volatile uint32_t gEpwmIsrCnt2 = 0; +/* EPWM period */ +volatile uint32_t gEpwmPrdVal; + +/* For handling up-down count alternating period + when period isn't divisible by 2 */ +Bool gToggleEpwmPrd=FALSE; /* Flag for EPWMs in alternating period mode */ +uint8_t gToggleEpwmPrdState=0; /* Alternating period state: 'Lower' or 'Upper' period written on alternating ISRs */ +uint32_t gEpwmPrdValL; /* 'Lower' EPWM period value written in 'Lower' state */ +uint32_t gEpwmPrdValU; /* 'Upper' EPWM period value written in 'Upper' state */ + +volatile Bool gRunFlag = TRUE; /* Flag for continuing to execute test */ + +volatile uint32_t gPruSddfIrqCnt=0; /* SDDF PRU FW IRQ count */ +volatile uint32_t gRtuSddfIrqCnt=0; /* SDDF RTU FW IRQ count */ + +/* Test ICSSG instance ID */ +#define TEST_ICSSG_INST_ID ( CONFIG_PRU_ICSS0 ) +/* Test ICSSG slice ID */ +#define TEST_ICSSG_SLICE_ID ( ICSSG_SLICE_ID_0 ) +/* Test PRU core instance IDs */ +#define TEST_PRU_INST_ID ( PRUICSS_PRU0 ) +#define TEST_RTU_INST_ID ( PRUICSS_RTU_PRU0 ) + +/* R5F interrupt settings for ICSSG */ +#define ICSSG_PRU_SDDF_INT_NUM ( CSLR_R5FSS0_CORE0_INTR_PRU_ICSSG0_PR1_HOST_INTR_PEND_3 ) /* VIM interrupt number */ +#define ICSSG_RTU_SDDF_INT_NUM ( CSLR_R5FSS0_CORE0_INTR_PRU_ICSSG0_PR1_HOST_INTR_PEND_4 ) /* VIM interrupt number */ +#define ICSSG_TX_PRU_SDDF_INT_NUM ( CSLR_R5FSS0_CORE0_INTR_PRU_ICSSG0_PR1_HOST_INTR_PEND_5 ) /* VIM interrupt number */ + +/* HWI global variables */ +static HwiP_Object gIcssgPruSddfHwiObject; /* ICSSG PRU SDDF FW HWI */ +static HwiP_Object gIcssgRtuSddfHwiObject; /* ICSSG RTU SDDF FW HWI */ +static HwiP_Object gEpwm0HwiObject; /* EPWM0 HWI */ + +/* Test ICSSG handle */ +PRUICSS_Handle gPruIcssHandle; + +/* Test SDDF handles */ +//Sddf_handle gHPruSddf; +//Sddf_handle gHRtuSddf; +/* Test Sdfm handles */ +sdfm_handle gHPruSddf; +sdfm_handle gHRtuSddf; + +/* ICSSG_SA_MX_REG:G_MUX_EN */ +#if defined(SDDF_HW_EVM_ADAPTER_BP) +#if defined(AM243X_ALV) +#define PRUICSS_G_MUX_EN ( 0x00 ) +#endif +#if defined(AM243X_ALX) +#define PRUICSS_G_MUX_EN ( 0x80 ) +#endif +#endif + +#if (DEBUG_LEVEL == DEBUG_BUFFERS_ON) +/* debug, SDDF sample capture buffers */ +#define DEBUG_BUFF_SZ (32768) + +__attribute__((section(".gDebugBuff1"))) volatile float gDebugBuff0[DEBUG_BUFF_SZ] = { 0 }; +__attribute__((section(".gDebugBuff1"))) volatile float gDebugBuff1[DEBUG_BUFF_SZ] = { 0 }; +__attribute__((section(".gDebugBuff2"))) volatile float gDebugBuff2[DEBUG_BUFF_SZ] = { 0 }; +__attribute__((section(".gDebugBuff2"))) volatile float gDebugBuff3[DEBUG_BUFF_SZ] = { 0 }; +uint32_t gDebugBuffIdx = 0; +#endif + +uint32_t gCapSddfChSampsChNum = 0; +#ifdef SDDF_HW_EVM_ADAPTER_BP +#if defined(USE_PURE_OPEN_LOOP) +__attribute__((section(".gCtrlVars"))) float gSddfChOffsets[3] = { 335.125366, -647.005249, -536.584351 }; +__attribute__((section(".gCtrlVars"))) float gSddfChOffsets2[3] = { 335.125366, -647.005249, -536.584351 }; +#else +__attribute__((section(".gCtrlVars"))) float gSddfChOffsets[3] = { 0.0, 0.0, 0.0 }; +__attribute__((section(".gCtrlVars"))) float gSddfChOffsets2[3] = { 0.0, 0.0, 0.0 }; +#endif +#endif + +/* SDDF output samples, written by PRU */ +__attribute__((section(".gSddfChSampsRaw"))) uint32_t gSddfChSamps[ICSSG_NUM_SD_CH] = { 0 }; + +struct endat_priv *priv; + +/** \brief Global Structure pointer holding PRUSS1 memory Map. */ +__attribute__((section(".gSharedPrivStep"))) int32_t priv_step; +__attribute__((section(".gSharedPruHandle"))) PRUICSS_Handle gPruIcss0Handle; +PRUICSS_Handle gRtuIcss0Handle; +#define gPruIcssXHandle gPruIcss0Handle + +/* ADC offset calculation complete */ +uint8_t gSDDFOffsetComplete = FALSE; +uint8_t gSDDFOffsetComplete2 = FALSE; + +/* EnDat channel Info, written by PRU cores */ +__attribute__((section(".gEnDatChInfo"))) struct endatChRxInfo gEndatChInfo; + +#define ENDAT_MULTI_CH0 (1 << 0) +#define ENDAT_MULTI_CH1 (1 << 1) +#define ENDAT_MULTI_CH2 (1 << 2) + +#define ENDAT_INPUT_CLOCK_UART_FREQUENCY 192000000 +/* use uart clock only to start with */ +#define ENDAT_INPUT_CLOCK_FREQUENCY ENDAT_INPUT_CLOCK_UART_FREQUENCY + +#define ENDAT_RX_SAMPLE_SIZE 7 +#define ENDAT_RX_SESQUI_DIV (1 << 15) + +static int gEndat_is_multi_ch; +static unsigned char gEndat_multi_ch_mask; +static uint8_t gEndat_is_load_share_mode; + +static unsigned int gEndat_prop_delay[3]; +static unsigned int gEndat_prop_delay_max; + +__attribute__((section(".gEncChData"))) struct endat_pruss_xchg local_pruss_xchg; + +volatile Bool gUpdOutIsr = FALSE; /* Flag for updating PWM output in ISR */ + +arm_pid_instance_f32 gPiId; +arm_pid_instance_f32 gPiIq; +arm_pid_instance_f32 gPiSpd; +arm_pid_instance_f32 gPiPos; +volatile Bool gConstantsChanged = 0; + +/* ICSSG PRU SDDF FW IRQ handler */ +static void pruSddfIrqHandler(void *handle); +/* ICSSG RTU SDDF FW IRQ handler */ +static void rtuSddfIrqHandler(void *handle); + +#if defined(SINGLE_AXLE_USE_M1) +void enable_pwm_buffers(Bool enable) +{ + if(enable) { + GPIO_pinWriteLow(MTR_1_PWM_EN_BASE_ADDR, MTR_1_PWM_EN_PIN); + GPIO_pinWriteLow(MTR_2_PWM_EN_BASE_ADDR, MTR_2_PWM_EN_PIN); + GPIO_pinWriteHigh(BP_MUX_SEL_BASE_ADDR, BP_MUX_SEL_PIN); + } + else { + GPIO_pinWriteHigh(MTR_1_PWM_EN_BASE_ADDR, MTR_1_PWM_EN_PIN); + GPIO_pinWriteHigh(MTR_2_PWM_EN_BASE_ADDR, MTR_2_PWM_EN_PIN); + GPIO_pinWriteHigh(BP_MUX_SEL_BASE_ADDR, BP_MUX_SEL_PIN); + } +} +#endif + +uint64_t endat_get_fw_version(void) +{ +#if CONFIG_ENDAT0_MODE == ENDAT_MODE_MULTI_CHANNEL_SINGLE_PRU + return *((unsigned long *)EnDatFirmwareMulti_0 + 2); +#endif + +#if (CONFIG_ENDAT0_CHANNEL0) && (CONFIG_ENDAT0_MODE == ENDAT_MODE_MULTI_CHANNEL_MULTI_PRU) + return *((unsigned long *)EnDatFirmwareMultiMakeRTU_0 + 2); +#endif + +#if (CONFIG_ENDAT0_CHANNEL1) && (CONFIG_ENDAT0_MODE == ENDAT_MODE_MULTI_CHANNEL_MULTI_PRU) + return *((unsigned long *)EnDatFirmwareMultiMakePRU_0 + 2); +#endif + +#if (CONFIG_ENDAT0_CHANNEL2) && (CONFIG_ENDAT0_MODE == ENDAT_MODE_MULTI_CHANNEL_MULTI_PRU) + return *((unsigned long *)EnDatFirmwareMultiMakeTXPRU_0 + 2); +#endif + +#if CONFIG_ENDAT0_MODE == ENDAT_MODE_SINGLE_CHANNEL_SINGLE_PRU + return *((unsigned long *)EnDatFirmware_0 + 2); +#endif + +} + +static void endat_pruss_init(void) +{ + gPruIcssXHandle = PRUICSS_open(CONFIG_PRU_ICSS0); + /* Configure g_mux_en to 1 in ICSSG_SA_MX_REG Register. */ + PRUICSS_setSaMuxMode(gPruIcssXHandle, PRUICSS_SA_MUX_MODE_SD_ENDAT); + + /* Set in constant table C30 to shared RAM 0x40300000 */ + PRUICSS_setConstantTblEntry(gPruIcssXHandle, PRUICSS_PRUx, PRUICSS_CONST_TBL_ENTRY_C30, ((0x40300000 & 0x00FFFF00) >> 8)); + if(gEndat_is_load_share_mode) + { + PRUICSS_setConstantTblEntry(gPruIcssXHandle, PRUICSS_TXPRUx, PRUICSS_CONST_TBL_ENTRY_C30, ((0x40300000 & 0x00FFFF00) >> 8)); + PRUICSS_setConstantTblEntry(gPruIcssXHandle, PRUICSS_RTUPRUx, PRUICSS_CONST_TBL_ENTRY_C30, ((0x40300000 & 0x00FFFF00) >> 8)); + /*Set in constant table C29 for tx pru*/ + PRUICSS_setConstantTblEntry(gPruIcssXHandle, PRUICSS_TXPRUx, PRUICSS_CONST_TBL_ENTRY_C28, 0x258); + + } + /* clear ICSS0 PRU1 data RAM */ + PRUICSS_initMemory(gPruIcssXHandle, PRUICSS_DATARAM(PRUICSS_SLICEx)); + if(gEndat_is_load_share_mode) + { + PRUICSS_disableCore(gPruIcssXHandle, PRUICSS_RTUPRUx); + PRUICSS_disableCore(gPruIcssXHandle, PRUICSS_TXPRUx); + } + PRUICSS_disableCore(gPruIcssXHandle, PRUICSS_PRUx); + + +} + +void endat_pre_init(void) +{ + endat_pruss_init(); +} + +uint32_t endat_pruss_load_run_fw(struct endat_priv *priv) +{ + + uint32_t status = SystemP_FAILURE; + +#if CONFIG_ENDAT0_MODE == ENDAT_MODE_MULTI_CHANNEL_MULTI_PRU /*enable loadshare mode*/ + + + + status = PRUICSS_disableCore(gPruIcssXHandle, PRUICSS_RTUPRUx); + DebugP_assert(SystemP_SUCCESS == status); + status=PRUICSS_writeMemory(gPruIcssXHandle, PRUICSS_IRAM_RTU_PRU(PRUICSS_SLICEx), + 0, (uint32_t *) EnDatFirmwareMultiMakeRTU_0, + sizeof(EnDatFirmwareMultiMakeRTU_0)); + DebugP_assert(0 != status); + status = PRUICSS_resetCore(gPruIcssXHandle, PRUICSS_RTUPRUx); + DebugP_assert(SystemP_SUCCESS == status); + status = PRUICSS_enableCore(gPruIcssXHandle, PRUICSS_RTUPRUx); + DebugP_assert(SystemP_SUCCESS == status); + + + status=PRUICSS_disableCore(gPruIcssXHandle, PRUICSS_PRUx ); + DebugP_assert(SystemP_SUCCESS == status); + status = PRUICSS_writeMemory(gPruIcssXHandle, PRUICSS_IRAM_PRU(PRUICSS_SLICEx), + 0, (uint32_t *) EnDatFirmwareMultiMakePRU_0, + sizeof(EnDatFirmwareMultiMakePRU_0)); + DebugP_assert(0 != status); + status = PRUICSS_resetCore(gPruIcssXHandle, PRUICSS_PRUx); + DebugP_assert(SystemP_SUCCESS == status); + status = PRUICSS_enableCore(gPruIcssXHandle, PRUICSS_PRUx); + DebugP_assert(SystemP_SUCCESS == status); + + + status = PRUICSS_disableCore(gPruIcssXHandle, PRUICSS_TXPRUx); + DebugP_assert(SystemP_SUCCESS == status); + status = PRUICSS_writeMemory(gPruIcssXHandle, PRUICSS_IRAM_TX_PRU(PRUICSS_SLICEx), + 0, (uint32_t *) EnDatFirmwareMultiMakeTXPRU_0, + sizeof(EnDatFirmwareMultiMakeTXPRU_0)); + DebugP_assert(0 != status); + status = PRUICSS_resetCore(gPruIcssXHandle, PRUICSS_TXPRUx); + DebugP_assert(SystemP_SUCCESS == status); + status = PRUICSS_enableCore(gPruIcssXHandle, PRUICSS_TXPRUx); + DebugP_assert(SystemP_SUCCESS == status); + + + status=endat_wait_initialization(priv, WAIT_5_SECOND, gEndat_multi_ch_mask); + + +#else + + status = PRUICSS_disableCore(gPruIcssXHandle, PRUICSS_PRUx); + DebugP_assert(SystemP_SUCCESS == status); + +#if(CONFIG_ENDAT0_MODE == ENDAT_MODE_MULTI_CHANNEL_SINGLE_PRU) + + status = PRUICSS_writeMemory(gPruIcssXHandle, PRUICSS_IRAM_PRU(PRUICSS_SLICEx), + 0, (uint32_t *) EnDatFirmwareMulti_0, + sizeof(EnDatFirmwareMulti_0)); + +#else + + status = PRUICSS_writeMemory(gPruIcssXHandle, PRUICSS_IRAM_PRU(PRUICSS_SLICEx), + 0, (uint32_t *) EnDatFirmware_0, + sizeof(EnDatFirmware_0)); +#endif + DebugP_assert(0 != status); + + status = PRUICSS_resetCore(gPruIcssXHandle, PRUICSS_PRUx); + DebugP_assert(SystemP_SUCCESS == status); + + /*Run firmware */ + status = PRUICSS_enableCore(gPruIcssXHandle, PRUICSS_PRUx); + DebugP_assert(SystemP_SUCCESS == status); + + /* check initialization ack from firmware, with a timeout of 5 second */ + status = endat_wait_initialization(priv, WAIT_5_SECOND, gEndat_multi_ch_mask); +#endif + + return status; +} + + + +static int endat_calc_clock(unsigned freq, struct endat_clk_cfg *clk_cfg) +{ + unsigned ns; + + if(freq > 16000000 || (freq > 12000000 && freq < 16000000)) + { + DebugP_log("\r| ERROR: frequency above 16MHz, between 12 & 16MHz not allowed\n|\n|\n"); + return -1; + } + + if((freq != 16000000) && (ENDAT_INPUT_CLOCK_FREQUENCY % (freq * 8))) + DebugP_log("\r| WARNING: exact clock divider is not possible, frequencies set would be tx: %u\trx: %u\n", + ENDAT_INPUT_CLOCK_FREQUENCY / (ENDAT_INPUT_CLOCK_FREQUENCY / freq), + ENDAT_INPUT_CLOCK_FREQUENCY / (ENDAT_INPUT_CLOCK_FREQUENCY / (freq * 8))); + + ns = 2 * 1000000000 / freq; /* rx arm >= 2 clock */ + + /* should be divisible by 5 */ + if(ns % 5) + { + ns /= 5, ns += 1, ns *= 5; + } + + clk_cfg->tx_div = ENDAT_INPUT_CLOCK_FREQUENCY / freq - 1; + clk_cfg->rx_div = ENDAT_INPUT_CLOCK_FREQUENCY / (freq * 8) - 1; + clk_cfg->rx_en_cnt = ns; + clk_cfg->rx_div_attr = ENDAT_RX_SAMPLE_SIZE; + + if(freq == 16000000) + { + clk_cfg->rx_div_attr |= ENDAT_RX_SESQUI_DIV; + } + + DebugP_logInfo("\r| clock config values - tx_div: %u\trx_div: %u\trx_en_cnt: %u\trx_div_attr: %x\n", + clk_cfg->tx_div, clk_cfg->rx_div, clk_cfg->rx_en_cnt, clk_cfg->rx_div_attr); + + return 0; +} + +static void endat_handle_prop_delay(struct endat_priv *priv, + unsigned short prop_delay) +{ + if(prop_delay > priv->rx_en_cnt) + { + unsigned short dis = (prop_delay - priv->rx_en_cnt) * 2 / priv->rx_en_cnt; + + endat_config_rx_arm_cnt(priv, prop_delay); + /* propagation delay - 2T */ + endat_config_rx_clock_disable(priv, dis); + } + else + { + endat_config_rx_arm_cnt(priv, priv->rx_en_cnt); + endat_config_rx_clock_disable(priv, 0); + } +} + +static void endat_print_encoder_info(struct endat_priv *priv) +{ + DebugP_log("EnDat 2.%d %s encoder\tID: %u %s\tSN: %c %u %c\n\n", + priv->cmd_set_2_2 ? 2 : 1, + (priv->type == rotary) ? "rotary" : "linear", + priv->id.binary, (char *)&priv->id.ascii, + (char)priv->sn.ascii_msb, priv->sn.binary, (char)priv->sn.ascii_lsb); + DebugP_log("\rPosition: %d bits ", priv->pos_res); + + if(priv->type == rotary) + { + DebugP_log("(singleturn: %d, multiturn: %d) ", priv->single_turn_res, + priv->multi_turn_res); + } + + DebugP_log("[resolution: %d %s]", priv->step, + priv->type == rotary ? "M/rev" : "nm"); + DebugP_log("\r\n\nPropagation delay: %dns", + gEndat_prop_delay[priv->channel]); + DebugP_log("\n\n\n"); +} + +static unsigned endat_do_sanity_tst_delay(unsigned delay) +{ + /* (unsigned short)~0 is also a multiple of 5 */ + if(delay > (unsigned short)~0) + { + DebugP_log("\r| ERROR: delay greater than %uns, enter lesser value\n|\n|\n", + (unsigned short)~0); + return delay; + } + + if(delay % 5) + { + delay += 5, delay /= 5, delay *= 5; + DebugP_log("\r| WARNING: delay not multiple of 5ns, rounding to %uns\n|\n|\n", + delay); + } + + return delay; +} + +static void endat_init_clock(uint32_t frequency, struct endat_priv *priv) { + struct endat_clk_cfg clk_cfg; + int32_t j; + uint32_t delay; + uint16_t d; + + if(endat_calc_clock(frequency, &clk_cfg) < 0) + { + return; + } + + endat_config_clock(priv, &clk_cfg); + + priv->rx_en_cnt = clk_cfg.rx_en_cnt; + + for(j = 0; j < 3; j++) + { + if(gEndat_multi_ch_mask & 1 << j) + { + endat_multi_channel_set_cur(priv, j); + endat_handle_prop_delay(priv, gEndat_prop_delay[priv->channel]); + d = gEndat_prop_delay_max - gEndat_prop_delay[j]; + endat_config_wire_delay(priv, d); + } + } + + /* set tST to 2us if frequency > 1MHz, else turn it off */ + if(frequency >= 1000000) + { + frequency = 2000; + } + else + { + frequency = 0; + } + + delay = endat_do_sanity_tst_delay(frequency); + + if(delay <= (unsigned short)~0) + { + endat_config_tst_delay(priv, (unsigned short) delay); + } +} +volatile float gAngle = 0; +volatile uint32_t gRevolution = 0; + +static void endat_handle_rx(struct endat_priv *priv, int cmd) +{ + union endat_format_data endat_format_data; + + endat_recvd_process(priv, cmd, &endat_format_data); + endat_recvd_validate(priv, cmd, &endat_format_data); + gAngle = (float) endat_format_data.position_addinfo.position.position / priv->step * 360.0; + gRevolution = endat_format_data.position_addinfo.position.revolution; + + return; +} + + +volatile uint32_t gPruEncoderIrqCnt=0; /* EnDat PRU FW IRQ count */ +volatile uint32_t gPruEncoderIrqCnt2=0; /* EnDat PRU FW IRQ count */ +volatile uint32_t gPruEncoderIrqCnt2_after=0; /* EnDat PRU FW IRQ count */ +static HwiP_Object gIcssgEncoderHwiObject; /* ICSSG EnDat PRU FW HWI */ + +/* ICSSG Interrupt settings */ +#define ICSSG_PRU_ENDAT_INT_NUM ( CSLR_R5FSS0_CORE0_INTR_PRU_ICSSG0_PR1_HOST_INTR_PEND_0 ) /* interrupt number */ + +__STATIC_FORCEINLINE void space_vector_f32( +float32_t Ialpha, +float32_t Ibeta, +float32_t * pIa, +float32_t * pIb, +float32_t * pIc) +{ + float32_t tmp1, tmp2, tmp3; + uint8_t vector = 3; + + tmp1 = Ibeta; + tmp2 = (Ibeta / 2) + (0.8660254039f * Ialpha); + tmp3 = tmp2 - tmp1; + + vector = (tmp2 > 0) ? vector - 1: vector; + vector = (tmp3 > 0) ? vector - 1: vector; + vector = (tmp1 < 0) ? (7 - vector): vector; + + if(vector == 1 || vector == 4){ + *pIa = tmp2; + *pIb = tmp1 - tmp3; + *pIc = -tmp2; + } + else if (vector == 2 || vector == 5){ + *pIa = tmp3 + tmp2; + *pIb = tmp1; + *pIc = -tmp1; + } + else { + *pIa = tmp3; + *pIb = -tmp3; + *pIc = -(tmp1 + tmp2); + } +} + +volatile float gIq = 0.0; +volatile float gIqTarget, gIqSetPoint, gIqRef = 0.0; +__attribute__((section(".gCtrlVars"))) volatile float gIqArray[8] = {0,0.5,1.0,1.5,0,-.5,-1,0}; + +volatile float gId = 0.0; +volatile float gIdRef = 0.0; + +volatile float gSpdTarget, gSpdSetPoint = 0, gSpdRef = 0; +///__attribute__((section(".gCtrlVars"))) volatile float gSpdArray[8] = {0,500,750,-500,-750,0,0,0}; +__attribute__((section(".gCtrlVars"))) volatile float gSpdArray[8] = {MAX_SPD_RPM,MAX_SPD_RPM,MAX_SPD_RPM,MAX_SPD_RPM, + MAX_SPD_RPM,MAX_SPD_RPM,MAX_SPD_RPM,MAX_SPD_RPM}; + +volatile float gPosTarget, gPosSetPoint, gPosRef = 0; +__attribute__((section(".gCtrlVars"))) volatile float gPosArray[8] = {180,180,359.5,359.5,0.5,0.5,180,180}; + +volatile uint8_t count = 0; + +volatile uint8_t gInferFromLargestPhases = TRUE; +volatile uint8_t gInferA, gInferB = FALSE; + +__attribute__((section(".gCtrlVars"))) float gMechAngleOffset = 0; +float gLastMechTheta = 0; +uint16_t gLastMultiTurn = 0; +uint16_t gStartingMultiTurn = 0; + +uint8_t localEnDatGetSingleMulti(float32_t * mechTheta, uint16_t * multiTurn, int chan){ + uint32_t pos, rev; + + if ((chan<0)||(chan>2)) + return -1; + + /* Check CRC from the EnDat PRU */ + if(!(gEndatChInfo.ch[chan].crcStatus & ENDAT_CRC_DATA)) + return -1; + + /* Set CRC to 0 to ensure that the PRU re-populates it every time and we aren't reading old CRC flags*/ + gEndatChInfo.ch[chan].crcStatus = 0; + + /* grab position word 0/1 from the TCM */ + pos = gEndatChInfo.ch[chan].posWord0; + rev = gEndatChInfo.ch[chan].posWord1; + + /* Reverse the bits since they arrive at the PRU in reverse order */ + asm("rbit %0,%1" : "=r"(pos) : "r"(pos)); + asm("rbit %0,%1" : "=r"(rev) : "r"(rev)); + + /* Cobble the multiturn data together from pos0 and pos1 and create singleturn by shifting out F1/F2 and masking the multiturn bits */ + rev = ((rev & 0x07F00000) >> 15) | ((pos & 0xF8000000) >> 27); + pos = (pos >> 2) & 0x1FFFFFF; + + *mechTheta = (float32_t) pos / (float32_t) priv->step * 360.0; + *multiTurn = (uint16_t) rev; + + return 0; +} + +/* Arm CMSIS 'arm_pid_f32' function modified here to remove the derivative portion since it is unused */ +__STATIC_FORCEINLINE float32_t arm_pi_f32( +arm_pid_instance_f32 * S, +float32_t in) +{ + float32_t out; + + /* y[n] = y[n-1] + A0 * x[n] + A1 * x[n-1] */ + out = (S->A0 * in) + (S->A1 * S->state[0]) + (S->state[2]); + + /* Update state */ + S->state[1] = S->state[0]; + S->state[0] = in; + S->state[2] = out; + + /* return to application */ + return (out); +} + +uint32_t gLastEnDatCMP2 = 2897; + +float32_t gClarkeAlphaMeasured, gClarkeBetaMeasured; + +struct pdo_tx_data { + uint16_t controlWord; + int8_t modeOfOperation; + int32_t targetPosition; + int32_t targetVelocity; + int16_t targetTorque; +}; + +struct pdo_rx_data { + uint16_t statusWord; + int8_t modeOfOperationDisplay; + int32_t actualPosition; + int32_t actualVelocity; + int16_t actualTorque; +}; + +/* Target data from the PLC */ +__attribute__((section(".gTxDataSection"))) struct pdo_tx_data gTxData; +/* Actual data to send to the PLC */ +__attribute__((section(".gRxDataSection"))) struct pdo_rx_data gRxData; + +#ifdef SDDF_HW_EVM_ADAPTER_BP +/* EnDat PRU FW IRQ handler */ +#if defined(USE_PURE_OPEN_LOOP)||defined(USE_OPEN_LOOP_WITH_SDDF) +float32_t myMechTheta = 0.0; +float32_t myMechDelta = 0.0166667; /// for 50Khz PWM +float32_t myMechTheta2 = 0.0; +float32_t myMechDelta2 = 0.0166667; /// for 50Khz PWM +#endif + +#ifdef SINGLE_AXLE_USE_M1 +uint32_t gEncErrCnt = 0; +uint32_t gPruEncoderIrqCnt_after = 0; +__attribute__((section(".gEtherCatCia402"))) int32_t gCurTargetVelocity[3]; +__attribute__((section(".gEtherCatCia402"))) int32_t gCurActualVelocity[3]; +__attribute__((section(".critical_code"))) void pruEncoderIrqHandler(void *args) +{ + float32_t fdbkCurPhA, fdbkCurPhB; + float32_t mechTheta, elecTheta; + uint16_t multiTurn = 0; + float32_t elecThetaSinCos[2]; + float32_t parkIdOut, parkIqOut, parkIdMeasured, parkIqMeasured; + float32_t iparkAlphaOut, iparkBetaOut; + float32_t spcVectAOut, spcVectBOut, spcVectCOut; + float dc0, dc1, dc2; /* EPWM duty cycle values */ + uint16_t cmp0, cmp1, cmp2; /* EPWM CMPA values */ + float speed, angleDelta; + float halfPeriod; + + /* Hard-coded for now to trigger the EnDat reading twice, not benchmarked because this should be moved to the PRU in the future */ +#if 0 + if(gLastEnDatCMP2 == 2897) { + HW_WR_REG32(0x3002E098, 5897); + gLastEnDatCMP2 = 5897; + } + else { + HW_WR_REG32(0x3002E098, 2897); + gLastEnDatCMP2 = 2897; + } +#endif + /* Clear interrupt at source */ + PRUICSS_clearEvent(gPruIcss0Handle, ENDAT_EVENT); + +#if defined(USE_PURE_OPEN_LOOP) + gSDDFOffsetComplete = TRUE; + gPruEncoderIrqCnt = OFFSET_FINISHED+1; +#endif + + if (gSDDFOffsetComplete) { + /* debug, increment PRU SDDF IRQ count */ + gPruEncoderIrqCnt++; + + /* Start FOC loop and unlock the rotor */ + if (gPruEncoderIrqCnt > OFFSET_FINISHED) { +#if !defined(USE_PURE_OPEN_LOOP)&&!defined(USE_OPEN_LOOP_WITH_SDDF) + /* Get the latest mechanical theta and multi-turn position from the encoder */ + if (localEnDatGetSingleMulti(&mechTheta, &multiTurn, 0) != 0) + { + gEncErrCnt++; + return; + } + gPruEncoderIrqCnt_after++; +#endif + /* Use calculated offset from electrical 0, 4 pole pairs */ +#if defined(USE_PURE_OPEN_LOOP)||defined(USE_OPEN_LOOP_WITH_SDDF) + elecTheta = myMechTheta - gMechAngleOffset; +#else + elecTheta = mechTheta - gMechAngleOffset; +#endif + if(elecTheta < 0) + elecTheta += 90; + elecTheta *= 4.0; + + /* ti_r5fmath_sincos expects input in the range of 0-2pi radians so normalize here to 0-360 degrees */ + while (elecTheta > 360.0) + elecTheta -= 360.0; + +#if defined(USE_PURE_OPEN_LOOP)||defined(USE_OPEN_LOOP_WITH_SDDF) + angleDelta = myMechTheta - gLastMechTheta; +#else + angleDelta = mechTheta - gLastMechTheta; +#endif + /* Max angle change per period @ 3200RPMs with 50KHz period should be 0.384 degrees, outside that is rollover + * Use 5 as the bound to provide plenty of room for max acceleration cases */ + if (angleDelta < -50) + angleDelta += 360; + else if (angleDelta > 50) + angleDelta -= 360; + + /* Compute instantaneous RPMs using the change in angle and the PWM frequency */ + speed = (angleDelta / 360.0) / (ISR_PRD_IN_MINUTES); + +#if (PRECOMPUTE_LEVEL == NO_PRECOMPUTE) + /* Try to avoid the INA240 switching noise by selecting the 2 phases with the largest duty cycles */ + if (gInferA) { + fdbkCurPhB = (-((float)gSddfChSamps[1] - gSddfChOffsets[1] - SDDF_HALF_SCALE_FLT) / SDDF_HALF_SCALE_FLT) * 30.0; + fdbkCurPhA = -fdbkCurPhB - ((-((float)gSddfChSamps[2] - gSddfChOffsets[2] - SDDF_HALF_SCALE_FLT) / SDDF_HALF_SCALE_FLT) * 30.0); + + } + else if (gInferB){ + fdbkCurPhA = (-((float)gSddfChSamps[0] - gSddfChOffsets[0] - SDDF_HALF_SCALE_FLT) / SDDF_HALF_SCALE_FLT) * 30.0; + fdbkCurPhB = -fdbkCurPhA - ((-((float)gSddfChSamps[2] - gSddfChOffsets[2] - SDDF_HALF_SCALE_FLT) / SDDF_HALF_SCALE_FLT) * 30.0); + } + else { + fdbkCurPhA = (-((float)gSddfChSamps[0] - gSddfChOffsets[0] - SDDF_HALF_SCALE_FLT) / SDDF_HALF_SCALE_FLT) * 30.0; + fdbkCurPhB = (-((float)gSddfChSamps[1] - gSddfChOffsets[1] - SDDF_HALF_SCALE_FLT) / SDDF_HALF_SCALE_FLT) * 30.0; + } + +#if defined(USE_RTLIB_FOC) + CLARKE_run_twoInput(fdbkCurPhA, fdbkCurPhB, &gClarkeAlphaMeasured, &gClarkeBetaMeasured); +#else + /* Clarke transform */ + arm_clarke_f32(fdbkCurPhA, fdbkCurPhB, &gClarkeAlphaMeasured, &gClarkeBetaMeasured); +#endif +#endif + /* Calculate sine and cosine of the electrical angle (elecTheta converted to radians) */ + ti_r5fmath_sincos((elecTheta * TI_R5FMATH_PIOVER180), ti_r5fmath_sincosPIconst, ti_r5fmath_sincosCoef, elecThetaSinCos); +#if defined(USE_RTLIB_FOC) + /* Park transform */ + PARK_run(elecThetaSinCos[0], elecThetaSinCos[1], gClarkeAlphaMeasured, gClarkeBetaMeasured, &parkIdMeasured, &parkIqMeasured); +#else + /* Park transform */ + arm_park_f32(gClarkeAlphaMeasured, gClarkeBetaMeasured, &parkIdMeasured, &parkIqMeasured, elecThetaSinCos[0], elecThetaSinCos[1]); +#endif + +// Open loop Iq +#if (BUILDLEVEL == OPEN_LOOP_IQ_ID) + if(gIq < IQ_TESTING) + gIq += 0.01; + + parkIdOut = 0.0; + parkIqOut = gIq; + +#if defined(USE_PURE_OPEN_LOOP)||defined(USE_OPEN_LOOP_WITH_SDDF) + myMechTheta += myMechDelta; + + if (myMechTheta>359.9999) + myMechTheta = 0.0; +#endif +#endif +//Closed loop Iq and Id tuning +#if (BUILDLEVEL == CLOSED_LOOP_IQ_ID) + gIqTarget = 0.5; ///gIqArray[count]; + gIqSetPoint = gIqTarget; + + if((gPruEncoderIrqCnt - OFFSET_FINISHED) % CYCLES_PER_TARGET == 0){ + count++; + if(count == 8) + count = 0; + } + + parkIqOut = arm_pi_f32(&gPiIq, gIqSetPoint - parkIqMeasured); + parkIdOut = arm_pi_f32(&gPiId, 0.0 - parkIdMeasured); + if (parkIqOut>IQ_TESTING) parkIqOut = IQ_TESTING; + if (parkIqOut<-1.0*IQ_TESTING) parkIqOut = -1.0*IQ_TESTING; + if (parkIdOut>ID_TESTING) parkIdOut = ID_TESTING; + if (parkIdOut<-1.0*ID_TESTING) parkIdOut = -1.0*ID_TESTING; +#endif +//Closed loop speed +#if (BUILDLEVEL == CLOSED_LOOP_SPEED) + gSpdTarget = gCurTargetVelocity[0]; + if(gSpdSetPoint < gSpdTarget) + gSpdSetPoint += MAX_SPD_CHANGE; + else if (gSpdSetPoint > gSpdTarget) + gSpdSetPoint -= MAX_SPD_CHANGE; + + // update the gCurActualVelocity[0] based on the gSpdSetPoint + gCurActualVelocity[0] = (uint32_t)gSpdSetPoint; + + gIqRef = arm_pi_f32(&gPiSpd, gSpdSetPoint - speed); + parkIqOut = arm_pi_f32(&gPiIq, gIqRef - parkIqMeasured); + parkIdOut = arm_pi_f32(&gPiId, 0.0 - parkIdMeasured); + if (parkIqOut>IQ_TESTING) parkIqOut = IQ_TESTING; + if (parkIqOut<-1.0*IQ_TESTING) parkIqOut = -1.0*IQ_TESTING; + if (parkIdOut>ID_TESTING) parkIdOut = ID_TESTING; + if (parkIdOut<-1.0*ID_TESTING) parkIdOut = -1.0*ID_TESTING; +#endif + +//Closed loop CiA402 Data +#if (BUILDLEVEL == CLOSED_LOOP_CIA402) + switch(gTxData.modeOfOperation){ + case CYCLIC_SYNC_POSITION_MODE: + gRxData.actualPosition = (int32_t) (mechTheta * 1000.0); + /* Create a 0-1080 degree reference frame using the multiturn data + * 0-360 is overflow with a counter-clockwise turn + * 360-720 is no overflow condition (same revolution as start point) + * 720-1080 is overflow with a clockwise turn + */ + if (multiTurn == gStartingMultiTurn) /* no overflow, move to center of the reference frame */ + relativeMechTheta = mechTheta + 360; + else if ((multiTurn == (gStartingMultiTurn + 1)) || ((gStartingMultiTurn > 1) && (multiTurn == 0))) /* clockwise overflow */ + relativeMechTheta = mechTheta + 720; + else /* counter-clockwise overflow, leave in the lower end of the reference frame */ + relativeMechTheta = mechTheta; + + gPosTarget = (float) gTxData.targetPosition / 1000.0; + if(gPosSetPoint < gPosTarget) { + gPosSetPoint += MAX_POS_CHANGE; + if (gPosSetPoint > gPosTarget) /* Increment went over the request */ + gPosSetPoint = gPosTarget; + } + else if (gPosSetPoint > gPosTarget) { + gPosSetPoint -= MAX_POS_CHANGE; + if (gPosSetPoint < gPosTarget) /* Decrement went below the request */ + gPosSetPoint = gPosTarget; + } + + /* Move the setpoint to the 360-720 reference frame and compare*/ + gSpdRef = arm_pi_f32(&gPiPos, (gPosSetPoint + 360) - relativeMechTheta); + gIqRef = arm_pi_f32(&gPiSpd, gSpdRef - speed); + parkIqOut = arm_pi_f32(&gPiIq, gIqRef - parkIqMeasured); + parkIdOut = arm_pi_f32(&gPiId, 0.0 - parkIdMeasured); + break; + case CYCLIC_SYNC_VELOCITY_MODE: + gRxData.actualVelocity = (int32_t) (speed * 1000.0); + gSpdTarget = (float) gTxData.targetVelocity / 1000.0; + if(gSpdSetPoint < gSpdTarget) + gSpdSetPoint += MAX_SPD_CHANGE; + else if (gSpdSetPoint > gSpdTarget) + gSpdSetPoint -= MAX_SPD_CHANGE; + + gIqRef = arm_pi_f32(&gPiSpd, gSpdSetPoint - speed); + parkIqOut = arm_pi_f32(&gPiIq, gIqRef - parkIqMeasured); + parkIdOut = arm_pi_f32(&gPiId, 0.0 - parkIdMeasured); + break; + case CYCLIC_SYNC_TORQUE_MODE: + ///gRxData.actualTorque = (int16_t) (parkIqOut * 1000.0); + gIqTarget = (float) gTxData.targetTorque / 1000.0; + gIqSetPoint = gIqTarget; + + parkIqOut = arm_pi_f32(&gPiIq, gIqSetPoint - parkIqMeasured); + parkIdOut = arm_pi_f32(&gPiId, 0.0 - parkIdMeasured); + gRxData.actualTorque = (int16_t) (parkIqOut * 1000.0); + break; + default: + break; + } +#endif + +#if defined(USE_RTLIB_FOC) + /* Inverse Park transform */ + IPARK_run(elecThetaSinCos[0], elecThetaSinCos[1], parkIdOut, parkIqOut, &iparkAlphaOut, &iparkBetaOut); + /* Space Vector Generation */ + SVGEN_run(1.0f, iparkAlphaOut, iparkBetaOut, &spcVectAOut, &spcVectBOut, &spcVectCOut); +#else + /* Inverse Park transform */ + arm_inv_park_f32(parkIdOut, parkIqOut, &iparkAlphaOut, &iparkBetaOut, elecThetaSinCos[0], elecThetaSinCos[1]); + /* Space Vector Generation */ + space_vector_f32(iparkAlphaOut, iparkBetaOut, &spcVectAOut, &spcVectBOut, &spcVectCOut); +#endif + + /* Write next CMPA values. Swap cmp0 and cmp2 because the HW connect PWM0 to Phase C and PWM2 to Phase A */ + halfPeriod = (float)gEpwmPrdVal / 2.0; +#if defined(SINGLE_AXLE_USE_M1) +#if defined(USE_RTLIB_FOC) + writeCmpA(gEpwm0BaseAddr, (uint16_t) ((1 + spcVectCOut) * halfPeriod)); + writeCmpA(gEpwm1BaseAddr, (uint16_t) ((1 + spcVectBOut) * halfPeriod)); + writeCmpA(gEpwm2BaseAddr, (uint16_t) ((1 + spcVectAOut) * halfPeriod)); +#else + writeCmpA(gEpwm0BaseAddr, (uint16_t) ((1 - spcVectCOut) * halfPeriod)); + writeCmpA(gEpwm1BaseAddr, (uint16_t) ((1 - spcVectBOut) * halfPeriod)); + writeCmpA(gEpwm2BaseAddr, (uint16_t) ((1 - spcVectAOut) * halfPeriod)); +#endif +#endif +#if defined(SINGLE_AXLE_USE_M2) + writeCmpA(gEpwm0BaseAddr2A, (uint16_t) ((1 - spcVectCOut) * halfPeriod)); + writeCmpA(gEpwm0BaseAddr2B, (uint16_t) ((1 - spcVectCOut) * halfPeriod)); + writeCmpA(gEpwm1BaseAddr2, (uint16_t) ((1 - spcVectBOut) * halfPeriod)); + writeCmpA(gEpwm2BaseAddr2, (uint16_t) ((1 - spcVectAOut) * halfPeriod)); +#endif + asm(" dsb"); + + /* Determine if Phase A or Phase B currents need to be inferred in the next cycle based on the two largest phases */ + gInferA = FALSE; + gInferB = FALSE; + + if (spcVectCOut > spcVectAOut || spcVectCOut > spcVectBOut) { /* If C is larger than either A or B */ + if (spcVectAOut > spcVectBOut) { /* A and C are the largest, infer B in the next cycle */ + gInferB = TRUE; + } + else { /* B and C are the largest, infer A in the next cycle */ + gInferA = TRUE; + } + } + +#if defined(USE_PURE_OPEN_LOOP)||defined(USE_OPEN_LOOP_WITH_SDDF) + gLastMechTheta = myMechTheta; + gLastMultiTurn = 0; +#else + gLastMechTheta = mechTheta; + gLastMultiTurn = multiTurn; +#endif + +#if (DEBUG_LEVEL == DEBUG_BUFFERS_ON) +#if (BUILDLEVEL == OPEN_LOOP_IQ_ID) + gDebugBuff1[gDebugBuffIdx] = spcVectBOut; + ///gDebugBuff2[gDebugBuffIdx] = (uint32_t)spcVectAOut; + ///gDebugBuff3[gDebugBuffIdx] = (uint32_t)gSddfChSamps[0]; +#if defined(USE_PURE_OPEN_LOOP)||defined(USE_OPEN_LOOP_WITH_SDDF) + gDebugBuff3[gDebugBuffIdx] = (uint32_t)gSddfChSamps[3]; ///myMechTheta; +#else + ///gDebugBuff3[gDebugBuffIdx] = mechTheta; +#endif +#endif +#if (BUILDLEVEL == CLOSED_LOOP_IQ_ID) + gDebugBuff1[gDebugBuffIdx] = spcVectBOut; + ///gDebugBuff2[gDebugBuffIdx] = parkIqMeasured; + ///gDebugBuff3[gDebugBuffIdx] = parkIdMeasured; +#endif +#if (BUILDLEVEL == CLOSED_LOOP_SPEED) + ///gDebugBuff1[gDebugBuffIdx] = spcVectBOut; ///speed; ///gClarkeBetaMeasured; + ///gDebugBuff2[gDebugBuffIdx] = spcVectAOut; ///parkIdOut; ///parkIqMeasured; + gDebugBuff0[gDebugBuffIdx] = (uint32_t)gSddfChSamps[0]; + gDebugBuff1[gDebugBuffIdx] = (uint32_t)mechTheta; +#endif +#endif + +#if (PID_TUNE_LEVEL == NO_TUNING) /* No tuning */ +#if (DEBUG_LEVEL == DEBUG_BUFFERS_ON) +#if (DEBUG_WRAP_TYPE == DEBUG_BUFFER_WRAP) /* No tuning, wrap buffer */ + /* debug, update capture buffers index */ + gDebugBuffIdx++; + if (gDebugBuffIdx >= DEBUG_BUFF_SZ) { + gDebugBuffIdx = 0; + } +#elif (DEBUG_WRAP_TYPE == DEBUG_BUFFER_SINGLE) /* No tuning, single buffer store */ + + /* debug, update capture buffers index */ + gDebugBuffIdx++; + if (gDebugBuffIdx >= DEBUG_BUFF_SZ) { + gDebugBuffIdx = DEBUG_BUFF_SZ - 1; + } +#endif +#endif +#endif + } + /* Calculate mechanical/electrical angle offset */ + else { + /* Get the latest mechanical theta from the encoder */ +#if defined(SINGLE_AXLE_USE_M1) + if (localEnDatGetSingleMulti(&mechTheta, &multiTurn, 0) != 0) + { + gEncErrCnt++; + return; + } + gPruEncoderIrqCnt_after++; +#endif +#if defined(SINGLE_AXLE_USE_M2) + localEnDatGetSingleMulti(&mechTheta, &multiTurn, 2); +#endif + if (gPruEncoderIrqCnt > SETTLING_COUNT) +#if defined(USE_PURE_OPEN_LOOP)||defined(USE_OPEN_LOOP_WITH_SDDF) + gMechAngleOffset += myMechTheta; +#else + gMechAngleOffset += mechTheta; +#endif + if (gPruEncoderIrqCnt == OFFSET_FINISHED) { + gMechAngleOffset /= SETTLING_COUNT; + while (gMechAngleOffset > 90) + gMechAngleOffset -= 90; + + /* Electrical Angle offset complete, turn off all phases */ + computeCmpx(0.001, gEpwmPrdVal, &dc0, &cmp0); + computeCmpx(-0.001, gEpwmPrdVal, &dc1, &cmp1); + computeCmpx(-0.001, gEpwmPrdVal, &dc2, &cmp2); + + /* Write next CMPA values. Swap cmp0 and cmp2 because the HW connect PWM0 to Phase C and PWM2 to Phase A */ +#if defined(SINGLE_AXLE_USE_M1) + writeCmpA(gEpwm0BaseAddr, cmp2); + writeCmpA(gEpwm1BaseAddr, cmp1); + writeCmpA(gEpwm2BaseAddr, cmp0); +#endif +#if defined(SINGLE_AXLE_USE_M2) + writeCmpA(gEpwm0BaseAddr2A, cmp2); + writeCmpA(gEpwm0BaseAddr2B, cmp2); + writeCmpA(gEpwm1BaseAddr2, cmp1); + writeCmpA(gEpwm2BaseAddr2, cmp0); +#endif + +#if defined(USE_PURE_OPEN_LOOP)||defined(USE_OPEN_LOOP_WITH_SDDF) + gLastMechTheta = myMechTheta; + gLastMultiTurn = 0; + gStartingMultiTurn = 0; + + /* Set initial position information */ + gPosSetPoint = myMechTheta; + gTxData.targetPosition = myMechTheta; +#else + gLastMechTheta = mechTheta; + gLastMultiTurn = multiTurn; + gStartingMultiTurn = multiTurn; + + /* Set initial position information */ + gPosSetPoint = mechTheta; + gTxData.targetPosition = mechTheta; +#endif + } + } + } +} +#endif + +#ifdef SINGLE_AXLE_USE_M2 +uint32_t gEncErrCnt2 = 0; +__attribute__((section(".critical_code"))) void pruEncoderIrqHandler2(void *args) +{ + float32_t fdbkCurPhA, fdbkCurPhB; + float32_t mechTheta, elecTheta, relativeMechTheta = 0; + uint16_t multiTurn = 0; + float32_t elecThetaSinCos[2]; + float32_t parkIdOut, parkIqOut, parkIdMeasured, parkIqMeasured; + float32_t iparkAlphaOut, iparkBetaOut; + float32_t spcVectAOut, spcVectBOut, spcVectCOut; + float dc0, dc1, dc2; /* EPWM duty cycle values */ + uint16_t cmp0, cmp1, cmp2; /* EPWM CMPA values */ + float speed, angleDelta; + float halfPeriod; + + /* Hard-coded for now to trigger the EnDat reading twice, not benchmarked because this should be moved to the PRU in the future */ +#if 0 + if(gLastEnDatCMP2 == 2897) { + HW_WR_REG32(0x3002E098, 5897); + gLastEnDatCMP2 = 5897; + } + else { + HW_WR_REG32(0x3002E098, 2897); + gLastEnDatCMP2 = 2897; + } +#endif + /* Clear interrupt at source */ + PRUICSS_clearEvent(gPruIcss0Handle, ENDAT_EVENT+2); + +#if defined(USE_PURE_OPEN_LOOP) + gSDDFOffsetComplete2 = TRUE; + gPruEncoderIrqCnt2 = OFFSET_FINISHED+1; +#endif + + if (gSDDFOffsetComplete2) { + /* debug, increment PRU SDDF IRQ count */ + gPruEncoderIrqCnt2++; + + /* Start FOC loop and unlock the rotor */ + if (gPruEncoderIrqCnt2 > OFFSET_FINISHED) { +#if !defined(USE_PURE_OPEN_LOOP)&&!defined(USE_OPEN_LOOP_WITH_SDDF) + /* Get the latest mechanical theta and multi-turn position from the encoder */ + if (localEnDatGetSingleMulti(&mechTheta, &multiTurn, 2) != 0) + { + gEncErrCnt2++; + return; + } + gPruEncoderIrqCnt2_after++; +#endif + /* Use calculated offset from electrical 0, 4 pole pairs */ +#if defined(USE_PURE_OPEN_LOOP)||defined(USE_OPEN_LOOP_WITH_SDDF) + elecTheta = myMechTheta2 - gMechAngleOffset; +#else + elecTheta = mechTheta - gMechAngleOffset; +#endif + if(elecTheta < 0) + elecTheta += 90; + elecTheta *= 4.0; + + /* ti_r5fmath_sincos expects input in the range of 0-2pi radians so normalize here to 0-360 degrees */ + while (elecTheta > 360.0) + elecTheta -= 360.0; + +#if defined(USE_PURE_OPEN_LOOP)||defined(USE_OPEN_LOOP_WITH_SDDF) + angleDelta = myMechTheta2 - gLastMechTheta; +#else + angleDelta = mechTheta - gLastMechTheta; +#endif + /* Max angle change per period @ 3200RPMs with 50KHz period should be 0.384 degrees, outside that is rollover + * Use 5 as the bound to provide plenty of room for max acceleration cases */ + if (angleDelta < -50) + angleDelta += 360; + else if (angleDelta > 50) + angleDelta -= 360; + + /* Compute instantaneous RPMs using the change in angle and the PWM frequency */ + speed = (angleDelta / 360.0) / (ISR_PRD_IN_MINUTES); + +#if (PRECOMPUTE_LEVEL == NO_PRECOMPUTE) + /* Try to avoid the INA240 switching noise by selecting the 2 phases with the largest duty cycles */ + if (gInferA) { + fdbkCurPhB = (-((float)gSddfChSamps[4] - gSddfChOffsets2[1] - SDDF_HALF_SCALE_FLT) / SDDF_HALF_SCALE_FLT) * 30.0; + fdbkCurPhA = -fdbkCurPhB - ((-((float)gSddfChSamps[5] - gSddfChOffsets2[2] - SDDF_HALF_SCALE_FLT) / SDDF_HALF_SCALE_FLT) * 30.0); + + } + else if (gInferB){ + fdbkCurPhA = (-((float)gSddfChSamps[3] - gSddfChOffsets2[0] - SDDF_HALF_SCALE_FLT) / SDDF_HALF_SCALE_FLT) * 30.0; + fdbkCurPhB = -fdbkCurPhA - ((-((float)gSddfChSamps[5] - gSddfChOffsets2[2] - SDDF_HALF_SCALE_FLT) / SDDF_HALF_SCALE_FLT) * 30.0); + } + else { + fdbkCurPhA = (-((float)gSddfChSamps[3] - gSddfChOffsets2[0] - SDDF_HALF_SCALE_FLT) / SDDF_HALF_SCALE_FLT) * 30.0; + fdbkCurPhB = (-((float)gSddfChSamps[4] - gSddfChOffsets2[1] - SDDF_HALF_SCALE_FLT) / SDDF_HALF_SCALE_FLT) * 30.0; + } + + /* Clarke transform */ + arm_clarke_f32(fdbkCurPhA, fdbkCurPhB, &gClarkeAlphaMeasured, &gClarkeBetaMeasured); +#endif + /* Calculate sine and cosine of the electrical angle (elecTheta converted to radians) */ + ti_r5fmath_sincos((elecTheta * TI_R5FMATH_PIOVER180), ti_r5fmath_sincosPIconst, ti_r5fmath_sincosCoef, elecThetaSinCos); + /* Park transform */ + arm_park_f32(gClarkeAlphaMeasured, gClarkeBetaMeasured, &parkIdMeasured, &parkIqMeasured, elecThetaSinCos[0], elecThetaSinCos[1]); + +// Open loop Iq +#if (BUILDLEVEL == OPEN_LOOP_IQ_ID) + if(gIq < IQ_TESTING) + gIq += 0.01; + + parkIdOut = 0.0; + parkIqOut = gIq; + +#if defined(USE_PURE_OPEN_LOOP)||defined(USE_OPEN_LOOP_WITH_SDDF) + myMechTheta2 += myMechDelta2; + + if (myMechTheta2>359.9999) + myMechTheta2 = 0.0; + +#endif +#endif +//Closed loop Iq and Id tuning +#if (BUILDLEVEL == CLOSED_LOOP_IQ_ID) + gIqTarget = 0.5; ///gIqArray[count]; + gIqSetPoint = gIqTarget; + + ///if((gPruEncoderIrqCnt - OFFSET_FINISHED) % CYCLES_PER_TARGET == 0){ + /// count++; + /// if(count == 8) + /// count = 0; + ///} + + parkIqOut = arm_pi_f32(&gPiIq, gIqSetPoint - parkIqMeasured); + parkIdOut = arm_pi_f32(&gPiId, 0.0 - parkIdMeasured); + if (parkIqOut>IQ_TESTING) parkIqOut = IQ_TESTING; + if (parkIqOut<-1.0*IQ_TESTING) parkIqOut = -1.0*IQ_TESTING; + if (parkIdOut>ID_TESTING) parkIdOut = ID_TESTING; + if (parkIdOut<-1.0*ID_TESTING) parkIdOut = -1.0*ID_TESTING; +#endif +//Closed loop speed +#if (BUILDLEVEL == CLOSED_LOOP_SPEED) + gSpdTarget = gSpdArray[0]; + if(gSpdSetPoint < gSpdTarget) + gSpdSetPoint += MAX_SPD_CHANGE; + else if (gSpdSetPoint > gSpdTarget) + gSpdSetPoint -= MAX_SPD_CHANGE; + + ///if((gPruEncoderIrqCnt - OFFSET_FINISHED) % CYCLES_PER_TARGET == 0){ + /// count++; + /// if(count == 8) + /// count = 0; + ///} + + gIqRef = arm_pi_f32(&gPiSpd, gSpdSetPoint - speed); + parkIqOut = arm_pi_f32(&gPiIq, gIqRef - parkIqMeasured); + parkIdOut = arm_pi_f32(&gPiId, 0.0 - parkIdMeasured); + if (parkIqOut>IQ_TESTING) parkIqOut = IQ_TESTING; + if (parkIqOut<-1.0*IQ_TESTING) parkIqOut = -1.0*IQ_TESTING; + if (parkIdOut>ID_TESTING) parkIdOut = ID_TESTING; + if (parkIdOut<-1.0*ID_TESTING) parkIdOut = -1.0*ID_TESTING; +#endif + /* Inverse Park transform */ + arm_inv_park_f32(parkIdOut, parkIqOut, &iparkAlphaOut, &iparkBetaOut, elecThetaSinCos[0], elecThetaSinCos[1]); + /* Space Vector Generation */ + space_vector_f32(iparkAlphaOut, iparkBetaOut, &spcVectAOut, &spcVectBOut, &spcVectCOut); + + /* Write next CMPA values. Swap cmp0 and cmp2 because the HW connect PWM0 to Phase C and PWM2 to Phase A */ + halfPeriod = (float)gEpwmPrdVal / 2.0; +#if defined(SINGLE_AXLE_USE_M1) + writeCmpA(gEpwm0BaseAddr, (uint16_t) ((1 - spcVectCOut) * halfPeriod)); + writeCmpA(gEpwm1BaseAddr, (uint16_t) ((1 - spcVectBOut) * halfPeriod)); + writeCmpA(gEpwm2BaseAddr, (uint16_t) ((1 - spcVectAOut) * halfPeriod)); +#endif +#if defined(SINGLE_AXLE_USE_M2) + writeCmpA(gEpwm0BaseAddr2A, (uint16_t) ((1 - spcVectCOut) * halfPeriod)); + writeCmpA(gEpwm0BaseAddr2B, (uint16_t) ((1 - spcVectCOut) * halfPeriod)); + writeCmpA(gEpwm1BaseAddr2, (uint16_t) ((1 - spcVectBOut) * halfPeriod)); + writeCmpA(gEpwm2BaseAddr2, (uint16_t) ((1 - spcVectAOut) * halfPeriod)); +#endif + asm(" dsb"); + + /* Determine if Phase A or Phase B currents need to be inferred in the next cycle based on the two largest phases */ + gInferA = FALSE; + gInferB = FALSE; + + if (spcVectCOut > spcVectAOut || spcVectCOut > spcVectBOut) { /* If C is larger than either A or B */ + if (spcVectAOut > spcVectBOut) { /* A and C are the largest, infer B in the next cycle */ + gInferB = TRUE; + } + else { /* B and C are the largest, infer A in the next cycle */ + gInferA = TRUE; + } + } + +#if defined(USE_PURE_OPEN_LOOP)||defined(USE_OPEN_LOOP_WITH_SDDF) + gLastMechTheta = myMechTheta2; + gLastMultiTurn = 0; +#else + gLastMechTheta = mechTheta; + gLastMultiTurn = multiTurn; +#endif + +#if (DEBUG_LEVEL == DEBUG_BUFFERS_ON) +#if (BUILDLEVEL == OPEN_LOOP_IQ_ID) + ///gDebugBuff1[gDebugBuffIdx] = (uint32_t)gSddfChSamps[4]; + gDebugBuff2[gDebugBuffIdx] = (uint32_t)gSddfChSamps[3]; +#if defined(USE_PURE_OPEN_LOOP)||defined(USE_OPEN_LOOP_WITH_SDDF) + gDebugBuff3[gDebugBuffIdx] = (uint32_t)gSddfChSamps[3]; ///myMechTheta; +#else + gDebugBuff3[gDebugBuffIdx] = mechTheta; +#endif +#endif +#if (BUILDLEVEL == CLOSED_LOOP_IQ_ID) + gDebugBuff1[gDebugBuffIdx] = gClarkeBetaMeasured; + gDebugBuff2[gDebugBuffIdx] = parkIqMeasured; + gDebugBuff3[gDebugBuffIdx] = parkIdMeasured; +#endif +#if (BUILDLEVEL == CLOSED_LOOP_SPEED) + ///gDebugBuff1[gDebugBuffIdx] = parkIqOut; ///gClarkeBetaMeasured; + ///gDebugBuff2[gDebugBuffIdx] = parkIdOut; ///parkIqMeasured; + gDebugBuff1[gDebugBuffIdx] = (uint32_t)gSddfChSamps[4]; + gDebugBuff2[gDebugBuffIdx] = (uint32_t)gSddfChSamps[5]; + + gDebugBuff3[gDebugBuffIdx] = parkIdMeasured; +#endif +#endif + +#if (PID_TUNE_LEVEL == NO_TUNING) /* No tuning */ +#if (DEBUG_LEVEL == DEBUG_BUFFERS_ON) +#if (DEBUG_WRAP_TYPE == DEBUG_BUFFER_WRAP) /* No tuning, wrap buffer */ + /* debug, update capture buffers index */ + gDebugBuffIdx++; + if (gDebugBuffIdx >= DEBUG_BUFF_SZ) { + gDebugBuffIdx = 0; + } +#elif (DEBUG_WRAP_TYPE == DEBUG_BUFFER_SINGLE) /* No tuning, single buffer store */ + + /* debug, update capture buffers index */ + gDebugBuffIdx++; + if (gDebugBuffIdx >= DEBUG_BUFF_SZ) { + gDebugBuffIdx = DEBUG_BUFF_SZ - 1; + } +#endif +#endif +#endif + } + /* Calculate mechanical/electrical angle offset */ + else { + /* Get the latest mechanical theta from the encoder */ +#ifdef SINGLE_AXLE_USE_M1 + localEnDatGetSingleMulti(&mechTheta, &multiTurn, 0); +#endif +#ifdef SINGLE_AXLE_USE_M2 + if (localEnDatGetSingleMulti(&mechTheta, &multiTurn, 2) != 0) + { + gEncErrCnt2++; + return; + } + gPruEncoderIrqCnt2_after++; +#endif + if (gPruEncoderIrqCnt2 > SETTLING_COUNT) +#if defined(USE_PURE_OPEN_LOOP)||defined(USE_OPEN_LOOP_WITH_SDDF) + gMechAngleOffset += myMechTheta; +#else + gMechAngleOffset += mechTheta; +#endif + if (gPruEncoderIrqCnt2 == OFFSET_FINISHED) { + gMechAngleOffset /= SETTLING_COUNT; + while (gMechAngleOffset > 90) + gMechAngleOffset -= 90; + + /* Electrical Angle offset complete, turn off all phases */ + computeCmpx(0.0001, gEpwmPrdVal, &dc0, &cmp0); + computeCmpx(-0.0001, gEpwmPrdVal, &dc1, &cmp1); + computeCmpx(-0.0001, gEpwmPrdVal, &dc2, &cmp2); + + /* Write next CMPA values. Swap cmp0 and cmp2 because the HW connect PWM0 to Phase C and PWM2 to Phase A */ +#if defined(SINGLE_AXLE_USE_M1) + writeCmpA(gEpwm0BaseAddr, cmp2); + writeCmpA(gEpwm1BaseAddr, cmp1); + writeCmpA(gEpwm2BaseAddr, cmp0); +#endif +#if defined(SINGLE_AXLE_USE_M2) + writeCmpA(gEpwm0BaseAddr2A, cmp2); + writeCmpA(gEpwm0BaseAddr2B, cmp2); + writeCmpA(gEpwm1BaseAddr2, cmp1); + writeCmpA(gEpwm2BaseAddr2, cmp0); +#endif + +#if defined(USE_PURE_OPEN_LOOP)||defined(USE_OPEN_LOOP_WITH_SDDF) + gLastMechTheta = myMechTheta; + gLastMultiTurn = 0; + gStartingMultiTurn = 0; + + /* Set initial position information */ + gPosSetPoint = myMechTheta; + gTxData.targetPosition = myMechTheta; +#else + gLastMechTheta = mechTheta; + gLastMultiTurn = multiTurn; + gStartingMultiTurn = multiTurn; + + /* Set initial position information */ + gPosSetPoint = mechTheta; + gTxData.targetPosition = mechTheta; +#endif + } + } + } +} +#endif + +#endif + +#if defined(SINGLE_AXLE_USE_M1) +void init_encoder(){ + int i, j; + HwiP_Params hwiPrms; + int32_t status; + + uint64_t icssgclk; + + void *pruss_cfg; + void *pruss_iep; + +#ifdef SDDF_HW_EVM_ADAPTER_BP + /* Configure g_mux_en to 0 in ICSSG_SA_MX_REG Register. */ + ///HW_WR_REG32((CSL_PRU_ICSSG0_PR1_CFG_SLV_BASE+0x40), (0x00)); + HW_WR_REG32((CSL_PRU_ICSSG0_PR1_CFG_SLV_BASE+0x40), (0x80)); +#endif + i = endat_get_fw_version(); + + // set initial velocity for 1st motor + gCurTargetVelocity[0] = MAX_SPD_RPM; + gCurActualVelocity[0] = MAX_SPD_RPM; + + DebugP_log("\n\n\n"); + DebugP_log("EnDat firmware \t: %x.%x.%x (%s)\n\n", (i >> 24) & 0x7F, + (i >> 16) & 0xFF, i & 0xFFFF, i & (1 << 31) ? "internal" : "release"); + +#ifdef SINGLE_AXLE_USE_M1 + /* Register & enable ICSSG EnDat PRU FW interrupt */ + HwiP_Params_init(&hwiPrms); + hwiPrms.intNum = ICSSG_PRU_ENDAT_INT_NUM; + hwiPrms.callback = &pruEncoderIrqHandler; + hwiPrms.args = 0; + hwiPrms.isPulse = FALSE; + hwiPrms.isFIQ = FALSE; + status = HwiP_construct(&gIcssgEncoderHwiObject, &hwiPrms); + DebugP_assert(status == SystemP_SUCCESS); +#endif +#ifdef SINGLE_AXLE_USE_M2 + /* Register & enable ICSSG EnDat PRU FW interrupt */ + HwiP_Params_init(&hwiPrms); + hwiPrms.intNum = ICSSG_PRU_ENDAT_INT_NUM + 2; + hwiPrms.callback = &pruEncoderIrqHandler2; + hwiPrms.args = 0; + hwiPrms.isPulse = FALSE; + hwiPrms.isFIQ = FALSE; + status = HwiP_construct(&gIcssgEncoderHwiObject2, &hwiPrms); + DebugP_assert(status == SystemP_SUCCESS); +#endif + + gPruIcss0Handle = PRUICSS_open(CONFIG_PRU_ICSS0); + + /* Set in constant table C30 to shared RAM 0x40300000 */ + PRUICSS_setConstantTblEntry(gPruIcss0Handle, PRUICSS_PRUx, PRUICSS_CONST_TBL_ENTRY_C30, ((0x40300000 & 0x00FFFF00) >> 8)); + + /* clear ICSS0 PRU1 data RAM */ + PRUICSS_initMemory(gPruIcss0Handle, PRUICSS_DATARAM(PRUICSS_PRUx)); + + PRUICSS_disableCore(gPruIcss0Handle, PRUICSS_PRUx); + + /* Select multi-channel */ + gEndat_is_multi_ch = 1; + /* Select the EnDat channel */ +#ifdef SINGLE_AXLE_USE_M1 +#ifdef DUAL_AXIS_USE_M1_M2 + /* for dual motor drive mode */ + gEndat_multi_ch_mask = ENDAT_MULTI_CH0|ENDAT_MULTI_CH2; +#else + gEndat_multi_ch_mask = ENDAT_MULTI_CH0; +#endif +#endif + +#ifdef SINGLE_AXLE_USE_M2 + gEndat_multi_ch_mask = ENDAT_MULTI_CH2; +#endif + + + + + gEndat_is_multi_ch = CONFIG_ENDAT0_MODE & 1; + gEndat_is_load_share_mode = CONFIG_ENDAT0_MODE & 2; + endat_pre_init(); + + if(gEndat_is_multi_ch || gEndat_is_load_share_mode) + { + gEndat_multi_ch_mask=(CONFIG_ENDAT0_CHANNEL0<<0|CONFIG_ENDAT0_CHANNEL1<<1|CONFIG_ENDAT0_CHANNEL2<<2); + + DebugP_log("\r\nchannels %s %s %s selected\n", + gEndat_multi_ch_mask & ENDAT_MULTI_CH0 ? "0" : "", + gEndat_multi_ch_mask & ENDAT_MULTI_CH1 ? "1" : "", + gEndat_multi_ch_mask & ENDAT_MULTI_CH2 ? "2" : ""); + + if(!gEndat_multi_ch_mask) + { + DebugP_log("\r\nERROR: please select channels to be used in multi channel configuration -\n\n"); + DebugP_log("\rexit %s as no channel selected in multichannel configuration\n", + __func__); + return; + } + } + else + { + + i = CONFIG_ENDAT0_CHANNEL0 & 0; + + i += CONFIG_ENDAT0_CHANNEL1; + + i += CONFIG_ENDAT0_CHANNEL2<<1; + + if(i < 0 || i > 2) + { + DebugP_log("\r\nWARNING: invalid channel selected, defaulting to Channel 0\n"); + i = 0; + } + } + + pruss_cfg = (void *)(((PRUICSS_HwAttrs *)(gPruIcssXHandle->hwAttrs))->cfgRegBase); + pruss_iep = (void *)(((PRUICSS_HwAttrs *)(gPruIcssXHandle->hwAttrs))->iep0RegBase); + + /*Translate the TCM local view addr to globel view addr */ + uint64_t gEndatChInfoGlobalAddr = CPU0_BTCM_SOCVIEW((uint64_t)&gEndatChInfo); + + priv = endat_init((struct endat_pruss_xchg *)((PRUICSS_HwAttrs *)( + gPruIcssXHandle->hwAttrs))->pru1DramBase, &gEndatChInfo, gEndatChInfoGlobalAddr, pruss_cfg, pruss_iep, PRUICSS_SLICEx); + + if(gEndat_is_multi_ch || gEndat_is_load_share_mode) + { + endat_config_multi_channel_mask(priv, gEndat_multi_ch_mask, gEndat_is_load_share_mode); + } + else + { + endat_config_channel(priv, i); + } + + endat_config_host_trigger(priv); + + /* Read the ICSSG configured clock frequency. */ + if(gPruIcssXHandle->hwAttrs->instance) + { + SOC_moduleGetClockFrequency(TISCI_DEV_PRU_ICSSG1, TISCI_DEV_PRU_ICSSG1_CORE_CLK, &icssgclk); + } + else + { + SOC_moduleGetClockFrequency(TISCI_DEV_PRU_ICSSG0, TISCI_DEV_PRU_ICSSG0_CORE_CLK, &icssgclk); + } + + /* Configure Delays based on the ICSSG frequency*/ + /* Count = ((required delay * icssgclk)/1000) */ + priv->pruss_xchg->endat_delay_125ns = ((icssgclk*125)/1000000000); + priv->pruss_xchg->endat_delay_51us = ((icssgclk*51)/1000000 ); + priv->pruss_xchg->endat_delay_5us = ((icssgclk*5)/1000000); + priv->pruss_xchg->endat_delay_1ms = ((icssgclk/1000) * 1); + priv->pruss_xchg->endat_delay_2ms = ((icssgclk/1000) * 2); + priv->pruss_xchg->endat_delay_12ms = ((icssgclk/1000) * 12); + priv->pruss_xchg->endat_delay_50ms = ((icssgclk/1000) * 50); + priv->pruss_xchg->endat_delay_380ms = ((icssgclk/1000) * 380); + priv->pruss_xchg->endat_delay_900ms = ((icssgclk/1000) * 900); + priv->pruss_xchg->icssg_clk = icssgclk; + + + + i = endat_pruss_load_run_fw(priv); + + if (i < 0) + { + DebugP_log("\rERROR: EnDat initialization failed -\n\n"); + + if(gEndat_is_multi_ch) + { + unsigned char tmp; + + tmp = endat_multi_channel_detected(priv) & gEndat_multi_ch_mask; + tmp ^= gEndat_multi_ch_mask; + DebugP_log("\r\tunable to detect encoder in channel %s %s %s\n", + tmp & ENDAT_MULTI_CH0 ? "0" : "", + tmp & ENDAT_MULTI_CH1 ? "1" : "", + tmp & ENDAT_MULTI_CH2 ? "2" : ""); + } + else + { + DebugP_log("\r\tcheck whether encoder is connected and ensure proper connections\n"); + } + + DebugP_log("\rexit %s due to failed firmware initialization\n", __func__); + return; + } + + /* read encoder info at low frequency so that cable length won't affect */ + endat_init_clock(200*1000, priv); + + for(j = 0; j < 3; j++) + { + if(gEndat_multi_ch_mask & 1 << j) + { + endat_multi_channel_set_cur(priv, j); + + if(endat_get_encoder_info(priv) < 0) + { + DebugP_log("\rEnDat initialization channel %d failed\n", j); + DebugP_log("\rexit %s due to failed initialization\n", __func__); + return; + } + + gEndat_prop_delay[priv->channel] = endat_get_prop_delay(priv); + DebugP_log("\n\t\t\t\tCHANNEL %d\n\n", j); + endat_print_encoder_info(priv); + } + } + + /* pass the encoder step to the R5F_0_1 */ + priv_step = priv->step; + + gEndat_prop_delay_max = gEndat_prop_delay[0] > gEndat_prop_delay[1] ? + gEndat_prop_delay[0] : gEndat_prop_delay[1]; + gEndat_prop_delay_max = gEndat_prop_delay_max > gEndat_prop_delay[2] ? + gEndat_prop_delay_max : gEndat_prop_delay[2]; + +#if 1 + /* default frequency - 16MHz for 2.2 encoders, 1MHz for 2.1 encoders */ + endat_init_clock(16 * 1000 * 1000, priv); + /* JR: Hard code propagation delay to make 16MHz work @300MHz PRU */ + endat_handle_prop_delay(priv, 265); +#else + /* default frequency - 8MHz for 2.2 encoders, 1MHz for 2.1 encoders */ + endat_init_clock(8 * 1000 * 1000, priv); + /* JR: Hard code propagation delay to make 16MHz work @300MHz PRU */ + endat_handle_prop_delay(priv, 530); +#endif + +#if 0 + /* set to EnDat 2.2 recovery time */ + memset(&cmd_supplement, 0, sizeof(cmd_supplement)); + cmd_supplement.address = 3; + cmd_supplement.data = 1; + endat_command_process(priv, 10, &cmd_supplement); + /* reset encoder */ + endat_command_process(priv, 5, NULL); + endat_addinfo_track(priv, 5, NULL); +#endif + + /* JR: Configures EnDat to trigger based on IEP CMP4 event */ + endat_config_periodic_trigger(priv); + + DebugP_assert(endat_command_process(priv, 8, NULL) >= 0); + + struct endat_periodic_interface endat_periodic_interface; + endat_periodic_interface.pruss_cfg = priv->pruss_cfg; + endat_periodic_interface.pruss_iep = priv->pruss_iep; + endat_periodic_interface.pruss_dmem = priv->pruss_xchg; + endat_periodic_interface.load_share = priv->load_share; + endat_periodic_interface.cmp3 = 3000; + endat_periodic_interface.cmp5 = 0; + endat_periodic_interface.cmp6 = 3000; + + status = endat_config_periodic_mode(&endat_periodic_interface, gPruIcssXHandle); + DebugP_assert(0 != status); + +#ifdef SINGLE_AXLE_USE_M1 + endat_multi_channel_set_cur(priv, 0); + DebugP_log("\r|\n|\t\t\t\tCHANNEL %d\n", 0); +#endif +#ifdef SINGLE_AXLE_USE_M2 + endat_multi_channel_set_cur(priv, 2); + DebugP_log("\r|\n|\t\t\t\tCHANNEL %d\n", 2); +#endif + endat_handle_rx(priv, 8); + + DebugP_log("Encoder Channel Init Completed!!!\n"); +} +#endif + +void init_encoder2(){ +#ifdef SINGLE_AXLE_USE_M2 + HwiP_Params hwiPrms; + int32_t status; + + /* Register & enable ICSSG EnDat PRU FW interrupt */ + HwiP_Params_init(&hwiPrms); + hwiPrms.intNum = ICSSG_PRU_ENDAT_INT_NUM + 2; + hwiPrms.callback = &pruEncoderIrqHandler2; + hwiPrms.args = 0; + hwiPrms.isPulse = FALSE; + hwiPrms.isFIQ = FALSE; + status = HwiP_construct(&gIcssgEncoderHwiObject2, &hwiPrms); + DebugP_assert(status == SystemP_SUCCESS); +#endif + + DebugP_log("Encoder Channel Init Completed!!!\n"); +} +/* Test Sdfm handles */ +sdfm_handle gHPruSdfm; + +/* Sdfm output samples, written by PRU cores */ +__attribute__((section(".gSdfmSampleOutput"))) uint32_t gSdfm_sampleOutput[NUM_CH_SUPPORTED]; +/* Test SDDF handle */ +sdfm_handle gHSddf; + +/* Test Sdfm parameters */ +SdfmPrms gTestSdfmPrms = { + 300000000, /*Value of IEP clock*/ + 20000000, /*Value of SD clock (It should be exact equal to sd clock value)*/ + 0, /*enable double update*/ + 10, /*first sample trigger time*/ + 0, /*second sample trigger time*/ + APP_EPWM_OUTPUT_FREQ, /*PWM output frequency*/ + {{3500, 1000,0}, /*threshold parameters(High, low & reserevd)*/ + {3500, 1000,0}, + {3500, 1000,0}}, + {{0,0}, /*clock sourse & clock inversion for all channels*/ + {0,0}, + {0,0}}, + 15, /*Over current osr: The effect count is OSR + 1*/ + 64, /*Normal current osr */ + 0, /*comparator enable*/ + (uint32_t)&gSddfChSamps /*Output samples base address*/ +}; + +/* Test SDDF parameters */ +/*//SddfPrms gTestSddfPrms = { + SDDF_MODE_TRIG, // sddfMode + {0, 0, 0, 0, 0, 0}, // fdPrms + 0x1FF, // chEn + 3, // trigSampCnt + //31, // trigSampCnt + //10, // trigSampCnt + //45200, // trigSampTime + //37500, + 3000, + //0, // trigSampTime + //4500, // trigSampTime + 63, // osr + {0, 0}, // sdClkPrms + (uint32_t)gSddfChSamps, // trigOutSampBuf + SDDF_CFG_OSR | SDDF_CFG_TRIG_SAMP_TIME | SDDF_CFG_TRIG_SAMP_CNT | SDDF_CFG_CH_EN | SDDF_CFG_TRIG_OUT_SAMP_BUF // cfgMask +};*/ + +#ifdef SDDF_HW_EVM_ADAPTER_BP +/* SDDF PRU FW IRQ handler */ +void pruSddfIrqHandler(void *args) +{ + /* debug, show ISR timing */ + //GPIO_pinWriteHigh(SDDF_DEBUG_BASE_ADDR, SDDF_DEBUG_PIN); + + /* debug, increment PRU SDDF IRQ count */ + gPruSddfIrqCnt++; + if(gPruSddfIrqCnt > SETTLING_COUNT && gPruSddfIrqCnt <= OFFSET_FINISHED){ + gSddfChOffsets2[0] += (int32_t) (gSddfChSamps[3] - SDDF_HALF_SCALE); + gSddfChOffsets2[1] += (int32_t) (gSddfChSamps[4] - SDDF_HALF_SCALE); + gSddfChOffsets2[2] += (int32_t) (gSddfChSamps[5] - SDDF_HALF_SCALE); + + if(gPruSddfIrqCnt == OFFSET_FINISHED) { + float dc0, dc1, dc2; + uint16_t cmp0, cmp1, cmp2; + + gSddfChOffsets2[0] = (gSddfChOffsets2[0] / SETTLING_COUNT); + gSddfChOffsets2[1] = (gSddfChOffsets2[1] / SETTLING_COUNT); + gSddfChOffsets2[2] = (gSddfChOffsets2[2] / SETTLING_COUNT); + + /* ADC offset complete, lock the rotor to electrical 0 */ + computeCmpx(0.167, gEpwmPrdVal, &dc0, &cmp0); + computeCmpx(-0.167, gEpwmPrdVal, &dc1, &cmp1); + computeCmpx(-0.167, gEpwmPrdVal, &dc2, &cmp2); + + /* Write next CMPA values. Swap cmp0 and cmp2 because the HW connect PWM0 to Phase C and PWM2 to Phase A */ + writeCmpA(gEpwm0BaseAddr2A, cmp2); + writeCmpA(gEpwm0BaseAddr2B, cmp2); + writeCmpA(gEpwm1BaseAddr2, cmp1); + writeCmpA(gEpwm2BaseAddr2, cmp0); + gSDDFOffsetComplete2 = TRUE; +#if (PRECOMPUTE_LEVEL == NO_PRECOMPUTE) + HwiP_disableInt(ICSSG_PRU_SDDF_INT_NUM); +#endif + } + + } +#if (PRECOMPUTE_LEVEL == PRECOMPUTE_CLARKE) + /* Offset has been calculated, pull the value and convert to float and scale it */ + else { + float32_t fdbkCurPhA, fdbkCurPhB; + + /* Try to avoid the INA240 switching noise by selecting the 2 phases with the largest duty cycles */ + if (gInferA) { + fdbkCurPhB = (-((float)gSddfChSamps[1] - gSddfChOffsets[1] - SDDF_HALF_SCALE_FLT) / SDDF_HALF_SCALE_FLT) * 30.0; + fdbkCurPhA = -fdbkCurPhB - ((-((float)gSddfChSamps[2] - gSddfChOffsets[2] - SDDF_HALF_SCALE_FLT) / SDDF_HALF_SCALE_FLT) * 30.0); + + } + else if (gInferB){ + fdbkCurPhA = (-((float)gSddfChSamps[0] - gSddfChOffsets[0] - SDDF_HALF_SCALE_FLT) / SDDF_HALF_SCALE_FLT) * 30.0; + fdbkCurPhB = -fdbkCurPhA - ((-((float)gSddfChSamps[2] - gSddfChOffsets[2] - SDDF_HALF_SCALE_FLT) / SDDF_HALF_SCALE_FLT) * 30.0); + } + else { + fdbkCurPhA = (-((float)gSddfChSamps[0] - gSddfChOffsets[0] - SDDF_HALF_SCALE_FLT) / SDDF_HALF_SCALE_FLT) * 30.0; + fdbkCurPhB = (-((float)gSddfChSamps[1] - gSddfChOffsets[1] - SDDF_HALF_SCALE_FLT) / SDDF_HALF_SCALE_FLT) * 30.0; + } + + /* Clarke transform */ + arm_clarke_f32(fdbkCurPhA, fdbkCurPhB, &gClarkeAlphaMeasured, &gClarkeBetaMeasured); + } +#endif + + /* Clear interrupt at source */ + /* Write 18 to ICSSG_STATUS_CLR_INDEX_REG + Firmware: TRIGGER_HOST_SDDF_IRQ defined as 18 + Host: SDDF_EVT defined as TRIGGER_HOST_SDDF_IRQ + 18 = 16+2, 2 is Host Interrupt Number. See AM654x TRM, Table 6-391. + */ + PRUICSS_clearEvent(gPruIcss0Handle, PRU_TRIGGER_HOST_SDFM_EVT); + + /* debug, show ISR timing */ + //GPIO_pinWriteLow(SDDF_DEBUG_BASE_ADDR, SDDF_DEBUG_PIN); +} + +/* SDDF PRU FW IRQ handler */ +void rtuSddfIrqHandler(void *args) +{ + /* debug, increment PRU SDDF IRQ count */ + gRtuSddfIrqCnt++; + + if(gRtuSddfIrqCnt > SETTLING_COUNT && gRtuSddfIrqCnt <= OFFSET_FINISHED){ + gSddfChOffsets[0] += (int32_t) (gSddfChSamps[0] - SDDF_HALF_SCALE); + gSddfChOffsets[1] += (int32_t) (gSddfChSamps[1] - SDDF_HALF_SCALE); + gSddfChOffsets[2] += (int32_t) (gSddfChSamps[2] - SDDF_HALF_SCALE); + + if(gRtuSddfIrqCnt == OFFSET_FINISHED) { + float dc0, dc1, dc2; + uint16_t cmp0, cmp1, cmp2; + + gSddfChOffsets[0] = (gSddfChOffsets[0] / SETTLING_COUNT); + gSddfChOffsets[1] = (gSddfChOffsets[1] / SETTLING_COUNT); + gSddfChOffsets[2] = (gSddfChOffsets[2] / SETTLING_COUNT); + + /* ADC offset complete, lock the rotor to electrical 0 */ + computeCmpx(0.167, gEpwmPrdVal, &dc0, &cmp0); + computeCmpx(-0.167, gEpwmPrdVal, &dc1, &cmp1); + computeCmpx(-0.167, gEpwmPrdVal, &dc2, &cmp2); + + /* Write next CMPA values. Swap cmp0 and cmp2 because the HW connect PWM0 to Phase C and PWM2 to Phase A */ + writeCmpA(gEpwm0BaseAddr, cmp2); + writeCmpA(gEpwm1BaseAddr, cmp1); + writeCmpA(gEpwm2BaseAddr, cmp0); + gSDDFOffsetComplete = TRUE; +#if (PRECOMPUTE_LEVEL == NO_PRECOMPUTE) + HwiP_disableInt(ICSSG_RTU_SDDF_INT_NUM); +#endif + } + + } +#if (PRECOMPUTE_LEVEL == PRECOMPUTE_CLARKE) + /* Offset has been calculated, pull the value and convert to float and scale it */ + else { + float32_t fdbkCurPhA, fdbkCurPhB; + + /* Try to avoid the INA240 switching noise by selecting the 2 phases with the largest duty cycles */ + if (gInferA) { + fdbkCurPhB = (-((float)gSddfChSamps[1] - gSddfChOffsets[1] - SDDF_HALF_SCALE_FLT) / SDDF_HALF_SCALE_FLT) * 30.0; + fdbkCurPhA = -fdbkCurPhB - ((-((float)gSddfChSamps[2] - gSddfChOffsets[2] - SDDF_HALF_SCALE_FLT) / SDDF_HALF_SCALE_FLT) * 30.0); + + } + else if (gInferB){ + fdbkCurPhA = (-((float)gSddfChSamps[0] - gSddfChOffsets[0] - SDDF_HALF_SCALE_FLT) / SDDF_HALF_SCALE_FLT) * 30.0; + fdbkCurPhB = -fdbkCurPhA - ((-((float)gSddfChSamps[2] - gSddfChOffsets[2] - SDDF_HALF_SCALE_FLT) / SDDF_HALF_SCALE_FLT) * 30.0); + } + else { + fdbkCurPhA = (-((float)gSddfChSamps[0] - gSddfChOffsets[0] - SDDF_HALF_SCALE_FLT) / SDDF_HALF_SCALE_FLT) * 30.0; + fdbkCurPhB = (-((float)gSddfChSamps[1] - gSddfChOffsets[1] - SDDF_HALF_SCALE_FLT) / SDDF_HALF_SCALE_FLT) * 30.0; + } + + /* Clarke transform */ + arm_clarke_f32(fdbkCurPhA, fdbkCurPhB, &gClarkeAlphaMeasured, &gClarkeBetaMeasured); + } +#endif + + /* Clear interrupt at source */ + /* Write 18 to ICSSG_STATUS_CLR_INDEX_REG + Firmware: TRIGGER_HOST_SDDF_IRQ defined as 18 + Host: SDDF_EVT defined as TRIGGER_HOST_SDDF_IRQ + 18 = 16+2, 2 is Host Interrupt Number. See AM654x TRM, Table 6-391. + */ + ///PRUICSS_clearEvent(gRtuIcss0Handle, RTU_TRIGGER_HOST_SDFM_EVT); + PRUICSS_clearEvent(gPruIcss0Handle, RTU_TRIGGER_HOST_SDFM_EVT); +} +#endif + +#ifdef SDDF_HW_EVM_ADAPTER_BP +#if defined(SINGLE_AXLE_USE_M1) +void init_sddf(){ + HwiP_Params hwiPrms; + int32_t status; + + /* Configure g_mux_en to PRUICSS_G_MUX_EN in ICSSG_SA_MX_REG Register. */ + HW_WR_REG32((CSL_PRU_ICSSG0_PR1_CFG_SLV_BASE+0x40), PRUICSS_G_MUX_EN); + + /* Configure ICSSG clock selection */ + /*status = cfgIcssgClkCfg(TEST_ICSSG_INST_ID, + CORE_CLK_SEL_ICSSGn_CORE_CLK, + ICSSGn_CORE_CLK_SEL_MAIN_PLL2_HSDIV0_CLKOUT, + ICSSGn_CORE_CLK_FREQ, + IEP_CLK_SEL_CORE_CLK, + 0, //ICSSGn_IEP_CLK_SEL_MAIN_PLL0_HSDIV6_CLKOUT, + 0 //ICSSGn_IEP_CLK_FREQ + ); + if (status != SDDF_ERR_NERR) { + DebugP_log("Error: cfgIcssgClkCfg() fail.\r\n"); + return; + }*/ + + /* Initialize IEP0, configure SYNC0/1 SD clocks */ + init_IEP0_SYNC(); + + /* Initialize ICSSG */ + status = initIcss(TEST_ICSSG_INST_ID, TEST_ICSSG_SLICE_ID, PRUICSS_G_MUX_EN, &gPruIcssHandle); + if (status != SDDF_ERR_NERR) { + DebugP_log("Error: initIcss() fail.\r\n"); + return; + } + + /* Register & enable ICSSG SDDF RTU FW interrupt */ + HwiP_Params_init(&hwiPrms); + hwiPrms.intNum = ICSSG_RTU_SDDF_INT_NUM; + hwiPrms.callback = &rtuSddfIrqHandler; + hwiPrms.args = 0; + hwiPrms.isPulse = FALSE; + hwiPrms.isFIQ = FALSE; + status = HwiP_construct(&gIcssgRtuSddfHwiObject, &hwiPrms); + DebugP_assert(status == SystemP_SUCCESS); + + /* Initialize RTU core for SDDF */ + status = initPruSddf(gPruIcssHandle, TEST_RTU_INST_ID, &gTestSdfmPrms, &gHRtuSddf); + if (status != SDDF_ERR_NERR) { + DebugP_log("Error: initPruSddf() fail.\r\n"); + return; + } + + /* Initialize PRU core for SDDF */ + gTestSdfmPrms.samplesBaseAddress += 0x80; + status = initPruSddf(gPruIcssHandle, TEST_PRU_INST_ID, &gTestSdfmPrms, &gHPruSddf); + if (status != SDDF_ERR_NERR) { + DebugP_log("Error: initPruSddf() fail.\r\n"); + return; + } + + /* Start IEP0 */ + start_IEP0(); + + /* Start EPWM0 clock */ + ///CSL_REG32_WR(CSL_CTRL_MMR0_CFG0_BASE + CSL_MAIN_CTRL_MMR_CFG0_EPWM_TB_CLKEN, 1); + + /* Force SW sync for EPWM0. Other PWMs will be sync'd through HW sync daisy-chain. */ + EPWM_tbTriggerSwSync(gEpwm0BaseAddr); + + /* Enable the PWM output buffer until gate driver configured and PWM signals at 50% duty cycle */ + enable_pwm_buffers(FALSE); +} +#endif + +void init_sddf2(){ + HwiP_Params hwiPrms; + int32_t status; + + /* Register & enable ICSSG PRU SDDF FW interrupt */ + HwiP_Params_init(&hwiPrms); + hwiPrms.intNum = ICSSG_PRU_SDDF_INT_NUM; + hwiPrms.callback = &pruSddfIrqHandler; + hwiPrms.args = 0; + hwiPrms.isPulse = FALSE; + hwiPrms.isFIQ = FALSE; + status = HwiP_construct(&gIcssgPruSddfHwiObject, &hwiPrms); + DebugP_assert(status == SystemP_SUCCESS); +} +#endif + +/* This example shows message exchange between multiple cores. + * + * One of the core is designated as the 'main' core + * and other cores are desginated as `remote` cores. + * + * The main core initiates IPC with remote core's by sending it a message. + * The remote cores echo the same message to the main core. + * + * The main core repeats this for gMsgEchoCount iterations. + * + * In each iteration of message exchange, the message value is incremented. + * + * When iteration count reaches gMsgEchoCount, a semaphore is posted and + * the pending thread/task on that core is unblocked. + * + * When a message or its echo is received, a user registered callback is invoked. + * The message is echoed from within the user callback itself. + * + * This is a example message exchange, in final systems, user can do more + * sophisticated message exchanges as needed for their applications. + */ + +/* number of iterations of message exchange to do */ +uint32_t gMsgEchoCount = 1000000u; +/* client ID that is used to send and receive messages */ +uint32_t gClientId = 4u; +/* main core that starts the message exchange */ +uint32_t gMainCoreId = CSL_CORE_ID_R5FSS1_0; +/* remote cores that echo messages from main core, make sure to NOT list main core in this list */ +uint32_t gRemoteCoreId[] = { + CSL_CORE_ID_R5FSS0_0, + CSL_CORE_ID_MAX /* this value indicates the end of the array */ +}; + +/* semaphore's used to indicate a main core has finished all message exchanges */ +SemaphoreP_Object gMainDoneSem[CSL_CORE_ID_MAX]; + +/* semaphore used to indicate a remote core has finished all message xchange */ +SemaphoreP_Object gRemoteDoneSem; + +void ipc_notify_msg_handler_remote_core(uint32_t remoteCoreId, uint16_t localClientId, uint32_t msgValue, void *args) +{ + /* on remote core, we have registered handler on the same client ID and current core client ID */ + IpcNotify_sendMsg(remoteCoreId, localClientId, msgValue, 1); + + /* if all messages received then post semaphore to exit */ + if(msgValue == (gMsgEchoCount-1)) + { + SemaphoreP_post(&gRemoteDoneSem); + } +} + +#if defined(SINGLE_AXLE_USE_M1) +int32_t rw_drv8350_register(uint16_t r_w, uint16_t reg_addr, uint16_t reg_val, uint16_t* read_val) +{ + MCSPI_Transaction spiTransaction; + uint16_t mcspiTxBuffer, mcspiRxBuffer; + int32_t transferOK; + + /* Initiate SPI transfer parameters */ + spiTransaction.channel = 0U; + spiTransaction.count = 1; + spiTransaction.txBuf = &mcspiTxBuffer; + spiTransaction.rxBuf = &mcspiRxBuffer; + spiTransaction.args = NULL; + + mcspiTxBuffer = r_w | (reg_addr << DRV8350_ADDR_SHIFT) | reg_val; +#ifdef SINGLE_AXLE_USE_M1 + ////GPIO_pinWriteLow(MTR_1_CS_BASE_ADDR, MTR_1_CS_PIN); + transferOK = MCSPI_transfer(gMcspiHandle[CONFIG_MCSPI0], &spiTransaction); + ////GPIO_pinWriteHigh(MTR_1_CS_BASE_ADDR, MTR_1_CS_PIN); +#endif +#ifdef SINGLE_AXLE_USE_M2 + ////GPIO_pinWriteLow(MTR_2_CS_BASE_ADDR, MTR_2_CS_PIN); + transferOK = MCSPI_transfer(gMcspiHandle[CONFIG_MCSPI0], &spiTransaction); + ////GPIO_pinWriteHigh(MTR_2_CS_BASE_ADDR, MTR_2_CS_PIN); +#endif + + if (read_val != NULL) + *read_val = mcspiRxBuffer; + + return transferOK; +} + +int32_t init_drv8350() +{ + int32_t status = SystemP_SUCCESS; + DRV8350_Vars drv8350; + uint16_t reg_vals[6]; + + /* Build the desired register values for the four control registers */ + drv8350.driver_control.all = 0; + drv8350.gate_drive_hs.all = 0; + drv8350.gate_drive_ls.all = 0; + drv8350.ocp_control.all = 0; + + drv8350.driver_control.bit.OCP_ACT = DRV8350_OCP_disable_three_phases; + + drv8350.gate_drive_hs.bit.IDRIVEN_HS = DRV8350_idriveN_600mA; + drv8350.gate_drive_hs.bit.IDRIVEP_HS = DRV8350_idriveP_300mA; + drv8350.gate_drive_hs.bit.LOCK = DRV8350_lock_disable; + + drv8350.gate_drive_ls.bit.CBC = DRV8350_OCP_ClrFaults_Cycle_by_Cycle_Yes; + drv8350.gate_drive_ls.bit.IDRIVEN_LS = DRV8350_idriveN_600mA; + drv8350.gate_drive_ls.bit.IDRIVEP_LS = DRV8350_idriveP_300mA; + drv8350.gate_drive_ls.bit.TDRIVE = DRV8350_tdrive_4000nS; + + drv8350.ocp_control.bit.DEAD_TIME = DRV8350_deadTime_50nS; + drv8350.ocp_control.bit.OCP_MODE = DRV8350_OCP_Latch_Fault; + drv8350.ocp_control.bit.OCP_DEG = DRV8350_deglitch_1us; + drv8350.ocp_control.bit.VDS_LVL = DRV8350_VDS_LVL_1000mV; + + /* Write the control registers */ + rw_drv8350_register(DRV8350_WRITE, DRV8350_DRIVER_CONTROL_ADDR, drv8350.driver_control.all, NULL); + rw_drv8350_register(DRV8350_WRITE, DRV8350_GATE_DRIVE_HS_ADDR, drv8350.gate_drive_hs.all, NULL); + rw_drv8350_register(DRV8350_WRITE, DRV8350_GATE_DRIVE_LS_ADDR, drv8350.gate_drive_ls.all, NULL); + rw_drv8350_register(DRV8350_WRITE, DRV8350_OCP_CONTROL_ADDR, drv8350.ocp_control.all, NULL); + + /* Read back the control registers to check for correctness */ + rw_drv8350_register(DRV8350_READ, DRV8350_DRIVER_CONTROL_ADDR, 0, ®_vals[DRV8350_DRIVER_CONTROL_ADDR]); + rw_drv8350_register(DRV8350_READ, DRV8350_GATE_DRIVE_HS_ADDR, 0, ®_vals[DRV8350_GATE_DRIVE_HS_ADDR]); + rw_drv8350_register(DRV8350_READ, DRV8350_GATE_DRIVE_LS_ADDR, 0, ®_vals[DRV8350_GATE_DRIVE_LS_ADDR]); + rw_drv8350_register(DRV8350_READ, DRV8350_OCP_CONTROL_ADDR, 0, ®_vals[DRV8350_OCP_CONTROL_ADDR]); + + /* Check against desired values */ + if ((drv8350.driver_control.all != reg_vals[DRV8350_DRIVER_CONTROL_ADDR]) || + (drv8350.gate_drive_hs.all != reg_vals[DRV8350_GATE_DRIVE_HS_ADDR]) || + (drv8350.gate_drive_ls.all != reg_vals[DRV8350_GATE_DRIVE_LS_ADDR]) || + (drv8350.ocp_control.all != reg_vals[DRV8350_OCP_CONTROL_ADDR])) { + status = SystemP_FAILURE; + DebugP_log("[Single Chip Servo] DRV8350 configuration failed!\r\n"); + } + else { + DebugP_log("[Single Chip Servo] DRV8350 configured!\r\n"); + } + + /* Lock the control registers of the DRV8350 to ensure there are no accidental writes */ + drv8350.gate_drive_hs.bit.LOCK = DRV8350_lock_enable; + rw_drv8350_register(DRV8350_WRITE, DRV8350_GATE_DRIVE_HS_ADDR, drv8350.gate_drive_hs.all, NULL); + rw_drv8350_register(DRV8350_READ, DRV8350_GATE_DRIVE_HS_ADDR, 0, ®_vals[DRV8350_GATE_DRIVE_HS_ADDR]); + + if (drv8350.gate_drive_hs.all == reg_vals[DRV8350_GATE_DRIVE_HS_ADDR]) + DebugP_log("[Single Chip Servo] DRV8350 Control registers locked!\r\n"); + + return status; +} + +int32_t check_adapter_board_power() +{ + int32_t status = SystemP_SUCCESS; + + /* Check the nRESET_SVS pin to ensure power on the 3-axis board is good */ + ////if(!GPIO_pinRead(NRESET_SVS_BASE_ADDR, NRESET_SVS_PIN)) { + //// DebugP_log("[Single Chip Servo] Adapter board is not powered or 3.3V rail is out of specification.\r\n"); + //// status = SystemP_FAILURE; + ////} + ////else { + //// DebugP_log("[Single Chip Servo] Adapter board power is good.\r\n"); + ////} + + return status; +} + +void init_gpio_state() +{ + /* Set the initial GPIO output state before configuring direction. This avoids ambiguity on outputs. */ + GPIO_pinWriteHigh(MTR_1_PWM_EN_BASE_ADDR, MTR_1_PWM_EN_PIN); + GPIO_pinWriteHigh(MTR_2_PWM_EN_BASE_ADDR, MTR_2_PWM_EN_PIN); + GPIO_pinWriteHigh(BP_MUX_SEL_BASE_ADDR, BP_MUX_SEL_PIN); + GPIO_pinWriteHigh(ENC1_EN_BASE_ADDR, ENC1_EN_PIN); + GPIO_pinWriteHigh(ENC2_EN_BASE_ADDR, ENC2_EN_PIN); + + GPIO_setDirMode(MTR_1_PWM_EN_BASE_ADDR, MTR_1_PWM_EN_PIN, MTR_1_PWM_EN_DIR); + GPIO_setDirMode(MTR_2_PWM_EN_BASE_ADDR, MTR_2_PWM_EN_PIN, MTR_2_PWM_EN_DIR); + GPIO_setDirMode(BP_MUX_SEL_BASE_ADDR, BP_MUX_SEL_PIN, BP_MUX_SEL_DIR); + GPIO_setDirMode(ENC1_EN_BASE_ADDR, ENC1_EN_PIN, ENC1_EN_DIR); + GPIO_setDirMode(ENC2_EN_BASE_ADDR, ENC2_EN_PIN, ENC2_EN_DIR); + +#ifdef SDDF_HW_EVM_ADAPTER_BP + ////GPIO_pinWriteHigh(HDSL_EN_BASE_ADDR, HDSL_EN_PIN); + ////GPIO_setDirMode(HDSL_EN_BASE_ADDR, HDSL_EN_PIN, GPIO_DIRECTION_OUTPUT); +#endif +} +#endif + +#if defined(SDDF_HW_EVM_ADAPTER_BP) +static TCA6424_Config gTCA6424_Config; +void i2c_io_expander(void *args) +{ + int32_t status = SystemP_SUCCESS; + TCA6424_Params tca6424Params; + TCA6424_Params_init(&tca6424Params); + status = TCA6424_open(&gTCA6424_Config, &tca6424Params); + uint32_t ioIndex; + + if(status == SystemP_SUCCESS) + { + /* set IO expander P12 to high */ + ioIndex = 0x0a; + status = TCA6424_setOutput( + &gTCA6424_Config, + ioIndex, + TCA6424_OUT_STATE_HIGH); + + /* Configure as output */ + status += TCA6424_config( + &gTCA6424_Config, + ioIndex, + TCA6424_MODE_OUTPUT); + } + TCA6424_close(&gTCA6424_Config); +} +#endif + +/* GPIO PIN Macros */ +#define GPIO0_BASE_ADDR (CSL_MCU_GPIO0_BASE) +#define GPIO_LED_PIN () +#define GPIO_LED_DIR (GPIO_DIRECTION_OUTPUT) +#define GPIO_LED_TRIG_TYPE (GPIO_TRIG_TYPE_NONE) + +#if defined(SINGLE_AXLE_USE_M1) +void misc_pinmux(){ +#if 0 + /* Sigma Delta pin mux */ + Pinmux_PerCfg_t miscPinMuxCfg[] = { +#if 0 + /* EHRPWM3 pin config */ +#ifdef SINGLE_AXLE_USE_M2 + /* EHRPWM5_A -> GPMC0_BE1n (P21) */ + { + PIN_GPMC0_BE1N, + ( PIN_MODE(3) | PIN_PULL_DISABLE ) + }, +#endif +#if defined(SDDF_HW_EVM_ADAPTER_BP) + /* PRG0_PRU0_GPO19, PRG0_IEP0_EDC_SYNC_OUT0, W1, BP J5.45 */ + { + PIN_PRG0_PRU0_GPO19, + ( PIN_MODE(2) | PIN_PULL_DISABLE ) + }, + /* PRG0_PRU0_GPO17, PRG0_IEP0_EDC_SYNC_OUT1, U1, BP J2.18 */ + { + PIN_PRG0_PRU0_GPO17, + ( PIN_MODE(2) | PIN_PULL_DISABLE ) + }, +#endif + /* SD8_CLK, + PRG0_PRU0_GPI16, SD8_CLK, U4, J2E:P9 */ + { + PIN_PRG0_PRU0_GPO16, + ( PIN_MODE(1) | PIN_INPUT_ENABLE | PIN_PULL_DISABLE ) + }, + /* PRG0_PRU1_GPI9 -> PRG0_PRU1_GPO9 (Y5) */ + { + PIN_PRG0_PRU1_GPO9, + ( PIN_MODE(1) | PIN_INPUT_ENABLE | PIN_PULL_DISABLE ) + }, + /* PRG0_PRU1_GPI10 -> PRG0_PRU1_GPO10 (V6) */ + { + PIN_PRG0_PRU1_GPO10, + ( PIN_MODE(1) | PIN_INPUT_ENABLE | PIN_PULL_DISABLE ) + }, + /* GPIO0_27 -> GPMC0_AD12 (W21) */ + { + PIN_GPMC0_AD12, + ( PIN_MODE(7) | PIN_INPUT_ENABLE | PIN_PULL_DISABLE ) + }, +#ifdef SINGLE_AXLE_USE_M1 +#if defined(AM243X_ALX) + /* SD0_D, + PRG0_PRU0_GPI1, SD0_D, J4, J4:32 */ + { + PIN_PRG0_PRU0_GPO1, + ( PIN_MODE(1) | PIN_INPUT_ENABLE | PIN_PULL_DISABLE ) + }, + /* SD1_D, + PRG0_PRU0_GPI3, SD1_D, H1, J2:19 */ + { + PIN_PRG0_PRU0_GPO3, + ( PIN_MODE(1) | PIN_INPUT_ENABLE | PIN_PULL_DISABLE ) + }, + /* SD2_D, + PRG0_PRU0_GPI5, SD2_D, F2, J2:13 */ + { + PIN_PRG0_PRU0_GPO5, + ( PIN_MODE(1) | PIN_INPUT_ENABLE | PIN_PULL_DISABLE ) + }, +#else + /* SD0_D, + PRG0_PRU0_GPI1, SD0_D, R4, J2E:P8 */ + { + PIN_PRG0_PRU0_GPO1, + ( PIN_MODE(1) | PIN_INPUT_ENABLE | PIN_PULL_DISABLE ) + }, + /* SD1_D, + PRG0_PRU0_GPI3m, SD1_D, V2, J2A:P9 */ + { + PIN_PRG0_PRU0_GPO3, + ( PIN_MODE(1) | PIN_INPUT_ENABLE | PIN_PULL_DISABLE ) + }, + /* SD2_D, + PRG0_PRU0_GPI5, SD2_D, R3, J2C:P6 */ + { + PIN_PRG0_PRU0_GPO5, + ( PIN_MODE(1) | PIN_INPUT_ENABLE | PIN_PULL_DISABLE ) + }, +#endif +#endif +#ifdef SINGLE_AXLE_USE_M1 ////// do pinmux for M2 here + /* SD3_D, + PRG0_PRU0_GPI7, SD3_D, T1, J2B:P7 */ + { + PIN_PRG0_PRU0_GPO7, + ( PIN_MODE(1) | PIN_INPUT_ENABLE | PIN_PULL_DISABLE ) + }, +#ifdef SDDF_HW_EVM_ADAPTER_BP + /* SD4_D, + PRG0_PRU0_GPI9, SD4_D, W6, J2D:P28 */ + { + PIN_PRG0_PRU0_GPO9, + ( PIN_MODE(1) | PIN_INPUT_ENABLE | PIN_PULL_DISABLE ) + }, +#endif + /* SD5_D, + PRG0_PRU0_GPI11, SD5_D, Y3, J2B:P14 */ + { + PIN_PRG0_PRU0_GPO11, + ( PIN_MODE(1) | PIN_INPUT_ENABLE | PIN_PULL_DISABLE ) + }, +#endif +#endif + + /* PRU_ICSSG0_PRU0 pin config */ + /* PRG0_PRU0_GPI1 -> PRG0_PRU0_GPO1 (J4) */ + { + PIN_PRG0_PRU0_GPO1, + ( PIN_MODE(1) | PIN_INPUT_ENABLE | PIN_PULL_DISABLE ) + }, + /* PRG0_PRU0_GPI11 -> PRG0_PRU0_GPO11 (L1) */ + { + PIN_PRG0_PRU0_GPO11, + ( PIN_MODE(1) | PIN_INPUT_ENABLE | PIN_PULL_DISABLE ) + }, + /* PRG0_PRU0_GPI16 -> PRG0_PRU0_GPO16 (N3) */ + { + PIN_PRG0_PRU0_GPO16, + ( PIN_MODE(1) | PIN_INPUT_ENABLE | PIN_PULL_DISABLE ) + }, + /* PRG0_PRU0_GPI18 -> PRG0_PRU0_GPO18 (K4) */ + { + PIN_PRG0_PRU0_GPO18, + ( PIN_MODE(1) | PIN_INPUT_ENABLE | PIN_PULL_DISABLE ) + }, + /* PRG0_PRU0_GPI3 -> PRG0_PRU0_GPO3 (H1) */ + { + PIN_PRG0_PRU0_GPO3, + ( PIN_MODE(1) | PIN_INPUT_ENABLE | PIN_PULL_DISABLE ) + }, + /* PRG0_PRU0_GPI5 -> PRG0_PRU0_GPO5 (F2) */ + { + PIN_PRG0_PRU0_GPO5, + ( PIN_MODE(1) | PIN_INPUT_ENABLE | PIN_PULL_DISABLE ) + }, + /* PRG0_PRU0_GPI7 -> PRG0_PRU0_GPO7 (E2) */ + { + PIN_PRG0_PRU0_GPO7, + ( PIN_MODE(1) | PIN_INPUT_ENABLE | PIN_PULL_DISABLE ) + }, + /* PRG0_PRU0_GPI8 -> PRG0_PRU0_GPO8 (H5) */ + { + PIN_PRG0_PRU0_GPO8, + ( PIN_MODE(1) | PIN_INPUT_ENABLE | PIN_PULL_DISABLE ) + }, + + /* PRU_ICSSG0_IEP0 pin config */ + /* PRG0_IEP0_EDC_SYNC_OUT0 -> PRG0_PRU0_GPO19 (G2) */ + { + PIN_PRG0_PRU0_GPO19, + ( PIN_MODE(2) | PIN_PULL_DISABLE ) + }, + /* PRG0_IEP0_EDC_SYNC_OUT1 -> PRG0_PRU0_GPO17 (E1) */ + { + PIN_PRG0_PRU0_GPO17, + ( PIN_MODE(2) | PIN_PULL_DISABLE ) + }, + + {PINMUX_END, PINMUX_END} + }; +#endif + + ///Pinmux_config(miscPinMuxCfg, PINMUX_DOMAIN_ID_MAIN); + +#if defined(SDDF_HW_EVM_ADAPTER_BP) + /* set IO expander P12 to high for using PIN_PRG0_PRU0_GPO9 */ + ////i2c_io_expander(NULL); +#endif + +#ifdef SINGLE_AXLE_USE_M2 + ///Pinmux_config(miscPinMuxCfg, PINMUX_DOMAIN_ID_MAIN); +#endif + +#if defined(AM243X_ALV) + GPIO_setDirMode(CSL_GPIO0_BASE, 27, GPIO_DIRECTION_OUTPUT); + GPIO_pinWriteHigh(CSL_GPIO0_BASE, 27); + + GPIO_setDirMode(CSL_GPIO0_BASE, 42, GPIO_DIRECTION_OUTPUT); + GPIO_pinWriteHigh(CSL_GPIO0_BASE, 42); +#endif +#if defined(AM243X_ALX) + GPIO_pinWriteHigh(ENC1_EN_BASE_ADDR, ENC1_EN_PIN); + GPIO_pinWriteHigh(ENC2_EN_BASE_ADDR, ENC2_EN_PIN); +#endif +} + +/* EPWM ISR */ +__attribute__((section(".critical_code"))) static void App_epwmIntrISR(void *args) +{ + AppEPwmIsrInfo_t *pAppEpwmIsrInfo; + uint32_t epwmBaseAddr; + SemaphoreP_Object *pEpwmSyncSemObject; + volatile uint16_t status; + + gEpwmIsrCnt++; + + /* Get EPWM info */ + pAppEpwmIsrInfo = (AppEPwmIsrInfo_t *)args; + epwmBaseAddr = pAppEpwmIsrInfo->epwmBaseAddr; + pEpwmSyncSemObject = pAppEpwmIsrInfo->pEpwmSyncSemObject; + + status = EPWM_etIntrStatus(epwmBaseAddr); + if (status & EPWM_ETFLG_INT_MASK) { + SemaphoreP_post(pEpwmSyncSemObject); + EPWM_etIntrClear(epwmBaseAddr); + } + +#if defined(SDDF_HW_EVM_ADAPTER_BP) + /* Call FOC loop here */ +#if defined(USE_PURE_OPEN_LOOP)||defined(USE_OPEN_LOOP_WITH_SDDF) + pruEncoderIrqHandler(NULL); +#endif +#endif + + return; +} +#endif + +__attribute__((section(".critical_code"))) static void App_epwmIntrISR2(void *args) +{ + AppEPwmIsrInfo_t *pAppEpwmIsrInfo; + uint32_t epwmBaseAddr; + SemaphoreP_Object *pEpwmSyncSemObject; + volatile uint16_t status; + + gEpwmIsrCnt2++; + + /* Get EPWM info */ + pAppEpwmIsrInfo = (AppEPwmIsrInfo_t *)args; + epwmBaseAddr = pAppEpwmIsrInfo->epwmBaseAddr; + pEpwmSyncSemObject = pAppEpwmIsrInfo->pEpwmSyncSemObject; + + status = EPWM_etIntrStatus(epwmBaseAddr); + if (status & EPWM_ETFLG_INT_MASK) { + SemaphoreP_post(pEpwmSyncSemObject); + EPWM_etIntrClear(epwmBaseAddr); + } + +#if defined(SDDF_HW_EVM_ADAPTER_BP) +#if defined(USE_PURE_OPEN_LOOP)||defined(USE_OPEN_LOOP_WITH_SDDF) + /* Call FOC loop here */ + pruEncoderIrqHandler2(NULL); +#endif +#endif + + return; +} + +void init_pwms(){ + int32_t status; + AppEPwmCfg_t appEpwmCfg; + HwiP_Params hwiPrms; + uint32_t epwm0PrdVal, epwm1PrdVal, epwm2PrdVal; + uint32_t epwm0CmpAVal, epwm1CmpAVal, epwm2CmpAVal; + + /* Address translate */ +#ifdef SINGLE_AXLE_USE_M1 + gEpwm0BaseAddr = (uint32_t)AddrTranslateP_getLocalAddr(EPWM0_BASE_ADDR); + gEpwm1BaseAddr = (uint32_t)AddrTranslateP_getLocalAddr(EPWM1_BASE_ADDR); + gEpwm2BaseAddr = (uint32_t)AddrTranslateP_getLocalAddr(EPWM2_BASE_ADDR); +#endif +#ifdef SINGLE_AXLE_USE_M2 + gEpwm0BaseAddr2A = (uint32_t)AddrTranslateP_getLocalAddr(EPWM3_OUTA_BASE_ADDR); + gEpwm0BaseAddr2B = (uint32_t)AddrTranslateP_getLocalAddr(EPWM3_OUTB_BASE_ADDR); + gEpwm1BaseAddr2 = (uint32_t)AddrTranslateP_getLocalAddr(EPWM4_BASE_ADDR); + gEpwm2BaseAddr2 = (uint32_t)AddrTranslateP_getLocalAddr(EPWM5_BASE_ADDR); +#endif + + SOC_controlModuleUnlockMMR(SOC_DOMAIN_ID_MAIN, 1); +#ifdef SINGLE_AXLE_USE_M1 + /* Configure the SYNCI/SYNCO mapping to tie the three PWM groups together and have PWM0 SYNC from Time Sync Router 38 */ + CSL_REG32_WR(CSL_CTRL_MMR0_CFG0_BASE + CSL_MAIN_CTRL_MMR_CFG0_EPWM0_CTRL, (2 << CSL_MAIN_CTRL_MMR_CFG0_EPWM0_CTRL_SYNCIN_SEL_SHIFT)); + /* Time Sync Router input 29 (ICSSG1 IEP0 SYNC0) -> Time Sync Router output 38 (0x26 + 4 = 0x2A + Time Sync Router Base */ + CSL_REG32_WR(CSL_TIMESYNC_EVENT_INTROUTER0_CFG_BASE + ((38 * 4) + 4), (0x10000 | 29)); +#endif +#ifdef SINGLE_AXLE_USE_M2 + /* Configure the SYNCI/SYNCO mapping to tie the three PWM groups together and have PWM3 SYNC from Time Sync Router 39 */ + CSL_REG32_WR(CSL_CTRL_MMR0_CFG0_BASE + CSL_MAIN_CTRL_MMR_CFG0_EPWM3_CTRL, (2 << CSL_MAIN_CTRL_MMR_CFG0_EPWM3_CTRL_SYNCIN_SEL_SHIFT)); + /* Time Sync Router input 29 (ICSSG1 IEP0 SYNC0) -> Time Sync Router output 39 (0x26 + 4 = 0x2A + Time Sync Router Base */ + CSL_REG32_WR(CSL_TIMESYNC_EVENT_INTROUTER0_CFG_BASE + ((39 * 4) + 4), (0x10000 | 29)); + CSL_REG32_WR(CSL_CTRL_MMR0_CFG0_BASE + CSL_MAIN_CTRL_MMR_CFG0_EPWM6_CTRL, (2 << CSL_MAIN_CTRL_MMR_CFG0_EPWM3_CTRL_SYNCIN_SEL_SHIFT)); + /* Time Sync Router input 29 (ICSSG1 IEP0 SYNC0) -> Time Sync Router output 39 (0x26 + 4 = 0x2A + Time Sync Router Base */ + CSL_REG32_WR(CSL_TIMESYNC_EVENT_INTROUTER0_CFG_BASE + ((40 * 4) + 4), (0x10000 | 29)); +#endif + + /* Configure the ISR triggered by EPWM0 */ + /* Create semaphore */ + status = SemaphoreP_constructBinary(&gEpwm0SyncSemObject, 0); + DebugP_assert(SystemP_SUCCESS == status); + status = SemaphoreP_constructBinary(&gEpwm0SyncSemObject2, 0); + DebugP_assert(SystemP_SUCCESS == status); + + +#if defined(SINGLE_AXLE_USE_M1) + /* Register & enable EPWM0 interrupt */ + gAppEPwm0Info.epwmBaseAddr = gEpwm0BaseAddr; + gAppEPwm0Info.pEpwmSyncSemObject = &gEpwm0SyncSemObject; + HwiP_Params_init(&hwiPrms); + hwiPrms.intNum = EPWM0_INTR; + hwiPrms.callback = &App_epwmIntrISR; + hwiPrms.args = &gAppEPwm0Info; + hwiPrms.isPulse = EPWM0_INTR_IS_PULSE; + status = HwiP_construct(&gEpwm0HwiObject, &hwiPrms); + DebugP_assert(status == SystemP_SUCCESS); + + /* Configure PWMs */ + /* Configure EPWM0 (Phase C) */ + appEpwmCfg.epwmBaseAddr = gEpwm0BaseAddr; + appEpwmCfg.epwmCh = EPWM_OUTPUT_CH_A; + appEpwmCfg.epwmFuncClk = EPWM0_FCLK; + appEpwmCfg.epwmTbFreq = EPWM0_FCLK; + appEpwmCfg.epwmOutFreq = gEpwmOutFreq; + appEpwmCfg.epwmDutyCycle = 50; + appEpwmCfg.epwmTbCounterDir = EPWM_TB_COUNTER_DIR_UP_DOWN; + appEpwmCfg.cfgTbSyncIn = TRUE; + appEpwmCfg.tbPhsValue = 7; + appEpwmCfg.tbSyncInCounterDir = EPWM_TB_COUNTER_DIR_DOWN; + appEpwmCfg.cfgTbSyncOut = TRUE; + appEpwmCfg.tbSyncOutMode = EPWM_TB_SYNC_OUT_EVT_CNT_EQ_ZERO; + appEpwmCfg.aqCfg.zeroAction = EPWM_AQ_ACTION_DONOTHING; + appEpwmCfg.aqCfg.prdAction = EPWM_AQ_ACTION_DONOTHING; + appEpwmCfg.aqCfg.cmpAUpAction = EPWM_AQ_ACTION_HIGH; + appEpwmCfg.aqCfg.cmpADownAction = EPWM_AQ_ACTION_LOW; + appEpwmCfg.aqCfg.cmpBUpAction = EPWM_AQ_ACTION_DONOTHING; + appEpwmCfg.aqCfg.cmpBDownAction = EPWM_AQ_ACTION_DONOTHING; + appEpwmCfg.cfgDb = TRUE; + appEpwmCfg.dbCfg.inputMode = EPWM_DB_IN_MODE_A_RED_A_FED; + appEpwmCfg.dbCfg.outputMode = EPWM_DB_OUT_MODE_A_RED_B_FED; + appEpwmCfg.dbCfg.polaritySelect = EPWM_DB_POL_SEL_ACTV_HIGH_COMPLEMENTARY; + appEpwmCfg.dbCfg.risingEdgeDelay = gDbRisingEdgeDelay; + appEpwmCfg.dbCfg.fallingEdgeDelay = gDbFallingEdgeDelay; + appEpwmCfg.cfgEt = TRUE; + appEpwmCfg.intSel = EPWM_ET_INTR_EVT_CNT_EQ_PRD; + appEpwmCfg.intPrd = EPWM_ET_INTR_PERIOD_FIRST_EVT; + App_epwmConfig(&appEpwmCfg, &epwm0PrdVal, &epwm0CmpAVal); + + /* Configure EPWM1 (Phase B), EPWM2 (Phase A) */ + appEpwmCfg.tbPhsValue = 0; + appEpwmCfg.tbSyncInCounterDir = EPWM_TB_COUNTER_DIR_UP; + appEpwmCfg.cfgEt = FALSE; + appEpwmCfg.epwmBaseAddr = gEpwm1BaseAddr; + App_epwmConfig(&appEpwmCfg, &epwm1PrdVal, &epwm1CmpAVal); + appEpwmCfg.epwmBaseAddr = gEpwm2BaseAddr; + App_epwmConfig(&appEpwmCfg, &epwm2PrdVal, &epwm2CmpAVal); + + DebugP_assert(epwm0PrdVal == epwm1PrdVal); + DebugP_assert(epwm1PrdVal == epwm2PrdVal); + + /* Period is the same for all EPWMs */ + gEpwmPrdVal = epwm0PrdVal; + + /* Force SW sync for EPWM0. Other PWMs will be sync'd through HW sync daisy-chain. */ + EPWM_tbTriggerSwSync(gEpwm0BaseAddr); +#endif + +#if defined(SINGLE_AXLE_USE_M2) + /* Register & enable EPWM0 interrupt */ + gAppEPwm0Info2.epwmBaseAddr = gEpwm0BaseAddr2A; + gAppEPwm0Info2.pEpwmSyncSemObject = &gEpwm0SyncSemObject2; + HwiP_Params_init(&hwiPrms); + hwiPrms.intNum = EPWM3_OUTA_INTR; + hwiPrms.callback = &App_epwmIntrISR2; + hwiPrms.args = &gAppEPwm0Info2; + hwiPrms.isPulse = EPWM3_OUTA_INTR_IS_PULSE; + status = HwiP_construct(&gEpwm0HwiObject2, &hwiPrms); + DebugP_assert(status == SystemP_SUCCESS); + + /* Configure PWMs */ + /* Configure EPWM3 (Phase C) */ + appEpwmCfg.epwmBaseAddr = gEpwm0BaseAddr2A; + appEpwmCfg.epwmCh = EPWM_OUTPUT_CH_A; + appEpwmCfg.epwmFuncClk = EPWM3_OUTA_FCLK; + appEpwmCfg.epwmTbFreq = EPWM3_OUTA_FCLK; + appEpwmCfg.epwmOutFreq = gEpwmOutFreq; + appEpwmCfg.epwmDutyCycle = 50; + appEpwmCfg.epwmTbCounterDir = EPWM_TB_COUNTER_DIR_UP_DOWN; + appEpwmCfg.cfgTbSyncIn = TRUE; + appEpwmCfg.tbPhsValue = 7; + appEpwmCfg.tbSyncInCounterDir = EPWM_TB_COUNTER_DIR_DOWN; + appEpwmCfg.cfgTbSyncOut = TRUE; + appEpwmCfg.tbSyncOutMode = EPWM_TB_SYNC_OUT_EVT_CNT_EQ_ZERO; + appEpwmCfg.aqCfg.zeroAction = EPWM_AQ_ACTION_DONOTHING; + appEpwmCfg.aqCfg.prdAction = EPWM_AQ_ACTION_DONOTHING; + appEpwmCfg.aqCfg.cmpAUpAction = EPWM_AQ_ACTION_HIGH; + appEpwmCfg.aqCfg.cmpADownAction = EPWM_AQ_ACTION_LOW; + appEpwmCfg.aqCfg.cmpBUpAction = EPWM_AQ_ACTION_DONOTHING; + appEpwmCfg.aqCfg.cmpBDownAction = EPWM_AQ_ACTION_DONOTHING; + appEpwmCfg.cfgDb = TRUE; + appEpwmCfg.dbCfg.inputMode = EPWM_DB_IN_MODE_A_RED_A_FED; + appEpwmCfg.dbCfg.outputMode = EPWM_DB_OUT_MODE_A_RED_B_FED; + appEpwmCfg.dbCfg.polaritySelect = EPWM_DB_POL_SEL_ACTV_HIGH_COMPLEMENTARY; + appEpwmCfg.dbCfg.risingEdgeDelay = gDbRisingEdgeDelay; + appEpwmCfg.dbCfg.fallingEdgeDelay = gDbFallingEdgeDelay; + appEpwmCfg.cfgEt = TRUE; + appEpwmCfg.intSel = EPWM_ET_INTR_EVT_CNT_EQ_PRD; + appEpwmCfg.intPrd = EPWM_ET_INTR_PERIOD_FIRST_EVT; + App_epwmConfig(&appEpwmCfg, &epwm0PrdVal, &epwm0CmpAVal); + appEpwmCfg.epwmBaseAddr = gEpwm0BaseAddr2B; + App_epwmConfig(&appEpwmCfg, &epwm0PrdVal, &epwm0CmpAVal); + + /* Configure EPWM1 (Phase B), EPWM2 (Phase A) */ + appEpwmCfg.tbPhsValue = 0; + appEpwmCfg.tbSyncInCounterDir = EPWM_TB_COUNTER_DIR_UP; + appEpwmCfg.cfgEt = FALSE; + appEpwmCfg.epwmBaseAddr = gEpwm1BaseAddr2; + App_epwmConfig(&appEpwmCfg, &epwm1PrdVal, &epwm1CmpAVal); + appEpwmCfg.epwmBaseAddr = gEpwm2BaseAddr2; + App_epwmConfig(&appEpwmCfg, &epwm2PrdVal, &epwm2CmpAVal); + + DebugP_assert(epwm0PrdVal == epwm1PrdVal); + DebugP_assert(epwm1PrdVal == epwm2PrdVal); + + /* Period is the same for all EPWMs */ + gEpwmPrdVal = epwm0PrdVal; + + /* Force SW sync for EPWM0. Other PWMs will be sync'd through HW sync daisy-chain. */ + EPWM_tbTriggerSwSync(gEpwm0BaseAddr2A); +#endif + + /* Enable the PWM output buffer until gate driver configured and PWM signals at 50% duty cycle */ + ///enable_pwm_buffers(FALSE); +} + +void init_pids(){ + /* 50KHz PWM frequency PID constants */ +#if 1 + gPiId.Kp = 0.2; + gPiId.Ki = 0.0001; + gPiId.Kd = 0; + arm_pid_init_f32(&gPiId, 1); + + gPiIq.Kp = 0.2; + gPiIq.Ki = 0.0001; + gPiIq.Kd = 0; + arm_pid_init_f32(&gPiIq, 1); + + /* Mmax 0.12 RPM step between periods */ + gPiSpd.Kp = MAX_SPD_CHANGE; ///0.06 + gPiSpd.Ki = 0.0003; + gPiSpd.Kd = 0; + arm_pid_init_f32(&gPiSpd, 1); + + /* Max 0.06 angle step between periods (500 RPM) */ + gPiPos.Kp = MAX_POS_CHANGE*MAX_SPD_RPM; ///30; + gPiPos.Ki = 0; + gPiPos.Kd = 0; + arm_pid_init_f32(&gPiPos, 1); +#endif + + /* 20KHz PWM frequency PID constants */ +#if 0 + gPiId.Kp = 0.225; + gPiId.Ki = 0.005; + gPiId.Kd = 0; + arm_pid_init_f32(&gPiId, 1); + + gPiIq.Kp = 0.2; + gPiIq.Ki = 0.005; + gPiIq.Kd = 0; + arm_pid_init_f32(&gPiIq, 1); + + /* Max 0.3 RPM step between periods */ + gPiSpd.Kp = 0.045; + gPiSpd.Ki = 0.0001; + gPiSpd.Kd = 0; + arm_pid_init_f32(&gPiSpd, 1); + + /* Max 0.15 angle step between periods (500 RPM) */ + gPiPos.Kp = 13; + gPiPos.Ki = 0.000025; + gPiPos.Kd = 0; + arm_pid_init_f32(&gPiPos, 1); +#endif +} + +void single_chip_servo_remote_core_start() +{ +#if (DEBUG_LEVEL == DEBUG_BUFFERS_ON) + /* Make sure that the Debug buffer size is larger than the target buffer size so that there are no index out of bounds issues */ + DebugP_assert(DEBUG_BUFF_SZ > TARGET_BUFF_SIZE); +#endif + +#if defined(SINGLE_AXLE_USE_M1) + /* Initialize GPIO state */ + init_gpio_state(); + +#if !defined(SDDF_HW_EVM_ADAPTER_BP) + /* Check the power on the adapter board */ + status = check_adapter_board_power(); + DebugP_assert(status==SystemP_SUCCESS); +#endif + + /* Disable the PWM output buffer until gate driver configured and PWM signals at 50% duty cycle */ + enable_pwm_buffers(FALSE); + +#if !defined(SDDF_HW_EVM_ADAPTER_BP) + /* Initialize the DRV8350 gate driver */ + status = init_drv8350(); + DebugP_assert(status==SystemP_SUCCESS); +#endif + + ///misc_pinmux(); +#endif + + /* Configure PWMs for complementary 3-phase and set duty cycle to 50% */ + init_pwms(); + +#if defined(SINGLE_AXLE_USE_M1) +#if !defined(USE_PURE_OPEN_LOOP) && !defined(USE_OPEN_LOOP_WITH_SDDF) + init_encoder(); + + init_sddf(); +#endif +#if defined(USE_OPEN_LOOP_WITH_SDDF) + init_sddf(); +#endif + + init_pids(); + +#if (BUILDLEVEL == CLOSED_LOOP_CIA402) + /* Default the CiA402 commands to torque control with a target value of 0 */ + gTxData.modeOfOperation = CYCLIC_SYNC_VELOCITY_MODE; ///CYCLIC_SYNC_TORQUE_MODE; + gTxData.targetPosition = 0; + gTxData.targetVelocity = 0; + gTxData.targetTorque = 0; +#endif + + /* Enable the PWM output buffers */ + enable_pwm_buffers(TRUE); +#endif + +#if defined(SINGLE_AXLE_USE_M2) +#if !defined(USE_PURE_OPEN_LOOP) && !defined(USE_OPEN_LOOP_WITH_SDDF) + init_pids(); + init_sddf2(); + + init_encoder2(); +#endif +#if defined(USE_OPEN_LOOP_WITH_SDDF) + init_sddf2(); +#endif + +#endif + + SemaphoreP_constructBinary(&gRemoteDoneSem, 0); + + /* register a handler to receive messages */ + ///status = IpcNotify_registerClient(gClientId, ipc_notify_msg_handler_remote_core, NULL); + ///DebugP_assert(status==SystemP_SUCCESS); + + /* wait for all cores to be ready */ + ///IpcNotify_syncAll(SystemP_WAIT_FOREVER); + + DebugP_log("\n\n[Single Chip Servo] All cores synchronized...\n\n"); + + while(gRunFlag == TRUE) + { +#if defined(SINGLE_AXLE_USE_M1) + SemaphoreP_pend(&gEpwm0SyncSemObject, SystemP_WAIT_FOREVER); +#endif +#if defined(SINGLE_AXLE_USE_M2) + SemaphoreP_pend(&gEpwm0SyncSemObject2, SystemP_WAIT_FOREVER); +#endif + gLoopCnt++; + } + + DebugP_log("Exiting!\r\n"); +} + +void single_chip_servo_main(void *args) +{ + Drivers_open(); + Board_driversOpen(); + + single_chip_servo_remote_core_start(); + + Board_driversClose(); + /* We dont close drivers to let the UART driver remain open and flush any pending messages to console */ + /* Drivers_close(); */ +} diff --git a/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-0_nortos/ti-arm-clang/example.projectspec b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-0_nortos/ti-arm-clang/example.projectspec new file mode 100644 index 0000000..7fd4058 --- /dev/null +++ b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-0_nortos/ti-arm-clang/example.projectspec @@ -0,0 +1,162 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-0_nortos/ti-arm-clang/linker.cmd b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-0_nortos/ti-arm-clang/linker.cmd new file mode 100644 index 0000000..e764147 --- /dev/null +++ b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-0_nortos/ti-arm-clang/linker.cmd @@ -0,0 +1,162 @@ + +/* This is the stack that is used by code running within main() + * In case of NORTOS, + * - This means all the code outside of ISR uses this stack + * In case of FreeRTOS + * - This means all the code until vTaskStartScheduler() is called in main() + * uses this stack. + * - After vTaskStartScheduler() each task created in FreeRTOS has its own stack + */ +--stack_size=16384 +/* This is the heap size for malloc() API in NORTOS and FreeRTOS + * This is also the heap used by pvPortMalloc in FreeRTOS + */ +--heap_size=32768 +-e_vectors /* This is the entry of the application, _vector MUST be plabed starting address 0x0 */ + +/* This is the size of stack when R5 is in IRQ mode + * In NORTOS, + * - Here interrupt nesting is disabled as of now + * - This is the stack used by ISRs registered as type IRQ + * In FreeRTOS, + * - Here interrupt nesting is enabled + * - This is stack that is used initally when a IRQ is received + * - But then the mode is switched to SVC mode and SVC stack is used for all user ISR callbacks + * - Hence in FreeRTOS, IRQ stack size is less and SVC stack size is more + */ +__IRQ_STACK_SIZE = 8192; +/* This is the size of stack when R5 is in IRQ mode + * - In both NORTOS and FreeRTOS nesting is disabled for FIQ + */ +__FIQ_STACK_SIZE = 256; +__SVC_STACK_SIZE = 8192; /* This is the size of stack when R5 is in SVC mode */ +__ABORT_STACK_SIZE = 256; /* This is the size of stack when R5 is in ABORT mode */ +__UNDEFINED_STACK_SIZE = 256; /* This is the size of stack when R5 is in UNDEF mode */ + +SECTIONS +{ + /* This has the R5F entry point and vector table, this MUST be at 0x0 */ + .vectors:{} palign(8) > R5F_VECS + + /* This has the R5F boot code until MPU is enabled, this MUST be at a address < 0x80000000 + * i.e this cannot be placed in DDR + */ + GROUP { + .text.hwi: palign(8) + .text.cache: palign(8) + .text.mpu: palign(8) + .text.boot: palign(8) + } > MSRAM_0_0 + + /* This is rest of code. This can be placed in DDR if DDR is available and needed */ + GROUP { + .text: {} palign(8) /* This is where code resides */ + .rodata: {} palign(8) /* This is where const's go */ + } > MSRAM_0_0 + + /* This is rest of initialized data. This can be placed in DDR if DDR is available and needed */ + GROUP { + .data: {} palign(8) /* This is where initialized globals and static go */ + } > MSRAM_0_0 + + /* This is rest of uninitialized data. This can be placed in DDR if DDR is available and needed */ + GROUP { + .bss: {} palign(8) /* This is where uninitialized globals go */ + RUN_START(__BSS_START) + RUN_END(__BSS_END) + .sysmem: {} palign(8) /* This is where the malloc heap goes */ + .stack: {} palign(8) /* This is where the main() stack goes */ + } > MSRAM_0_0 + + /* This is where the stacks for different R5F modes go */ + GROUP { + .irqstack: {. = . + __IRQ_STACK_SIZE;} align(8) + RUN_START(__IRQ_STACK_START) + RUN_END(__IRQ_STACK_END) + .fiqstack: {. = . + __FIQ_STACK_SIZE;} align(8) + RUN_START(__FIQ_STACK_START) + RUN_END(__FIQ_STACK_END) + .svcstack: {. = . + __SVC_STACK_SIZE;} align(8) + RUN_START(__SVC_STACK_START) + RUN_END(__SVC_STACK_END) + .abortstack: {. = . + __ABORT_STACK_SIZE;} align(8) + RUN_START(__ABORT_STACK_START) + RUN_END(__ABORT_STACK_END) + .undefinedstack: {. = . + __UNDEFINED_STACK_SIZE;} align(8) + RUN_START(__UNDEFINED_STACK_START) + RUN_END(__UNDEFINED_STACK_END) + } > MSRAM_0_0 + + /* General purpose user shared memory, used in some examples */ + .bss.user_shared_mem (NOLOAD) : {} > USER_SHM_MEM + /* this is used when Debug log's to shared memory are enabled, else this is not used */ + .bss.log_shared_mem (NOLOAD) : {} > LOG_SHM_MEM + /* this is used only when IPC RPMessage is enabled, else this is not used */ + .bss.ipc_vring_mem (NOLOAD) : {} > RTOS_NORTOS_IPC_SHM_MEM + + .gSddfChSampsRaw : {} align(4) > R5F_TCMB0_SDDF_0_0 + .gTxDataSection : {} align(4) > R5F_TCMB0_PDO + .gRxDataSection : {} align(4) > OTHER_R5F_TCMB0_PDO + + // debug, capture buffers + .gDebugBuff1 : {} align(4) > MSRAM1 + .gDebugBuff2 : {} align(4) > MSRAM2 + + /* TCM used by ICSS PRU to write endat channel Info */ + .gEnDatChInfo : {} align(4) > R5F_TCMB0_ENC + + .critical_code : {} palign(4) > R5F_TCMB0 + .critical_data : {} palign(8) > R5F_TCMB0 + + .gCtrlVars : {} palign(8) > MSRAM_CTRL_VARS_0_0 + + .gSharedPrivStep : {} palign(8) > USER_SHM_MEM + .gSharedPruHandle : {} palign(8) > USER_SHM_MEM + .gEtherCatCia402 : {} palign(4) > MSRAM_NO_CACHE +} + +/* +NOTE: Below memory is reserved for DMSC usage + - During Boot till security handoff is complete + 0x701E0000 - 0x701FFFFF (128KB) + - After "Security Handoff" is complete (i.e at run time) + 0x701FC000 - 0x701FFFFF (16KB) + + Security handoff is complete when this message is sent to the DMSC, + TISCI_MSG_SEC_HANDOVER + + This should be sent once all cores are loaded and all application + specific firewall calls are setup. +*/ + +MEMORY +{ + R5F_VECS : ORIGIN = 0x00000000 , LENGTH = 0x00000040 + R5F_TCMA : ORIGIN = 0x00000040 , LENGTH = 0x00007FC0 + R5F_TCMB0_SDDF_0_0 : ORIGIN = 0x41010000 , LENGTH = 0x80 + R5F_TCMB0_SDDF_0_1 : ORIGIN = 0x41010080 , LENGTH = 0x80 + R5F_TCMB0_ENC : ORIGIN = 0x41010100 , LENGTH = 0x100 + R5F_TCMB0_PDO : ORIGIN = 0x41010200 , LENGTH = 0x100 + R5F_TCMB0 : ORIGIN = 0x41010300 , LENGTH = 0x00008000 - 0x300 + /* when using multi-core application's i.e more than one R5F/M4F active, make sure + * this memory does not overlap with other R5F's + */ + MSRAM1 : ORIGIN = 0x70040000 , LENGTH = 0x40000 + MSRAM2 : ORIGIN = 0x70080000 , LENGTH = 0x40000 + MSRAM_0_0 : ORIGIN = 0x70140000 , LENGTH = 0x40000 + MSRAM_0_1 : ORIGIN = 0x70180000 , LENGTH = 0x40000 - 0x200 + MSRAM_1_0 : ORIGIN = 0x700C0000 , LENGTH = 0x70000 + MSRAM_CTRL_VARS_0_0 : ORIGIN = 0x701BFE00 , LENGTH = 0x100 + MSRAM_CTRL_VARS_0_1 : ORIGIN = 0x701BFF00 , LENGTH = 0x100 + MSRAM_NO_CACHE : ORIGIN = 0x701C0000, LENGTH = 0x100 + + /* shared memories that are used by RTOS/NORTOS cores */ + /* On R5F, + * - make sure there is a MPU entry which maps below regions as non-cache + */ + USER_SHM_MEM : ORIGIN = 0x701D0000, LENGTH = 0x00004000 + LOG_SHM_MEM : ORIGIN = 0x701D4000, LENGTH = 0x00004000 + RTOS_NORTOS_IPC_SHM_MEM : ORIGIN = 0x701D8000, LENGTH = 0x00008000 + + OTHER_R5F_TCMB0_PDO : ORIGIN = 0x78500000, LENGTH = 0x100 +} diff --git a/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-0_nortos/ti-arm-clang/makefile b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-0_nortos/ti-arm-clang/makefile new file mode 100644 index 0000000..ee9986a --- /dev/null +++ b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-0_nortos/ti-arm-clang/makefile @@ -0,0 +1,310 @@ +# +# Auto generated makefile +# + +export MOTOR_CONTROL_SDK_PATH?=$(abspath ../../../../../..) +include $(MOTOR_CONTROL_SDK_PATH)/imports.mak +include $(MOTOR_CONTROL_SDK_PATH)/devconfig/devconfig.mak + +CG_TOOL_ROOT=$(CGT_TI_ARM_CLANG_PATH) + +CC=$(CG_TOOL_ROOT)/bin/tiarmclang +LNK=$(CG_TOOL_ROOT)/bin/tiarmclang +STRIP=$(CG_TOOL_ROOT)/bin/tiarmstrip +OBJCOPY=$(CG_TOOL_ROOT)/bin/tiarmobjcopy +ifeq ($(OS), Windows_NT) + PYTHON=python +else + PYTHON=python3 +endif + +PROFILE?=release +ConfigName:=$(PROFILE) + +OUTNAME:=single_chip_servo.$(PROFILE).out + +BOOTIMAGE_PATH=$(abspath .) +BOOTIMAGE_NAME:=single_chip_servo.$(PROFILE).appimage +BOOTIMAGE_NAME_XIP:=single_chip_servo.$(PROFILE).appimage_xip +BOOTIMAGE_NAME_SIGNED:=single_chip_servo.$(PROFILE).appimage.signed +BOOTIMAGE_RPRC_NAME:=single_chip_servo.$(PROFILE).rprc +BOOTIMAGE_RPRC_NAME_XIP:=single_chip_servo.$(PROFILE).rprc_xip +BOOTIMAGE_RPRC_NAME_TMP:=single_chip_servo.$(PROFILE).rprc_tmp + +FILES_common := \ + endat_periodic_trigger.c \ + epwm_drv_aux.c \ + mclk_iep_sync.c \ + pwm.c \ + sddf.c \ + ti_r5fmath_trig.c \ + single_chip_servo.c \ + main.c \ + ti_drivers_config.c \ + ti_drivers_open_close.c \ + ti_board_config.c \ + ti_board_open_close.c \ + ti_dpl_config.c \ + ti_pinmux_config.c \ + ti_power_clock_config.c \ + +FILES_PATH_common = \ + .. \ + ../../.. \ + generated \ + +INCLUDES_common := \ + -I${CG_TOOL_ROOT}/include/c \ + -I${MOTOR_CONTROL_SDK_PATH}/mcu_plus_sdk/source \ + -I${MOTOR_CONTROL_SDK_PATH}/source \ + -I${CG_TOOL_ROOT}/include/c \ + -I${MOTOR_CONTROL_SDK_PATH}/mcu_plus_sdk/source/drivers \ + -I${MOTOR_CONTROL_SDK_PATH}/mcu_plus_sdk/source/board \ + -I${MOTOR_CONTROL_SDK_PATH}/mcu_plus_sdk/source/cmsis/DSP/Include \ + -I${MOTOR_CONTROL_SDK_PATH}/mcu_plus_sdk/source/cmsis/Core/Include \ + -I${MOTOR_CONTROL_SDK_PATH}/source/current_sense/sdfm/firmware \ + -I${MOTOR_CONTROL_SDK_PATH}/source/current_sense/sdfm/include \ + -I${MOTOR_CONTROL_SDK_PATH}/source/position_sense/endat/firmware \ + -I${MOTOR_CONTROL_SDK_PATH}/source/position_sense/endat/include \ + -I${MOTOR_CONTROL_SDK_PATH}/source/transforms/clarke \ + -I${MOTOR_CONTROL_SDK_PATH}/source/transforms/ipark \ + -I${MOTOR_CONTROL_SDK_PATH}/source/transforms/park \ + -I${MOTOR_CONTROL_SDK_PATH}/source/transforms/svgen \ + -Igenerated \ + +DEFINES_common := \ + -DSOC_AM243X \ + +CFLAGS_common := \ + -mcpu=cortex-r5 \ + -mfloat-abi=hard \ + -mfpu=vfpv3-d16 \ + -mthumb \ + -Wall \ + -Werror \ + -g \ + -Wno-gnu-variable-sized-type-not-at-end \ + -Wno-unused-function \ + +CFLAGS_cpp_common := \ + -Wno-c99-designator \ + -Wno-extern-c-compat \ + -Wno-c++11-narrowing \ + -Wno-reorder-init-list \ + -Wno-deprecated-register \ + -Wno-writable-strings \ + -Wno-enum-compare \ + -Wno-reserved-user-defined-literal \ + -Wno-unused-const-variable \ + -x c++ \ + +CFLAGS_debug := \ + -D_DEBUG_=1 \ + +CFLAGS_release := \ + -Os \ + +LNK_FILES_common = \ + linker.cmd \ + +LIBS_PATH_common = \ + -Wl,-i${CG_TOOL_ROOT}/lib \ + -Wl,-i${MOTOR_CONTROL_SDK_PATH}/mcu_plus_sdk/source/kernel/nortos/lib \ + -Wl,-i${MOTOR_CONTROL_SDK_PATH}/mcu_plus_sdk/source/drivers/lib \ + -Wl,-i${MOTOR_CONTROL_SDK_PATH}/mcu_plus_sdk/source/board/lib \ + -Wl,-i${MOTOR_CONTROL_SDK_PATH}/source/position_sense/endat/lib \ + -Wl,-i${MOTOR_CONTROL_SDK_PATH}/source/current_sense/sdfm/lib \ + -Wl,-i${MOTOR_CONTROL_SDK_PATH}/mcu_plus_sdk/source/cmsis/lib \ + -Wl,-i${CG_TOOL_ROOT}/lib \ + +LIBS_common = \ + -llibc.a \ + -lnortos.am243x.r5f.ti-arm-clang.${ConfigName}.lib \ + -ldrivers.am243x.r5f.ti-arm-clang.${ConfigName}.lib \ + -lboard.am243x.r5f.ti-arm-clang.${ConfigName}.lib \ + -lmotorcontrol_sdfm.am243x.r5f.ti-arm-clang.${ConfigName}.lib \ + -lmotorcontrol_endat.am243x.r5f.ti-arm-clang.${ConfigName}.lib \ + -lcmsis.am243x.r5f.ti-arm-clang.${ConfigName}.lib \ + -llibc.a \ + -llibsysbm.a \ + +LFLAGS_common = \ + -Wl,--diag_suppress=10063 \ + -Wl,--ram_model \ + -Wl,--reread_libs \ + + +LIBS_NAME = \ + libc.a \ + nortos.am243x.r5f.ti-arm-clang.${ConfigName}.lib \ + drivers.am243x.r5f.ti-arm-clang.${ConfigName}.lib \ + board.am243x.r5f.ti-arm-clang.${ConfigName}.lib \ + motorcontrol_sdfm.am243x.r5f.ti-arm-clang.${ConfigName}.lib \ + motorcontrol_endat.am243x.r5f.ti-arm-clang.${ConfigName}.lib \ + cmsis.am243x.r5f.ti-arm-clang.${ConfigName}.lib \ + libc.a \ + libsysbm.a \ + +LIBS_PATH_NAME = \ + ${CG_TOOL_ROOT}/lib \ + ${MOTOR_CONTROL_SDK_PATH}/mcu_plus_sdk/source/kernel/nortos/lib \ + ${MOTOR_CONTROL_SDK_PATH}/mcu_plus_sdk/source/drivers/lib \ + ${MOTOR_CONTROL_SDK_PATH}/mcu_plus_sdk/source/board/lib \ + ${MOTOR_CONTROL_SDK_PATH}/source/position_sense/endat/lib \ + ${MOTOR_CONTROL_SDK_PATH}/source/current_sense/sdfm/lib \ + ${MOTOR_CONTROL_SDK_PATH}/mcu_plus_sdk/source/cmsis/lib \ + ${CG_TOOL_ROOT}/lib \ + +FILES := $(FILES_common) $(FILES_$(PROFILE)) +ASMFILES := $(ASMFILES_common) $(ASMFILES_$(PROFILE)) +FILES_PATH := $(FILES_PATH_common) $(FILES_PATH_$(PROFILE)) +CFLAGS := $(CFLAGS_common) $(CFLAGS_$(PROFILE)) +DEFINES := $(DEFINES_common) $(DEFINES_$(PROFILE)) +INCLUDES := $(INCLUDES_common) $(INCLUDE_$(PROFILE)) +LIBS := $(LIBS_common) $(LIBS_$(PROFILE)) +LIBS_PATH := $(LIBS_PATH_common) $(LIBS_PATH_$(PROFILE)) +LFLAGS := $(LFLAGS_common) $(LFLAGS_$(PROFILE)) +LNKOPTFLAGS := $(LNKOPTFLAGS_common) $(LNKOPTFLAGS_$(PROFILE)) +LNK_FILES := $(LNK_FILES_common) $(LNK_FILES_$(PROFILE)) + +OBJDIR := obj/$(PROFILE)/ +OBJS := $(FILES:%.c=%.obj) +OBJS += $(ASMFILES:%.S=%.obj) +DEPS := $(FILES:%.c=%.d) + +vpath %.obj $(OBJDIR) +vpath %.c $(FILES_PATH) +vpath %.S $(FILES_PATH) +vpath %.lib $(LIBS_PATH_NAME) +vpath %.a $(LIBS_PATH_NAME) + +$(OBJDIR)/%.obj %.obj: %.c + @echo Compiling: am243x:r5fss0-0:nortos:ti-arm-clang $(OUTNAME): $< + $(CC) -c $(CFLAGS) $(INCLUDES) $(DEFINES) -MMD -o $(OBJDIR)/$@ $< + +$(OBJDIR)/%.obj %.obj: %.S + @echo Compiling: am243x:r5fss0-0:nortos:ti-arm-clang $(LIBNAME): $< + $(CC) -c $(CFLAGS) -o $(OBJDIR)/$@ $< + +all: $(BOOTIMAGE_NAME) + +SYSCFG_GEN_FILES=generated/ti_drivers_config.c generated/ti_drivers_config.h +SYSCFG_GEN_FILES+=generated/ti_drivers_open_close.c generated/ti_drivers_open_close.h +SYSCFG_GEN_FILES+=generated/ti_dpl_config.c generated/ti_dpl_config.h +SYSCFG_GEN_FILES+=generated/ti_pinmux_config.c generated/ti_power_clock_config.c +SYSCFG_GEN_FILES+=generated/ti_board_config.c generated/ti_board_config.h +SYSCFG_GEN_FILES+=generated/ti_board_open_close.c generated/ti_board_open_close.h + +$(OUTNAME): syscfg $(SYSCFG_GEN_FILES) $(OBJS) $(LNK_FILES) $(LIBS_NAME) + @echo . + @echo Linking: am243x:r5fss0-0:nortos:ti-arm-clang $@ ... + $(LNK) $(LNKOPTFLAGS) $(LFLAGS) $(LIBS_PATH) -Wl,-m=$(basename $@).map -o $@ $(addprefix $(OBJDIR), $(OBJS)) $(LIBS) $(LNK_FILES) + @echo Linking: am243x:r5fss0-0:nortos:ti-arm-clang $@ Done !!! + @echo . + +clean: + @echo Cleaning: am243x:r5fss0-0:nortos:ti-arm-clang $(OUTNAME) ... + $(RMDIR) $(OBJDIR) + $(RM) $(OUTNAME) + $(RM) $(BOOTIMAGE_NAME) + $(RM) $(BOOTIMAGE_NAME_XIP) + $(RM) $(BOOTIMAGE_NAME_SIGNED) + $(RM) $(BOOTIMAGE_NAME_HS) + $(RM) $(BOOTIMAGE_NAME_HS_FS) + $(RM) $(BOOTIMAGE_RPRC_NAME) + $(RM) $(BOOTIMAGE_RPRC_NAME_XIP) + $(RMDIR) generated/ + +scrub: + @echo Scrubing: am243x:r5fss0-0:nortos:ti-arm-clang single_chip_servo ... + $(RMDIR) obj +ifeq ($(OS),Windows_NT) + $(RM) \*.out + $(RM) \*.map + $(RM) \*.appimage* + $(RM) \*.rprc* + $(RM) \*.tiimage* + $(RM) \*.bin +else + $(RM) *.out + $(RM) *.map + $(RM) *.appimage* + $(RM) *.rprc* + $(RM) *.tiimage* + $(RM) *.bin +endif + $(RMDIR) generated + +$(OBJS): | $(OBJDIR) + +$(OBJDIR): + $(MKDIR) $@ + + +.NOTPARALLEL: + +.INTERMEDIATE: syscfg +$(SYSCFG_GEN_FILES): syscfg + +syscfg: ../example.syscfg + @echo Generating SysConfig files ... + $(SYSCFG_NODE) $(SYSCFG_CLI_PATH)/dist/cli.js --product $(SYSCFG_SDKPRODUCT) --context r5fss0-0 --part ALX --package ALX --output generated/ ../example.syscfg + +syscfg-gui: + $(SYSCFG_NWJS) $(SYSCFG_PATH) --product $(SYSCFG_SDKPRODUCT) --device AM243x_ALX_beta --context r5fss0-0 --part ALX --package ALX --output generated/ ../example.syscfg + +# +# Generation of boot image which can be loaded by Secondary Boot Loader (SBL) +# +ifeq ($(OS),Windows_NT) +EXE_EXT=.exe +endif +ifeq ($(OS),Windows_NT) + BOOTIMAGE_CERT_GEN_CMD=powershell -executionpolicy unrestricted -command $(MOTOR_CONTROL_SDK_PATH)/mcu_plus_sdk/tools/boot/signing/x509CertificateGen.ps1 +else + BOOTIMAGE_CERT_GEN_CMD=$(MOTOR_CONTROL_SDK_PATH)/mcu_plus_sdk/tools/boot/signing/x509CertificateGen.sh +endif +BOOTIMAGE_TEMP_OUT_FILE=temp_stdout_$(PROFILE).txt + +BOOTIMAGE_CERT_KEY=$(APP_SIGNING_KEY) + +BOOTIMAGE_CORE_ID_r5fss0-0 = 4 +BOOTIMAGE_CORE_ID_r5fss0-1 = 5 +BOOTIMAGE_CORE_ID_r5fss1-0 = 6 +BOOTIMAGE_CORE_ID_r5fss1-1 = 7 +BOOTIMAGE_CORE_ID_m4fss0-0 = 14 +SBL_RUN_ADDRESS=0x70000000 +SBL_DEV_ID=55 + +MULTI_CORE_IMAGE_GEN = $(SYSCFG_NODE) $(MOTOR_CONTROL_SDK_PATH)/mcu_plus_sdk/tools/boot/multicoreImageGen/multicoreImageGen.js +OUTRPRC_CMD = $(SYSCFG_NODE) $(MOTOR_CONTROL_SDK_PATH)/mcu_plus_sdk/tools/boot/out2rprc/elf2rprc.js + +ifeq ($(OS),Windows_NT) + XIPGEN_CMD=$(MOTOR_CONTROL_SDK_PATH)/mcu_plus_sdk/tools/boot/xipGen/xipGen.exe +else + XIPGEN_CMD=$(MOTOR_CONTROL_SDK_PATH)/mcu_plus_sdk/tools/boot/xipGen/xipGen.out +endif + +MULTI_CORE_IMAGE_PARAMS = \ + $(BOOTIMAGE_RPRC_NAME)@$(BOOTIMAGE_CORE_ID_r5fss0-0) \ + +MULTI_CORE_IMAGE_PARAMS_XIP = \ + $(BOOTIMAGE_RPRC_NAME_XIP)@$(BOOTIMAGE_CORE_ID_r5fss0-0) \ + +$(BOOTIMAGE_NAME): $(OUTNAME) + @echo Boot image: am243x:r5fss0-0:nortos:ti-arm-clang $(BOOTIMAGE_PATH)/$@ ... +ifneq ($(OS),Windows_NT) + $(CHMOD) a+x $(XIPGEN_CMD) +endif + $(OUTRPRC_CMD) $(OUTNAME) >> $(BOOTIMAGE_TEMP_OUT_FILE) + $(COPY) $(BOOTIMAGE_RPRC_NAME) $(BOOTIMAGE_RPRC_NAME_TMP) + $(RM) $(BOOTIMAGE_RPRC_NAME) + $(XIPGEN_CMD) -i $(BOOTIMAGE_RPRC_NAME_TMP) -o $(BOOTIMAGE_RPRC_NAME) -x $(BOOTIMAGE_RPRC_NAME_XIP) --flash-start-addr 0x60000000 -v > $(BOOTIMAGE_TEMP_OUT_FILE) + $(MULTI_CORE_IMAGE_GEN) --devID $(SBL_DEV_ID) --out $(BOOTIMAGE_NAME) $(MULTI_CORE_IMAGE_PARAMS) >> $(BOOTIMAGE_TEMP_OUT_FILE) + $(MULTI_CORE_IMAGE_GEN) --devID $(SBL_DEV_ID) --out $(BOOTIMAGE_NAME_XIP) $(MULTI_CORE_IMAGE_PARAMS_XIP) >> $(BOOTIMAGE_TEMP_OUT_FILE) + $(RM) $(BOOTIMAGE_RPRC_NAME_TMP) + $(RM) $(BOOTIMAGE_TEMP_OUT_FILE) + @echo Boot image: am243x:r5fss0-0:nortos:ti-arm-clang $(BOOTIMAGE_PATH)/$@ Done !!! + @echo . + +-include $(addprefix $(OBJDIR)/, $(DEPS)) diff --git a/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-0_nortos/ti-arm-clang/makefile_ccs_bootimage_gen b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-0_nortos/ti-arm-clang/makefile_ccs_bootimage_gen new file mode 100644 index 0000000..631db6f --- /dev/null +++ b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-0_nortos/ti-arm-clang/makefile_ccs_bootimage_gen @@ -0,0 +1,85 @@ +# +# Auto generated makefile +# + +# Below variables need to be defined outside this file or via command line +# - MOTOR_CONTROL_SDK_PATH +# - PROFILE +# - CG_TOOL_ROOT +# - OUTNAME +# - CCS_INSTALL_DIR +# - CCS_IDE_MODE + +CCS_PATH=$(CCS_INSTALL_DIR) +include ${MOTOR_CONTROL_SDK_PATH}/imports.mak +include ${MOTOR_CONTROL_SDK_PATH}/devconfig/devconfig.mak + +STRIP=$(CG_TOOL_ROOT)/bin/tiarmstrip +OBJCOPY=$(CG_TOOL_ROOT)/bin/tiarmobjcopy +ifeq ($(OS), Windows_NT) + PYTHON=python +else + PYTHON=python3 +endif + +OUTFILE=$(PROFILE)/$(OUTNAME).out +BOOTIMAGE_PATH=$(abspath ${PROFILE}) +BOOTIMAGE_NAME:=$(BOOTIMAGE_PATH)/$(OUTNAME).appimage +BOOTIMAGE_NAME_XIP:=$(BOOTIMAGE_PATH)/$(OUTNAME).appimage_xip +BOOTIMAGE_NAME_SIGNED:=$(BOOTIMAGE_PATH)/$(OUTNAME).appimage.signed +BOOTIMAGE_RPRC_NAME:=$(BOOTIMAGE_PATH)/$(OUTNAME).rprc +BOOTIMAGE_RPRC_NAME_XIP:=$(BOOTIMAGE_PATH)/$(OUTNAME).rprc_xip +BOOTIMAGE_RPRC_NAME_TMP:=$(BOOTIMAGE_PATH)/$(OUTNAME).rprc_tmp + +# +# Generation of boot image which can be loaded by Secondary Boot Loader (SBL) +# +ifeq ($(OS),Windows_NT) +EXE_EXT=.exe +endif +ifeq ($(OS),Windows_NT) + BOOTIMAGE_CERT_GEN_CMD=powershell -executionpolicy unrestricted -command $(MOTOR_CONTROL_SDK_PATH)/mcu_plus_sdk/tools/boot/signing/x509CertificateGen.ps1 +else + BOOTIMAGE_CERT_GEN_CMD=$(MOTOR_CONTROL_SDK_PATH)/mcu_plus_sdk/tools/boot/signing/x509CertificateGen.sh +endif +BOOTIMAGE_TEMP_OUT_FILE=$(PROFILE)/temp_stdout_$(PROFILE).txt + +BOOTIMAGE_CORE_ID_r5fss0-0 = 4 +BOOTIMAGE_CORE_ID_r5fss0-1 = 5 +BOOTIMAGE_CORE_ID_r5fss1-0 = 6 +BOOTIMAGE_CORE_ID_r5fss1-1 = 7 +BOOTIMAGE_CORE_ID_m4fss0-0 = 14 +SBL_RUN_ADDRESS=0x70000000 +SBL_DEV_ID=55 + +MULTI_CORE_IMAGE_GEN = $(CCS_NODE) $(MOTOR_CONTROL_SDK_PATH)/mcu_plus_sdk/tools/boot/multicoreImageGen/multicoreImageGen.js +OUTRPRC_CMD = $(CCS_NODE) $(MOTOR_CONTROL_SDK_PATH)/mcu_plus_sdk/tools/boot/out2rprc/elf2rprc.js + +ifeq ($(OS),Windows_NT) + XIPGEN_CMD=$(MOTOR_CONTROL_SDK_PATH)/mcu_plus_sdk/tools/boot/xipGen/xipGen.exe +else + XIPGEN_CMD=$(MOTOR_CONTROL_SDK_PATH)/mcu_plus_sdk/tools/boot/xipGen/xipGen.out +endif + +MULTI_CORE_IMAGE_PARAMS = \ + $(BOOTIMAGE_RPRC_NAME)@$(BOOTIMAGE_CORE_ID_r5fss0-0) \ + +MULTI_CORE_IMAGE_PARAMS_XIP = \ + $(BOOTIMAGE_RPRC_NAME_XIP)@$(BOOTIMAGE_CORE_ID_r5fss0-0) \ + +all: +ifeq ($(CCS_IDE_MODE),cloud) +# No post build steps +else + @echo Boot image: am243x:r5fss0-0:nortos:ti-arm-clang $(BOOTIMAGE_NAME) ... + $(OUTRPRC_CMD) $(OUTFILE) >> $(BOOTIMAGE_TEMP_OUT_FILE) + $(COPY) $(OUTNAME).rprc $(BOOTIMAGE_RPRC_NAME) + $(COPY) $(BOOTIMAGE_RPRC_NAME) $(BOOTIMAGE_RPRC_NAME_TMP) + $(RM) $(BOOTIMAGE_RPRC_NAME) + $(XIPGEN_CMD) -i $(BOOTIMAGE_RPRC_NAME_TMP) -o $(BOOTIMAGE_RPRC_NAME) -x $(BOOTIMAGE_RPRC_NAME_XIP) --flash-start-addr 0x60000000 -v > $(BOOTIMAGE_TEMP_OUT_FILE) + $(MULTI_CORE_IMAGE_GEN) --devID $(SBL_DEV_ID) --out $(BOOTIMAGE_NAME) $(MULTI_CORE_IMAGE_PARAMS) >> $(BOOTIMAGE_TEMP_OUT_FILE) + $(MULTI_CORE_IMAGE_GEN) --devID $(SBL_DEV_ID) --out $(BOOTIMAGE_NAME_XIP) $(MULTI_CORE_IMAGE_PARAMS_XIP) >> $(BOOTIMAGE_TEMP_OUT_FILE) + $(RM) $(BOOTIMAGE_RPRC_NAME_TMP) + @echo Boot image: am243x:r5fss0-0:nortos:ti-arm-clang $(BOOTIMAGE_NAME) Done !!! + @echo . +endif diff --git a/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-0_nortos/ti-arm-clang/makefile_projectspec b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-0_nortos/ti-arm-clang/makefile_projectspec new file mode 100644 index 0000000..0c14c21 --- /dev/null +++ b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-0_nortos/ti-arm-clang/makefile_projectspec @@ -0,0 +1,20 @@ +# +# Auto generated makefile +# + +export MOTOR_CONTROL_SDK_PATH?=$(abspath ../../../../../..) +include $(MOTOR_CONTROL_SDK_PATH)/imports.mak + +PROFILE?=Release + +PROJECT_NAME=single_chip_servo_am243x-lp_r5fss0-0_nortos_ti-arm-clang + +all: + $(CCS_ECLIPSE) -noSplash -data $(MOTOR_CONTROL_SDK_PATH)/ccs_projects -application com.ti.ccstudio.apps.projectBuild -ccs.projects $(PROJECT_NAME) -ccs.configuration $(PROFILE) + +clean: + $(CCS_ECLIPSE) -noSplash -data $(MOTOR_CONTROL_SDK_PATH)/ccs_projects -application com.ti.ccstudio.apps.projectBuild -ccs.projects $(PROJECT_NAME) -ccs.configuration $(PROFILE) -ccs.clean + +export: + $(MKDIR) $(MOTOR_CONTROL_SDK_PATH)/ccs_projects + $(CCS_ECLIPSE) -noSplash -data $(MOTOR_CONTROL_SDK_PATH)/ccs_projects -application com.ti.ccstudio.apps.projectCreate -ccs.projectSpec example.projectspec -ccs.overwrite full diff --git a/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-0_nortos/ti-arm-clang/syscfg_c.rov.xs b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-0_nortos/ti-arm-clang/syscfg_c.rov.xs new file mode 100644 index 0000000..d46875e --- /dev/null +++ b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-0_nortos/ti-arm-clang/syscfg_c.rov.xs @@ -0,0 +1,8 @@ +/* + * ======== syscfg_c.rov.xs ======== + * This file contains the information needed by the Runtime Object + * View (ROV) tool. + */ +var crovFiles = [ + "mcu_plus_sdk/source/kernel/freertos/rov/FreeRTOS.rov.js", +]; diff --git a/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-0_nortos/ti_r5fmath_trig.c b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-0_nortos/ti_r5fmath_trig.c new file mode 100644 index 0000000..a5c5339 --- /dev/null +++ b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-0_nortos/ti_r5fmath_trig.c @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2020 Texas Instruments Incorporated - http://www.ti.com/ + * + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Texas Instruments Incorporated nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include "ti_r5fmath_trig.h" + +/* first 4 coef are for sin, second 4 are for cos */ +__attribute__((section(".critical_data"))) float ti_r5fmath_sincosCoef[8] = { + 1.0f, + -0.166666507720947265625f, + 0.008331954479217529296875f, + -0.00019490718841552734375f, + 1.0f, + -0.499998867511749267578125f, + 4.165589809417724609375e-2f, + -1.35934352874755859375e-3f + }; +/* 1/(PI/4), PI/2 */ + +__attribute__((section(".critical_data"))) float ti_r5fmath_sincosPIconst[2] = { + TI_R5FMATH_ONEOVERPIOVER4, + TI_R5FMATH_PIOVER2 + }; + +//void Cfast_sincos9(float angleRad, float *constPIVal, float *constCoefVal, float *retValues) +__attribute__((section(".critical_code"))) void ti_r5fmath_sincos(float angleRad, float *PIconst, float *sincosCoef, float *retValues) +{ + // PIconst + // [0] 3PI/2 [1] 2PI [2] PI/2 [3] PI + // sincosCoef + // [0] SIN1 [1] SIN3 [2] SIN5 [3] SIN7 + // [0] COS0 [1] COS2 [2] COS4 [3] COS6 [4] COS8 + + float a2, a4,sinVal, cosVal, modVal; + uint32_t swapVal, signS, signC; + int32_t r; + + swapVal = 0x0066; + signS = 0x001e; + signC = 0x0078; + + // mult by 1/(PI/4) and take floor + + r = (int) (angleRad * PIconst[0]); // 0 < 1/4 3/4> x > 1/4 = 1 > 3/4 = 2 + modVal = angleRad - ((r+1)>>1) * PIconst[1]; // brings into 0 -> PI/4 + + a2 = modVal * modVal; + a4 = a2 * a2; + + sinVal = modVal* sincosCoef[0]; + sinVal += modVal*sincosCoef[1] * a2; + sinVal += modVal*sincosCoef[2] * a4; + sinVal += modVal*sincosCoef[3] * a4 * a2; + + cosVal = sincosCoef[4]; + cosVal += sincosCoef[5]*a2; + cosVal += sincosCoef[6]*a4; + cosVal += sincosCoef[7]*a4*a2; + + swapVal = (swapVal >> r) & 0x1; + signS = (signS >> r) & 0x1; + signC = (signC >> r) & 0x1; + + if (signS) + sinVal = -sinVal; + if (signC) + cosVal = -cosVal; + + retValues[swapVal] = sinVal; + retValues[swapVal^1] = cosVal; +} diff --git a/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-0_nortos/ti_r5fmath_trig.h b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-0_nortos/ti_r5fmath_trig.h new file mode 100644 index 0000000..c0c5882 --- /dev/null +++ b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-0_nortos/ti_r5fmath_trig.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2020 Texas Instruments Incorporated - http://www.ti.com/ + * + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Texas Instruments Incorporated nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef TI_R5FMATH_TRIG_H_ +#define TI_R5FMATH_TRIG_H_ + +#define TI_R5FMATH_PI 3.141592653589793238f +#define TI_R5FMATH_2PI 6.28318530717959f +#define TI_R5FMATH_PIOVER2 1.5707963267948966f +#define TI_R5FMATH_3PIOVER2 4.71238898f +#define TI_R5FMATH_PIOVER4 0.78539816f +#define TI_R5FMATH_ONEOVERPIOVER4 1.273239545f +#define TI_R5FMATH_PIOVER6 0.5235987755f +#define TI_R5FMATH_TANPIOVER6 0.577350269f +#define TI_R5FMATH_TANPIOVER12 0.26794919f +#define TI_R5FMATH_PIOVER180 0.017453292519943295769f + +void ti_r5fmath_sincos(float inputRadians, float *PIconstants, float *sincosCoefficients, float *returnValues); + +// globals +extern float ti_r5fmath_sincosCoef[8]; +extern float ti_r5fmath_sincosPIconst[2]; + +#endif /* TI_R5FMATH_TRIG.H */ diff --git a/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-0_nortos/tisddf_pruss_intc_mapping.h b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-0_nortos/tisddf_pruss_intc_mapping.h new file mode 100644 index 0000000..9fc85a1 --- /dev/null +++ b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-0_nortos/tisddf_pruss_intc_mapping.h @@ -0,0 +1,201 @@ +/* + * Copyright (c) 2021, Texas Instruments Incorporated + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of Texas Instruments Incorporated nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * +*/ + +/** +* @file ti_uart_pruss_intc_mapping.h +* +* @brief Pruss interrupt mapping related macros +* +*/ + +#ifndef TI_UART_PRUSS_INTC_MAPPING_H +#define TI_UART_PRUSS_INTC_MAPPING_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define IEP_TIM_CAP_CMP_EVENT 7 +#define SYNC1_OUT_EVENT 13 +#define SYNC0_OUT_EVENT 14 + +/* SYS_EVT_16-31 can be used for generating interrupts for IPC with hosts/prus etc */ +#define PRU_ARM_EVENT00 16 +#define PRU_ARM_EVENT01 17 +#define PRU_ARM_EVENT02 18 +#define PRU_ARM_EVENT03 19 +#define PRU_ARM_EVENT04 20 +#define PRU_ARM_EVENT05 21 +#define PRU_ARM_EVENT06 22 +#define PRU_ARM_EVENT07 23 +#define PRU_ARM_EVENT08 24 +#define PRU_ARM_EVENT09 25 +#define PRU_ARM_EVENT10 26 +#define PRU_ARM_EVENT11 27 +#define PRU_ARM_EVENT12 28 +#define PRU_ARM_EVENT13 29 +#define PRU_ARM_EVENT14 30 +#define PRU_ARM_EVENT15 31 + +#define PRU0_RX_ERR32_EVENT 33 +#define PORT1_TX_UNDERFLOW 39 +#define PORT1_TX_OVERFLOW 40 +#define MII_LINK0_EVENT 41 +#define PORT1_RX_EOF_EVENT 42 +#define PRU1_RX_ERR32_EVENT 45 +#define PORT2_TX_UNDERFLOW 51 +#define PORT2_TX_OVERFLOW 53 +#define PORT2_RX_EOF_EVENT 54 +#define MII_LINK1_EVENT 53 + +#define CHANNEL0 0 +#define CHANNEL1 1 +#define CHANNEL2 2 +#define CHANNEL3 3 +#define CHANNEL4 4 +#define CHANNEL5 5 +#define CHANNEL6 6 +#define CHANNEL7 7 +#define CHANNEL8 8 +#define CHANNEL9 9 + +#define PRU0 0 +#define PRU1 1 +#define PRU_EVTOUT0 2 +#define PRU_EVTOUT1 3 +#define PRU_EVTOUT2 4 +#define PRU_EVTOUT3 5 +#define PRU_EVTOUT4 6 +#define PRU_EVTOUT5 7 +#define PRU_EVTOUT6 8 +#define PRU_EVTOUT7 9 + +#define PRU0_HOSTEN_MASK ((uint32_t)0x0001) +#define PRU1_HOSTEN_MASK ((uint32_t)0x0002) +#define PRU_EVTOUT0_HOSTEN_MASK ((uint32_t)0x0004) +#define PRU_EVTOUT1_HOSTEN_MASK ((uint32_t)0x0008) +#define PRU_EVTOUT2_HOSTEN_MASK ((uint32_t)0x0010) +#define PRU_EVTOUT3_HOSTEN_MASK ((uint32_t)0x0020) +#define PRU_EVTOUT4_HOSTEN_MASK ((uint32_t)0x0040) +#define PRU_EVTOUT5_HOSTEN_MASK ((uint32_t)0x0080) +#define PRU_EVTOUT6_HOSTEN_MASK ((uint32_t)0x0100) +#define PRU_EVTOUT7_HOSTEN_MASK ((uint32_t)0x0200) + +#define SYS_EVT_POLARITY_LOW 0 +#define SYS_EVT_POLARITY_HIGH 1 + +#define SYS_EVT_TYPE_PULSE 0 +#define SYS_EVT_TYPE_EDGE 1 + +#define PRUICSS_INTC_INITDATA { \ +{ IEP_TIM_CAP_CMP_EVENT, PRU_ARM_EVENT02, PRU_ARM_EVENT03, PRU_ARM_EVENT04, PRU_ARM_EVENT05, PRU_ARM_EVENT06, \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* initializing member [6-15] for Misra C standards */ \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* initializing member [16-31] for Misra C standards */ \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* initializing member [32-47] for Misra C standards */ \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, /* initializing member [48-63] for Misra C standards */ \ +{ {IEP_TIM_CAP_CMP_EVENT, CHANNEL1, SYS_EVT_POLARITY_HIGH, SYS_EVT_TYPE_PULSE},\ + {PRU_ARM_EVENT02, CHANNEL2, SYS_EVT_POLARITY_HIGH, SYS_EVT_TYPE_PULSE},\ + {PRU_ARM_EVENT03, CHANNEL3, SYS_EVT_POLARITY_HIGH, SYS_EVT_TYPE_PULSE},\ + {PRU_ARM_EVENT04, CHANNEL4, SYS_EVT_POLARITY_HIGH, SYS_EVT_TYPE_PULSE},\ + {PRU_ARM_EVENT05, CHANNEL5, SYS_EVT_POLARITY_HIGH, SYS_EVT_TYPE_PULSE},\ + {PRU_ARM_EVENT06, CHANNEL6, SYS_EVT_POLARITY_HIGH, SYS_EVT_TYPE_PULSE},\ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [6] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [7] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [8] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [9] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [10] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [11] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [12] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [13] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [14] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [15] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [16] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [17] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [18] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [19] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [20] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [21] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [22] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [23] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [24] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [25] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [26] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [27] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [28] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [29] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [30] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [31] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [32] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [33] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [34] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [35] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [36] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [37] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [38] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [39] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [40] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [41] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [42] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [43] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [44] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [45] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [46] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [47] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [48] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [49] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [50] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [51] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [52] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [53] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [54] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [55] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [56] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [57] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [58] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [59] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [60] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [61] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [62] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}}, /* initializing member [63] for Misra C standards */ \ + { {CHANNEL1, PRU1}, {CHANNEL2, PRU_EVTOUT0}, {CHANNEL3, PRU_EVTOUT1},\ + {CHANNEL4, PRU_EVTOUT2}, {CHANNEL5, PRU_EVTOUT3}, {CHANNEL6, PRU_EVTOUT4}, \ + {0xFF, 0xFF}, {0xFF, 0xFF}, {0xFF, 0xFF}, {0xFF, 0xFF} }, /* Initializing members [6,7,8,9] of array for Misra C standards */ \ + (PRU1_HOSTEN_MASK | PRU_EVTOUT0_HOSTEN_MASK | PRU_EVTOUT1_HOSTEN_MASK | PRU_EVTOUT2_HOSTEN_MASK | PRU_EVTOUT3_HOSTEN_MASK | PRU_EVTOUT4_HOSTEN_MASK) /* PRU_EVTOUT0 */ \ +} + +#ifdef __cplusplus +} +#endif + + +#endif /* TI_UART_PRUSS_INTC_MAPPING_H */ diff --git a/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-1_nortos/epwm_drv_aux.c b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-1_nortos/epwm_drv_aux.c new file mode 100644 index 0000000..3b36c15 --- /dev/null +++ b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-1_nortos/epwm_drv_aux.c @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2023 Texas Instruments Incorporated + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * Neither the name of Texas Instruments Incorporated nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include "epwm_drv_aux.h" + +#include + +/* Configure PWM Time base counter Frequency/Period */ +void tbPwmFreqCfg( + uint32_t baseAddr, + uint32_t tbClk, + uint32_t pwmFreq, + uint32_t counterDir, + uint32_t enableShadowWrite, + uint32_t *pPeriodCount +) +{ + uint32_t tbPeriodCount; + float tbPeriodCount_f; + uint32_t regVal = 0U; + + regVal = HW_RD_REG16(baseAddr + PWMSS_EPWM_TBCTL); + HW_SET_FIELD32(regVal, PWMSS_EPWM_TBCTL_PRDLD, enableShadowWrite); + HW_SET_FIELD32(regVal, PWMSS_EPWM_TBCTL_CTRMODE, counterDir); + HW_WR_REG16((baseAddr + PWMSS_EPWM_TBCTL), + (uint16_t)regVal); + + /* compute period using floating point */ + tbPeriodCount_f = (float)tbClk / pwmFreq; + if (EPWM_TB_COUNTER_DIR_UP_DOWN == counterDir) { + tbPeriodCount_f = tbPeriodCount_f / 2.0; + } + tbPeriodCount_f = roundf(tbPeriodCount_f); + tbPeriodCount = (uint32_t)tbPeriodCount_f; + +#if 0 /* use this in case there is some reason not to use floating point */ + /* compute period using fixed point */ + tbPeriodCount = tbClk << 4; /* U32Q4 */ + tbPeriodCount /= pwmFreq; + if (EPWM_TB_COUNTER_DIR_UP_DOWN == counterDir) { + tbPeriodCount /= 2; + } + tbPeriodCount += 1<<3; /* biased rouding to 0.5 */ + tbPeriodCount >>= 4; /* U32Q0 */ +#endif + + regVal = (counterDir == EPWM_TB_COUNTER_DIR_UP_DOWN) ? + tbPeriodCount : tbPeriodCount-1; + HW_WR_REG16((baseAddr + PWMSS_EPWM_TBPRD), + (uint16_t)regVal); + + *pPeriodCount = tbPeriodCount; +} diff --git a/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-1_nortos/epwm_drv_aux.h b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-1_nortos/epwm_drv_aux.h new file mode 100644 index 0000000..adac419 --- /dev/null +++ b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-1_nortos/epwm_drv_aux.h @@ -0,0 +1,190 @@ +/* + * Copyright (C) 2021 Texas Instruments Incorporated + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * Neither the name of Texas Instruments Incorporated nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _EPWM_DRV_AUX_H_ +#define _EPWM_DRV_AUX_H_ + +#include +#include +#include + +/* Write EPWM CMPA */ +static inline void writeCmpA( + uint32_t baseAddr, + uint32_t cmpVal +) +{ + HW_WR_REG16((baseAddr + PWMSS_EPWM_CMPA), (uint16_t)cmpVal); +} + +/* Write EPWM CMPB */ +static inline void writeCmpB( + uint32_t baseAddr, + uint32_t cmpVal +) +{ + HW_WR_REG16((baseAddr + PWMSS_EPWM_CMPB), (uint16_t)cmpVal); +} + +/* Write EPWM CMPA/CMPB */ +static inline void writeCmpAB( + uint32_t baseAddr, + uint32_t cmpAVal, + uint32_t cmpBVal +) +{ + HW_WR_REG16((baseAddr + PWMSS_EPWM_CMPA), (uint16_t)cmpAVal); + HW_WR_REG16((baseAddr + PWMSS_EPWM_CMPB), (uint16_t)cmpBVal); +} + +/* Configure Output ChannelA AQ Zero */ +static inline void cfgOutChAAqZero( + uint32_t baseAddr, + uint32_t zeroAction +) +{ + uint32_t regVal = 0U; + + regVal = HW_RD_REG16(baseAddr + PWMSS_EPWM_AQCTLA); + HW_SET_FIELD32(regVal, PWMSS_EPWM_AQCTLA_ZRO, zeroAction); + HW_WR_REG16((baseAddr + PWMSS_EPWM_AQCTLA), (uint16_t)regVal); +} + +/* Configure Output ChannelA AQ CMPA Up */ +static inline void cfgOutChAAqCAU( + uint32_t baseAddr, + uint32_t cmpAUpAction +) +{ + uint32_t regVal = 0U; + + regVal = HW_RD_REG16(baseAddr + PWMSS_EPWM_AQCTLA); + HW_SET_FIELD32(regVal, PWMSS_EPWM_AQCTLA_CAU, cmpAUpAction); + HW_WR_REG16((baseAddr + PWMSS_EPWM_AQCTLA), (uint16_t)regVal); +}; + +/* Configure Output ChannelA AQ CMPA Down */ +static inline void cfgOutChAAqCAD( + uint32_t baseAddr, + uint32_t cmpADownAction +) +{ + uint32_t regVal = 0U; + + regVal = HW_RD_REG16(baseAddr + PWMSS_EPWM_AQCTLA); + HW_SET_FIELD32(regVal, PWMSS_EPWM_AQCTLA_CAD, cmpADownAction); + HW_WR_REG16((baseAddr + PWMSS_EPWM_AQCTLA), (uint16_t)regVal); +} + +/* Configure Output ChannelB AQ Zero */ +static inline void cfgOutChBAqZero( + uint32_t baseAddr, + uint32_t zeroAction +) +{ + uint32_t regVal = 0U; + + regVal = HW_RD_REG16(baseAddr + PWMSS_EPWM_AQCTLB); + HW_SET_FIELD32(regVal, PWMSS_EPWM_AQCTLB_ZRO, zeroAction); + HW_WR_REG16((baseAddr + PWMSS_EPWM_AQCTLB), (uint16_t)regVal); +} + +/* Configure Output ChannelA AQ CMPB Up */ +static inline void cfgOutChAAqCBU( + uint32_t baseAddr, + uint32_t cmpBUpAction +) +{ + uint32_t regVal = 0U; + + regVal = HW_RD_REG16(baseAddr + PWMSS_EPWM_AQCTLA); + HW_SET_FIELD32(regVal, PWMSS_EPWM_AQCTLA_CBU, cmpBUpAction); + HW_WR_REG16((baseAddr + PWMSS_EPWM_AQCTLA), (uint16_t)regVal); +} + +/* Write TB Period */ +static inline void writeTbPrd( + uint32_t baseAddr, + uint32_t tbPeriodCount +) +{ + HW_WR_REG16((baseAddr + PWMSS_EPWM_TBPRD), (uint16_t)tbPeriodCount); +} + +/* Write TB Phase */ +static inline void writeTbPhase( + uint32_t baseAddr, + uint32_t tbPhsValue +) +{ + HW_WR_REG16((baseAddr + PWMSS_EPWM_TBPHS), (uint16_t)tbPhsValue); +} + +/* Write TBCTL HSPDIV & CLKDIV */ +static inline void writeTbClkDiv( + uint32_t baseAddr, + uint32_t hspClkDiv, + uint32_t clkDiv +) +{ + uint32_t regVal = 0U; + + regVal = HW_RD_REG16(baseAddr + PWMSS_EPWM_TBCTL); + HW_SET_FIELD32(regVal, PWMSS_EPWM_TBCTL_CLKDIV, clkDiv); + HW_SET_FIELD32(regVal, PWMSS_EPWM_TBCTL_HSPCLKDIV, hspClkDiv); + HW_WR_REG16((baseAddr + PWMSS_EPWM_TBCTL), (uint16_t)regVal); +} + +/* Write TBCTL CTRMODE */ +static inline void writeTbCtrMode( + uint32_t baseAddr, + uint32_t ctrMode +) +{ + uint32_t regVal = 0U; + + regVal = HW_RD_REG16(baseAddr + PWMSS_EPWM_TBCTL); + HW_SET_FIELD32(regVal, PWMSS_EPWM_TBCTL_CTRMODE, ctrMode); + HW_WR_REG16((baseAddr + PWMSS_EPWM_TBCTL), (uint16_t)regVal); +} + +/* Configure PWM Time base counter Frequency/Period */ +void tbPwmFreqCfg( + uint32_t baseAddr, + uint32_t tbClk, + uint32_t pwmFreq, + uint32_t counterDir, + uint32_t enableShadowWrite, + uint32_t *pPeriodCount +); + +#endif /* _EPWM_DRV_AUX_H_ */ diff --git a/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-1_nortos/example.syscfg b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-1_nortos/example.syscfg new file mode 100644 index 0000000..ba16cca --- /dev/null +++ b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-1_nortos/example.syscfg @@ -0,0 +1,149 @@ +/** + * These arguments were used when this file was generated. They will be automatically applied on subsequent loads + * via the GUI or CLI. Run CLI with '--help' for additional information on how to override these arguments. + * @cliArgs --device "AM243x_ALX_beta" --package "ALX" --part "ALX" --context "r5fss0-1" --product "MOTOR_CONTROL_SDK_AM243x@09.01.00" + * @versions {"tool":"1.18.0+3266"} + */ + +/** + * Import the modules used in this configuration. + */ +const epwm = scripting.addModule("/drivers/epwm/epwm", {}, false); +const epwm1 = epwm.addInstance(); +const epwm2 = epwm.addInstance(); +const epwm3 = epwm.addInstance(); +const epwm4 = epwm.addInstance(); +const ipc = scripting.addModule("/drivers/ipc/ipc"); +const debug_log = scripting.addModule("/kernel/dpl/debug_log"); +const mpu_armv7 = scripting.addModule("/kernel/dpl/mpu_armv7", {}, false); +const mpu_armv71 = mpu_armv7.addInstance(); +const mpu_armv72 = mpu_armv7.addInstance(); +const mpu_armv73 = mpu_armv7.addInstance(); +const mpu_armv74 = mpu_armv7.addInstance(); +const mpu_armv75 = mpu_armv7.addInstance(); +const mpu_armv76 = mpu_armv7.addInstance(); +const mpu_armv77 = mpu_armv7.addInstance(); +const mpu_armv78 = mpu_armv7.addInstance(); +const mpu_armv79 = mpu_armv7.addInstance(); +const mpu_armv710 = mpu_armv7.addInstance(); +const mpu_armv711 = mpu_armv7.addInstance(); +const mpu_armv712 = mpu_armv7.addInstance(); +const mpu_armv713 = mpu_armv7.addInstance(); + +/** + * Write custom configuration values to the imported modules. + */ +epwm1.$name = "EPWM3_OUTA"; +epwm1.EPWM.$assign = "EHRPWM5"; +epwm1.EPWM.A.$assign = "GPMC0_BE1n"; +epwm1.EPWM.B.$used = false; +epwm1.EPWM.SYNCO.$used = false; +epwm1.EPWM.SYNCI.$used = false; + +epwm2.$name = "EPWM4"; +epwm2.EPWM.$assign = "EHRPWM7"; +epwm2.EPWM.A.$assign = "PRG0_PRU1_GPO18"; +epwm2.EPWM.B.$assign = "PRG0_PRU1_GPO19"; +epwm2.EPWM.SYNCO.$used = false; +epwm2.EPWM.SYNCI.$used = false; + +epwm3.$name = "EPWM5"; +epwm3.EPWM.$assign = "EHRPWM8"; +epwm3.EPWM.A.$assign = "GPMC0_AD7"; +epwm3.EPWM.SYNCO.$used = false; +epwm3.EPWM.SYNCI.$used = false; + +epwm4.$name = "EPWM3_OUTB"; +epwm4.EPWM.$assign = "EHRPWM3"; +epwm4.EPWM.A.$used = false; +epwm4.EPWM.SYNCO.$used = false; +epwm4.EPWM.SYNCI.$used = false; + +ipc.r5fss0_0 = "notify"; +ipc.m4fss0_0 = "NONE"; +ipc.r5fss1_1 = "NONE"; +ipc.r5fss1_0 = "NONE"; + +debug_log.enableCssLog = false; + +mpu_armv71.$name = "CONFIG_MPU_REGION0"; +mpu_armv71.size = 31; +mpu_armv71.attributes = "Device"; +mpu_armv71.accessPermissions = "Supervisor RD+WR, User RD"; +mpu_armv71.allowExecute = false; + +mpu_armv72.$name = "CONFIG_MPU_REGION1"; +mpu_armv72.accessPermissions = "Supervisor RD+WR, User RD"; +mpu_armv72.size = 16; +mpu_armv72.attributes = "NonCached"; + +mpu_armv73.$name = "CONFIG_MPU_REGION2"; +mpu_armv73.baseAddr = 0x41010000; +mpu_armv73.accessPermissions = "Supervisor RD+WR, User RD"; +mpu_armv73.size = 16; +mpu_armv73.attributes = "NonCached"; + +mpu_armv74.$name = "CONFIG_MPU_REGION3"; +mpu_armv74.accessPermissions = "Supervisor RD+WR, User RD"; +mpu_armv74.baseAddr = 0x70000000; +mpu_armv74.size = 21; + +mpu_armv75.$name = "CONFIG_MPU_REGION4"; +mpu_armv75.baseAddr = 0x60000000; +mpu_armv75.size = 28; +mpu_armv75.attributes = "Device"; +mpu_armv75.allowExecute = false; + +mpu_armv76.$name = "CONFIG_MPU_REGION5_GPIO"; +mpu_armv76.baseAddr = 0x600000; +mpu_armv76.size = 19; +mpu_armv76.attributes = "Device"; +mpu_armv76.allowExecute = false; + +mpu_armv77.$name = "CONFIG_MPU_REGION6_ICSSG0"; +mpu_armv77.baseAddr = 0x30000000; +mpu_armv77.size = 19; +mpu_armv77.allowExecute = false; +mpu_armv77.attributes = "NonCached"; + +mpu_armv78.$name = "CONFIG_MPU_REGION7_PWMs0_8"; +mpu_armv78.baseAddr = 0x23000000; +mpu_armv78.size = 19; +mpu_armv78.attributes = "NonCached"; +mpu_armv78.allowExecute = false; + +mpu_armv79.$name = "CONFIG_MPU_REGION8_PWM9"; +mpu_armv79.attributes = "NonCached"; +mpu_armv79.size = 16; +mpu_armv79.baseAddr = 0x23080000; + +mpu_armv710.$name = "CONFIG_MPU_REGION9_OTHER_R5F_TCMB"; +mpu_armv710.baseAddr = 0x78500000; +mpu_armv710.size = 15; +mpu_armv710.allowExecute = false; +mpu_armv710.attributes = "NonCached"; + +mpu_armv711.$name = "CONFIG_MPU_MSRAM_CTRLVARS"; +mpu_armv711.baseAddr = 0x701BFF00; +mpu_armv711.size = 8; +mpu_armv711.allowExecute = false; + +mpu_armv712.$name = "CONFIG_MPU_MSRAM_NOCACHE"; +mpu_armv712.baseAddr = 0x701D0000; +mpu_armv712.size = 16; +mpu_armv712.attributes = "NonCached"; +mpu_armv712.allowExecute = false; + +mpu_armv713.$name = "CONFIG_MPU_MSRAM_NOCACHE0"; +mpu_armv713.baseAddr = 0x701C0000; +mpu_armv713.size = 16; +mpu_armv713.attributes = "NonCached"; +mpu_armv713.allowExecute = false; + +/** + * Pinmux solution for unlocked pins/peripherals. This ensures that minor changes to the automatic solver in a future + * version of the tool will not impact the pinmux you originally saw. These lines can be completely deleted in order to + * re-solve from scratch. + */ +epwm3.EPWM.B.$suggestSolution = "GPMC0_AD10"; +epwm4.EPWM.B.$suggestSolution = "GPMC0_AD14"; diff --git a/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-1_nortos/main.c b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-1_nortos/main.c new file mode 100644 index 0000000..6ad1b9e --- /dev/null +++ b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-1_nortos/main.c @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2018-2021 Texas Instruments Incorporated + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * Neither the name of Texas Instruments Incorporated nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include "ti_drivers_config.h" +#include "ti_board_config.h" + +void single_chip_servo_main(void *args); + +int main(void) +{ + System_init(); + Board_init(); + + single_chip_servo_main(NULL); + + Board_deinit(); + System_deinit(); + + return 0; +} diff --git a/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-1_nortos/pwm.c b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-1_nortos/pwm.c new file mode 100644 index 0000000..a4844bb --- /dev/null +++ b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-1_nortos/pwm.c @@ -0,0 +1,177 @@ +/* + * Copyright (C) 2023 Texas Instruments Incorporated + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * Neither the name of Texas Instruments Incorporated nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include "pwm.h" + +/* Compute Duty Cycle & CMPx given Vref & EPWM period */ +__attribute__((always_inline)) inline void computeCmpx( + float Vref, + uint32_t epwmPrdVal, + float *pEpwmDutyCycle, + uint16_t *pEpwmCmpVal +) +{ + float dc_f; + float cmp_f; + uint16_t cmp; + + if (Vref > VREF_MAX) { + /* 100% duty cycle */ + dc_f = 1.0; + cmp = 0; + } + else if (Vref < VREF_MIN) { + /* 0% duty cycle */ + dc_f = 0.0; + cmp = epwmPrdVal; + } + else { + /* compute Duty Cycle */ + dc_f = 0.5*(Vref + 1.0); + + /* compute CMPx */ + cmp_f = (1.0 - dc_f)*epwmPrdVal; /* up-down count */ + cmp = (uint16_t)cmp_f; + } + + *pEpwmDutyCycle = dc_f; + *pEpwmCmpVal = cmp; +} + +void App_epwmConfig( + AppEPwmCfg_t *pAppEPwmCfg, + uint32_t *pEpwmPrdVal, + uint32_t *pEpwmCmpAVal +) +{ + uint32_t epwmBaseAddr; /* EPWM base address */ + uint32_t epwmCh; /* EPWM output channel */ + uint32_t epwmFuncClk; /* EPWM functional clock */ + uint32_t epwmTbFreq; /* EPWM timebase clock */ + uint32_t epwmOutFreq; /* EPWM output frequency */ + uint32_t epwmDutyCycle; /* EPWM duty cycle */ + uint32_t epwmTbCounterDir; /* EPWM TB counter direction */ + uint32_t epwmPrdVal; + uint32_t epwmCmpAVal; + + /* Get configuration parameters */ + epwmBaseAddr = pAppEPwmCfg->epwmBaseAddr; + epwmCh = pAppEPwmCfg->epwmCh; + epwmFuncClk = pAppEPwmCfg->epwmFuncClk; + epwmTbFreq = pAppEPwmCfg->epwmTbFreq; + epwmOutFreq = pAppEPwmCfg->epwmOutFreq; + epwmDutyCycle = pAppEPwmCfg->epwmDutyCycle; + epwmTbCounterDir = pAppEPwmCfg->epwmTbCounterDir; + + /* Configure Time Base submodule */ + EPWM_tbTimebaseClkCfg(epwmBaseAddr, epwmTbFreq, epwmFuncClk); + EPWM_tbPwmFreqCfg(epwmBaseAddr, epwmTbFreq, epwmOutFreq, + epwmTbCounterDir, EPWM_SHADOW_REG_CTRL_ENABLE); + + /* Configure TB Sync In Mode */ + if (pAppEPwmCfg->cfgTbSyncIn == FALSE) { + EPWM_tbSyncDisable(epwmBaseAddr); + } + else { + EPWM_tbSyncEnable(epwmBaseAddr, pAppEPwmCfg->tbPhsValue, pAppEPwmCfg->tbSyncInCounterDir); + } + + /* Configure TB Sync Out Mode */ + if (pAppEPwmCfg->cfgTbSyncOut == FALSE) { + EPWM_tbSetSyncOutMode(epwmBaseAddr, EPWM_TB_SYNC_OUT_EVT_DISABLE ); + } + else { + EPWM_tbSetSyncOutMode(epwmBaseAddr, pAppEPwmCfg->tbSyncOutMode); + } + + EPWM_tbSetEmulationMode(epwmBaseAddr, EPWM_TB_EMU_MODE_FREE_RUN); + + /* + * PRD value - this determines the period + */ + /* PRD = (TBCLK/PWM FREQ) */ + epwmPrdVal = epwmTbFreq / epwmOutFreq; + if (epwmTbCounterDir == EPWM_TB_COUNTER_DIR_UP_DOWN) { + /* + * PRD = (TBCLK/PWM FREQ) / 2 + * /2 is added because up&down counter is selected. So period is 2 times. + */ + epwmPrdVal /= 2U; + } + + /* + * COMPA value - this determines the duty cycle + * COMPA = (PRD - ((dutycycle * PRD) / 100) + */ + epwmCmpAVal = (epwmPrdVal - ((epwmDutyCycle * epwmPrdVal) / 100U)); + + /* Configure counter compare submodule */ + EPWM_counterComparatorCfg(epwmBaseAddr, EPWM_CC_CMP_A, + epwmCmpAVal, EPWM_SHADOW_REG_CTRL_ENABLE, + EPWM_CC_CMP_LOAD_MODE_CNT_EQ_ZERO_OR_PRD, TRUE); + EPWM_counterComparatorCfg(epwmBaseAddr, EPWM_CC_CMP_B, + epwmCmpAVal, EPWM_SHADOW_REG_CTRL_ENABLE, + EPWM_CC_CMP_LOAD_MODE_CNT_EQ_ZERO_OR_PRD, TRUE); + + /* Configure Action Qualifier Submodule */ + EPWM_aqActionOnOutputCfg(epwmBaseAddr, epwmCh, &pAppEPwmCfg->aqCfg); + + if (pAppEPwmCfg->cfgDb == TRUE) { + /* Configure Dead Band Submodule */ + EPWM_deadbandCfg(epwmBaseAddr, &pAppEPwmCfg->dbCfg); + } + else { + /* Configure Dead Band Submodule */ + EPWM_deadbandBypass(epwmBaseAddr); + } + + /* Configure Chopper Submodule */ + EPWM_chopperEnable(epwmBaseAddr, FALSE); + + /* Configure trip zone Submodule */ + EPWM_tzTripEventDisable(epwmBaseAddr, EPWM_TZ_EVENT_ONE_SHOT, 0U); + EPWM_tzTripEventDisable(epwmBaseAddr, EPWM_TZ_EVENT_CYCLE_BY_CYCLE, 0U); + + if (pAppEPwmCfg->cfgEt == TRUE) { + /* Configure event trigger Submodule */ + EPWM_etIntrCfg(epwmBaseAddr, pAppEPwmCfg->intSel, + pAppEPwmCfg->intPrd); + EPWM_etIntrEnable(epwmBaseAddr); + } + + /* Set return values */ + *pEpwmPrdVal = epwmPrdVal; + *pEpwmCmpAVal = epwmCmpAVal; +} diff --git a/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-1_nortos/pwm.h b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-1_nortos/pwm.h new file mode 100644 index 0000000..1450d17 --- /dev/null +++ b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-1_nortos/pwm.h @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2021 Texas Instruments Incorporated + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * Neither the name of Texas Instruments Incorporated nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _PWM_H_ +#define _PWM_H_ + +#include +#include +#include +#include "epwm_drv_aux.h" + +/* Switching control for EPWM output frequency */ +#define SET_EPWM_OUT_FREQ8K_THR ( 4000 ) +#define SET_EPWM_OUT_FREQ16K_THR ( SET_EPWM_OUT_FREQ8K_THR + 8000 ) +#define SET_EPWM_OUT_FREQ4K_THR ( SET_EPWM_OUT_FREQ16K_THR + 16000 ) + +/* Frequency of PWM output signal in Hz */ +#define APP_EPWM_OUTPUT_FREQ_4K ( 1U * 4000U ) +#define APP_EPWM_OUTPUT_FREQ_8K ( 1U * 8000U ) +#define APP_EPWM_OUTPUT_FREQ_20K ( 1U * 20000U ) +#define APP_EPWM_OUTPUT_FREQ_50K ( 1U * 50000U ) +#define APP_EPWM_OUTPUT_FREQ ( APP_EPWM_OUTPUT_FREQ_50K ) /* init freq */ +/* Deadband RED/FED timer counts */ +#define APP_EPWM_DB_RED_COUNT ( 5 ) /* 20 nsec @ 250 MHz */ +#define APP_EPWM_DB_FED_COUNT ( 5 ) /* 20 nsec @ 250 MHz */ + +/* Min / max output amplitude. + Waveform amplitude values beyond these thresholds are saturated. */ +#define VREF_MAX ( 1.0f ) +#define VREF_MIN ( -1.0f ) + +/* Sinusoid parameters */ +#define SIN_FREQ ( 6 ) /* sinusoid frequency */ +#define SIN_AMP ( 0.0 ) /* sinusoid amplitude */ + +/* EPWM configuration */ +typedef struct _AppEPwmCfg_t +{ + uint32_t epwmBaseAddr; /* EPWM base address */ + uint32_t epwmCh; /* EPWM output channel */ + uint32_t epwmFuncClk; /* EPWM functional clock */ + uint32_t epwmTbFreq; /* EPWM timebase clock */ + uint32_t epwmOutFreq; /* EPWM output frequency */ + uint32_t epwmDutyCycle; /* EPWM duty cycle */ + uint32_t epwmTbCounterDir; /* EPWM counter direction (Up, Down, Up/Down) */ + /* TB sync in config */ + Bool cfgTbSyncIn; /* config TB sync in flag (true/false) */ + uint32_t tbPhsValue; /* cfgTbSyncIn==TRUE: timer phase value to load on Sync In event */ + uint32_t tbSyncInCounterDir; /* cfgTbSyncIn==TRUE: counter direction on Sync In event */ + /* TB sync out config */ + Bool cfgTbSyncOut; /* config TB sync output flag (true/false) */ + uint32_t tbSyncOutMode; /* cfgTbSyncOut==TRUE: Sync Out mode */ + /* AQ config */ + EPWM_AqActionCfg aqCfg; /* Action Qualifier config */ + /* DB config */ + Bool cfgDb; /* config DB flag (true/false) */ + EPWM_DeadbandCfg dbCfg; /* Deadband config */ + /* ET config */ + Bool cfgEt; /* config ET module */ + uint32_t intSel; /* ET interrupt select */ + uint32_t intPrd; /* ET interrupt period */ +} AppEPwmCfg_t; + +/* Application specific initial PWM configuration */ +void App_epwmConfig( + AppEPwmCfg_t *pAppEPwmCfg, + uint32_t *pEpwmPrdVal, + uint32_t *pEpwmCmpAVal +); + +/* Compute Duty Cycle & CMPx given Vref & EPWM period */ +void computeCmpx( + float Vref, + uint32_t epwmPrdVal, + float *pEpwmDutyCycle, + uint16_t *pEpwmCmpVal +); + +#endif /* _PWM_H_ */ diff --git a/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-1_nortos/settings.h b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-1_nortos/settings.h new file mode 100644 index 0000000..010efef --- /dev/null +++ b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-1_nortos/settings.h @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2023 Texas Instruments Incorporated + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * Neither the name of Texas Instruments Incorporated nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* Following is the list of the Build Level choices */ +#define OPEN_LOOP_IQ_ID 1 /* Open loop Iq, Id */ +#define CLOSED_LOOP_IQ_ID 2 /* Closed loop Iq with reference array, Id closed loop to 0.0 */ +#define CLOSED_LOOP_SPEED 3 /* Closed loop Speed */ +#define CLOSED_LOOP_POSITION 4 /* Closed loop Position */ +#define CLOSED_LOOP_CIA402 5 /* Closed loop Iq, Speed, or Position based on EtherCAT CiA402 */ + +#define PID_TUNING 1 /* Enable the runtime PID tuning code */ +#define NO_TUNING 2 /* Disabe the runtime PID tuning, tuning has already occurred */ + +#define DEBUG_BUFFERS_ON 1 /* Log data into the debug buffers */ +#define DEBUG_BUFFERS_OFF 2 /* No data logging */ + +#define DEBUG_BUFFER_WRAP 1 /* Wrap the debug buffer continuously */ +#define DEBUG_BUFFER_SINGLE 2 /* Fill the debug buffer once to focus on startup conditions */ + +#define PRECOMPUTE_CLARKE 1 /* Use the SDDF ISR to convert/scale phase currents and compute Clarke Transform */ +#define NO_PRECOMPUTE 2 /* Convert/scale and compute Clarke Transform in the EnDat ISR along with the FOC loop */ + +#define BUILDLEVEL CLOSED_LOOP_SPEED ///CLOSED_LOOP_CIA402 ///CLOSED_LOOP_SPEED ///CLOSED_LOOP_IQ_ID ///OPEN_LOOP_IQ_ID +#define PID_TUNE_LEVEL NO_TUNING +#define DEBUG_LEVEL DEBUG_BUFFERS_OFF +#define DEBUG_WRAP_TYPE DEBUG_BUFFER_WRAP +#define PRECOMPUTE_LEVEL NO_PRECOMPUTE + +/* The number of ISR cycles to use the same target from the list of 8 targets */ +#define CYCLES_PER_TARGET 600 +#define TARGET_BUFF_SIZE CYCLES_PER_TARGET * 8 /* This value needs to be less than DEBUG_BUFF_SZ (65536) if DEBUG_BUFFERS_ON */ + +/* Iq testing value for open loop */ +#define INIT_PWM_DIFF 0.05 ///0.1 +#define IQ_TESTING 0.3 ///0.2 +#define ID_TESTING 0.0 + +/* Max speed change request allowed between updates */ +#define MAX_SPD_CHANGE 0.12 ///0.12 +/* Max position change request allowed between updates */ +#define MAX_POS_CHANGE 0.06 /* 500RPMs max speed movement between positions at 100KHz update rate */ + +#define MAX_SPD_RPM 120 ///500 + +#define ISR_PRD_IN_SECONDS 0.00002 /* 50KHz @ 1x update is 20us */ +#define ISR_PRD_IN_MINUTES (ISR_PRD_IN_SECONDS / 60.0) + +/* PRU event to clear for the EnDat interrupt */ +#define ENDAT_EVENT ( 18 ) /* 18 (EVT) for 120 (INT#) pr0_pru_mst_intr[4]_intr_req */ + +/* Sigma Delta definitions for SINC3 OSR64 - 0 - 2^18 */ +#define SDDF_FULL_SCALE 262144 +#define SDDF_HALF_SCALE 131072 +#define SDDF_HALF_SCALE_FLT 131072.0 + +/* Intial settling counts for SDDF and Electrical Angle offset calculations */ +#define SETTLING_COUNT 8192.0 +#define OFFSET_FINISHED (uint32_t) (SETTLING_COUNT * 2.0) + +#define CYCLIC_SYNC_POSITION_MODE 8 /**< \brief Cyclic Synchronous Position mode*/ +#define CYCLIC_SYNC_VELOCITY_MODE 9 /**< \brief Cyclic Synchronous Velocity mode*/ +#define CYCLIC_SYNC_TORQUE_MODE 10/**< \brief Cyclic Synchronous Torque mode*/ + +///#define SINGLE_AXLE_USE_M1 /* for R5F_0_0, it controls the M1 */ +///#define DUAL_AXIS_USE_M1_M2 /* for R5F_0_0, it controls the M1. for R5F_0_1, it controls the M2 */ + +#define SINGLE_AXLE_USE_M2 /* for R5F_0_1, it controls the M2 */ + +#define CORE_R5F_0_0 + +#define SDDF_HW_EVM_ADAPTER_BP +///#define AM243X_ALV +#define AM243X_ALX + +///#define USE_PURE_OPEN_LOOP +///#define USE_OPEN_LOOP_WITH_SDDF + +///#define USE_RTLIB_FOC + diff --git a/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-1_nortos/single_chip_servo.c b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-1_nortos/single_chip_servo.c new file mode 100644 index 0000000..d98fd60 --- /dev/null +++ b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-1_nortos/single_chip_servo.c @@ -0,0 +1,2782 @@ +/* + * Copyright (C) 2023 Texas Instruments Incorporated + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * Neither the name of Texas Instruments Incorporated nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ti_drivers_open_close.h" +#include "ti_board_open_close.h" +#include "pwm.h" +#include "settings.h" +#include "ti_r5fmath_trig.h" +#include + +#include "tisddf_pruss_intc_mapping.h" +#include + +#include + +#if defined(USE_RTLIB_FOC) +#include "clarke.h" +#include "park.h" +#include "ipark.h" +#include "svgen.h" +#endif + +#if PRU_ICSSGx_PRU_SLICE +#define PRUICSS_PRUx PRUICSS_PRU1 +#define PRUICSS_TXPRUx PRUICSS_TX_PRU1 +#define PRUICSS_RTUPRUx PRUICSS_RTU_PRU1 +#else +#define PRUICSS_PRUx PRUICSS_PRU0 +#define PRUICSS_TXPRUx PRUICSS_TX_PRU0 +#define PRUICSS_RTUPRUx PRUICSS_RTU_PRU0 +#endif +#define PRUICSS_SLICEx PRU_ICSSGx_PRU_SLICE + +#if CONFIG_ENDAT0_MODE == ENDAT_MODE_MULTI_CHANNEL_SINGLE_PRU +#include +#endif + +#if (CONFIG_ENDAT0_MODE == ENDAT_MODE_MULTI_CHANNEL_MULTI_PRU) +#include +#endif + +#if (CONFIG_ENDAT0_MODE == ENDAT_MODE_MULTI_CHANNEL_MULTI_PRU) +#include +#endif + +#if (CONFIG_ENDAT0_MODE == ENDAT_MODE_MULTI_CHANNEL_MULTI_PRU) +#include +#endif + +#if CONFIG_ENDAT0_MODE == ENDAT_MODE_SINGLE_CHANNEL_SINGLE_PRU +#include +#endif + +#define WAIT_5_SECOND (5000) +#define TASK_STACK_SIZE (4096) +#define TASK_PRIORITY (6) + +#define ENDAT_RX_SAMPLE_SIZE 7 +#define ENDAT_RX_SESQUI_DIV (1 << 15) + +#define MRS_POS_VAL2_WORD1 0x42 +#define MRS_POS_VAL2_WORD2 0x43 +#define MRS_POS_VAL2_WORD3 0x44 + +/* Translate the TCM local view addr to SoC view addr */ +#define CPU0_ATCM_SOCVIEW(x) (CSL_R5FSS0_CORE0_ATCM_BASE+(x)) +#define CPU1_ATCM_SOCVIEW(x) (CSL_R5FSS1_CORE0_ATCM_BASE+(x)) +#define CPU0_BTCM_SOCVIEW(x) (CSL_R5FSS0_CORE0_BTCM_BASE+(x - CSL_R5FSS0_BTCM_BASE)) +#define CPU1_BTCM_SOCVIEW(x) (CSL_R5FSS1_CORE0_BTCM_BASE+(x - CSL_R5FSS1_BTCM_BASE)) + +#define NUM_CH_SUPPORTED ( 3 ) + +/* EPWM ISR information */ +typedef struct _AppEPwmIsrInfo_t +{ + uint32_t epwmBaseAddr; + SemaphoreP_Object *pEpwmSyncSemObject; +} AppEPwmIsrInfo_t; +/* Interrupt globals */ +static SemaphoreP_Object gEpwm0SyncSemObject; +static HwiP_Object gEpwm0HwiObject2; +static SemaphoreP_Object gEpwm0SyncSemObject2; +/* variable to hold EPWM base address and semaphore address for ISR */ +AppEPwmIsrInfo_t gAppEPwm0Info; +AppEPwmIsrInfo_t gAppEPwm0Info2; + +/* variables to hold EPWM base addresses */ +uint32_t gEpwm0BaseAddr; +uint32_t gEpwm1BaseAddr; +uint32_t gEpwm2BaseAddr; + +uint32_t gEpwm0BaseAddr2A; +uint32_t gEpwm0BaseAddr2B; +uint32_t gEpwm1BaseAddr2; +uint32_t gEpwm2BaseAddr2; + +/* EPWM output frequency */ +volatile uint32_t gEpwmOutFreq = APP_EPWM_OUTPUT_FREQ; +/* EPWM output frequency set value */ +volatile uint32_t gEpwmOutFreqSet = APP_EPWM_OUTPUT_FREQ; +/* EPWM Rising Edge Delay */ +uint32_t gDbRisingEdgeDelay = APP_EPWM_DB_RED_COUNT; +/* EPWM Falling Edge Delay */ +uint32_t gDbFallingEdgeDelay = APP_EPWM_DB_FED_COUNT; + +volatile Bool gSetEPwmOutFreq8K = TRUE; +volatile Bool gSetEPwmOutFreq16K = TRUE; +volatile Bool gSetEPwmOutFreq4K = TRUE; + +// debug, mainloop count +uint32_t gLoopCnt = 0; + +// debug, ISR counts +volatile uint32_t gEpwmIsrCnt = 0; +volatile uint32_t gEpwmIsrCnt2 = 0; +/* EPWM period */ +volatile uint32_t gEpwmPrdVal; + +/* For handling up-down count alternating period + when period isn't divisible by 2 */ +Bool gToggleEpwmPrd=FALSE; /* Flag for EPWMs in alternating period mode */ +uint8_t gToggleEpwmPrdState=0; /* Alternating period state: 'Lower' or 'Upper' period written on alternating ISRs */ +uint32_t gEpwmPrdValL; /* 'Lower' EPWM period value written in 'Lower' state */ +uint32_t gEpwmPrdValU; /* 'Upper' EPWM period value written in 'Upper' state */ + +volatile Bool gRunFlag = TRUE; /* Flag for continuing to execute test */ + +volatile uint32_t gPruSddfIrqCnt=0; /* SDDF PRU FW IRQ count */ +volatile uint32_t gRtuSddfIrqCnt=0; /* SDDF RTU FW IRQ count */ + +/* Test ICSSG instance ID */ +#define TEST_ICSSG_INST_ID ( CONFIG_PRU_ICSS0 ) +/* Test ICSSG slice ID */ +#define TEST_ICSSG_SLICE_ID ( ICSSG_SLICE_ID_0 ) +/* Test PRU core instance IDs */ +#define TEST_PRU_INST_ID ( PRUICSS_PRU0 ) +#define TEST_RTU_INST_ID ( PRUICSS_RTU_PRU0 ) + +/* R5F interrupt settings for ICSSG */ +#define ICSSG_PRU_SDDF_INT_NUM ( CSLR_R5FSS0_CORE0_INTR_PRU_ICSSG0_PR1_HOST_INTR_PEND_3 ) /* VIM interrupt number */ +#define ICSSG_RTU_SDDF_INT_NUM ( CSLR_R5FSS0_CORE0_INTR_PRU_ICSSG0_PR1_HOST_INTR_PEND_4 ) /* VIM interrupt number */ +#define ICSSG_TX_PRU_SDDF_INT_NUM ( CSLR_R5FSS0_CORE0_INTR_PRU_ICSSG0_PR1_HOST_INTR_PEND_5 ) /* VIM interrupt number */ + +/* HWI global variables */ +static HwiP_Object gIcssgPruSddfHwiObject; /* ICSSG PRU SDDF FW HWI */ + +/* Test ICSSG handle */ +PRUICSS_Handle gPruIcssHandle; + +/* Test SDDF handles */ +//Sddf_handle gHPruSddf; +//Sddf_handle gHRtuSddf; +/* Test Sdfm handles */ +sdfm_handle gHPruSddf; +sdfm_handle gHRtuSddf; + +/* ICSSG_SA_MX_REG:G_MUX_EN */ +#if defined(SDDF_HW_EVM_ADAPTER_BP) +#if defined(AM243X_ALV) +#define PRUICSS_G_MUX_EN ( 0x00 ) +#endif +#if defined(AM243X_ALX) +#define PRUICSS_G_MUX_EN ( 0x80 ) +#endif +#endif + +#if (DEBUG_LEVEL == DEBUG_BUFFERS_ON) +/* debug, SDDF sample capture buffers */ +#define DEBUG_BUFF_SZ (32768) + +__attribute__((section(".gDebugBuff1"))) volatile float gDebugBuff0[DEBUG_BUFF_SZ] = { 0 }; +__attribute__((section(".gDebugBuff1"))) volatile float gDebugBuff1[DEBUG_BUFF_SZ] = { 0 }; +__attribute__((section(".gDebugBuff2"))) volatile float gDebugBuff2[DEBUG_BUFF_SZ] = { 0 }; +__attribute__((section(".gDebugBuff2"))) volatile float gDebugBuff3[DEBUG_BUFF_SZ] = { 0 }; +uint32_t gDebugBuffIdx = 0; +#endif + +uint32_t gCapSddfChSampsChNum = 0; +#ifdef SDDF_HW_EVM_ADAPTER_BP +#if defined(USE_PURE_OPEN_LOOP) +__attribute__((section(".gCtrlVars"))) float gSddfChOffsets[3] = { 335.125366, -647.005249, -536.584351 }; +__attribute__((section(".gCtrlVars"))) float gSddfChOffsets2[3] = { 335.125366, -647.005249, -536.584351 }; +#else +__attribute__((section(".gCtrlVars"))) float gSddfChOffsets[3] = { 0.0, 0.0, 0.0 }; +__attribute__((section(".gCtrlVars"))) float gSddfChOffsets2[3] = { 0.0, 0.0, 0.0 }; +#endif +#endif + +/* SDDF output samples, written by PRU */ +__attribute__((section(".gSddfChSampsRaw"))) uint32_t gSddfChSamps[ICSSG_NUM_SD_CH] = { 0 }; + +struct endat_priv *priv; + +/** \brief Global Structure pointer holding PRUSS1 memory Map. */ +__attribute__((section(".gSharedPrivStep"))) int32_t priv_step; +__attribute__((section(".gSharedPruHandle"))) PRUICSS_Handle gPruIcss0Handle; +PRUICSS_Handle gRtuIcss0Handle; +#define gPruIcssXHandle gPruIcss0Handle + +/* ADC offset calculation complete */ +uint8_t gSDDFOffsetComplete = FALSE; +uint8_t gSDDFOffsetComplete2 = FALSE; + +/* EnDat channel Info, written by PRU cores */ +__attribute__((section(".gEnDatChInfo"))) struct endatChRxInfo gEndatChInfo; + +#define ENDAT_MULTI_CH0 (1 << 0) +#define ENDAT_MULTI_CH1 (1 << 1) +#define ENDAT_MULTI_CH2 (1 << 2) + +#define ENDAT_INPUT_CLOCK_UART_FREQUENCY 192000000 +/* use uart clock only to start with */ +#define ENDAT_INPUT_CLOCK_FREQUENCY ENDAT_INPUT_CLOCK_UART_FREQUENCY + +#define ENDAT_RX_SAMPLE_SIZE 7 +#define ENDAT_RX_SESQUI_DIV (1 << 15) + +static unsigned char gEndat_multi_ch_mask; + +static unsigned int gEndat_prop_delay[3]; +static unsigned int gEndat_prop_delay_max; + +__attribute__((section(".gEncChData"))) struct endat_pruss_xchg local_pruss_xchg; + +volatile Bool gUpdOutIsr = FALSE; /* Flag for updating PWM output in ISR */ + +arm_pid_instance_f32 gPiId; +arm_pid_instance_f32 gPiIq; +arm_pid_instance_f32 gPiSpd; +arm_pid_instance_f32 gPiPos; +volatile Bool gConstantsChanged = 0; + +/* ICSSG PRU SDDF FW IRQ handler */ +static void pruSddfIrqHandler(void *handle); +/* ICSSG RTU SDDF FW IRQ handler */ +static void rtuSddfIrqHandler(void *handle); + +#if defined(SINGLE_AXLE_USE_M1) +void enable_pwm_buffers(Bool enable) +{ + if(enable) { + GPIO_pinWriteLow(MTR_1_PWM_EN_BASE_ADDR, MTR_1_PWM_EN_PIN); + GPIO_pinWriteLow(MTR_2_PWM_EN_BASE_ADDR, MTR_2_PWM_EN_PIN); + GPIO_pinWriteHigh(BP_MUX_SEL_BASE_ADDR, BP_MUX_SEL_PIN); + } + else { + GPIO_pinWriteHigh(MTR_1_PWM_EN_BASE_ADDR, MTR_1_PWM_EN_PIN); + GPIO_pinWriteHigh(MTR_2_PWM_EN_BASE_ADDR, MTR_2_PWM_EN_PIN); + GPIO_pinWriteHigh(BP_MUX_SEL_BASE_ADDR, BP_MUX_SEL_PIN); + } +} + +uint64_t endat_get_fw_version(void) +{ +#if CONFIG_ENDAT0_MODE == ENDAT_MODE_MULTI_CHANNEL_SINGLE_PRU + return *((unsigned long *)EnDatFirmwareMulti_0 + 2); +#endif + +#if (CONFIG_ENDAT0_CHANNEL0) && (CONFIG_ENDAT0_MODE == ENDAT_MODE_MULTI_CHANNEL_MULTI_PRU) + return *((unsigned long *)EnDatFirmwareMultiMakeRTU_0 + 2); +#endif + +#if (CONFIG_ENDAT0_CHANNEL1) && (CONFIG_ENDAT0_MODE == ENDAT_MODE_MULTI_CHANNEL_MULTI_PRU) + return *((unsigned long *)EnDatFirmwareMultiMakePRU_0 + 2); +#endif + +#if (CONFIG_ENDAT0_CHANNEL2) && (CONFIG_ENDAT0_MODE == ENDAT_MODE_MULTI_CHANNEL_MULTI_PRU) + return *((unsigned long *)EnDatFirmwareMultiMakeTXPRU_0 + 2); +#endif + +#if CONFIG_ENDAT0_MODE == ENDAT_MODE_SINGLE_CHANNEL_SINGLE_PRU + return *((unsigned long *)EnDatFirmware_0 + 2); +#endif + +} + +static void endat_pruss_init(void) +{ + gPruIcssXHandle = PRUICSS_open(CONFIG_PRU_ICSS0); + /* Configure g_mux_en to 1 in ICSSG_SA_MX_REG Register. */ + PRUICSS_setSaMuxMode(gPruIcssXHandle, PRUICSS_SA_MUX_MODE_SD_ENDAT); + + /* Set in constant table C30 to shared RAM 0x40300000 */ + PRUICSS_setConstantTblEntry(gPruIcssXHandle, PRUICSS_PRUx, PRUICSS_CONST_TBL_ENTRY_C30, ((0x40300000 & 0x00FFFF00) >> 8)); + if(gEndat_is_load_share_mode) + { + PRUICSS_setConstantTblEntry(gPruIcssXHandle, PRUICSS_TXPRUx, PRUICSS_CONST_TBL_ENTRY_C30, ((0x40300000 & 0x00FFFF00) >> 8)); + PRUICSS_setConstantTblEntry(gPruIcssXHandle, PRUICSS_RTUPRUx, PRUICSS_CONST_TBL_ENTRY_C30, ((0x40300000 & 0x00FFFF00) >> 8)); + /*Set in constant table C29 for tx pru*/ + PRUICSS_setConstantTblEntry(gPruIcssXHandle, PRUICSS_TXPRUx, PRUICSS_CONST_TBL_ENTRY_C28, 0x258); + + } + /* clear ICSS0 PRU1 data RAM */ + PRUICSS_initMemory(gPruIcssXHandle, PRUICSS_DATARAM(PRUICSS_SLICEx)); + if(gEndat_is_load_share_mode) + { + PRUICSS_disableCore(gPruIcssXHandle, PRUICSS_RTUPRUx); + PRUICSS_disableCore(gPruIcssXHandle, PRUICSS_TXPRUx); + } + PRUICSS_disableCore(gPruIcssXHandle, PRUICSS_PRUx); + + +} + +void endat_pre_init(void) +{ + endat_pruss_init(); +} + +uint32_t endat_pruss_load_run_fw(struct endat_priv *priv) +{ + + uint32_t status = SystemP_FAILURE; + +#if CONFIG_ENDAT0_MODE == ENDAT_MODE_MULTI_CHANNEL_MULTI_PRU /*enable loadshare mode*/ + + + + status = PRUICSS_disableCore(gPruIcssXHandle, PRUICSS_RTUPRUx); + DebugP_assert(SystemP_SUCCESS == status); + status=PRUICSS_writeMemory(gPruIcssXHandle, PRUICSS_IRAM_RTU_PRU(PRUICSS_SLICEx), + 0, (uint32_t *) EnDatFirmwareMultiMakeRTU_0, + sizeof(EnDatFirmwareMultiMakeRTU_0)); + DebugP_assert(0 != status); + status = PRUICSS_resetCore(gPruIcssXHandle, PRUICSS_RTUPRUx); + DebugP_assert(SystemP_SUCCESS == status); + status = PRUICSS_enableCore(gPruIcssXHandle, PRUICSS_RTUPRUx); + DebugP_assert(SystemP_SUCCESS == status); + + + status=PRUICSS_disableCore(gPruIcssXHandle, PRUICSS_PRUx ); + DebugP_assert(SystemP_SUCCESS == status); + status = PRUICSS_writeMemory(gPruIcssXHandle, PRUICSS_IRAM_PRU(PRUICSS_SLICEx), + 0, (uint32_t *) EnDatFirmwareMultiMakePRU_0, + sizeof(EnDatFirmwareMultiMakePRU_0)); + DebugP_assert(0 != status); + status = PRUICSS_resetCore(gPruIcssXHandle, PRUICSS_PRUx); + DebugP_assert(SystemP_SUCCESS == status); + status = PRUICSS_enableCore(gPruIcssXHandle, PRUICSS_PRUx); + DebugP_assert(SystemP_SUCCESS == status); + + + status = PRUICSS_disableCore(gPruIcssXHandle, PRUICSS_TXPRUx); + DebugP_assert(SystemP_SUCCESS == status); + status = PRUICSS_writeMemory(gPruIcssXHandle, PRUICSS_IRAM_TX_PRU(PRUICSS_SLICEx), + 0, (uint32_t *) EnDatFirmwareMultiMakeTXPRU_0, + sizeof(EnDatFirmwareMultiMakeTXPRU_0)); + DebugP_assert(0 != status); + status = PRUICSS_resetCore(gPruIcssXHandle, PRUICSS_TXPRUx); + DebugP_assert(SystemP_SUCCESS == status); + status = PRUICSS_enableCore(gPruIcssXHandle, PRUICSS_TXPRUx); + DebugP_assert(SystemP_SUCCESS == status); + + + status=endat_wait_initialization(priv, WAIT_5_SECOND, gEndat_multi_ch_mask); + + +#else + + status = PRUICSS_disableCore(gPruIcssXHandle, PRUICSS_PRUx); + DebugP_assert(SystemP_SUCCESS == status); + +#if(CONFIG_ENDAT0_MODE == ENDAT_MODE_MULTI_CHANNEL_SINGLE_PRU) + + status = PRUICSS_writeMemory(gPruIcssXHandle, PRUICSS_IRAM_PRU(PRUICSS_SLICEx), + 0, (uint32_t *) EnDatFirmwareMulti_0, + sizeof(EnDatFirmwareMulti_0)); + +#else + + status = PRUICSS_writeMemory(gPruIcssXHandle, PRUICSS_IRAM_PRU(PRUICSS_SLICEx), + 0, (uint32_t *) EnDatFirmware_0, + sizeof(EnDatFirmware_0)); +#endif + DebugP_assert(0 != status); + + status = PRUICSS_resetCore(gPruIcssXHandle, PRUICSS_PRUx); + DebugP_assert(SystemP_SUCCESS == status); + + /*Run firmware */ + status = PRUICSS_enableCore(gPruIcssXHandle, PRUICSS_PRUx); + DebugP_assert(SystemP_SUCCESS == status); + + /* check initialization ack from firmware, with a timeout of 5 second */ + status = endat_wait_initialization(priv, WAIT_5_SECOND, gEndat_multi_ch_mask); +#endif + + return status; +} +#endif + +static int endat_calc_clock(unsigned freq, struct endat_clk_cfg *clk_cfg) +{ + unsigned ns; + + if(freq > 16000000 || (freq > 12000000 && freq < 16000000)) + { + DebugP_log("\r| ERROR: frequency above 16MHz, between 12 & 16MHz not allowed\n|\n|\n"); + return -1; + } + + if((freq != 16000000) && (ENDAT_INPUT_CLOCK_FREQUENCY % (freq * 8))) + DebugP_log("\r| WARNING: exact clock divider is not possible, frequencies set would be tx: %u\trx: %u\n", + ENDAT_INPUT_CLOCK_FREQUENCY / (ENDAT_INPUT_CLOCK_FREQUENCY / freq), + ENDAT_INPUT_CLOCK_FREQUENCY / (ENDAT_INPUT_CLOCK_FREQUENCY / (freq * 8))); + + ns = 2 * 1000000000 / freq; /* rx arm >= 2 clock */ + + /* should be divisible by 5 */ + if(ns % 5) + { + ns /= 5, ns += 1, ns *= 5; + } + + clk_cfg->tx_div = ENDAT_INPUT_CLOCK_FREQUENCY / freq - 1; + clk_cfg->rx_div = ENDAT_INPUT_CLOCK_FREQUENCY / (freq * 8) - 1; + clk_cfg->rx_en_cnt = ns; + clk_cfg->rx_div_attr = ENDAT_RX_SAMPLE_SIZE; + + if(freq == 16000000) + { + clk_cfg->rx_div_attr |= ENDAT_RX_SESQUI_DIV; + } + + DebugP_logInfo("\r| clock config values - tx_div: %u\trx_div: %u\trx_en_cnt: %u\trx_div_attr: %x\n", + clk_cfg->tx_div, clk_cfg->rx_div, clk_cfg->rx_en_cnt, clk_cfg->rx_div_attr); + + return 0; +} + +static void endat_handle_prop_delay(struct endat_priv *priv, + unsigned short prop_delay) +{ + if(prop_delay > priv->rx_en_cnt) + { + unsigned short dis = (prop_delay - priv->rx_en_cnt) * 2 / priv->rx_en_cnt; + + endat_config_rx_arm_cnt(priv, prop_delay); + /* propagation delay - 2T */ + endat_config_rx_clock_disable(priv, dis); + } + else + { + endat_config_rx_arm_cnt(priv, priv->rx_en_cnt); + endat_config_rx_clock_disable(priv, 0); + } +} + +static void endat_print_encoder_info(struct endat_priv *priv) +{ + DebugP_log("EnDat 2.%d %s encoder\tID: %u %s\tSN: %c %u %c\n\n", + priv->cmd_set_2_2 ? 2 : 1, + (priv->type == rotary) ? "rotary" : "linear", + priv->id.binary, (char *)&priv->id.ascii, + (char)priv->sn.ascii_msb, priv->sn.binary, (char)priv->sn.ascii_lsb); + DebugP_log("\rPosition: %d bits ", priv->pos_res); + + if(priv->type == rotary) + { + DebugP_log("(singleturn: %d, multiturn: %d) ", priv->single_turn_res, + priv->multi_turn_res); + } + + DebugP_log("[resolution: %d %s]", priv->step, + priv->type == rotary ? "M/rev" : "nm"); + DebugP_log("\r\n\nPropagation delay: %dns", + gEndat_prop_delay[priv->channel]); + DebugP_log("\n\n\n"); +} + +static unsigned endat_do_sanity_tst_delay(unsigned delay) +{ + /* (unsigned short)~0 is also a multiple of 5 */ + if(delay > (unsigned short)~0) + { + DebugP_log("\r| ERROR: delay greater than %uns, enter lesser value\n|\n|\n", + (unsigned short)~0); + return delay; + } + + if(delay % 5) + { + delay += 5, delay /= 5, delay *= 5; + DebugP_log("\r| WARNING: delay not multiple of 5ns, rounding to %uns\n|\n|\n", + delay); + } + + return delay; +} + +static void endat_init_clock(uint32_t frequency, struct endat_priv *priv) { + struct endat_clk_cfg clk_cfg; + int32_t j; + uint32_t delay; + uint16_t d; + + if(endat_calc_clock(frequency, &clk_cfg) < 0) + { + return; + } + + endat_config_clock(priv, &clk_cfg); + + priv->rx_en_cnt = clk_cfg.rx_en_cnt; + + for(j = 0; j < 3; j++) + { + if(gEndat_multi_ch_mask & 1 << j) + { + endat_multi_channel_set_cur(priv, j); + endat_handle_prop_delay(priv, gEndat_prop_delay[priv->channel]); + d = gEndat_prop_delay_max - gEndat_prop_delay[j]; + endat_config_wire_delay(priv, d); + } + } + + /* set tST to 2us if frequency > 1MHz, else turn it off */ + if(frequency >= 1000000) + { + frequency = 2000; + } + else + { + frequency = 0; + } + + delay = endat_do_sanity_tst_delay(frequency); + + if(delay <= (unsigned short)~0) + { + endat_config_tst_delay(priv, (unsigned short) delay); + } +} +volatile float gAngle = 0; +volatile uint32_t gRevolution = 0; + +static void endat_handle_rx(struct endat_priv *priv, int cmd) +{ + union endat_format_data endat_format_data; + + endat_recvd_process(priv, cmd, &endat_format_data); + endat_recvd_validate(priv, cmd, &endat_format_data); + gAngle = (float) endat_format_data.position_addinfo.position.position / priv->step * 360.0; + gRevolution = endat_format_data.position_addinfo.position.revolution; + + return; +} + + +volatile uint32_t gPruEncoderIrqCnt=0; /* EnDat PRU FW IRQ count */ +volatile uint32_t gPruEncoderIrqCnt2=0; /* EnDat PRU FW IRQ count */ +volatile uint32_t gPruEncoderIrqCnt2_after=0; /* EnDat PRU FW IRQ count */ +static HwiP_Object gIcssgEncoderHwiObject2; /* ICSSG EnDat PRU FW HWI */ + +/* ICSSG Interrupt settings */ +#define ICSSG_PRU_ENDAT_INT_NUM ( CSLR_R5FSS0_CORE0_INTR_PRU_ICSSG0_PR1_HOST_INTR_PEND_0 ) /* interrupt number */ + +__STATIC_FORCEINLINE void space_vector_f32( +float32_t Ialpha, +float32_t Ibeta, +float32_t * pIa, +float32_t * pIb, +float32_t * pIc) +{ + float32_t tmp1, tmp2, tmp3; + uint8_t vector = 3; + + tmp1 = Ibeta; + tmp2 = (Ibeta / 2) + (0.8660254039f * Ialpha); + tmp3 = tmp2 - tmp1; + + vector = (tmp2 > 0) ? vector - 1: vector; + vector = (tmp3 > 0) ? vector - 1: vector; + vector = (tmp1 < 0) ? (7 - vector): vector; + + if(vector == 1 || vector == 4){ + *pIa = tmp2; + *pIb = tmp1 - tmp3; + *pIc = -tmp2; + } + else if (vector == 2 || vector == 5){ + *pIa = tmp3 + tmp2; + *pIb = tmp1; + *pIc = -tmp1; + } + else { + *pIa = tmp3; + *pIb = -tmp3; + *pIc = -(tmp1 + tmp2); + } +} + +volatile float gIq = 0.0; +volatile float gIqTarget, gIqSetPoint, gIqRef = 0.0; +__attribute__((section(".gCtrlVars"))) volatile float gIqArray[8] = {0,0.5,1.0,1.5,0,-.5,-1,0}; + +volatile float gId = 0.0; +volatile float gIdRef = 0.0; + +volatile float gSpdTarget, gSpdSetPoint = 0, gSpdRef = 0; +///__attribute__((section(".gCtrlVars"))) volatile float gSpdArray[8] = {0,500,750,-500,-750,0,0,0}; +__attribute__((section(".gCtrlVars"))) volatile float gSpdArray[8] = {MAX_SPD_RPM,MAX_SPD_RPM,MAX_SPD_RPM,MAX_SPD_RPM, + MAX_SPD_RPM,MAX_SPD_RPM,MAX_SPD_RPM,MAX_SPD_RPM}; + +volatile float gPosTarget, gPosSetPoint, gPosRef = 0; +__attribute__((section(".gCtrlVars"))) volatile float gPosArray[8] = {180,180,359.5,359.5,0.5,0.5,180,180}; + +volatile uint8_t count = 0; + +volatile uint8_t gInferFromLargestPhases = TRUE; +volatile uint8_t gInferA, gInferB = FALSE; + +__attribute__((section(".gCtrlVars"))) float gMechAngleOffset = 0; +float gLastMechTheta = 0; +uint16_t gLastMultiTurn = 0; +uint16_t gStartingMultiTurn = 0; + +uint8_t localEnDatGetSingleMulti(float32_t * mechTheta, uint16_t * multiTurn, int chan){ + uint32_t pos, rev; + + if ((chan<0)||(chan>2)) + return -1; + + /* Check CRC from the EnDat PRU */ + if(!(gEndatChInfo.ch[chan].crcStatus & ENDAT_CRC_DATA)) + return -1; + + /* Set CRC to 0 to ensure that the PRU re-populates it every time and we aren't reading old CRC flags*/ + gEndatChInfo.ch[chan].crcStatus = 0; + + /* grab position word 0/1 from the TCM */ + pos = gEndatChInfo.ch[chan].posWord0; + rev = gEndatChInfo.ch[chan].posWord1; + + /* Reverse the bits since they arrive at the PRU in reverse order */ + asm("rbit %0,%1" : "=r"(pos) : "r"(pos)); + asm("rbit %0,%1" : "=r"(rev) : "r"(rev)); + + /* Cobble the multiturn data together from pos0 and pos1 and create singleturn by shifting out F1/F2 and masking the multiturn bits */ + rev = ((rev & 0x07F00000) >> 15) | ((pos & 0xF8000000) >> 27); + pos = (pos >> 2) & 0x1FFFFFF; + + *mechTheta = (float32_t) pos / (float32_t) priv_step * 360.0; + *multiTurn = (uint16_t) rev; + + return 0; +} + +/* Arm CMSIS 'arm_pid_f32' function modified here to remove the derivative portion since it is unused */ +__STATIC_FORCEINLINE float32_t arm_pi_f32( +arm_pid_instance_f32 * S, +float32_t in) +{ + float32_t out; + + /* y[n] = y[n-1] + A0 * x[n] + A1 * x[n-1] */ + out = (S->A0 * in) + (S->A1 * S->state[0]) + (S->state[2]); + + /* Update state */ + S->state[1] = S->state[0]; + S->state[0] = in; + S->state[2] = out; + + /* return to application */ + return (out); +} + +uint32_t gLastEnDatCMP2 = 2897; + +float32_t gClarkeAlphaMeasured, gClarkeBetaMeasured; + +struct pdo_tx_data { + uint16_t controlWord; + int8_t modeOfOperation; + int32_t targetPosition; + int32_t targetVelocity; + int16_t targetTorque; +}; + +struct pdo_rx_data { + uint16_t statusWord; + int8_t modeOfOperationDisplay; + int32_t actualPosition; + int32_t actualVelocity; + int16_t actualTorque; +}; + +/* Target data from the PLC */ +__attribute__((section(".gTxDataSection"))) struct pdo_tx_data gTxData; +/* Actual data to send to the PLC */ +__attribute__((section(".gRxDataSection"))) struct pdo_rx_data gRxData; + +#ifdef SDDF_HW_EVM_ADAPTER_BP +/* EnDat PRU FW IRQ handler */ +#if defined(USE_PURE_OPEN_LOOP)||defined(USE_OPEN_LOOP_WITH_SDDF) +float32_t myMechTheta = 0.0; +float32_t myMechDelta = 0.0166667; /// for 50Khz PWM +float32_t myMechTheta2 = 0.0; +float32_t myMechDelta2 = 0.0166667; /// for 50Khz PWM +#endif + +#ifdef SINGLE_AXLE_USE_M1 +uint32_t gEncErrCnt = 0; +uint32_t gPruEncoderIrqCnt_after = 0; +__attribute__((section(".gEtherCatCia402"))) int32_t gCurTargetVelocity[3]; +__attribute__((section(".gEtherCatCia402"))) int32_t gCurActualVelocity[3]; +__attribute__((section(".critical_code"))) void pruEncoderIrqHandler(void *args) +{ + float32_t fdbkCurPhA, fdbkCurPhB; + float32_t mechTheta, elecTheta, relativeMechTheta = 0; + uint16_t multiTurn = 0; + float32_t elecThetaSinCos[2]; + float32_t parkIdOut, parkIqOut, parkIdMeasured, parkIqMeasured; + float32_t iparkAlphaOut, iparkBetaOut; + float32_t spcVectAOut, spcVectBOut, spcVectCOut; + float dc0, dc1, dc2; /* EPWM duty cycle values */ + uint16_t cmp0, cmp1, cmp2; /* EPWM CMPA values */ + float speed, angleDelta; + float halfPeriod; + + /* Hard-coded for now to trigger the EnDat reading twice, not benchmarked because this should be moved to the PRU in the future */ +#if 0 + if(gLastEnDatCMP2 == 2897) { + HW_WR_REG32(0x3002E098, 5897); + gLastEnDatCMP2 = 5897; + } + else { + HW_WR_REG32(0x3002E098, 2897); + gLastEnDatCMP2 = 2897; + } +#endif + /* Clear interrupt at source */ + PRUICSS_clearEvent(gPruIcss0Handle, ENDAT_EVENT); + +#if defined(USE_PURE_OPEN_LOOP) + gSDDFOffsetComplete = TRUE; + gPruEncoderIrqCnt = OFFSET_FINISHED+1; +#endif + + if (gSDDFOffsetComplete) { + /* debug, increment PRU SDDF IRQ count */ + gPruEncoderIrqCnt++; + + /* Start FOC loop and unlock the rotor */ + if (gPruEncoderIrqCnt > OFFSET_FINISHED) { +#if !defined(USE_PURE_OPEN_LOOP)&&!defined(USE_OPEN_LOOP_WITH_SDDF) + /* Get the latest mechanical theta and multi-turn position from the encoder */ + if (localEnDatGetSingleMulti(&mechTheta, &multiTurn, 0) != 0) + { + gEncErrCnt++; + return; + } + gPruEncoderIrqCnt_after++; +#endif + /* Use calculated offset from electrical 0, 4 pole pairs */ +#if defined(USE_PURE_OPEN_LOOP)||defined(USE_OPEN_LOOP_WITH_SDDF) + elecTheta = myMechTheta - gMechAngleOffset; +#else + elecTheta = mechTheta - gMechAngleOffset; +#endif + if(elecTheta < 0) + elecTheta += 90; + elecTheta *= 4.0; + + /* ti_r5fmath_sincos expects input in the range of 0-2pi radians so normalize here to 0-360 degrees */ + while (elecTheta > 360.0) + elecTheta -= 360.0; + +#if defined(USE_PURE_OPEN_LOOP)||defined(USE_OPEN_LOOP_WITH_SDDF) + angleDelta = myMechTheta - gLastMechTheta; +#else + angleDelta = mechTheta - gLastMechTheta; +#endif + /* Max angle change per period @ 3200RPMs with 50KHz period should be 0.384 degrees, outside that is rollover + * Use 5 as the bound to provide plenty of room for max acceleration cases */ + if (angleDelta < -50) + angleDelta += 360; + else if (angleDelta > 50) + angleDelta -= 360; + + /* Compute instantaneous RPMs using the change in angle and the PWM frequency */ + speed = (angleDelta / 360.0) / (ISR_PRD_IN_MINUTES); + +#if (PRECOMPUTE_LEVEL == NO_PRECOMPUTE) + /* Try to avoid the INA240 switching noise by selecting the 2 phases with the largest duty cycles */ + if (gInferA) { + fdbkCurPhB = (-((float)gSddfChSamps[1] - gSddfChOffsets[1] - SDDF_HALF_SCALE_FLT) / SDDF_HALF_SCALE_FLT) * 30.0; + fdbkCurPhA = -fdbkCurPhB - ((-((float)gSddfChSamps[2] - gSddfChOffsets[2] - SDDF_HALF_SCALE_FLT) / SDDF_HALF_SCALE_FLT) * 30.0); + + } + else if (gInferB){ + fdbkCurPhA = (-((float)gSddfChSamps[0] - gSddfChOffsets[0] - SDDF_HALF_SCALE_FLT) / SDDF_HALF_SCALE_FLT) * 30.0; + fdbkCurPhB = -fdbkCurPhA - ((-((float)gSddfChSamps[2] - gSddfChOffsets[2] - SDDF_HALF_SCALE_FLT) / SDDF_HALF_SCALE_FLT) * 30.0); + } + else { + fdbkCurPhA = (-((float)gSddfChSamps[0] - gSddfChOffsets[0] - SDDF_HALF_SCALE_FLT) / SDDF_HALF_SCALE_FLT) * 30.0; + fdbkCurPhB = (-((float)gSddfChSamps[1] - gSddfChOffsets[1] - SDDF_HALF_SCALE_FLT) / SDDF_HALF_SCALE_FLT) * 30.0; + } + + /* Clarke transform */ + arm_clarke_f32(fdbkCurPhA, fdbkCurPhB, &gClarkeAlphaMeasured, &gClarkeBetaMeasured); +#endif + /* Calculate sine and cosine of the electrical angle (elecTheta converted to radians) */ + ti_r5fmath_sincos((elecTheta * TI_R5FMATH_PIOVER180), ti_r5fmath_sincosPIconst, ti_r5fmath_sincosCoef, elecThetaSinCos); + /* Park transform */ + arm_park_f32(gClarkeAlphaMeasured, gClarkeBetaMeasured, &parkIdMeasured, &parkIqMeasured, elecThetaSinCos[0], elecThetaSinCos[1]); + +// Open loop Iq +#if (BUILDLEVEL == OPEN_LOOP_IQ_ID) + if(gIq < IQ_TESTING) + gIq += 0.01; + + parkIdOut = 0.0; + parkIqOut = gIq; + +#if defined(USE_PURE_OPEN_LOOP)||defined(USE_OPEN_LOOP_WITH_SDDF) + myMechTheta += myMechDelta; + + if (myMechTheta>359.9999) + myMechTheta = 0.0; +#endif +#endif +//Closed loop Iq and Id tuning +#if (BUILDLEVEL == CLOSED_LOOP_IQ_ID) + gIqTarget = 0.5; ///gIqArray[count]; + gIqSetPoint = gIqTarget; + + if((gPruEncoderIrqCnt - OFFSET_FINISHED) % CYCLES_PER_TARGET == 0){ + count++; + if(count == 8) + count = 0; + } + + parkIqOut = arm_pi_f32(&gPiIq, gIqSetPoint - parkIqMeasured); + parkIdOut = arm_pi_f32(&gPiId, 0.0 - parkIdMeasured); + if (parkIqOut>IQ_TESTING) parkIqOut = IQ_TESTING; + if (parkIqOut<-1.0*IQ_TESTING) parkIqOut = -1.0*IQ_TESTING; + if (parkIdOut>ID_TESTING) parkIdOut = ID_TESTING; + if (parkIdOut<-1.0*ID_TESTING) parkIdOut = -1.0*ID_TESTING; +#endif +//Closed loop speed +#if (BUILDLEVEL == CLOSED_LOOP_SPEED) + gSpdTarget = gCurTargetVelocity[0]; + if(gSpdSetPoint < gSpdTarget) + gSpdSetPoint += MAX_SPD_CHANGE; + else if (gSpdSetPoint > gSpdTarget) + gSpdSetPoint -= MAX_SPD_CHANGE; + + // update the gCurActualVelocity[0] based on the gSpdSetPoint + gCurActualVelocity[0] = (uint32_t)gSpdSetPoint; + + gIqRef = arm_pi_f32(&gPiSpd, gSpdSetPoint - speed); + parkIqOut = arm_pi_f32(&gPiIq, gIqRef - parkIqMeasured); + parkIdOut = arm_pi_f32(&gPiId, 0.0 - parkIdMeasured); + if (parkIqOut>IQ_TESTING) parkIqOut = IQ_TESTING; + if (parkIqOut<-1.0*IQ_TESTING) parkIqOut = -1.0*IQ_TESTING; + if (parkIdOut>ID_TESTING) parkIdOut = ID_TESTING; + if (parkIdOut<-1.0*ID_TESTING) parkIdOut = -1.0*ID_TESTING; +#endif + +//Closed loop CiA402 Data +#if (BUILDLEVEL == CLOSED_LOOP_CIA402) + switch(gTxData.modeOfOperation){ + case CYCLIC_SYNC_POSITION_MODE: + gRxData.actualPosition = (int32_t) (mechTheta * 1000.0); + /* Create a 0-1080 degree reference frame using the multiturn data + * 0-360 is overflow with a counter-clockwise turn + * 360-720 is no overflow condition (same revolution as start point) + * 720-1080 is overflow with a clockwise turn + */ + if (multiTurn == gStartingMultiTurn) /* no overflow, move to center of the reference frame */ + relativeMechTheta = mechTheta + 360; + else if ((multiTurn == (gStartingMultiTurn + 1)) || ((gStartingMultiTurn > 1) && (multiTurn == 0))) /* clockwise overflow */ + relativeMechTheta = mechTheta + 720; + else /* counter-clockwise overflow, leave in the lower end of the reference frame */ + relativeMechTheta = mechTheta; + + gPosTarget = (float) gTxData.targetPosition / 1000.0; + if(gPosSetPoint < gPosTarget) { + gPosSetPoint += MAX_POS_CHANGE; + if (gPosSetPoint > gPosTarget) /* Increment went over the request */ + gPosSetPoint = gPosTarget; + } + else if (gPosSetPoint > gPosTarget) { + gPosSetPoint -= MAX_POS_CHANGE; + if (gPosSetPoint < gPosTarget) /* Decrement went below the request */ + gPosSetPoint = gPosTarget; + } + + /* Move the setpoint to the 360-720 reference frame and compare*/ + gSpdRef = arm_pi_f32(&gPiPos, (gPosSetPoint + 360) - relativeMechTheta); + gIqRef = arm_pi_f32(&gPiSpd, gSpdRef - speed); + parkIqOut = arm_pi_f32(&gPiIq, gIqRef - parkIqMeasured); + parkIdOut = arm_pi_f32(&gPiId, 0.0 - parkIdMeasured); + break; + case CYCLIC_SYNC_VELOCITY_MODE: + gRxData.actualVelocity = (int32_t) (speed * 1000.0); + gSpdTarget = (float) gTxData.targetVelocity / 1000.0; + if(gSpdSetPoint < gSpdTarget) + gSpdSetPoint += MAX_SPD_CHANGE; + else if (gSpdSetPoint > gSpdTarget) + gSpdSetPoint -= MAX_SPD_CHANGE; + + gIqRef = arm_pi_f32(&gPiSpd, gSpdSetPoint - speed); + parkIqOut = arm_pi_f32(&gPiIq, gIqRef - parkIqMeasured); + parkIdOut = arm_pi_f32(&gPiId, 0.0 - parkIdMeasured); + break; + case CYCLIC_SYNC_TORQUE_MODE: + ///gRxData.actualTorque = (int16_t) (parkIqOut * 1000.0); + gIqTarget = (float) gTxData.targetTorque / 1000.0; + gIqSetPoint = gIqTarget; + + parkIqOut = arm_pi_f32(&gPiIq, gIqSetPoint - parkIqMeasured); + parkIdOut = arm_pi_f32(&gPiId, 0.0 - parkIdMeasured); + gRxData.actualTorque = (int16_t) (parkIqOut * 1000.0); + break; + default: + break; + } +#endif + + /* Inverse Park transform */ + arm_inv_park_f32(parkIdOut, parkIqOut, &iparkAlphaOut, &iparkBetaOut, elecThetaSinCos[0], elecThetaSinCos[1]); + /* Space Vector Generation */ + space_vector_f32(iparkAlphaOut, iparkBetaOut, &spcVectAOut, &spcVectBOut, &spcVectCOut); + + /* Write next CMPA values. Swap cmp0 and cmp2 because the HW connect PWM0 to Phase C and PWM2 to Phase A */ + halfPeriod = (float)gEpwmPrdVal / 2.0; +#if defined(SINGLE_AXLE_USE_M1) + writeCmpA(gEpwm0BaseAddr, (uint16_t) ((1 - spcVectCOut) * halfPeriod)); + writeCmpA(gEpwm1BaseAddr, (uint16_t) ((1 - spcVectBOut) * halfPeriod)); + writeCmpA(gEpwm2BaseAddr, (uint16_t) ((1 - spcVectAOut) * halfPeriod)); +#endif +#if defined(SINGLE_AXLE_USE_M2) + writeCmpA(gEpwm0BaseAddr2A, (uint16_t) ((1 - spcVectCOut) * halfPeriod)); + writeCmpA(gEpwm0BaseAddr2B, (uint16_t) ((1 - spcVectCOut) * halfPeriod)); + writeCmpA(gEpwm1BaseAddr2, (uint16_t) ((1 - spcVectBOut) * halfPeriod)); + writeCmpA(gEpwm2BaseAddr2, (uint16_t) ((1 - spcVectAOut) * halfPeriod)); +#endif + asm(" dsb"); + + /* Determine if Phase A or Phase B currents need to be inferred in the next cycle based on the two largest phases */ + gInferA = FALSE; + gInferB = FALSE; + + if (spcVectCOut > spcVectAOut || spcVectCOut > spcVectBOut) { /* If C is larger than either A or B */ + if (spcVectAOut > spcVectBOut) { /* A and C are the largest, infer B in the next cycle */ + gInferB = TRUE; + } + else { /* B and C are the largest, infer A in the next cycle */ + gInferA = TRUE; + } + } + +#if defined(USE_PURE_OPEN_LOOP)||defined(USE_OPEN_LOOP_WITH_SDDF) + gLastMechTheta = myMechTheta; + gLastMultiTurn = 0; +#else + gLastMechTheta = mechTheta; + gLastMultiTurn = multiTurn; +#endif + +#if (DEBUG_LEVEL == DEBUG_BUFFERS_ON) +#if (BUILDLEVEL == OPEN_LOOP_IQ_ID) + gDebugBuff1[gDebugBuffIdx] = spcVectBOut; + ///gDebugBuff2[gDebugBuffIdx] = (uint32_t)spcVectAOut; + ///gDebugBuff3[gDebugBuffIdx] = (uint32_t)gSddfChSamps[0]; +#if defined(USE_PURE_OPEN_LOOP)||defined(USE_OPEN_LOOP_WITH_SDDF) + gDebugBuff3[gDebugBuffIdx] = (uint32_t)gSddfChSamps[3]; ///myMechTheta; +#else + ///gDebugBuff3[gDebugBuffIdx] = mechTheta; +#endif +#endif +#if (BUILDLEVEL == CLOSED_LOOP_IQ_ID) + gDebugBuff1[gDebugBuffIdx] = spcVectBOut; + ///gDebugBuff2[gDebugBuffIdx] = parkIqMeasured; + ///gDebugBuff3[gDebugBuffIdx] = parkIdMeasured; +#endif +#if (BUILDLEVEL == CLOSED_LOOP_SPEED) + ///gDebugBuff1[gDebugBuffIdx] = spcVectBOut; ///speed; ///gClarkeBetaMeasured; + ///gDebugBuff2[gDebugBuffIdx] = spcVectAOut; ///parkIdOut; ///parkIqMeasured; + gDebugBuff0[gDebugBuffIdx] = (uint32_t)gSddfChSamps[0]; + gDebugBuff1[gDebugBuffIdx] = (uint32_t)mechTheta; +#endif +#endif + +#if (PID_TUNE_LEVEL == NO_TUNING) /* No tuning */ +#if (DEBUG_LEVEL == DEBUG_BUFFERS_ON) +#if (DEBUG_WRAP_TYPE == DEBUG_BUFFER_WRAP) /* No tuning, wrap buffer */ + /* debug, update capture buffers index */ + gDebugBuffIdx++; + if (gDebugBuffIdx >= DEBUG_BUFF_SZ) { + gDebugBuffIdx = 0; + } +#elif (DEBUG_WRAP_TYPE == DEBUG_BUFFER_SINGLE) /* No tuning, single buffer store */ + + /* debug, update capture buffers index */ + gDebugBuffIdx++; + if (gDebugBuffIdx >= DEBUG_BUFF_SZ) { + gDebugBuffIdx = DEBUG_BUFF_SZ - 1; + } +#endif +#endif +#endif + } + /* Calculate mechanical/electrical angle offset */ + else { + /* Get the latest mechanical theta from the encoder */ +#if defined(SINGLE_AXLE_USE_M1) + if (localEnDatGetSingleMulti(&mechTheta, &multiTurn, 0) != 0) + { + gEncErrCnt++; + return; + } + gPruEncoderIrqCnt_after++; +#endif +#if defined(SINGLE_AXLE_USE_M2) + localEnDatGetSingleMulti(&mechTheta, &multiTurn, 2); +#endif + if (gPruEncoderIrqCnt > SETTLING_COUNT) +#if defined(USE_PURE_OPEN_LOOP)||defined(USE_OPEN_LOOP_WITH_SDDF) + gMechAngleOffset += myMechTheta; +#else + gMechAngleOffset += mechTheta; +#endif + if (gPruEncoderIrqCnt == OFFSET_FINISHED) { + gMechAngleOffset /= SETTLING_COUNT; + while (gMechAngleOffset > 90) + gMechAngleOffset -= 90; + + /* Electrical Angle offset complete, turn off all phases */ + computeCmpx(0.001, gEpwmPrdVal, &dc0, &cmp0); + computeCmpx(-0.001, gEpwmPrdVal, &dc1, &cmp1); + computeCmpx(-0.001, gEpwmPrdVal, &dc2, &cmp2); + + /* Write next CMPA values. Swap cmp0 and cmp2 because the HW connect PWM0 to Phase C and PWM2 to Phase A */ +#if defined(SINGLE_AXLE_USE_M1) + writeCmpA(gEpwm0BaseAddr, cmp2); + writeCmpA(gEpwm1BaseAddr, cmp1); + writeCmpA(gEpwm2BaseAddr, cmp0); +#endif +#if defined(SINGLE_AXLE_USE_M2) + writeCmpA(gEpwm0BaseAddr2A, cmp2); + writeCmpA(gEpwm0BaseAddr2B, cmp2); + writeCmpA(gEpwm1BaseAddr2, cmp1); + writeCmpA(gEpwm2BaseAddr2, cmp0); +#endif + +#if defined(USE_PURE_OPEN_LOOP)||defined(USE_OPEN_LOOP_WITH_SDDF) + gLastMechTheta = myMechTheta; + gLastMultiTurn = 0; + gStartingMultiTurn = 0; + + /* Set initial position information */ + gPosSetPoint = myMechTheta; + gTxData.targetPosition = myMechTheta; +#else + gLastMechTheta = mechTheta; + gLastMultiTurn = multiTurn; + gStartingMultiTurn = multiTurn; + + /* Set initial position information */ + gPosSetPoint = mechTheta; + gTxData.targetPosition = mechTheta; +#endif + } + } + } +} +#endif + +#ifdef SINGLE_AXLE_USE_M2 +uint32_t gEncErrCnt2 = 0; +__attribute__((section(".critical_code"))) void pruEncoderIrqHandler2(void *args); +__attribute__((section(".gEtherCatCia402"))) int32_t gCurTargetVelocity[3]; +__attribute__((section(".gEtherCatCia402"))) int32_t gCurActualVelocity[3]; +__attribute__((section(".critical_code"))) void pruEncoderIrqHandler2(void *args) +{ + float32_t fdbkCurPhA, fdbkCurPhB; + float32_t mechTheta, elecTheta; + uint16_t multiTurn = 0; + float32_t elecThetaSinCos[2]; + float32_t parkIdOut, parkIqOut, parkIdMeasured, parkIqMeasured; + float32_t iparkAlphaOut, iparkBetaOut; + float32_t spcVectAOut, spcVectBOut, spcVectCOut; + float dc0, dc1, dc2; /* EPWM duty cycle values */ + uint16_t cmp0, cmp1, cmp2; /* EPWM CMPA values */ + float speed, angleDelta; + float halfPeriod; + + /* Hard-coded for now to trigger the EnDat reading twice, not benchmarked because this should be moved to the PRU in the future */ +#if 0 + if(gLastEnDatCMP2 == 2897) { + HW_WR_REG32(0x3002E098, 5897); + gLastEnDatCMP2 = 5897; + } + else { + HW_WR_REG32(0x3002E098, 2897); + gLastEnDatCMP2 = 2897; + } +#endif + /* Clear interrupt at source */ + PRUICSS_clearEvent(gPruIcss0Handle, ENDAT_EVENT+2); + +#if defined(USE_PURE_OPEN_LOOP) + gSDDFOffsetComplete2 = TRUE; + gPruEncoderIrqCnt2 = OFFSET_FINISHED+1; +#endif + + if (gSDDFOffsetComplete2) { + /* debug, increment PRU SDDF IRQ count */ + gPruEncoderIrqCnt2++; + + /* Start FOC loop and unlock the rotor */ + if (gPruEncoderIrqCnt2 > OFFSET_FINISHED) { +#if !defined(USE_PURE_OPEN_LOOP)&&!defined(USE_OPEN_LOOP_WITH_SDDF) + /* Get the latest mechanical theta and multi-turn position from the encoder */ + if (localEnDatGetSingleMulti(&mechTheta, &multiTurn, 2) != 0) + { + gEncErrCnt2++; + return; + } + gPruEncoderIrqCnt2_after++; +#endif + /* Use calculated offset from electrical 0, 4 pole pairs */ +#if defined(USE_PURE_OPEN_LOOP)||defined(USE_OPEN_LOOP_WITH_SDDF) + elecTheta = myMechTheta2 - gMechAngleOffset; +#else + elecTheta = mechTheta - gMechAngleOffset; +#endif + if(elecTheta < 0) + elecTheta += 90; + elecTheta *= 4.0; + + /* ti_r5fmath_sincos expects input in the range of 0-2pi radians so normalize here to 0-360 degrees */ + while (elecTheta > 360.0) + elecTheta -= 360.0; + +#if defined(USE_PURE_OPEN_LOOP)||defined(USE_OPEN_LOOP_WITH_SDDF) + angleDelta = myMechTheta2 - gLastMechTheta; +#else + angleDelta = mechTheta - gLastMechTheta; +#endif + /* Max angle change per period @ 3200RPMs with 50KHz period should be 0.384 degrees, outside that is rollover + * Use 5 as the bound to provide plenty of room for max acceleration cases */ + if (angleDelta < -50) + angleDelta += 360; + else if (angleDelta > 50) + angleDelta -= 360; + + /* Compute instantaneous RPMs using the change in angle and the PWM frequency */ + speed = (angleDelta / 360.0) / (ISR_PRD_IN_MINUTES); + +#if (PRECOMPUTE_LEVEL == NO_PRECOMPUTE) + /* Try to avoid the INA240 switching noise by selecting the 2 phases with the largest duty cycles */ + if (gInferA) { + fdbkCurPhB = (-((float)gSddfChSamps[1] - gSddfChOffsets2[1] - SDDF_HALF_SCALE_FLT) / SDDF_HALF_SCALE_FLT) * 30.0; + fdbkCurPhA = -fdbkCurPhB - ((-((float)gSddfChSamps[2] - gSddfChOffsets2[2] - SDDF_HALF_SCALE_FLT) / SDDF_HALF_SCALE_FLT) * 30.0); + + } + else if (gInferB){ + fdbkCurPhA = (-((float)gSddfChSamps[0] - gSddfChOffsets2[0] - SDDF_HALF_SCALE_FLT) / SDDF_HALF_SCALE_FLT) * 30.0; + fdbkCurPhB = -fdbkCurPhA - ((-((float)gSddfChSamps[2] - gSddfChOffsets2[2] - SDDF_HALF_SCALE_FLT) / SDDF_HALF_SCALE_FLT) * 30.0); + } + else { + fdbkCurPhA = (-((float)gSddfChSamps[0] - gSddfChOffsets2[0] - SDDF_HALF_SCALE_FLT) / SDDF_HALF_SCALE_FLT) * 30.0; + fdbkCurPhB = (-((float)gSddfChSamps[1] - gSddfChOffsets2[1] - SDDF_HALF_SCALE_FLT) / SDDF_HALF_SCALE_FLT) * 30.0; + } + +#if defined(USE_RTLIB_FOC) + CLARKE_run_twoInput(fdbkCurPhA, fdbkCurPhB, &gClarkeAlphaMeasured, &gClarkeBetaMeasured); +#else + /* Clarke transform */ + arm_clarke_f32(fdbkCurPhA, fdbkCurPhB, &gClarkeAlphaMeasured, &gClarkeBetaMeasured); +#endif +#endif + /* Calculate sine and cosine of the electrical angle (elecTheta converted to radians) */ + ti_r5fmath_sincos((elecTheta * TI_R5FMATH_PIOVER180), ti_r5fmath_sincosPIconst, ti_r5fmath_sincosCoef, elecThetaSinCos); +#if defined(USE_RTLIB_FOC) + PARK_run( elecThetaSinCos[0], elecThetaSinCos[1], gClarkeAlphaMeasured, gClarkeBetaMeasured, &parkIdMeasured, &parkIqMeasured); +#else + /* Park transform */ + arm_park_f32(gClarkeAlphaMeasured, gClarkeBetaMeasured, &parkIdMeasured, &parkIqMeasured, elecThetaSinCos[0], elecThetaSinCos[1]); +#endif + +// Open loop Iq +#if (BUILDLEVEL == OPEN_LOOP_IQ_ID) + if(gIq < IQ_TESTING) + gIq += 0.01; + + parkIdOut = 0.0; + parkIqOut = gIq; + +#if defined(USE_PURE_OPEN_LOOP)||defined(USE_OPEN_LOOP_WITH_SDDF) + myMechTheta2 += myMechDelta2; + + if (myMechTheta2>359.9999) + myMechTheta2 = 0.0; + +#endif +#endif +//Closed loop Iq and Id tuning +#if (BUILDLEVEL == CLOSED_LOOP_IQ_ID) + gIqTarget = 0.5; ///gIqArray[count]; + gIqSetPoint = gIqTarget; + + ///if((gPruEncoderIrqCnt - OFFSET_FINISHED) % CYCLES_PER_TARGET == 0){ + /// count++; + /// if(count == 8) + /// count = 0; + ///} + + parkIqOut = arm_pi_f32(&gPiIq, gIqSetPoint - parkIqMeasured); + parkIdOut = arm_pi_f32(&gPiId, 0.0 - parkIdMeasured); + if (parkIqOut>IQ_TESTING) parkIqOut = IQ_TESTING; + if (parkIqOut<-1.0*IQ_TESTING) parkIqOut = -1.0*IQ_TESTING; + if (parkIdOut>ID_TESTING) parkIdOut = ID_TESTING; + if (parkIdOut<-1.0*ID_TESTING) parkIdOut = -1.0*ID_TESTING; +#endif +//Closed loop speed +#if (BUILDLEVEL == CLOSED_LOOP_SPEED) + gSpdTarget = gCurTargetVelocity[1]; + if(gSpdSetPoint < gSpdTarget) + gSpdSetPoint += MAX_SPD_CHANGE; + else if (gSpdSetPoint > gSpdTarget) + gSpdSetPoint -= MAX_SPD_CHANGE; + + // update the gCurActualVelocity[1] based on gSpdSetPoint + gCurActualVelocity[1] = (uint32_t)gSpdSetPoint; + + gIqRef = arm_pi_f32(&gPiSpd, gSpdSetPoint - speed); + parkIqOut = arm_pi_f32(&gPiIq, gIqRef - parkIqMeasured); + parkIdOut = arm_pi_f32(&gPiId, 0.0 - parkIdMeasured); + if (parkIqOut>IQ_TESTING) parkIqOut = IQ_TESTING; + if (parkIqOut<-1.0*IQ_TESTING) parkIqOut = -1.0*IQ_TESTING; + if (parkIdOut>ID_TESTING) parkIdOut = ID_TESTING; + if (parkIdOut<-1.0*ID_TESTING) parkIdOut = -1.0*ID_TESTING; +#endif +#if defined(USE_RTLIB_FOC) + /* Inverse Park transform */ + IPARK_run(elecThetaSinCos[0], elecThetaSinCos[1], parkIdOut, parkIqOut, &iparkAlphaOut, &iparkBetaOut); + /* Space Vector Generation */ + SVGEN_run(1.0f, iparkAlphaOut, iparkBetaOut, &spcVectAOut, &spcVectBOut, &spcVectCOut); +#else + /* Inverse Park transform */ + arm_inv_park_f32(parkIdOut, parkIqOut, &iparkAlphaOut, &iparkBetaOut, elecThetaSinCos[0], elecThetaSinCos[1]); + /* Space Vector Generation */ + space_vector_f32(iparkAlphaOut, iparkBetaOut, &spcVectAOut, &spcVectBOut, &spcVectCOut); +#endif + + /* Write next CMPA values. Swap cmp0 and cmp2 because the HW connect PWM0 to Phase C and PWM2 to Phase A */ + halfPeriod = (float)gEpwmPrdVal / 2.0; +#if defined(SINGLE_AXLE_USE_M1) + writeCmpA(gEpwm0BaseAddr, (uint16_t) ((1 - spcVectCOut) * halfPeriod)); + writeCmpA(gEpwm1BaseAddr, (uint16_t) ((1 - spcVectBOut) * halfPeriod)); + writeCmpA(gEpwm2BaseAddr, (uint16_t) ((1 - spcVectAOut) * halfPeriod)); +#endif +#if defined(SINGLE_AXLE_USE_M2) +#if defined(USE_RTLIB_FOC) + writeCmpA(gEpwm0BaseAddr2A, (uint16_t) ((1 + spcVectCOut) * halfPeriod)); + writeCmpA(gEpwm0BaseAddr2B, (uint16_t) ((1 + spcVectCOut) * halfPeriod)); + writeCmpA(gEpwm1BaseAddr2, (uint16_t) ((1 + spcVectBOut) * halfPeriod)); + writeCmpA(gEpwm2BaseAddr2, (uint16_t) ((1 + spcVectAOut) * halfPeriod)); +#else + writeCmpA(gEpwm0BaseAddr2A, (uint16_t) ((1 - spcVectCOut) * halfPeriod)); + writeCmpA(gEpwm0BaseAddr2B, (uint16_t) ((1 - spcVectCOut) * halfPeriod)); + writeCmpA(gEpwm1BaseAddr2, (uint16_t) ((1 - spcVectBOut) * halfPeriod)); + writeCmpA(gEpwm2BaseAddr2, (uint16_t) ((1 - spcVectAOut) * halfPeriod)); +#endif +#endif + asm(" dsb"); + + /* Determine if Phase A or Phase B currents need to be inferred in the next cycle based on the two largest phases */ + gInferA = FALSE; + gInferB = FALSE; + + if (spcVectCOut > spcVectAOut || spcVectCOut > spcVectBOut) { /* If C is larger than either A or B */ + if (spcVectAOut > spcVectBOut) { /* A and C are the largest, infer B in the next cycle */ + gInferB = TRUE; + } + else { /* B and C are the largest, infer A in the next cycle */ + gInferA = TRUE; + } + } + +#if defined(USE_PURE_OPEN_LOOP)||defined(USE_OPEN_LOOP_WITH_SDDF) + gLastMechTheta = myMechTheta2; + gLastMultiTurn = 0; +#else + gLastMechTheta = mechTheta; + gLastMultiTurn = multiTurn; +#endif + +#if (DEBUG_LEVEL == DEBUG_BUFFERS_ON) +#if (BUILDLEVEL == OPEN_LOOP_IQ_ID) + ///gDebugBuff1[gDebugBuffIdx] = spcVectBOut; ///(uint32_t)gSddfChSamps[4]; + ///gDebugBuff2[gDebugBuffIdx] = spcVectAOut; ///(uint32_t)gSddfChSamps[5]; +#if defined(USE_PURE_OPEN_LOOP)||defined(USE_OPEN_LOOP_WITH_SDDF) + gDebugBuff3[gDebugBuffIdx] = (uint32_t)gSddfChSamps[3]; ///myMechTheta; +#else + gDebugBuff3[gDebugBuffIdx] = spcVectCOut; +#endif +#endif +#if (BUILDLEVEL == CLOSED_LOOP_IQ_ID) + ///gDebugBuff1[gDebugBuffIdx] = parkIqOut; ///gClarkeBetaMeasured; + ///gDebugBuff2[gDebugBuffIdx] = fdbkCurPhA; ///parkIqMeasured; + gDebugBuff3[gDebugBuffIdx] = spcVectCOut; ///parkIdMeasured; +#endif +#if (BUILDLEVEL == CLOSED_LOOP_SPEED) + ///gDebugBuff1[gDebugBuffIdx] = parkIqOut; ///gClarkeBetaMeasured; + ///gDebugBuff2[gDebugBuffIdx] = parkIdOut; ///parkIqMeasured; + gDebugBuff2[gDebugBuffIdx] = (uint32_t)gSddfChSamps[3]; + gDebugBuff3[gDebugBuffIdx] = (uint32_t)mechTheta; +#endif +#endif + +#if (PID_TUNE_LEVEL == NO_TUNING) /* No tuning */ +#if (DEBUG_LEVEL == DEBUG_BUFFERS_ON) +#if (DEBUG_WRAP_TYPE == DEBUG_BUFFER_WRAP) /* No tuning, wrap buffer */ + /* debug, update capture buffers index */ + gDebugBuffIdx++; + if (gDebugBuffIdx >= DEBUG_BUFF_SZ) { + gDebugBuffIdx = 0; + } +#elif (DEBUG_WRAP_TYPE == DEBUG_BUFFER_SINGLE) /* No tuning, single buffer store */ + + /* debug, update capture buffers index */ + gDebugBuffIdx++; + if (gDebugBuffIdx >= DEBUG_BUFF_SZ) { + gDebugBuffIdx = DEBUG_BUFF_SZ - 1; + } +#endif +#endif +#endif + } + /* Calculate mechanical/electrical angle offset */ + else { + /* Get the latest mechanical theta from the encoder */ +#ifdef SINGLE_AXLE_USE_M1 + localEnDatGetSingleMulti(&mechTheta, &multiTurn, 0); +#endif +#ifdef SINGLE_AXLE_USE_M2 + if (localEnDatGetSingleMulti(&mechTheta, &multiTurn, 2) != 0) + { + gEncErrCnt2++; + return; + } + gPruEncoderIrqCnt2_after++; +#endif + if (gPruEncoderIrqCnt2 > SETTLING_COUNT) +#if defined(USE_PURE_OPEN_LOOP)||defined(USE_OPEN_LOOP_WITH_SDDF) + gMechAngleOffset += myMechTheta; +#else + gMechAngleOffset += mechTheta; +#endif + if (gPruEncoderIrqCnt2 == OFFSET_FINISHED) { + gMechAngleOffset /= SETTLING_COUNT; + while (gMechAngleOffset > 90) + gMechAngleOffset -= 90; + + /* Electrical Angle offset complete, turn off all phases */ + computeCmpx(0.001, gEpwmPrdVal, &dc0, &cmp0); + computeCmpx(-0.001, gEpwmPrdVal, &dc1, &cmp1); + computeCmpx(-0.001, gEpwmPrdVal, &dc2, &cmp2); + + /* Write next CMPA values. Swap cmp0 and cmp2 because the HW connect PWM0 to Phase C and PWM2 to Phase A */ +#if defined(SINGLE_AXLE_USE_M1) + writeCmpA(gEpwm0BaseAddr, cmp2); + writeCmpA(gEpwm1BaseAddr, cmp1); + writeCmpA(gEpwm2BaseAddr, cmp0); +#endif +#if defined(SINGLE_AXLE_USE_M2) + writeCmpA(gEpwm0BaseAddr2A, cmp2); + writeCmpA(gEpwm0BaseAddr2B, cmp2); + writeCmpA(gEpwm1BaseAddr2, cmp1); + writeCmpA(gEpwm2BaseAddr2, cmp0); +#endif + +#if defined(USE_PURE_OPEN_LOOP)||defined(USE_OPEN_LOOP_WITH_SDDF) + gLastMechTheta = myMechTheta2; + gLastMultiTurn = 0; + gStartingMultiTurn = 0; + + /* Set initial position information */ + gPosSetPoint = myMechTheta2; + gTxData.targetPosition = myMechTheta2; +#else + gLastMechTheta = mechTheta; + gLastMultiTurn = multiTurn; + gStartingMultiTurn = multiTurn; + + /* Set initial position information */ + gPosSetPoint = mechTheta; + gTxData.targetPosition = mechTheta; +#endif + } + } + } +} +#endif + +#endif + +#if defined(SINGLE_AXLE_USE_M1) +void init_encoder(){ + int i, j; + HwiP_Params hwiPrms; + int32_t status; + struct cmd_supplement cmd_supplement; + + uint64_t icssgclk; + + void *pruss_cfg; + void *pruss_iep; + +#ifdef SDDF_HW_EVM_ADAPTER_BP + /* Configure g_mux_en to 0 in ICSSG_SA_MX_REG Register. */ + ///HW_WR_REG32((CSL_PRU_ICSSG0_PR1_CFG_SLV_BASE+0x40), (0x00)); + HW_WR_REG32((CSL_PRU_ICSSG0_PR1_CFG_SLV_BASE+0x40), (0x80)); +#endif + i = endat_get_fw_version(); + + // set initial velocity for 1st motor + gCurTargetVelocity[0] = MAX_SPD_RPM; + gCurActualVelocity[0] = MAX_SPD_RPM; + + DebugP_log("\n\n\n"); + DebugP_log("EnDat firmware \t: %x.%x.%x (%s)\n\n", (i >> 24) & 0x7F, + (i >> 16) & 0xFF, i & 0xFFFF, i & (1 << 31) ? "internal" : "release"); + +#ifdef SINGLE_AXLE_USE_M1 + /* Register & enable ICSSG EnDat PRU FW interrupt */ + HwiP_Params_init(&hwiPrms); + hwiPrms.intNum = ICSSG_PRU_ENDAT_INT_NUM; + hwiPrms.callback = &pruEncoderIrqHandler; + hwiPrms.args = 0; + hwiPrms.isPulse = FALSE; + hwiPrms.isFIQ = FALSE; + status = HwiP_construct(&gIcssgEncoderHwiObject, &hwiPrms); + DebugP_assert(status == SystemP_SUCCESS); +#endif +#ifdef SINGLE_AXLE_USE_M2 + /* Register & enable ICSSG EnDat PRU FW interrupt */ + HwiP_Params_init(&hwiPrms); + hwiPrms.intNum = ICSSG_PRU_ENDAT_INT_NUM + 2; + hwiPrms.callback = &pruEncoderIrqHandler2; + hwiPrms.args = 0; + hwiPrms.isPulse = FALSE; + hwiPrms.isFIQ = FALSE; + status = HwiP_construct(&gIcssgEncoderHwiObject2, &hwiPrms); + DebugP_assert(status == SystemP_SUCCESS); +#endif + + gPruIcss0Handle = PRUICSS_open(CONFIG_PRU_ICSS0); + + /* Set in constant table C30 to shared RAM 0x40300000 */ + PRUICSS_setConstantTblEntry(gPruIcss0Handle, PRUICSS_PRUx, PRUICSS_CONST_TBL_ENTRY_C30, ((0x40300000 & 0x00FFFF00) >> 8)); + + /* clear ICSS0 PRU1 data RAM */ + PRUICSS_initMemory(gPruIcss0Handle, PRUICSS_DATARAM(PRUICSS_PRUx)); + + PRUICSS_disableCore(gPruIcss0Handle, PRUICSS_PRUx); + + /* Select multi-channel */ + gEndat_is_multi_ch = 1; + /* Select the EnDat channel */ +#ifdef SINGLE_AXLE_USE_M1 +#ifdef DUAL_AXIS_USE_M1_M2 + /* for dual motor drive mode */ + gEndat_multi_ch_mask = ENDAT_MULTI_CH0|ENDAT_MULTI_CH2; +#else + gEndat_multi_ch_mask = ENDAT_MULTI_CH0; +#endif +#endif + +#ifdef SINGLE_AXLE_USE_M2 + gEndat_multi_ch_mask = ENDAT_MULTI_CH2; +#endif + + + + + gEndat_is_multi_ch = CONFIG_ENDAT0_MODE & 1; + gEndat_is_load_share_mode = CONFIG_ENDAT0_MODE & 2; + endat_pre_init(); + + if(gEndat_is_multi_ch || gEndat_is_load_share_mode) + { + gEndat_multi_ch_mask=(CONFIG_ENDAT0_CHANNEL0<<0|CONFIG_ENDAT0_CHANNEL1<<1|CONFIG_ENDAT0_CHANNEL2<<2); + + DebugP_log("\r\nchannels %s %s %s selected\n", + gEndat_multi_ch_mask & ENDAT_MULTI_CH0 ? "0" : "", + gEndat_multi_ch_mask & ENDAT_MULTI_CH1 ? "1" : "", + gEndat_multi_ch_mask & ENDAT_MULTI_CH2 ? "2" : ""); + + if(!gEndat_multi_ch_mask) + { + DebugP_log("\r\nERROR: please select channels to be used in multi channel configuration -\n\n"); + DebugP_log("\rexit %s as no channel selected in multichannel configuration\n", + __func__); + return; + } + } + else + { + + i = CONFIG_ENDAT0_CHANNEL0 & 0; + + i += CONFIG_ENDAT0_CHANNEL1; + + i += CONFIG_ENDAT0_CHANNEL2<<1; + + if(i < 0 || i > 2) + { + DebugP_log("\r\nWARNING: invalid channel selected, defaulting to Channel 0\n"); + i = 0; + } + } + + pruss_cfg = (void *)(((PRUICSS_HwAttrs *)(gPruIcssXHandle->hwAttrs))->cfgRegBase); + pruss_iep = (void *)(((PRUICSS_HwAttrs *)(gPruIcssXHandle->hwAttrs))->iep0RegBase); + + /*Translate the TCM local view addr to globel view addr */ + uint64_t gEndatChInfoGlobalAddr = CPU0_BTCM_SOCVIEW((uint64_t)&gEndatChInfo); + + priv = endat_init((struct endat_pruss_xchg *)((PRUICSS_HwAttrs *)( + gPruIcssXHandle->hwAttrs))->pru1DramBase, &gEndatChInfo, gEndatChInfoGlobalAddr, pruss_cfg, pruss_iep, PRUICSS_SLICEx); + + if(gEndat_is_multi_ch || gEndat_is_load_share_mode) + { + endat_config_multi_channel_mask(priv, gEndat_multi_ch_mask, gEndat_is_load_share_mode); + } + else + { + endat_config_channel(priv, i); + } + + endat_config_host_trigger(priv); + + /* Read the ICSSG configured clock frequency. */ + if(gPruIcssXHandle->hwAttrs->instance) + { + SOC_moduleGetClockFrequency(TISCI_DEV_PRU_ICSSG1, TISCI_DEV_PRU_ICSSG1_CORE_CLK, &icssgclk); + } + else + { + SOC_moduleGetClockFrequency(TISCI_DEV_PRU_ICSSG0, TISCI_DEV_PRU_ICSSG0_CORE_CLK, &icssgclk); + } + + /* Configure Delays based on the ICSSG frequency*/ + /* Count = ((required delay * icssgclk)/1000) */ + priv->pruss_xchg->endat_delay_125ns = ((icssgclk*125)/1000000000); + priv->pruss_xchg->endat_delay_51us = ((icssgclk*51)/1000000 ); + priv->pruss_xchg->endat_delay_5us = ((icssgclk*5)/1000000); + priv->pruss_xchg->endat_delay_1ms = ((icssgclk/1000) * 1); + priv->pruss_xchg->endat_delay_2ms = ((icssgclk/1000) * 2); + priv->pruss_xchg->endat_delay_12ms = ((icssgclk/1000) * 12); + priv->pruss_xchg->endat_delay_50ms = ((icssgclk/1000) * 50); + priv->pruss_xchg->endat_delay_380ms = ((icssgclk/1000) * 380); + priv->pruss_xchg->endat_delay_900ms = ((icssgclk/1000) * 900); + priv->pruss_xchg->icssg_clk = icssgclk; + + + + i = endat_pruss_load_run_fw(priv); + + if (i < 0) + { + DebugP_log("\rERROR: EnDat initialization failed -\n\n"); + + if(gEndat_is_multi_ch) + { + unsigned char tmp; + + tmp = endat_multi_channel_detected(priv) & gEndat_multi_ch_mask; + tmp ^= gEndat_multi_ch_mask; + DebugP_log("\r\tunable to detect encoder in channel %s %s %s\n", + tmp & ENDAT_MULTI_CH0 ? "0" : "", + tmp & ENDAT_MULTI_CH1 ? "1" : "", + tmp & ENDAT_MULTI_CH2 ? "2" : ""); + } + else + { + DebugP_log("\r\tcheck whether encoder is connected and ensure proper connections\n"); + } + + DebugP_log("\rexit %s due to failed firmware initialization\n", __func__); + return; + } + + /* read encoder info at low frequency so that cable length won't affect */ + endat_init_clock(200*1000, priv); + + for(j = 0; j < 3; j++) + { + if(gEndat_multi_ch_mask & 1 << j) + { + endat_multi_channel_set_cur(priv, j); + + if(endat_get_encoder_info(priv) < 0) + { + DebugP_log("\rEnDat initialization channel %d failed\n", j); + DebugP_log("\rexit %s due to failed initialization\n", __func__); + return; + } + + gEndat_prop_delay[priv->channel] = endat_get_prop_delay(priv); + DebugP_log("\n\t\t\t\tCHANNEL %d\n\n", j); + endat_print_encoder_info(priv); + } + } + + /* pass the encoder step to the R5F_0_1 */ + priv_step = priv->step; + + gEndat_prop_delay_max = gEndat_prop_delay[0] > gEndat_prop_delay[1] ? + gEndat_prop_delay[0] : gEndat_prop_delay[1]; + gEndat_prop_delay_max = gEndat_prop_delay_max > gEndat_prop_delay[2] ? + gEndat_prop_delay_max : gEndat_prop_delay[2]; + +#if 0 + /* default frequency - 16MHz for 2.2 encoders, 1MHz for 2.1 encoders */ + endat_init_clock(16 * 1000 * 1000, priv); + /* JR: Hard code propagation delay to make 16MHz work @300MHz PRU */ + endat_handle_prop_delay(priv, 265); +#else + /* default frequency - 8MHz for 2.2 encoders, 1MHz for 2.1 encoders */ + endat_init_clock(8 * 1000 * 1000, priv); + /* JR: Hard code propagation delay to make 16MHz work @300MHz PRU */ + endat_handle_prop_delay(priv, 530); +#endif + +#if 0 + /* set to EnDat 2.2 recovery time */ + memset(&cmd_supplement, 0, sizeof(cmd_supplement)); + cmd_supplement.address = 3; + cmd_supplement.data = 1; + endat_command_process(priv, 10, &cmd_supplement); + /* reset encoder */ + endat_command_process(priv, 5, NULL); + endat_addinfo_track(priv, 5, NULL); +#endif + + /* JR: Configures EnDat to trigger based on IEP CMP4 event */ + endat_config_periodic_trigger(priv); + + DebugP_assert(endat_command_process(priv, 8, NULL) >= 0); + + struct endat_periodic_interface endat_periodic_interface; + endat_periodic_interface.pruss_cfg = priv->pruss_cfg; + endat_periodic_interface.pruss_iep = priv->pruss_iep; + endat_periodic_interface.pruss_dmem = priv->pruss_xchg; + endat_periodic_interface.load_share = priv->load_share; + endat_periodic_interface.cmp3 = 3000; + endat_periodic_interface.cmp5 = 0; + endat_periodic_interface.cmp6 = 3000; + + status = endat_config_periodic_mode(&endat_periodic_interface, gPruIcssXHandle); + DebugP_assert(0 != status); + +#ifdef SINGLE_AXLE_USE_M1 + endat_multi_channel_set_cur(priv, 0); + DebugP_log("\r|\n|\t\t\t\tCHANNEL %d\n", 0); +#endif +#ifdef SINGLE_AXLE_USE_M2 + endat_multi_channel_set_cur(priv, 2); + DebugP_log("\r|\n|\t\t\t\tCHANNEL %d\n", 2); +#endif + endat_handle_rx(priv, 8); + + DebugP_log("Encoder Channel Init Completed!!!\n"); +} +#endif + +void init_encoder2(){ + HwiP_Params hwiPrms; + int32_t status; + + // set initial velocity for 2nd motor + gCurTargetVelocity[1] = MAX_SPD_RPM; + gCurActualVelocity[1] = MAX_SPD_RPM; +#ifdef SINGLE_AXLE_USE_M2 + /* Register & enable ICSSG EnDat PRU FW interrupt */ + HwiP_Params_init(&hwiPrms); + hwiPrms.intNum = ICSSG_PRU_ENDAT_INT_NUM + 2; + hwiPrms.callback = &pruEncoderIrqHandler2; + hwiPrms.args = 0; + hwiPrms.isPulse = FALSE; + hwiPrms.isFIQ = FALSE; + status = HwiP_construct(&gIcssgEncoderHwiObject2, &hwiPrms); + DebugP_assert(status == SystemP_SUCCESS); +#endif + + DebugP_log("Encoder Channel Init Completed!!!\n"); +} +/* Test Sdfm handles */ +sdfm_handle gHPruSdfm; + +/* Sdfm output samples, written by PRU cores */ +__attribute__((section(".gSdfmSampleOutput"))) uint32_t gSdfm_sampleOutput[NUM_CH_SUPPORTED]; +/* Test SDDF handle */ +sdfm_handle gHSddf; + +#ifdef SDDF_HW_EVM_ADAPTER_BP +/* SDDF PRU FW IRQ handler */ +void pruSddfIrqHandler(void *args) +{ + /* debug, show ISR timing */ + //GPIO_pinWriteHigh(SDDF_DEBUG_BASE_ADDR, SDDF_DEBUG_PIN); + + /* debug, increment PRU SDDF IRQ count */ + gPruSddfIrqCnt++; + if(gPruSddfIrqCnt > SETTLING_COUNT && gPruSddfIrqCnt <= OFFSET_FINISHED){ + gSddfChOffsets2[0] += (int32_t) (gSddfChSamps[0] - SDDF_HALF_SCALE); + gSddfChOffsets2[1] += (int32_t) (gSddfChSamps[1] - SDDF_HALF_SCALE); + gSddfChOffsets2[2] += (int32_t) (gSddfChSamps[2] - SDDF_HALF_SCALE); + + if(gPruSddfIrqCnt == OFFSET_FINISHED) { + float dc0, dc1, dc2; + uint16_t cmp0, cmp1, cmp2; + + gSddfChOffsets2[0] = (gSddfChOffsets2[0] / SETTLING_COUNT); + gSddfChOffsets2[1] = (gSddfChOffsets2[1] / SETTLING_COUNT); + gSddfChOffsets2[2] = (gSddfChOffsets2[2] / SETTLING_COUNT); + + /* ADC offset complete, lock the rotor to electrical 0 */ + computeCmpx(0.167, gEpwmPrdVal, &dc0, &cmp0); + computeCmpx(-0.167, gEpwmPrdVal, &dc1, &cmp1); + computeCmpx(-0.167, gEpwmPrdVal, &dc2, &cmp2); + + /* Write next CMPA values. Swap cmp0 and cmp2 because the HW connect PWM0 to Phase C and PWM2 to Phase A */ + writeCmpA(gEpwm0BaseAddr2A, cmp2); + writeCmpA(gEpwm0BaseAddr2B, cmp2); + writeCmpA(gEpwm1BaseAddr2, cmp1); + writeCmpA(gEpwm2BaseAddr2, cmp0); + gSDDFOffsetComplete2 = TRUE; +#if (PRECOMPUTE_LEVEL == NO_PRECOMPUTE) + HwiP_disableInt(ICSSG_PRU_SDDF_INT_NUM); +#endif + } + + } +#if (PRECOMPUTE_LEVEL == PRECOMPUTE_CLARKE) + /* Offset has been calculated, pull the value and convert to float and scale it */ + else { + float32_t fdbkCurPhA, fdbkCurPhB; + + /* Try to avoid the INA240 switching noise by selecting the 2 phases with the largest duty cycles */ + if (gInferA) { + fdbkCurPhB = (-((float)gSddfChSamps[1] - gSddfChOffsets[1] - SDDF_HALF_SCALE_FLT) / SDDF_HALF_SCALE_FLT) * 30.0; + fdbkCurPhA = -fdbkCurPhB - ((-((float)gSddfChSamps[2] - gSddfChOffsets[2] - SDDF_HALF_SCALE_FLT) / SDDF_HALF_SCALE_FLT) * 30.0); + + } + else if (gInferB){ + fdbkCurPhA = (-((float)gSddfChSamps[0] - gSddfChOffsets[0] - SDDF_HALF_SCALE_FLT) / SDDF_HALF_SCALE_FLT) * 30.0; + fdbkCurPhB = -fdbkCurPhA - ((-((float)gSddfChSamps[2] - gSddfChOffsets[2] - SDDF_HALF_SCALE_FLT) / SDDF_HALF_SCALE_FLT) * 30.0); + } + else { + fdbkCurPhA = (-((float)gSddfChSamps[0] - gSddfChOffsets[0] - SDDF_HALF_SCALE_FLT) / SDDF_HALF_SCALE_FLT) * 30.0; + fdbkCurPhB = (-((float)gSddfChSamps[1] - gSddfChOffsets[1] - SDDF_HALF_SCALE_FLT) / SDDF_HALF_SCALE_FLT) * 30.0; + } + + /* Clarke transform */ + arm_clarke_f32(fdbkCurPhA, fdbkCurPhB, &gClarkeAlphaMeasured, &gClarkeBetaMeasured); + } +#endif + + /* Clear interrupt at source */ + /* Write 18 to ICSSG_STATUS_CLR_INDEX_REG + Firmware: TRIGGER_HOST_SDDF_IRQ defined as 18 + Host: SDDF_EVT defined as TRIGGER_HOST_SDDF_IRQ + 18 = 16+2, 2 is Host Interrupt Number. See AM654x TRM, Table 6-391. + */ + PRUICSS_clearEvent(gPruIcss0Handle, PRU_TRIGGER_HOST_SDFM_EVT); + + /* debug, show ISR timing */ + //GPIO_pinWriteLow(SDDF_DEBUG_BASE_ADDR, SDDF_DEBUG_PIN); +} + +/* SDDF PRU FW IRQ handler */ +void rtuSddfIrqHandler(void *args) +{ + /* debug, increment PRU SDDF IRQ count */ + gRtuSddfIrqCnt++; + + if(gRtuSddfIrqCnt > SETTLING_COUNT && gRtuSddfIrqCnt <= OFFSET_FINISHED){ + gSddfChOffsets[0] += (int32_t) (gSddfChSamps[0] - SDDF_HALF_SCALE); + gSddfChOffsets[1] += (int32_t) (gSddfChSamps[1] - SDDF_HALF_SCALE); + gSddfChOffsets[2] += (int32_t) (gSddfChSamps[2] - SDDF_HALF_SCALE); + + if(gRtuSddfIrqCnt == OFFSET_FINISHED) { + float dc0, dc1, dc2; + uint16_t cmp0, cmp1, cmp2; + + gSddfChOffsets[0] = (gSddfChOffsets[0] / SETTLING_COUNT); + gSddfChOffsets[1] = (gSddfChOffsets[1] / SETTLING_COUNT); + gSddfChOffsets[2] = (gSddfChOffsets[2] / SETTLING_COUNT); + + /* ADC offset complete, lock the rotor to electrical 0 */ + computeCmpx(0.167, gEpwmPrdVal, &dc0, &cmp0); + computeCmpx(-0.167, gEpwmPrdVal, &dc1, &cmp1); + computeCmpx(-0.167, gEpwmPrdVal, &dc2, &cmp2); + + /* Write next CMPA values. Swap cmp0 and cmp2 because the HW connect PWM0 to Phase C and PWM2 to Phase A */ + writeCmpA(gEpwm0BaseAddr, cmp2); + writeCmpA(gEpwm1BaseAddr, cmp1); + writeCmpA(gEpwm2BaseAddr, cmp0); + gSDDFOffsetComplete = TRUE; +#if (PRECOMPUTE_LEVEL == NO_PRECOMPUTE) + HwiP_disableInt(ICSSG_RTU_SDDF_INT_NUM); +#endif + } + + } +#if (PRECOMPUTE_LEVEL == PRECOMPUTE_CLARKE) + /* Offset has been calculated, pull the value and convert to float and scale it */ + else { + float32_t fdbkCurPhA, fdbkCurPhB; + + /* Try to avoid the INA240 switching noise by selecting the 2 phases with the largest duty cycles */ + if (gInferA) { + fdbkCurPhB = (-((float)gSddfChSamps[1] - gSddfChOffsets[1] - SDDF_HALF_SCALE_FLT) / SDDF_HALF_SCALE_FLT) * 30.0; + fdbkCurPhA = -fdbkCurPhB - ((-((float)gSddfChSamps[2] - gSddfChOffsets[2] - SDDF_HALF_SCALE_FLT) / SDDF_HALF_SCALE_FLT) * 30.0); + + } + else if (gInferB){ + fdbkCurPhA = (-((float)gSddfChSamps[0] - gSddfChOffsets[0] - SDDF_HALF_SCALE_FLT) / SDDF_HALF_SCALE_FLT) * 30.0; + fdbkCurPhB = -fdbkCurPhA - ((-((float)gSddfChSamps[2] - gSddfChOffsets[2] - SDDF_HALF_SCALE_FLT) / SDDF_HALF_SCALE_FLT) * 30.0); + } + else { + fdbkCurPhA = (-((float)gSddfChSamps[0] - gSddfChOffsets[0] - SDDF_HALF_SCALE_FLT) / SDDF_HALF_SCALE_FLT) * 30.0; + fdbkCurPhB = (-((float)gSddfChSamps[1] - gSddfChOffsets[1] - SDDF_HALF_SCALE_FLT) / SDDF_HALF_SCALE_FLT) * 30.0; + } + + /* Clarke transform */ + arm_clarke_f32(fdbkCurPhA, fdbkCurPhB, &gClarkeAlphaMeasured, &gClarkeBetaMeasured); + } +#endif + + /* Clear interrupt at source */ + /* Write 18 to ICSSG_STATUS_CLR_INDEX_REG + Firmware: TRIGGER_HOST_SDDF_IRQ defined as 18 + Host: SDDF_EVT defined as TRIGGER_HOST_SDDF_IRQ + 18 = 16+2, 2 is Host Interrupt Number. See AM654x TRM, Table 6-391. + */ + ///PRUICSS_clearEvent(gRtuIcss0Handle, RTU_TRIGGER_HOST_SDFM_EVT); + PRUICSS_clearEvent(gPruIcss0Handle, RTU_TRIGGER_HOST_SDFM_EVT); +} +#endif + +#ifdef SDDF_HW_EVM_ADAPTER_BP +#if defined(SINGLE_AXLE_USE_M1) +void init_sddf(){ + HwiP_Params hwiPrms; + int32_t status; + + /* Configure g_mux_en to PRUICSS_G_MUX_EN in ICSSG_SA_MX_REG Register. */ + HW_WR_REG32((CSL_PRU_ICSSG0_PR1_CFG_SLV_BASE+0x40), PRUICSS_G_MUX_EN); + + /* Configure ICSSG clock selection */ + /*status = cfgIcssgClkCfg(TEST_ICSSG_INST_ID, + CORE_CLK_SEL_ICSSGn_CORE_CLK, + ICSSGn_CORE_CLK_SEL_MAIN_PLL2_HSDIV0_CLKOUT, + ICSSGn_CORE_CLK_FREQ, + IEP_CLK_SEL_CORE_CLK, + 0, //ICSSGn_IEP_CLK_SEL_MAIN_PLL0_HSDIV6_CLKOUT, + 0 //ICSSGn_IEP_CLK_FREQ + ); + if (status != SDDF_ERR_NERR) { + DebugP_log("Error: cfgIcssgClkCfg() fail.\r\n"); + return; + }*/ + + /* Initialize IEP0, configure SYNC0/1 SD clocks */ + init_IEP0_SYNC(); + + /* Initialize ICSSG */ + status = initIcss(TEST_ICSSG_INST_ID, TEST_ICSSG_SLICE_ID, PRUICSS_G_MUX_EN, &gPruIcssHandle); + if (status != SDDF_ERR_NERR) { + DebugP_log("Error: initIcss() fail.\r\n"); + return; + } + + /* Register & enable ICSSG SDDF RTU FW interrupt */ + HwiP_Params_init(&hwiPrms); + hwiPrms.intNum = ICSSG_RTU_SDDF_INT_NUM; + hwiPrms.callback = &rtuSddfIrqHandler; + hwiPrms.args = 0; + hwiPrms.isPulse = FALSE; + hwiPrms.isFIQ = FALSE; + status = HwiP_construct(&gIcssgRtuSddfHwiObject, &hwiPrms); + DebugP_assert(status == SystemP_SUCCESS); + + /* Initialize RTU core for SDDF */ + status = initPruSddf(gPruIcssHandle, TEST_RTU_INST_ID, &gTestSdfmPrms, &gHRtuSddf); + if (status != SDDF_ERR_NERR) { + DebugP_log("Error: initPruSddf() fail.\r\n"); + return; + } + + /* Initialize PRU core for SDDF */ + gTestSdfmPrms.samplesBaseAddress += 0x80; + status = initPruSddf(gPruIcssHandle, TEST_PRU_INST_ID, &gTestSdfmPrms, &gHPruSddf); + if (status != SDDF_ERR_NERR) { + DebugP_log("Error: initPruSddf() fail.\r\n"); + return; + } + + /* Start IEP0 */ + start_IEP0(); + + /* Start EPWM0 clock */ + ///CSL_REG32_WR(CSL_CTRL_MMR0_CFG0_BASE + CSL_MAIN_CTRL_MMR_CFG0_EPWM_TB_CLKEN, 1); + + /* Force SW sync for EPWM0. Other PWMs will be sync'd through HW sync daisy-chain. */ + EPWM_tbTriggerSwSync(gEpwm0BaseAddr); + + /* Enable the PWM output buffer until gate driver configured and PWM signals at 50% duty cycle */ + enable_pwm_buffers(FALSE); +} +#endif + +void init_sddf2(){ + HwiP_Params hwiPrms; + int32_t status; + + /* Register & enable ICSSG PRU SDDF FW interrupt */ + HwiP_Params_init(&hwiPrms); + hwiPrms.intNum = ICSSG_PRU_SDDF_INT_NUM; + hwiPrms.callback = &pruSddfIrqHandler; + hwiPrms.args = 0; + hwiPrms.isPulse = FALSE; + hwiPrms.isFIQ = FALSE; + status = HwiP_construct(&gIcssgPruSddfHwiObject, &hwiPrms); + DebugP_assert(status == SystemP_SUCCESS); +} +#endif + +/* This example shows message exchange between multiple cores. + * + * One of the core is designated as the 'main' core + * and other cores are desginated as `remote` cores. + * + * The main core initiates IPC with remote core's by sending it a message. + * The remote cores echo the same message to the main core. + * + * The main core repeats this for gMsgEchoCount iterations. + * + * In each iteration of message exchange, the message value is incremented. + * + * When iteration count reaches gMsgEchoCount, a semaphore is posted and + * the pending thread/task on that core is unblocked. + * + * When a message or its echo is received, a user registered callback is invoked. + * The message is echoed from within the user callback itself. + * + * This is a example message exchange, in final systems, user can do more + * sophisticated message exchanges as needed for their applications. + */ + +/* number of iterations of message exchange to do */ +uint32_t gMsgEchoCount = 1000000u; +/* client ID that is used to send and receive messages */ +uint32_t gClientId = 4u; +/* main core that starts the message exchange */ +uint32_t gMainCoreId = CSL_CORE_ID_R5FSS1_0; +/* remote cores that echo messages from main core, make sure to NOT list main core in this list */ +uint32_t gRemoteCoreId[] = { + CSL_CORE_ID_R5FSS0_0, + CSL_CORE_ID_MAX /* this value indicates the end of the array */ +}; + +/* semaphore's used to indicate a main core has finished all message exchanges */ +SemaphoreP_Object gMainDoneSem[CSL_CORE_ID_MAX]; + +/* semaphore used to indicate a remote core has finished all message xchange */ +SemaphoreP_Object gRemoteDoneSem; + +void ipc_notify_msg_handler_remote_core(uint32_t remoteCoreId, uint16_t localClientId, uint32_t msgValue, void *args) +{ + /* on remote core, we have registered handler on the same client ID and current core client ID */ + IpcNotify_sendMsg(remoteCoreId, localClientId, msgValue, 1); + + /* if all messages received then post semaphore to exit */ + if(msgValue == (gMsgEchoCount-1)) + { + SemaphoreP_post(&gRemoteDoneSem); + } +} + +#if defined(SINGLE_AXLE_USE_M1) +int32_t rw_drv8350_register(uint16_t r_w, uint16_t reg_addr, uint16_t reg_val, uint16_t* read_val) +{ + MCSPI_Transaction spiTransaction; + uint16_t mcspiTxBuffer, mcspiRxBuffer; + int32_t transferOK; + + /* Initiate SPI transfer parameters */ + spiTransaction.channel = 0U; + spiTransaction.count = 1; + spiTransaction.txBuf = &mcspiTxBuffer; + spiTransaction.rxBuf = &mcspiRxBuffer; + spiTransaction.args = NULL; + + mcspiTxBuffer = r_w | (reg_addr << DRV8350_ADDR_SHIFT) | reg_val; +#ifdef SINGLE_AXLE_USE_M1 + ////GPIO_pinWriteLow(MTR_1_CS_BASE_ADDR, MTR_1_CS_PIN); + transferOK = MCSPI_transfer(gMcspiHandle[CONFIG_MCSPI0], &spiTransaction); + ////GPIO_pinWriteHigh(MTR_1_CS_BASE_ADDR, MTR_1_CS_PIN); +#endif +#ifdef SINGLE_AXLE_USE_M2 + ////GPIO_pinWriteLow(MTR_2_CS_BASE_ADDR, MTR_2_CS_PIN); + transferOK = MCSPI_transfer(gMcspiHandle[CONFIG_MCSPI0], &spiTransaction); + ////GPIO_pinWriteHigh(MTR_2_CS_BASE_ADDR, MTR_2_CS_PIN); +#endif + + if (read_val != NULL) + *read_val = mcspiRxBuffer; + + return transferOK; +} + +int32_t init_drv8350() +{ + int32_t status = SystemP_SUCCESS; + DRV8350_Vars drv8350; + uint16_t reg_vals[6]; + + /* Build the desired register values for the four control registers */ + drv8350.driver_control.all = 0; + drv8350.gate_drive_hs.all = 0; + drv8350.gate_drive_ls.all = 0; + drv8350.ocp_control.all = 0; + + drv8350.driver_control.bit.OCP_ACT = DRV8350_OCP_disable_three_phases; + + drv8350.gate_drive_hs.bit.IDRIVEN_HS = DRV8350_idriveN_600mA; + drv8350.gate_drive_hs.bit.IDRIVEP_HS = DRV8350_idriveP_300mA; + drv8350.gate_drive_hs.bit.LOCK = DRV8350_lock_disable; + + drv8350.gate_drive_ls.bit.CBC = DRV8350_OCP_ClrFaults_Cycle_by_Cycle_Yes; + drv8350.gate_drive_ls.bit.IDRIVEN_LS = DRV8350_idriveN_600mA; + drv8350.gate_drive_ls.bit.IDRIVEP_LS = DRV8350_idriveP_300mA; + drv8350.gate_drive_ls.bit.TDRIVE = DRV8350_tdrive_4000nS; + + drv8350.ocp_control.bit.DEAD_TIME = DRV8350_deadTime_50nS; + drv8350.ocp_control.bit.OCP_MODE = DRV8350_OCP_Latch_Fault; + drv8350.ocp_control.bit.OCP_DEG = DRV8350_deglitch_1us; + drv8350.ocp_control.bit.VDS_LVL = DRV8350_VDS_LVL_1000mV; + + /* Write the control registers */ + rw_drv8350_register(DRV8350_WRITE, DRV8350_DRIVER_CONTROL_ADDR, drv8350.driver_control.all, NULL); + rw_drv8350_register(DRV8350_WRITE, DRV8350_GATE_DRIVE_HS_ADDR, drv8350.gate_drive_hs.all, NULL); + rw_drv8350_register(DRV8350_WRITE, DRV8350_GATE_DRIVE_LS_ADDR, drv8350.gate_drive_ls.all, NULL); + rw_drv8350_register(DRV8350_WRITE, DRV8350_OCP_CONTROL_ADDR, drv8350.ocp_control.all, NULL); + + /* Read back the control registers to check for correctness */ + rw_drv8350_register(DRV8350_READ, DRV8350_DRIVER_CONTROL_ADDR, 0, ®_vals[DRV8350_DRIVER_CONTROL_ADDR]); + rw_drv8350_register(DRV8350_READ, DRV8350_GATE_DRIVE_HS_ADDR, 0, ®_vals[DRV8350_GATE_DRIVE_HS_ADDR]); + rw_drv8350_register(DRV8350_READ, DRV8350_GATE_DRIVE_LS_ADDR, 0, ®_vals[DRV8350_GATE_DRIVE_LS_ADDR]); + rw_drv8350_register(DRV8350_READ, DRV8350_OCP_CONTROL_ADDR, 0, ®_vals[DRV8350_OCP_CONTROL_ADDR]); + + /* Check against desired values */ + if ((drv8350.driver_control.all != reg_vals[DRV8350_DRIVER_CONTROL_ADDR]) || + (drv8350.gate_drive_hs.all != reg_vals[DRV8350_GATE_DRIVE_HS_ADDR]) || + (drv8350.gate_drive_ls.all != reg_vals[DRV8350_GATE_DRIVE_LS_ADDR]) || + (drv8350.ocp_control.all != reg_vals[DRV8350_OCP_CONTROL_ADDR])) { + status = SystemP_FAILURE; + DebugP_log("[Single Chip Servo] DRV8350 configuration failed!\r\n"); + } + else { + DebugP_log("[Single Chip Servo] DRV8350 configured!\r\n"); + } + + /* Lock the control registers of the DRV8350 to ensure there are no accidental writes */ + drv8350.gate_drive_hs.bit.LOCK = DRV8350_lock_enable; + rw_drv8350_register(DRV8350_WRITE, DRV8350_GATE_DRIVE_HS_ADDR, drv8350.gate_drive_hs.all, NULL); + rw_drv8350_register(DRV8350_READ, DRV8350_GATE_DRIVE_HS_ADDR, 0, ®_vals[DRV8350_GATE_DRIVE_HS_ADDR]); + + if (drv8350.gate_drive_hs.all == reg_vals[DRV8350_GATE_DRIVE_HS_ADDR]) + DebugP_log("[Single Chip Servo] DRV8350 Control registers locked!\r\n"); + + return status; +} + +int32_t check_adapter_board_power() +{ + int32_t status = SystemP_SUCCESS; + + /* Check the nRESET_SVS pin to ensure power on the 3-axis board is good */ + ////if(!GPIO_pinRead(NRESET_SVS_BASE_ADDR, NRESET_SVS_PIN)) { + //// DebugP_log("[Single Chip Servo] Adapter board is not powered or 3.3V rail is out of specification.\r\n"); + //// status = SystemP_FAILURE; + ////} + ////else { + //// DebugP_log("[Single Chip Servo] Adapter board power is good.\r\n"); + ////} + + return status; +} + +void init_gpio_state() +{ + /* Set the initial GPIO output state before configuring direction. This avoids ambiguity on outputs. */ + GPIO_pinWriteHigh(MTR_1_PWM_EN_BASE_ADDR, MTR_1_PWM_EN_PIN); + GPIO_pinWriteHigh(MTR_2_PWM_EN_BASE_ADDR, MTR_2_PWM_EN_PIN); + GPIO_pinWriteHigh(BP_MUX_SEL_BASE_ADDR, BP_MUX_SEL_PIN); + GPIO_pinWriteHigh(ENC1_EN_BASE_ADDR, ENC1_EN_PIN); + GPIO_pinWriteHigh(ENC2_EN_BASE_ADDR, ENC2_EN_PIN); + + GPIO_setDirMode(MTR_1_PWM_EN_BASE_ADDR, MTR_1_PWM_EN_PIN, MTR_1_PWM_EN_DIR); + GPIO_setDirMode(MTR_2_PWM_EN_BASE_ADDR, MTR_2_PWM_EN_PIN, MTR_2_PWM_EN_DIR); + GPIO_setDirMode(BP_MUX_SEL_BASE_ADDR, BP_MUX_SEL_PIN, BP_MUX_SEL_DIR); + GPIO_setDirMode(ENC1_EN_BASE_ADDR, ENC1_EN_PIN, ENC1_EN_DIR); + GPIO_setDirMode(ENC2_EN_BASE_ADDR, ENC2_EN_PIN, ENC2_EN_DIR); + +#ifdef SDDF_HW_EVM_ADAPTER_BP + ////GPIO_pinWriteHigh(HDSL_EN_BASE_ADDR, HDSL_EN_PIN); + ////GPIO_setDirMode(HDSL_EN_BASE_ADDR, HDSL_EN_PIN, GPIO_DIRECTION_OUTPUT); +#endif +} +#endif + +#if defined(SDDF_HW_EVM_ADAPTER_BP) +static TCA6424_Config gTCA6424_Config; +void i2c_io_expander(void *args) +{ + int32_t status = SystemP_SUCCESS; + TCA6424_Params tca6424Params; + TCA6424_Params_init(&tca6424Params); + status = TCA6424_open(&gTCA6424_Config, &tca6424Params); + uint32_t ioIndex; + + if(status == SystemP_SUCCESS) + { + /* set IO expander P12 to high */ + ioIndex = 0x0a; + status = TCA6424_setOutput( + &gTCA6424_Config, + ioIndex, + TCA6424_OUT_STATE_HIGH); + + /* Configure as output */ + status += TCA6424_config( + &gTCA6424_Config, + ioIndex, + TCA6424_MODE_OUTPUT); + } + TCA6424_close(&gTCA6424_Config); +} +#endif + +/* GPIO PIN Macros */ +#define GPIO0_BASE_ADDR (CSL_MCU_GPIO0_BASE) +#define GPIO_LED_PIN () +#define GPIO_LED_DIR (GPIO_DIRECTION_OUTPUT) +#define GPIO_LED_TRIG_TYPE (GPIO_TRIG_TYPE_NONE) + +#if defined(SINGLE_AXLE_USE_M1) +void misc_pinmux(){ + /* Sigma Delta pin mux */ + Pinmux_PerCfg_t miscPinMuxCfg[] = { +#if 0 + /* EHRPWM3 pin config */ +#ifdef SINGLE_AXLE_USE_M2 + /* EHRPWM5_A -> GPMC0_BE1n (P21) */ + { + PIN_GPMC0_BE1N, + ( PIN_MODE(3) | PIN_PULL_DISABLE ) + }, +#endif +#if defined(SDDF_HW_EVM_ADAPTER_BP) + /* PRG0_PRU0_GPO19, PRG0_IEP0_EDC_SYNC_OUT0, W1, BP J5.45 */ + { + PIN_PRG0_PRU0_GPO19, + ( PIN_MODE(2) | PIN_PULL_DISABLE ) + }, + /* PRG0_PRU0_GPO17, PRG0_IEP0_EDC_SYNC_OUT1, U1, BP J2.18 */ + { + PIN_PRG0_PRU0_GPO17, + ( PIN_MODE(2) | PIN_PULL_DISABLE ) + }, +#endif + /* SD8_CLK, + PRG0_PRU0_GPI16, SD8_CLK, U4, J2E:P9 */ + { + PIN_PRG0_PRU0_GPO16, + ( PIN_MODE(1) | PIN_INPUT_ENABLE | PIN_PULL_DISABLE ) + }, + /* PRG0_PRU1_GPI9 -> PRG0_PRU1_GPO9 (Y5) */ + { + PIN_PRG0_PRU1_GPO9, + ( PIN_MODE(1) | PIN_INPUT_ENABLE | PIN_PULL_DISABLE ) + }, + /* PRG0_PRU1_GPI10 -> PRG0_PRU1_GPO10 (V6) */ + { + PIN_PRG0_PRU1_GPO10, + ( PIN_MODE(1) | PIN_INPUT_ENABLE | PIN_PULL_DISABLE ) + }, + /* GPIO0_27 -> GPMC0_AD12 (W21) */ + { + PIN_GPMC0_AD12, + ( PIN_MODE(7) | PIN_INPUT_ENABLE | PIN_PULL_DISABLE ) + }, +#ifdef SINGLE_AXLE_USE_M1 +#if defined(AM243X_ALX) + /* SD0_D, + PRG0_PRU0_GPI1, SD0_D, J4, J4:32 */ + { + PIN_PRG0_PRU0_GPO1, + ( PIN_MODE(1) | PIN_INPUT_ENABLE | PIN_PULL_DISABLE ) + }, + /* SD1_D, + PRG0_PRU0_GPI3, SD1_D, H1, J2:19 */ + { + PIN_PRG0_PRU0_GPO3, + ( PIN_MODE(1) | PIN_INPUT_ENABLE | PIN_PULL_DISABLE ) + }, + /* SD2_D, + PRG0_PRU0_GPI5, SD2_D, F2, J2:13 */ + { + PIN_PRG0_PRU0_GPO5, + ( PIN_MODE(1) | PIN_INPUT_ENABLE | PIN_PULL_DISABLE ) + }, +#else + /* SD0_D, + PRG0_PRU0_GPI1, SD0_D, R4, J2E:P8 */ + { + PIN_PRG0_PRU0_GPO1, + ( PIN_MODE(1) | PIN_INPUT_ENABLE | PIN_PULL_DISABLE ) + }, + /* SD1_D, + PRG0_PRU0_GPI3m, SD1_D, V2, J2A:P9 */ + { + PIN_PRG0_PRU0_GPO3, + ( PIN_MODE(1) | PIN_INPUT_ENABLE | PIN_PULL_DISABLE ) + }, + /* SD2_D, + PRG0_PRU0_GPI5, SD2_D, R3, J2C:P6 */ + { + PIN_PRG0_PRU0_GPO5, + ( PIN_MODE(1) | PIN_INPUT_ENABLE | PIN_PULL_DISABLE ) + }, +#endif +#endif +#ifdef SINGLE_AXLE_USE_M1 ////// do pinmux for M2 here + /* SD3_D, + PRG0_PRU0_GPI7, SD3_D, T1, J2B:P7 */ + { + PIN_PRG0_PRU0_GPO7, + ( PIN_MODE(1) | PIN_INPUT_ENABLE | PIN_PULL_DISABLE ) + }, +#ifdef SDDF_HW_EVM_ADAPTER_BP + /* SD4_D, + PRG0_PRU0_GPI9, SD4_D, W6, J2D:P28 */ + { + PIN_PRG0_PRU0_GPO9, + ( PIN_MODE(1) | PIN_INPUT_ENABLE | PIN_PULL_DISABLE ) + }, +#endif + /* SD5_D, + PRG0_PRU0_GPI11, SD5_D, Y3, J2B:P14 */ + { + PIN_PRG0_PRU0_GPO11, + ( PIN_MODE(1) | PIN_INPUT_ENABLE | PIN_PULL_DISABLE ) + }, +#endif +#endif + + /* PRU_ICSSG0_PRU0 pin config */ + /* PRG0_PRU0_GPI1 -> PRG0_PRU0_GPO1 (J4) */ + { + PIN_PRG0_PRU0_GPO1, + ( PIN_MODE(1) | PIN_INPUT_ENABLE | PIN_PULL_DISABLE ) + }, + /* PRG0_PRU0_GPI11 -> PRG0_PRU0_GPO11 (L1) */ + { + PIN_PRG0_PRU0_GPO11, + ( PIN_MODE(1) | PIN_INPUT_ENABLE | PIN_PULL_DISABLE ) + }, + /* PRG0_PRU0_GPI16 -> PRG0_PRU0_GPO16 (N3) */ + { + PIN_PRG0_PRU0_GPO16, + ( PIN_MODE(1) | PIN_INPUT_ENABLE | PIN_PULL_DISABLE ) + }, + /* PRG0_PRU0_GPI18 -> PRG0_PRU0_GPO18 (K4) */ + { + PIN_PRG0_PRU0_GPO18, + ( PIN_MODE(1) | PIN_INPUT_ENABLE | PIN_PULL_DISABLE ) + }, + /* PRG0_PRU0_GPI3 -> PRG0_PRU0_GPO3 (H1) */ + { + PIN_PRG0_PRU0_GPO3, + ( PIN_MODE(1) | PIN_INPUT_ENABLE | PIN_PULL_DISABLE ) + }, + /* PRG0_PRU0_GPI5 -> PRG0_PRU0_GPO5 (F2) */ + { + PIN_PRG0_PRU0_GPO5, + ( PIN_MODE(1) | PIN_INPUT_ENABLE | PIN_PULL_DISABLE ) + }, + /* PRG0_PRU0_GPI7 -> PRG0_PRU0_GPO7 (E2) */ + { + PIN_PRG0_PRU0_GPO7, + ( PIN_MODE(1) | PIN_INPUT_ENABLE | PIN_PULL_DISABLE ) + }, + /* PRG0_PRU0_GPI8 -> PRG0_PRU0_GPO8 (H5) */ + { + PIN_PRG0_PRU0_GPO8, + ( PIN_MODE(1) | PIN_INPUT_ENABLE | PIN_PULL_DISABLE ) + }, + + /* PRU_ICSSG0_IEP0 pin config */ + /* PRG0_IEP0_EDC_SYNC_OUT0 -> PRG0_PRU0_GPO19 (G2) */ + { + PIN_PRG0_PRU0_GPO19, + ( PIN_MODE(2) | PIN_PULL_DISABLE ) + }, + /* PRG0_IEP0_EDC_SYNC_OUT1 -> PRG0_PRU0_GPO17 (E1) */ + { + PIN_PRG0_PRU0_GPO17, + ( PIN_MODE(2) | PIN_PULL_DISABLE ) + }, + + {PINMUX_END, PINMUX_END} + }; + + Pinmux_config(miscPinMuxCfg, PINMUX_DOMAIN_ID_MAIN); + + #if defined(SDDF_HW_EVM_ADAPTER_BP) + /* set IO expander P12 to high for using PIN_PRG0_PRU0_GPO9 */ + ////i2c_io_expander(NULL); +#endif + +#ifdef SINGLE_AXLE_USE_M2 + ///Pinmux_config(miscPinMuxCfg, PINMUX_DOMAIN_ID_MAIN); +#endif + +#if defined(AM243X_ALV) + GPIO_setDirMode(CSL_GPIO0_BASE, 27, GPIO_DIRECTION_OUTPUT); + GPIO_pinWriteHigh(CSL_GPIO0_BASE, 27); + + GPIO_setDirMode(CSL_GPIO0_BASE, 42, GPIO_DIRECTION_OUTPUT); + GPIO_pinWriteHigh(CSL_GPIO0_BASE, 42); +#endif +#if defined(AM243X_ALX) + GPIO_pinWriteHigh(ENC1_EN_BASE_ADDR, ENC1_EN_PIN); + GPIO_pinWriteHigh(ENC2_EN_BASE_ADDR, ENC2_EN_PIN); +#endif +} + +/* EPWM ISR */ +__attribute__((section(".critical_code"))) static void App_epwmIntrISR(void *args) +{ + AppEPwmIsrInfo_t *pAppEpwmIsrInfo; + uint32_t epwmBaseAddr; + SemaphoreP_Object *pEpwmSyncSemObject; + volatile uint16_t status; + + gEpwmIsrCnt++; + + /* Get EPWM info */ + pAppEpwmIsrInfo = (AppEPwmIsrInfo_t *)args; + epwmBaseAddr = pAppEpwmIsrInfo->epwmBaseAddr; + pEpwmSyncSemObject = pAppEpwmIsrInfo->pEpwmSyncSemObject; + + status = EPWM_etIntrStatus(epwmBaseAddr); + if (status & EPWM_ETFLG_INT_MASK) { + SemaphoreP_post(pEpwmSyncSemObject); + EPWM_etIntrClear(epwmBaseAddr); + } + +#if defined(SDDF_HW_EVM_ADAPTER_BP) + /* Call FOC loop here */ +#if defined(USE_PURE_OPEN_LOOP)||defined(USE_OPEN_LOOP_WITH_SDDF) + pruEncoderIrqHandler(NULL); +#endif +#endif + + return; +} +#endif + +__attribute__((section(".critical_code"))) static void App_epwmIntrISR2(void *args) +{ + AppEPwmIsrInfo_t *pAppEpwmIsrInfo; + uint32_t epwmBaseAddr; + SemaphoreP_Object *pEpwmSyncSemObject; + volatile uint16_t status; + + gEpwmIsrCnt2++; + + /* Get EPWM info */ + pAppEpwmIsrInfo = (AppEPwmIsrInfo_t *)args; + epwmBaseAddr = pAppEpwmIsrInfo->epwmBaseAddr; + pEpwmSyncSemObject = pAppEpwmIsrInfo->pEpwmSyncSemObject; + + status = EPWM_etIntrStatus(epwmBaseAddr); + if (status & EPWM_ETFLG_INT_MASK) { + SemaphoreP_post(pEpwmSyncSemObject); + EPWM_etIntrClear(epwmBaseAddr); + } + +#if defined(SDDF_HW_EVM_ADAPTER_BP) +#if defined(USE_PURE_OPEN_LOOP)||defined(USE_OPEN_LOOP_WITH_SDDF) + /* Call FOC loop here */ + pruEncoderIrqHandler2(NULL); +#endif +#endif + + return; +} + +void init_pwms(){ + int32_t status; + AppEPwmCfg_t appEpwmCfg; + HwiP_Params hwiPrms; + uint32_t epwm0PrdVal, epwm1PrdVal, epwm2PrdVal; + uint32_t epwm0CmpAVal, epwm1CmpAVal, epwm2CmpAVal; + + /* Address translate */ +#ifdef SINGLE_AXLE_USE_M1 + gEpwm0BaseAddr = (uint32_t)AddrTranslateP_getLocalAddr(EPWM0_BASE_ADDR); + gEpwm1BaseAddr = (uint32_t)AddrTranslateP_getLocalAddr(EPWM1_BASE_ADDR); + gEpwm2BaseAddr = (uint32_t)AddrTranslateP_getLocalAddr(EPWM2_BASE_ADDR); +#endif +#ifdef SINGLE_AXLE_USE_M2 + gEpwm0BaseAddr2A = (uint32_t)AddrTranslateP_getLocalAddr(EPWM3_OUTA_BASE_ADDR); + gEpwm0BaseAddr2B = (uint32_t)AddrTranslateP_getLocalAddr(EPWM3_OUTB_BASE_ADDR); + gEpwm1BaseAddr2 = (uint32_t)AddrTranslateP_getLocalAddr(EPWM4_BASE_ADDR); + gEpwm2BaseAddr2 = (uint32_t)AddrTranslateP_getLocalAddr(EPWM5_BASE_ADDR); +#endif + + SOC_controlModuleUnlockMMR(SOC_DOMAIN_ID_MAIN, 1); +#ifdef SINGLE_AXLE_USE_M1 + /* Configure the SYNCI/SYNCO mapping to tie the three PWM groups together and have PWM0 SYNC from Time Sync Router 38 */ + CSL_REG32_WR(CSL_CTRL_MMR0_CFG0_BASE + CSL_MAIN_CTRL_MMR_CFG0_EPWM0_CTRL, (2 << CSL_MAIN_CTRL_MMR_CFG0_EPWM0_CTRL_SYNCIN_SEL_SHIFT)); + /* Time Sync Router input 29 (ICSSG1 IEP0 SYNC0) -> Time Sync Router output 38 (0x26 + 4 = 0x2A + Time Sync Router Base */ + CSL_REG32_WR(CSL_TIMESYNC_EVENT_INTROUTER0_CFG_BASE + ((38 * 4) + 4), (0x10000 | 29)); +#endif +#ifdef SINGLE_AXLE_USE_M2 + /* Configure the SYNCI/SYNCO mapping to tie the three PWM groups together and have PWM3 SYNC from Time Sync Router 39 */ + CSL_REG32_WR(CSL_CTRL_MMR0_CFG0_BASE + CSL_MAIN_CTRL_MMR_CFG0_EPWM3_CTRL, (2 << CSL_MAIN_CTRL_MMR_CFG0_EPWM3_CTRL_SYNCIN_SEL_SHIFT)); + /* Time Sync Router input 29 (ICSSG1 IEP0 SYNC0) -> Time Sync Router output 39 (0x26 + 4 = 0x2A + Time Sync Router Base */ + CSL_REG32_WR(CSL_TIMESYNC_EVENT_INTROUTER0_CFG_BASE + ((39 * 4) + 4), (0x10000 | 29)); + CSL_REG32_WR(CSL_CTRL_MMR0_CFG0_BASE + CSL_MAIN_CTRL_MMR_CFG0_EPWM6_CTRL, (2 << CSL_MAIN_CTRL_MMR_CFG0_EPWM3_CTRL_SYNCIN_SEL_SHIFT)); + /* Time Sync Router input 29 (ICSSG1 IEP0 SYNC0) -> Time Sync Router output 39 (0x26 + 4 = 0x2A + Time Sync Router Base */ + CSL_REG32_WR(CSL_TIMESYNC_EVENT_INTROUTER0_CFG_BASE + ((40 * 4) + 4), (0x10000 | 29)); +#endif + + /* Configure the ISR triggered by EPWM0 */ + /* Create semaphore */ + status = SemaphoreP_constructBinary(&gEpwm0SyncSemObject, 0); + DebugP_assert(SystemP_SUCCESS == status); + status = SemaphoreP_constructBinary(&gEpwm0SyncSemObject2, 0); + DebugP_assert(SystemP_SUCCESS == status); + + +#if defined(SINGLE_AXLE_USE_M1) + /* Register & enable EPWM0 interrupt */ + gAppEPwm0Info.epwmBaseAddr = gEpwm0BaseAddr; + gAppEPwm0Info.pEpwmSyncSemObject = &gEpwm0SyncSemObject; + HwiP_Params_init(&hwiPrms); + hwiPrms.intNum = EPWM0_INTR; + hwiPrms.callback = &App_epwmIntrISR; + hwiPrms.args = &gAppEPwm0Info; + hwiPrms.isPulse = EPWM0_INTR_IS_PULSE; + status = HwiP_construct(&gEpwm0HwiObject, &hwiPrms); + DebugP_assert(status == SystemP_SUCCESS); + + /* Configure PWMs */ + /* Configure EPWM0 (Phase C) */ + appEpwmCfg.epwmBaseAddr = gEpwm0BaseAddr; + appEpwmCfg.epwmCh = EPWM_OUTPUT_CH_A; + appEpwmCfg.epwmFuncClk = EPWM0_FCLK; + appEpwmCfg.epwmTbFreq = EPWM0_FCLK; + appEpwmCfg.epwmOutFreq = gEpwmOutFreq; + appEpwmCfg.epwmDutyCycle = 50; + appEpwmCfg.epwmTbCounterDir = EPWM_TB_COUNTER_DIR_UP_DOWN; + appEpwmCfg.cfgTbSyncIn = TRUE; + appEpwmCfg.tbPhsValue = 7; + appEpwmCfg.tbSyncInCounterDir = EPWM_TB_COUNTER_DIR_DOWN; + appEpwmCfg.cfgTbSyncOut = TRUE; + appEpwmCfg.tbSyncOutMode = EPWM_TB_SYNC_OUT_EVT_CNT_EQ_ZERO; + appEpwmCfg.aqCfg.zeroAction = EPWM_AQ_ACTION_DONOTHING; + appEpwmCfg.aqCfg.prdAction = EPWM_AQ_ACTION_DONOTHING; + appEpwmCfg.aqCfg.cmpAUpAction = EPWM_AQ_ACTION_HIGH; + appEpwmCfg.aqCfg.cmpADownAction = EPWM_AQ_ACTION_LOW; + appEpwmCfg.aqCfg.cmpBUpAction = EPWM_AQ_ACTION_DONOTHING; + appEpwmCfg.aqCfg.cmpBDownAction = EPWM_AQ_ACTION_DONOTHING; + appEpwmCfg.cfgDb = TRUE; + appEpwmCfg.dbCfg.inputMode = EPWM_DB_IN_MODE_A_RED_A_FED; + appEpwmCfg.dbCfg.outputMode = EPWM_DB_OUT_MODE_A_RED_B_FED; + appEpwmCfg.dbCfg.polaritySelect = EPWM_DB_POL_SEL_ACTV_HIGH_COMPLEMENTARY; + appEpwmCfg.dbCfg.risingEdgeDelay = gDbRisingEdgeDelay; + appEpwmCfg.dbCfg.fallingEdgeDelay = gDbFallingEdgeDelay; + appEpwmCfg.cfgEt = TRUE; + appEpwmCfg.intSel = EPWM_ET_INTR_EVT_CNT_EQ_PRD; + appEpwmCfg.intPrd = EPWM_ET_INTR_PERIOD_FIRST_EVT; + App_epwmConfig(&appEpwmCfg, &epwm0PrdVal, &epwm0CmpAVal); + + /* Configure EPWM1 (Phase B), EPWM2 (Phase A) */ + appEpwmCfg.tbPhsValue = 0; + appEpwmCfg.tbSyncInCounterDir = EPWM_TB_COUNTER_DIR_UP; + appEpwmCfg.cfgEt = FALSE; + appEpwmCfg.epwmBaseAddr = gEpwm1BaseAddr; + App_epwmConfig(&appEpwmCfg, &epwm1PrdVal, &epwm1CmpAVal); + appEpwmCfg.epwmBaseAddr = gEpwm2BaseAddr; + App_epwmConfig(&appEpwmCfg, &epwm2PrdVal, &epwm2CmpAVal); + + DebugP_assert(epwm0PrdVal == epwm1PrdVal); + DebugP_assert(epwm1PrdVal == epwm2PrdVal); + + /* Period is the same for all EPWMs */ + gEpwmPrdVal = epwm0PrdVal; + + /* Force SW sync for EPWM0. Other PWMs will be sync'd through HW sync daisy-chain. */ + EPWM_tbTriggerSwSync(gEpwm0BaseAddr); +#endif + +#if defined(SINGLE_AXLE_USE_M2) + /* Register & enable EPWM0 interrupt */ + gAppEPwm0Info2.epwmBaseAddr = gEpwm0BaseAddr2A; + gAppEPwm0Info2.pEpwmSyncSemObject = &gEpwm0SyncSemObject2; + HwiP_Params_init(&hwiPrms); + hwiPrms.intNum = EPWM3_OUTA_INTR; + hwiPrms.callback = &App_epwmIntrISR2; + hwiPrms.args = &gAppEPwm0Info2; + hwiPrms.isPulse = EPWM3_OUTA_INTR_IS_PULSE; + status = HwiP_construct(&gEpwm0HwiObject2, &hwiPrms); + DebugP_assert(status == SystemP_SUCCESS); + + /* Configure PWMs */ + /* Configure EPWM3 (Phase C) */ + appEpwmCfg.epwmBaseAddr = gEpwm0BaseAddr2A; + appEpwmCfg.epwmCh = EPWM_OUTPUT_CH_A; + appEpwmCfg.epwmFuncClk = EPWM3_OUTA_FCLK; + appEpwmCfg.epwmTbFreq = EPWM3_OUTA_FCLK; + appEpwmCfg.epwmOutFreq = gEpwmOutFreq; + appEpwmCfg.epwmDutyCycle = 50; + appEpwmCfg.epwmTbCounterDir = EPWM_TB_COUNTER_DIR_UP_DOWN; + appEpwmCfg.cfgTbSyncIn = TRUE; + appEpwmCfg.tbPhsValue = 7; + appEpwmCfg.tbSyncInCounterDir = EPWM_TB_COUNTER_DIR_DOWN; + appEpwmCfg.cfgTbSyncOut = TRUE; + appEpwmCfg.tbSyncOutMode = EPWM_TB_SYNC_OUT_EVT_CNT_EQ_ZERO; + appEpwmCfg.aqCfg.zeroAction = EPWM_AQ_ACTION_DONOTHING; + appEpwmCfg.aqCfg.prdAction = EPWM_AQ_ACTION_DONOTHING; + appEpwmCfg.aqCfg.cmpAUpAction = EPWM_AQ_ACTION_HIGH; + appEpwmCfg.aqCfg.cmpADownAction = EPWM_AQ_ACTION_LOW; + appEpwmCfg.aqCfg.cmpBUpAction = EPWM_AQ_ACTION_DONOTHING; + appEpwmCfg.aqCfg.cmpBDownAction = EPWM_AQ_ACTION_DONOTHING; + appEpwmCfg.cfgDb = TRUE; + appEpwmCfg.dbCfg.inputMode = EPWM_DB_IN_MODE_A_RED_A_FED; + appEpwmCfg.dbCfg.outputMode = EPWM_DB_OUT_MODE_A_RED_B_FED; + appEpwmCfg.dbCfg.polaritySelect = EPWM_DB_POL_SEL_ACTV_HIGH_COMPLEMENTARY; + appEpwmCfg.dbCfg.risingEdgeDelay = gDbRisingEdgeDelay; + appEpwmCfg.dbCfg.fallingEdgeDelay = gDbFallingEdgeDelay; + appEpwmCfg.cfgEt = TRUE; + appEpwmCfg.intSel = EPWM_ET_INTR_EVT_CNT_EQ_PRD; + appEpwmCfg.intPrd = EPWM_ET_INTR_PERIOD_FIRST_EVT; + App_epwmConfig(&appEpwmCfg, &epwm0PrdVal, &epwm0CmpAVal); + appEpwmCfg.epwmBaseAddr = gEpwm0BaseAddr2B; + App_epwmConfig(&appEpwmCfg, &epwm0PrdVal, &epwm0CmpAVal); + + /* Configure EPWM1 (Phase B), EPWM2 (Phase A) */ + appEpwmCfg.tbPhsValue = 0; + appEpwmCfg.tbSyncInCounterDir = EPWM_TB_COUNTER_DIR_UP; + appEpwmCfg.cfgEt = FALSE; + appEpwmCfg.epwmBaseAddr = gEpwm1BaseAddr2; + App_epwmConfig(&appEpwmCfg, &epwm1PrdVal, &epwm1CmpAVal); + appEpwmCfg.epwmBaseAddr = gEpwm2BaseAddr2; + App_epwmConfig(&appEpwmCfg, &epwm2PrdVal, &epwm2CmpAVal); + + DebugP_assert(epwm0PrdVal == epwm1PrdVal); + DebugP_assert(epwm1PrdVal == epwm2PrdVal); + + /* Period is the same for all EPWMs */ + gEpwmPrdVal = epwm0PrdVal; + + /* Force SW sync for EPWM0. Other PWMs will be sync'd through HW sync daisy-chain. */ + EPWM_tbTriggerSwSync(gEpwm0BaseAddr2A); +#endif + + /* Enable the PWM output buffer until gate driver configured and PWM signals at 50% duty cycle */ + ///enable_pwm_buffers(FALSE); +} + +void init_pids(){ + /* 50KHz PWM frequency PID constants */ +#if 1 + gPiId.Kp = 0.2; + gPiId.Ki = 0.0001; + gPiId.Kd = 0; + arm_pid_init_f32(&gPiId, 1); + + gPiIq.Kp = 0.2; + gPiIq.Ki = 0.0001; + gPiIq.Kd = 0; + arm_pid_init_f32(&gPiIq, 1); + + /* Mmax 0.12 RPM step between periods */ + gPiSpd.Kp = MAX_SPD_CHANGE; ///0.06 + gPiSpd.Ki = 0.0003; + gPiSpd.Kd = 0; + arm_pid_init_f32(&gPiSpd, 1); + + /* Max 0.06 angle step between periods (500 RPM) */ + gPiPos.Kp = MAX_POS_CHANGE*MAX_SPD_RPM; ///30; + gPiPos.Ki = 0; + gPiPos.Kd = 0; + arm_pid_init_f32(&gPiPos, 1); +#endif + + /* 20KHz PWM frequency PID constants */ +#if 0 + gPiId.Kp = 0.225; + gPiId.Ki = 0.005; + gPiId.Kd = 0; + arm_pid_init_f32(&gPiId, 1); + + gPiIq.Kp = 0.2; + gPiIq.Ki = 0.005; + gPiIq.Kd = 0; + arm_pid_init_f32(&gPiIq, 1); + + /* Max 0.3 RPM step between periods */ + gPiSpd.Kp = 0.045; + gPiSpd.Ki = 0.0001; + gPiSpd.Kd = 0; + arm_pid_init_f32(&gPiSpd, 1); + + /* Max 0.15 angle step between periods (500 RPM) */ + gPiPos.Kp = 13; + gPiPos.Ki = 0.000025; + gPiPos.Kd = 0; + arm_pid_init_f32(&gPiPos, 1); +#endif +} + +void single_chip_servo_remote_core_start() +{ +#if (DEBUG_LEVEL == DEBUG_BUFFERS_ON) + /* Make sure that the Debug buffer size is larger than the target buffer size so that there are no index out of bounds issues */ + DebugP_assert(DEBUG_BUFF_SZ > TARGET_BUFF_SIZE); +#endif + +#if defined(SINGLE_AXLE_USE_M1) + /* Initialize GPIO state */ + init_gpio_state(); + +#if !defined(SDDF_HW_EVM_ADAPTER_BP) + /* Check the power on the adapter board */ + status = check_adapter_board_power(); + DebugP_assert(status==SystemP_SUCCESS); +#endif + + /* Disable the PWM output buffer until gate driver configured and PWM signals at 50% duty cycle */ + enable_pwm_buffers(FALSE); + +#if !defined(SDDF_HW_EVM_ADAPTER_BP) + /* Initialize the DRV8350 gate driver */ + status = init_drv8350(); + DebugP_assert(status==SystemP_SUCCESS); +#endif + + misc_pinmux(); +#endif + + /* Configure PWMs for complementary 3-phase and set duty cycle to 50% */ + init_pwms(); + +#if defined(SINGLE_AXLE_USE_M1) +#if !defined(USE_PURE_OPEN_LOOP) && !defined(USE_OPEN_LOOP_WITH_SDDF) + init_encoder(); + + init_sddf(); +#endif +#if defined(USE_OPEN_LOOP_WITH_SDDF) + init_sddf(); +#endif + + init_pids(); + +#if (BUILDLEVEL == CLOSED_LOOP_CIA402) + /* Default the CiA402 commands to torque control with a target value of 0 */ + gTxData.modeOfOperation = CYCLIC_SYNC_VELOCITY_MODE; ///CYCLIC_SYNC_TORQUE_MODE; + gTxData.targetPosition = 0; + gTxData.targetVelocity = 0; + gTxData.targetTorque = 0; +#endif + + /* Enable the PWM output buffers */ + enable_pwm_buffers(TRUE); +#endif + +#if defined(SINGLE_AXLE_USE_M2) +#if !defined(USE_PURE_OPEN_LOOP) && !defined(USE_OPEN_LOOP_WITH_SDDF) + init_pids(); + init_sddf2(); + + init_encoder2(); +#endif +#if defined(USE_OPEN_LOOP_WITH_SDDF) + init_sddf2(); +#endif + +#endif + + SemaphoreP_constructBinary(&gRemoteDoneSem, 0); + + /* register a handler to receive messages */ + ///status = IpcNotify_registerClient(gClientId, ipc_notify_msg_handler_remote_core, NULL); + ///DebugP_assert(status==SystemP_SUCCESS); + + /* wait for all cores to be ready */ + ///IpcNotify_syncAll(SystemP_WAIT_FOREVER); + + DebugP_log("\n\n[Single Chip Servo] All cores synchronized...\n\n"); + + while(gRunFlag == TRUE) + { +#if defined(SINGLE_AXLE_USE_M1) + SemaphoreP_pend(&gEpwm0SyncSemObject, SystemP_WAIT_FOREVER); +#endif +#if defined(SINGLE_AXLE_USE_M2) + SemaphoreP_pend(&gEpwm0SyncSemObject2, SystemP_WAIT_FOREVER); +#endif + gLoopCnt++; + } + + DebugP_log("Exiting!\r\n"); +} + +void single_chip_servo_main(void *args) +{ + Drivers_open(); + Board_driversOpen(); + + single_chip_servo_remote_core_start(); + + Board_driversClose(); + /* We dont close drivers to let the UART driver remain open and flush any pending messages to console */ + /* Drivers_close(); */ +} diff --git a/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-1_nortos/ti-arm-clang/example.projectspec b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-1_nortos/ti-arm-clang/example.projectspec new file mode 100644 index 0000000..aa0662d --- /dev/null +++ b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-1_nortos/ti-arm-clang/example.projectspec @@ -0,0 +1,148 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-1_nortos/ti-arm-clang/linker.cmd b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-1_nortos/ti-arm-clang/linker.cmd new file mode 100644 index 0000000..ca81cb7 --- /dev/null +++ b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-1_nortos/ti-arm-clang/linker.cmd @@ -0,0 +1,163 @@ + +/* This is the stack that is used by code running within main() + * In case of NORTOS, + * - This means all the code outside of ISR uses this stack + * In case of FreeRTOS + * - This means all the code until vTaskStartScheduler() is called in main() + * uses this stack. + * - After vTaskStartScheduler() each task created in FreeRTOS has its own stack + */ +--stack_size=16384 +/* This is the heap size for malloc() API in NORTOS and FreeRTOS + * This is also the heap used by pvPortMalloc in FreeRTOS + */ +--heap_size=32768 +-e_vectors /* This is the entry of the application, _vector MUST be plabed starting address 0x0 */ + +/* This is the size of stack when R5 is in IRQ mode + * In NORTOS, + * - Here interrupt nesting is disabled as of now + * - This is the stack used by ISRs registered as type IRQ + * In FreeRTOS, + * - Here interrupt nesting is enabled + * - This is stack that is used initally when a IRQ is received + * - But then the mode is switched to SVC mode and SVC stack is used for all user ISR callbacks + * - Hence in FreeRTOS, IRQ stack size is less and SVC stack size is more + */ +__IRQ_STACK_SIZE = 8192; +/* This is the size of stack when R5 is in IRQ mode + * - In both NORTOS and FreeRTOS nesting is disabled for FIQ + */ +__FIQ_STACK_SIZE = 256; +__SVC_STACK_SIZE = 8192; /* This is the size of stack when R5 is in SVC mode */ +__ABORT_STACK_SIZE = 256; /* This is the size of stack when R5 is in ABORT mode */ +__UNDEFINED_STACK_SIZE = 256; /* This is the size of stack when R5 is in UNDEF mode */ + +SECTIONS +{ + /* This has the R5F entry point and vector table, this MUST be at 0x0 */ + .vectors:{} palign(8) > R5F_VECS + + /* This has the R5F boot code until MPU is enabled, this MUST be at a address < 0x80000000 + * i.e this cannot be placed in DDR + */ + GROUP { + .text.hwi: palign(8) + .text.cache: palign(8) + .text.mpu: palign(8) + .text.boot: palign(8) + } > MSRAM_0_1 + + /* This is rest of code. This can be placed in DDR if DDR is available and needed */ + GROUP { + .text: {} palign(8) /* This is where code resides */ + .rodata: {} palign(8) /* This is where const's go */ + } > MSRAM_0_1 + + /* This is rest of initialized data. This can be placed in DDR if DDR is available and needed */ + GROUP { + .data: {} palign(8) /* This is where initialized globals and static go */ + } > MSRAM_0_1 + + /* This is rest of uninitialized data. This can be placed in DDR if DDR is available and needed */ + GROUP { + .bss: {} palign(8) /* This is where uninitialized globals go */ + RUN_START(__BSS_START) + RUN_END(__BSS_END) + .sysmem: {} palign(8) /* This is where the malloc heap goes */ + .stack: {} palign(8) /* This is where the main() stack goes */ + } > MSRAM_0_1 + + /* This is where the stacks for different R5F modes go */ + GROUP { + .irqstack: {. = . + __IRQ_STACK_SIZE;} align(8) + RUN_START(__IRQ_STACK_START) + RUN_END(__IRQ_STACK_END) + .fiqstack: {. = . + __FIQ_STACK_SIZE;} align(8) + RUN_START(__FIQ_STACK_START) + RUN_END(__FIQ_STACK_END) + .svcstack: {. = . + __SVC_STACK_SIZE;} align(8) + RUN_START(__SVC_STACK_START) + RUN_END(__SVC_STACK_END) + .abortstack: {. = . + __ABORT_STACK_SIZE;} align(8) + RUN_START(__ABORT_STACK_START) + RUN_END(__ABORT_STACK_END) + .undefinedstack: {. = . + __UNDEFINED_STACK_SIZE;} align(8) + RUN_START(__UNDEFINED_STACK_START) + RUN_END(__UNDEFINED_STACK_END) + } > MSRAM_0_1 + + /* General purpose user shared memory, used in some examples */ + .bss.user_shared_mem (NOLOAD) : {} > USER_SHM_MEM + /* this is used when Debug log's to shared memory are enabled, else this is not used */ + .bss.log_shared_mem (NOLOAD) : {} > LOG_SHM_MEM + /* this is used only when IPC RPMessage is enabled, else this is not used */ + .bss.ipc_vring_mem (NOLOAD) : {} > RTOS_NORTOS_IPC_SHM_MEM + + .gSddfChSampsRaw (NOLOAD) : {} align(4) > R5F_TCMB0_SDDF_0_1 + .gTxDataSection : {} align(4) > R5F_TCMB0_PDO + .gRxDataSection : {} align(4) > OTHER_R5F_TCMB0_PDO + + // debug, capture buffers + .gDebugBuff1 : {} align(4) > MSRAM1 + .gDebugBuff2 : {} align(4) > MSRAM2 + + .gEnDatChInfo (NOLOAD) : {} align(4) > R5F_TCMB0_ENC_0_1 + + .critical_code : {} palign(4) > R5F_TCMB0 + .critical_data : {} palign(8) > R5F_TCMB0 + + .gCtrlVars : {} palign(8) > MSRAM_CTRL_VARS_0_1 + + .gSharedPrivStep (NOLOAD) : {} palign(8) > USER_SHM_MEM + .gSharedPruHandle (NOLOAD) : {} palign(8) > USER_SHM_MEM + .gEtherCatCia402 (NOLOAD) : {} palign(4) > MSRAM_NO_CACHE +} + +/* +NOTE: Below memory is reserved for DMSC usage + - During Boot till security handoff is complete + 0x701E0000 - 0x701FFFFF (128KB) + - After "Security Handoff" is complete (i.e at run time) + 0x701FC000 - 0x701FFFFF (16KB) + + Security handoff is complete when this message is sent to the DMSC, + TISCI_MSG_SEC_HANDOVER + + This should be sent once all cores are loaded and all application + specific firewall calls are setup. +*/ + +MEMORY +{ + R5F_VECS : ORIGIN = 0x00000000 , LENGTH = 0x00000040 + R5F_TCMA : ORIGIN = 0x00000040 , LENGTH = 0x00007FC0 + R5F_TCMB0_SDDF_0_0 : ORIGIN = 0x078100000 , LENGTH = 0x80 + R5F_TCMB0_SDDF_0_1 : ORIGIN = 0x078100080 , LENGTH = 0x80 + R5F_TCMB0_ENC : ORIGIN = 0x41010100 , LENGTH = 0x100 + R5F_TCMB0_ENC_0_1 : ORIGIN = 0x078100100 , LENGTH = 0x100 + R5F_TCMB0_PDO : ORIGIN = 0x41010200 , LENGTH = 0x100 + R5F_TCMB0 : ORIGIN = 0x41010300 , LENGTH = 0x00008000 - 0x300 + /* when using multi-core application's i.e more than one R5F/M4F active, make sure + * this memory does not overlap with other R5F's + */ + /* MSRAM0 : ORIGIN = 0x70000000 , LENGTH = 0x40000 */ + MSRAM1 : ORIGIN = 0x70040000 , LENGTH = 0x40000 + MSRAM2 : ORIGIN = 0x70080000 , LENGTH = 0x40000 + MSRAM_0_0 : ORIGIN = 0x70140000 , LENGTH = 0x40000 + MSRAM_0_1 : ORIGIN = 0x70180000 , LENGTH = 0x40000 - 0x200 + MSRAM_1_0 : ORIGIN = 0x700C0000 , LENGTH = 0x70000 + MSRAM_CTRL_VARS_0_0 : ORIGIN = 0x701BFE00 , LENGTH = 0x100 + MSRAM_CTRL_VARS_0_1 : ORIGIN = 0x701BFF00 , LENGTH = 0x100 + MSRAM_NO_CACHE : ORIGIN = 0x701C0000, LENGTH = 0x100 + + /* shared memories that are used by RTOS/NORTOS cores */ + /* On R5F, + * - make sure there is a MPU entry which maps below regions as non-cache + */ + USER_SHM_MEM : ORIGIN = 0x701D0000, LENGTH = 0x00004000 + LOG_SHM_MEM : ORIGIN = 0x701D4000, LENGTH = 0x00004000 + RTOS_NORTOS_IPC_SHM_MEM : ORIGIN = 0x701D8000, LENGTH = 0x00008000 + + OTHER_R5F_TCMB0_PDO : ORIGIN = 0x78500000, LENGTH = 0x100 +} diff --git a/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-1_nortos/ti-arm-clang/makefile b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-1_nortos/ti-arm-clang/makefile new file mode 100644 index 0000000..b5caa30 --- /dev/null +++ b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-1_nortos/ti-arm-clang/makefile @@ -0,0 +1,307 @@ +# +# Auto generated makefile +# + +export MOTOR_CONTROL_SDK_PATH?=$(abspath ../../../../../..) +include $(MOTOR_CONTROL_SDK_PATH)/imports.mak +include $(MOTOR_CONTROL_SDK_PATH)/devconfig/devconfig.mak + +CG_TOOL_ROOT=$(CGT_TI_ARM_CLANG_PATH) + +CC=$(CG_TOOL_ROOT)/bin/tiarmclang +LNK=$(CG_TOOL_ROOT)/bin/tiarmclang +STRIP=$(CG_TOOL_ROOT)/bin/tiarmstrip +OBJCOPY=$(CG_TOOL_ROOT)/bin/tiarmobjcopy +ifeq ($(OS), Windows_NT) + PYTHON=python +else + PYTHON=python3 +endif + +PROFILE?=release +ConfigName:=$(PROFILE) + +OUTNAME:=single_chip_servo.$(PROFILE).out + +BOOTIMAGE_PATH=$(abspath .) +BOOTIMAGE_NAME:=single_chip_servo.$(PROFILE).appimage +BOOTIMAGE_NAME_XIP:=single_chip_servo.$(PROFILE).appimage_xip +BOOTIMAGE_NAME_SIGNED:=single_chip_servo.$(PROFILE).appimage.signed +BOOTIMAGE_RPRC_NAME:=single_chip_servo.$(PROFILE).rprc +BOOTIMAGE_RPRC_NAME_XIP:=single_chip_servo.$(PROFILE).rprc_xip +BOOTIMAGE_RPRC_NAME_TMP:=single_chip_servo.$(PROFILE).rprc_tmp + +FILES_common := \ + epwm_drv_aux.c \ + pwm.c \ + ti_r5fmath_trig.c \ + single_chip_servo.c \ + main.c \ + ti_drivers_config.c \ + ti_drivers_open_close.c \ + ti_board_config.c \ + ti_board_open_close.c \ + ti_dpl_config.c \ + ti_pinmux_config.c \ + ti_power_clock_config.c \ + +FILES_PATH_common = \ + .. \ + ../../.. \ + generated \ + +INCLUDES_common := \ + -I${CG_TOOL_ROOT}/include/c \ + -I${MOTOR_CONTROL_SDK_PATH}/mcu_plus_sdk/source \ + -I${MOTOR_CONTROL_SDK_PATH}/source \ + -I${CG_TOOL_ROOT}/include/c \ + -I${MOTOR_CONTROL_SDK_PATH}/mcu_plus_sdk/source/drivers \ + -I${MOTOR_CONTROL_SDK_PATH}/mcu_plus_sdk/source/board \ + -I${MOTOR_CONTROL_SDK_PATH}/mcu_plus_sdk/source/cmsis/DSP/Include \ + -I${MOTOR_CONTROL_SDK_PATH}/mcu_plus_sdk/source/cmsis/Core/Include \ + -I${MOTOR_CONTROL_SDK_PATH}/source/current_sense/sdfm/firmware \ + -I${MOTOR_CONTROL_SDK_PATH}/source/current_sense/sdfm/include \ + -I${MOTOR_CONTROL_SDK_PATH}/source/position_sense/endat/firmware \ + -I${MOTOR_CONTROL_SDK_PATH}/source/position_sense/endat/include \ + -I${MOTOR_CONTROL_SDK_PATH}/source/transforms/clarke \ + -I${MOTOR_CONTROL_SDK_PATH}/source/transforms/ipark \ + -I${MOTOR_CONTROL_SDK_PATH}/source/transforms/park \ + -I${MOTOR_CONTROL_SDK_PATH}/source/transforms/svgen \ + -Igenerated \ + +DEFINES_common := \ + -DSOC_AM243X \ + +CFLAGS_common := \ + -mcpu=cortex-r5 \ + -mfloat-abi=hard \ + -mfpu=vfpv3-d16 \ + -mthumb \ + -Wall \ + -Werror \ + -g \ + -Wno-gnu-variable-sized-type-not-at-end \ + -Wno-unused-function \ + +CFLAGS_cpp_common := \ + -Wno-c99-designator \ + -Wno-extern-c-compat \ + -Wno-c++11-narrowing \ + -Wno-reorder-init-list \ + -Wno-deprecated-register \ + -Wno-writable-strings \ + -Wno-enum-compare \ + -Wno-reserved-user-defined-literal \ + -Wno-unused-const-variable \ + -x c++ \ + +CFLAGS_debug := \ + -D_DEBUG_=1 \ + +CFLAGS_release := \ + -Os \ + +LNK_FILES_common = \ + linker.cmd \ + +LIBS_PATH_common = \ + -Wl,-i${CG_TOOL_ROOT}/lib \ + -Wl,-i${MOTOR_CONTROL_SDK_PATH}/mcu_plus_sdk/source/kernel/nortos/lib \ + -Wl,-i${MOTOR_CONTROL_SDK_PATH}/mcu_plus_sdk/source/drivers/lib \ + -Wl,-i${MOTOR_CONTROL_SDK_PATH}/mcu_plus_sdk/source/board/lib \ + -Wl,-i${MOTOR_CONTROL_SDK_PATH}/source/position_sense/endat/lib \ + -Wl,-i${MOTOR_CONTROL_SDK_PATH}/source/current_sense/sdfm/lib \ + -Wl,-i${MOTOR_CONTROL_SDK_PATH}/mcu_plus_sdk/source/cmsis/lib \ + -Wl,-i${CG_TOOL_ROOT}/lib \ + +LIBS_common = \ + -llibc.a \ + -lnortos.am243x.r5f.ti-arm-clang.${ConfigName}.lib \ + -ldrivers.am243x.r5f.ti-arm-clang.${ConfigName}.lib \ + -lboard.am243x.r5f.ti-arm-clang.${ConfigName}.lib \ + -lmotorcontrol_sdfm.am243x.r5f.ti-arm-clang.${ConfigName}.lib \ + -lmotorcontrol_endat.am243x.r5f.ti-arm-clang.${ConfigName}.lib \ + -lcmsis.am243x.r5f.ti-arm-clang.${ConfigName}.lib \ + -llibc.a \ + -llibsysbm.a \ + +LFLAGS_common = \ + -Wl,--diag_suppress=10063 \ + -Wl,--ram_model \ + -Wl,--reread_libs \ + + +LIBS_NAME = \ + libc.a \ + nortos.am243x.r5f.ti-arm-clang.${ConfigName}.lib \ + drivers.am243x.r5f.ti-arm-clang.${ConfigName}.lib \ + board.am243x.r5f.ti-arm-clang.${ConfigName}.lib \ + motorcontrol_sdfm.am243x.r5f.ti-arm-clang.${ConfigName}.lib \ + motorcontrol_endat.am243x.r5f.ti-arm-clang.${ConfigName}.lib \ + cmsis.am243x.r5f.ti-arm-clang.${ConfigName}.lib \ + libc.a \ + libsysbm.a \ + +LIBS_PATH_NAME = \ + ${CG_TOOL_ROOT}/lib \ + ${MOTOR_CONTROL_SDK_PATH}/mcu_plus_sdk/source/kernel/nortos/lib \ + ${MOTOR_CONTROL_SDK_PATH}/mcu_plus_sdk/source/drivers/lib \ + ${MOTOR_CONTROL_SDK_PATH}/mcu_plus_sdk/source/board/lib \ + ${MOTOR_CONTROL_SDK_PATH}/source/position_sense/endat/lib \ + ${MOTOR_CONTROL_SDK_PATH}/source/current_sense/sdfm/lib \ + ${MOTOR_CONTROL_SDK_PATH}/mcu_plus_sdk/source/cmsis/lib \ + ${CG_TOOL_ROOT}/lib \ + +FILES := $(FILES_common) $(FILES_$(PROFILE)) +ASMFILES := $(ASMFILES_common) $(ASMFILES_$(PROFILE)) +FILES_PATH := $(FILES_PATH_common) $(FILES_PATH_$(PROFILE)) +CFLAGS := $(CFLAGS_common) $(CFLAGS_$(PROFILE)) +DEFINES := $(DEFINES_common) $(DEFINES_$(PROFILE)) +INCLUDES := $(INCLUDES_common) $(INCLUDE_$(PROFILE)) +LIBS := $(LIBS_common) $(LIBS_$(PROFILE)) +LIBS_PATH := $(LIBS_PATH_common) $(LIBS_PATH_$(PROFILE)) +LFLAGS := $(LFLAGS_common) $(LFLAGS_$(PROFILE)) +LNKOPTFLAGS := $(LNKOPTFLAGS_common) $(LNKOPTFLAGS_$(PROFILE)) +LNK_FILES := $(LNK_FILES_common) $(LNK_FILES_$(PROFILE)) + +OBJDIR := obj/$(PROFILE)/ +OBJS := $(FILES:%.c=%.obj) +OBJS += $(ASMFILES:%.S=%.obj) +DEPS := $(FILES:%.c=%.d) + +vpath %.obj $(OBJDIR) +vpath %.c $(FILES_PATH) +vpath %.S $(FILES_PATH) +vpath %.lib $(LIBS_PATH_NAME) +vpath %.a $(LIBS_PATH_NAME) + +$(OBJDIR)/%.obj %.obj: %.c + @echo Compiling: am243x:r5fss0-1:nortos:ti-arm-clang $(OUTNAME): $< + $(CC) -c $(CFLAGS) $(INCLUDES) $(DEFINES) -MMD -o $(OBJDIR)/$@ $< + +$(OBJDIR)/%.obj %.obj: %.S + @echo Compiling: am243x:r5fss0-1:nortos:ti-arm-clang $(LIBNAME): $< + $(CC) -c $(CFLAGS) -o $(OBJDIR)/$@ $< + +all: $(BOOTIMAGE_NAME) + +SYSCFG_GEN_FILES=generated/ti_drivers_config.c generated/ti_drivers_config.h +SYSCFG_GEN_FILES+=generated/ti_drivers_open_close.c generated/ti_drivers_open_close.h +SYSCFG_GEN_FILES+=generated/ti_dpl_config.c generated/ti_dpl_config.h +SYSCFG_GEN_FILES+=generated/ti_pinmux_config.c generated/ti_power_clock_config.c +SYSCFG_GEN_FILES+=generated/ti_board_config.c generated/ti_board_config.h +SYSCFG_GEN_FILES+=generated/ti_board_open_close.c generated/ti_board_open_close.h + +$(OUTNAME): syscfg $(SYSCFG_GEN_FILES) $(OBJS) $(LNK_FILES) $(LIBS_NAME) + @echo . + @echo Linking: am243x:r5fss0-1:nortos:ti-arm-clang $@ ... + $(LNK) $(LNKOPTFLAGS) $(LFLAGS) $(LIBS_PATH) -Wl,-m=$(basename $@).map -o $@ $(addprefix $(OBJDIR), $(OBJS)) $(LIBS) $(LNK_FILES) + @echo Linking: am243x:r5fss0-1:nortos:ti-arm-clang $@ Done !!! + @echo . + +clean: + @echo Cleaning: am243x:r5fss0-1:nortos:ti-arm-clang $(OUTNAME) ... + $(RMDIR) $(OBJDIR) + $(RM) $(OUTNAME) + $(RM) $(BOOTIMAGE_NAME) + $(RM) $(BOOTIMAGE_NAME_XIP) + $(RM) $(BOOTIMAGE_NAME_SIGNED) + $(RM) $(BOOTIMAGE_NAME_HS) + $(RM) $(BOOTIMAGE_NAME_HS_FS) + $(RM) $(BOOTIMAGE_RPRC_NAME) + $(RM) $(BOOTIMAGE_RPRC_NAME_XIP) + $(RMDIR) generated/ + +scrub: + @echo Scrubing: am243x:r5fss0-1:nortos:ti-arm-clang single_chip_servo ... + $(RMDIR) obj +ifeq ($(OS),Windows_NT) + $(RM) \*.out + $(RM) \*.map + $(RM) \*.appimage* + $(RM) \*.rprc* + $(RM) \*.tiimage* + $(RM) \*.bin +else + $(RM) *.out + $(RM) *.map + $(RM) *.appimage* + $(RM) *.rprc* + $(RM) *.tiimage* + $(RM) *.bin +endif + $(RMDIR) generated + +$(OBJS): | $(OBJDIR) + +$(OBJDIR): + $(MKDIR) $@ + + +.NOTPARALLEL: + +.INTERMEDIATE: syscfg +$(SYSCFG_GEN_FILES): syscfg + +syscfg: ../example.syscfg + @echo Generating SysConfig files ... + $(SYSCFG_NODE) $(SYSCFG_CLI_PATH)/dist/cli.js --product $(SYSCFG_SDKPRODUCT) --context r5fss0-1 --part ALX --package ALX --output generated/ ../example.syscfg + +syscfg-gui: + $(SYSCFG_NWJS) $(SYSCFG_PATH) --product $(SYSCFG_SDKPRODUCT) --device AM243x_ALX_beta --context r5fss0-1 --part ALX --package ALX --output generated/ ../example.syscfg + +# +# Generation of boot image which can be loaded by Secondary Boot Loader (SBL) +# +ifeq ($(OS),Windows_NT) +EXE_EXT=.exe +endif +ifeq ($(OS),Windows_NT) + BOOTIMAGE_CERT_GEN_CMD=powershell -executionpolicy unrestricted -command $(MOTOR_CONTROL_SDK_PATH)/mcu_plus_sdk/tools/boot/signing/x509CertificateGen.ps1 +else + BOOTIMAGE_CERT_GEN_CMD=$(MOTOR_CONTROL_SDK_PATH)/mcu_plus_sdk/tools/boot/signing/x509CertificateGen.sh +endif +BOOTIMAGE_TEMP_OUT_FILE=temp_stdout_$(PROFILE).txt + +BOOTIMAGE_CERT_KEY=$(APP_SIGNING_KEY) + +BOOTIMAGE_CORE_ID_r5fss0-0 = 4 +BOOTIMAGE_CORE_ID_r5fss0-1 = 5 +BOOTIMAGE_CORE_ID_r5fss1-0 = 6 +BOOTIMAGE_CORE_ID_r5fss1-1 = 7 +BOOTIMAGE_CORE_ID_m4fss0-0 = 14 +SBL_RUN_ADDRESS=0x70000000 +SBL_DEV_ID=55 + +MULTI_CORE_IMAGE_GEN = $(SYSCFG_NODE) $(MOTOR_CONTROL_SDK_PATH)/mcu_plus_sdk/tools/boot/multicoreImageGen/multicoreImageGen.js +OUTRPRC_CMD = $(SYSCFG_NODE) $(MOTOR_CONTROL_SDK_PATH)/mcu_plus_sdk/tools/boot/out2rprc/elf2rprc.js + +ifeq ($(OS),Windows_NT) + XIPGEN_CMD=$(MOTOR_CONTROL_SDK_PATH)/mcu_plus_sdk/tools/boot/xipGen/xipGen.exe +else + XIPGEN_CMD=$(MOTOR_CONTROL_SDK_PATH)/mcu_plus_sdk/tools/boot/xipGen/xipGen.out +endif + +MULTI_CORE_IMAGE_PARAMS = \ + $(BOOTIMAGE_RPRC_NAME)@$(BOOTIMAGE_CORE_ID_r5fss0-1) \ + +MULTI_CORE_IMAGE_PARAMS_XIP = \ + $(BOOTIMAGE_RPRC_NAME_XIP)@$(BOOTIMAGE_CORE_ID_r5fss0-1) \ + +$(BOOTIMAGE_NAME): $(OUTNAME) + @echo Boot image: am243x:r5fss0-1:nortos:ti-arm-clang $(BOOTIMAGE_PATH)/$@ ... +ifneq ($(OS),Windows_NT) + $(CHMOD) a+x $(XIPGEN_CMD) +endif + $(OUTRPRC_CMD) $(OUTNAME) >> $(BOOTIMAGE_TEMP_OUT_FILE) + $(COPY) $(BOOTIMAGE_RPRC_NAME) $(BOOTIMAGE_RPRC_NAME_TMP) + $(RM) $(BOOTIMAGE_RPRC_NAME) + $(XIPGEN_CMD) -i $(BOOTIMAGE_RPRC_NAME_TMP) -o $(BOOTIMAGE_RPRC_NAME) -x $(BOOTIMAGE_RPRC_NAME_XIP) --flash-start-addr 0x60000000 -v > $(BOOTIMAGE_TEMP_OUT_FILE) + $(MULTI_CORE_IMAGE_GEN) --devID $(SBL_DEV_ID) --out $(BOOTIMAGE_NAME) $(MULTI_CORE_IMAGE_PARAMS) >> $(BOOTIMAGE_TEMP_OUT_FILE) + $(MULTI_CORE_IMAGE_GEN) --devID $(SBL_DEV_ID) --out $(BOOTIMAGE_NAME_XIP) $(MULTI_CORE_IMAGE_PARAMS_XIP) >> $(BOOTIMAGE_TEMP_OUT_FILE) + $(RM) $(BOOTIMAGE_RPRC_NAME_TMP) + $(RM) $(BOOTIMAGE_TEMP_OUT_FILE) + @echo Boot image: am243x:r5fss0-1:nortos:ti-arm-clang $(BOOTIMAGE_PATH)/$@ Done !!! + @echo . + +-include $(addprefix $(OBJDIR)/, $(DEPS)) diff --git a/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-1_nortos/ti-arm-clang/makefile_ccs_bootimage_gen b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-1_nortos/ti-arm-clang/makefile_ccs_bootimage_gen new file mode 100644 index 0000000..3366dca --- /dev/null +++ b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-1_nortos/ti-arm-clang/makefile_ccs_bootimage_gen @@ -0,0 +1,85 @@ +# +# Auto generated makefile +# + +# Below variables need to be defined outside this file or via command line +# - MOTOR_CONTROL_SDK_PATH +# - PROFILE +# - CG_TOOL_ROOT +# - OUTNAME +# - CCS_INSTALL_DIR +# - CCS_IDE_MODE + +CCS_PATH=$(CCS_INSTALL_DIR) +include ${MOTOR_CONTROL_SDK_PATH}/imports.mak +include ${MOTOR_CONTROL_SDK_PATH}/devconfig/devconfig.mak + +STRIP=$(CG_TOOL_ROOT)/bin/tiarmstrip +OBJCOPY=$(CG_TOOL_ROOT)/bin/tiarmobjcopy +ifeq ($(OS), Windows_NT) + PYTHON=python +else + PYTHON=python3 +endif + +OUTFILE=$(PROFILE)/$(OUTNAME).out +BOOTIMAGE_PATH=$(abspath ${PROFILE}) +BOOTIMAGE_NAME:=$(BOOTIMAGE_PATH)/$(OUTNAME).appimage +BOOTIMAGE_NAME_XIP:=$(BOOTIMAGE_PATH)/$(OUTNAME).appimage_xip +BOOTIMAGE_NAME_SIGNED:=$(BOOTIMAGE_PATH)/$(OUTNAME).appimage.signed +BOOTIMAGE_RPRC_NAME:=$(BOOTIMAGE_PATH)/$(OUTNAME).rprc +BOOTIMAGE_RPRC_NAME_XIP:=$(BOOTIMAGE_PATH)/$(OUTNAME).rprc_xip +BOOTIMAGE_RPRC_NAME_TMP:=$(BOOTIMAGE_PATH)/$(OUTNAME).rprc_tmp + +# +# Generation of boot image which can be loaded by Secondary Boot Loader (SBL) +# +ifeq ($(OS),Windows_NT) +EXE_EXT=.exe +endif +ifeq ($(OS),Windows_NT) + BOOTIMAGE_CERT_GEN_CMD=powershell -executionpolicy unrestricted -command $(MOTOR_CONTROL_SDK_PATH)/mcu_plus_sdk/tools/boot/signing/x509CertificateGen.ps1 +else + BOOTIMAGE_CERT_GEN_CMD=$(MOTOR_CONTROL_SDK_PATH)/mcu_plus_sdk/tools/boot/signing/x509CertificateGen.sh +endif +BOOTIMAGE_TEMP_OUT_FILE=$(PROFILE)/temp_stdout_$(PROFILE).txt + +BOOTIMAGE_CORE_ID_r5fss0-0 = 4 +BOOTIMAGE_CORE_ID_r5fss0-1 = 5 +BOOTIMAGE_CORE_ID_r5fss1-0 = 6 +BOOTIMAGE_CORE_ID_r5fss1-1 = 7 +BOOTIMAGE_CORE_ID_m4fss0-0 = 14 +SBL_RUN_ADDRESS=0x70000000 +SBL_DEV_ID=55 + +MULTI_CORE_IMAGE_GEN = $(CCS_NODE) $(MOTOR_CONTROL_SDK_PATH)/mcu_plus_sdk/tools/boot/multicoreImageGen/multicoreImageGen.js +OUTRPRC_CMD = $(CCS_NODE) $(MOTOR_CONTROL_SDK_PATH)/mcu_plus_sdk/tools/boot/out2rprc/elf2rprc.js + +ifeq ($(OS),Windows_NT) + XIPGEN_CMD=$(MOTOR_CONTROL_SDK_PATH)/mcu_plus_sdk/tools/boot/xipGen/xipGen.exe +else + XIPGEN_CMD=$(MOTOR_CONTROL_SDK_PATH)/mcu_plus_sdk/tools/boot/xipGen/xipGen.out +endif + +MULTI_CORE_IMAGE_PARAMS = \ + $(BOOTIMAGE_RPRC_NAME)@$(BOOTIMAGE_CORE_ID_r5fss0-1) \ + +MULTI_CORE_IMAGE_PARAMS_XIP = \ + $(BOOTIMAGE_RPRC_NAME_XIP)@$(BOOTIMAGE_CORE_ID_r5fss0-1) \ + +all: +ifeq ($(CCS_IDE_MODE),cloud) +# No post build steps +else + @echo Boot image: am243x:r5fss0-1:nortos:ti-arm-clang $(BOOTIMAGE_NAME) ... + $(OUTRPRC_CMD) $(OUTFILE) >> $(BOOTIMAGE_TEMP_OUT_FILE) + $(COPY) $(OUTNAME).rprc $(BOOTIMAGE_RPRC_NAME) + $(COPY) $(BOOTIMAGE_RPRC_NAME) $(BOOTIMAGE_RPRC_NAME_TMP) + $(RM) $(BOOTIMAGE_RPRC_NAME) + $(XIPGEN_CMD) -i $(BOOTIMAGE_RPRC_NAME_TMP) -o $(BOOTIMAGE_RPRC_NAME) -x $(BOOTIMAGE_RPRC_NAME_XIP) --flash-start-addr 0x60000000 -v > $(BOOTIMAGE_TEMP_OUT_FILE) + $(MULTI_CORE_IMAGE_GEN) --devID $(SBL_DEV_ID) --out $(BOOTIMAGE_NAME) $(MULTI_CORE_IMAGE_PARAMS) >> $(BOOTIMAGE_TEMP_OUT_FILE) + $(MULTI_CORE_IMAGE_GEN) --devID $(SBL_DEV_ID) --out $(BOOTIMAGE_NAME_XIP) $(MULTI_CORE_IMAGE_PARAMS_XIP) >> $(BOOTIMAGE_TEMP_OUT_FILE) + $(RM) $(BOOTIMAGE_RPRC_NAME_TMP) + @echo Boot image: am243x:r5fss0-1:nortos:ti-arm-clang $(BOOTIMAGE_NAME) Done !!! + @echo . +endif diff --git a/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-1_nortos/ti-arm-clang/makefile_projectspec b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-1_nortos/ti-arm-clang/makefile_projectspec new file mode 100644 index 0000000..163a367 --- /dev/null +++ b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-1_nortos/ti-arm-clang/makefile_projectspec @@ -0,0 +1,20 @@ +# +# Auto generated makefile +# + +export MOTOR_CONTROL_SDK_PATH?=$(abspath ../../../../../..) +include $(MOTOR_CONTROL_SDK_PATH)/imports.mak + +PROFILE?=Release + +PROJECT_NAME=single_chip_servo_am243x-lp_r5fss0-1_nortos_ti-arm-clang + +all: + $(CCS_ECLIPSE) -noSplash -data $(MOTOR_CONTROL_SDK_PATH)/ccs_projects -application com.ti.ccstudio.apps.projectBuild -ccs.projects $(PROJECT_NAME) -ccs.configuration $(PROFILE) + +clean: + $(CCS_ECLIPSE) -noSplash -data $(MOTOR_CONTROL_SDK_PATH)/ccs_projects -application com.ti.ccstudio.apps.projectBuild -ccs.projects $(PROJECT_NAME) -ccs.configuration $(PROFILE) -ccs.clean + +export: + $(MKDIR) $(MOTOR_CONTROL_SDK_PATH)/ccs_projects + $(CCS_ECLIPSE) -noSplash -data $(MOTOR_CONTROL_SDK_PATH)/ccs_projects -application com.ti.ccstudio.apps.projectCreate -ccs.projectSpec example.projectspec -ccs.overwrite full diff --git a/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-1_nortos/ti-arm-clang/syscfg_c.rov.xs b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-1_nortos/ti-arm-clang/syscfg_c.rov.xs new file mode 100644 index 0000000..d46875e --- /dev/null +++ b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-1_nortos/ti-arm-clang/syscfg_c.rov.xs @@ -0,0 +1,8 @@ +/* + * ======== syscfg_c.rov.xs ======== + * This file contains the information needed by the Runtime Object + * View (ROV) tool. + */ +var crovFiles = [ + "mcu_plus_sdk/source/kernel/freertos/rov/FreeRTOS.rov.js", +]; diff --git a/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-1_nortos/ti_r5fmath_trig.c b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-1_nortos/ti_r5fmath_trig.c new file mode 100644 index 0000000..a5c5339 --- /dev/null +++ b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-1_nortos/ti_r5fmath_trig.c @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2020 Texas Instruments Incorporated - http://www.ti.com/ + * + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Texas Instruments Incorporated nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include "ti_r5fmath_trig.h" + +/* first 4 coef are for sin, second 4 are for cos */ +__attribute__((section(".critical_data"))) float ti_r5fmath_sincosCoef[8] = { + 1.0f, + -0.166666507720947265625f, + 0.008331954479217529296875f, + -0.00019490718841552734375f, + 1.0f, + -0.499998867511749267578125f, + 4.165589809417724609375e-2f, + -1.35934352874755859375e-3f + }; +/* 1/(PI/4), PI/2 */ + +__attribute__((section(".critical_data"))) float ti_r5fmath_sincosPIconst[2] = { + TI_R5FMATH_ONEOVERPIOVER4, + TI_R5FMATH_PIOVER2 + }; + +//void Cfast_sincos9(float angleRad, float *constPIVal, float *constCoefVal, float *retValues) +__attribute__((section(".critical_code"))) void ti_r5fmath_sincos(float angleRad, float *PIconst, float *sincosCoef, float *retValues) +{ + // PIconst + // [0] 3PI/2 [1] 2PI [2] PI/2 [3] PI + // sincosCoef + // [0] SIN1 [1] SIN3 [2] SIN5 [3] SIN7 + // [0] COS0 [1] COS2 [2] COS4 [3] COS6 [4] COS8 + + float a2, a4,sinVal, cosVal, modVal; + uint32_t swapVal, signS, signC; + int32_t r; + + swapVal = 0x0066; + signS = 0x001e; + signC = 0x0078; + + // mult by 1/(PI/4) and take floor + + r = (int) (angleRad * PIconst[0]); // 0 < 1/4 3/4> x > 1/4 = 1 > 3/4 = 2 + modVal = angleRad - ((r+1)>>1) * PIconst[1]; // brings into 0 -> PI/4 + + a2 = modVal * modVal; + a4 = a2 * a2; + + sinVal = modVal* sincosCoef[0]; + sinVal += modVal*sincosCoef[1] * a2; + sinVal += modVal*sincosCoef[2] * a4; + sinVal += modVal*sincosCoef[3] * a4 * a2; + + cosVal = sincosCoef[4]; + cosVal += sincosCoef[5]*a2; + cosVal += sincosCoef[6]*a4; + cosVal += sincosCoef[7]*a4*a2; + + swapVal = (swapVal >> r) & 0x1; + signS = (signS >> r) & 0x1; + signC = (signC >> r) & 0x1; + + if (signS) + sinVal = -sinVal; + if (signC) + cosVal = -cosVal; + + retValues[swapVal] = sinVal; + retValues[swapVal^1] = cosVal; +} diff --git a/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-1_nortos/ti_r5fmath_trig.h b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-1_nortos/ti_r5fmath_trig.h new file mode 100644 index 0000000..c0c5882 --- /dev/null +++ b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-1_nortos/ti_r5fmath_trig.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2020 Texas Instruments Incorporated - http://www.ti.com/ + * + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Texas Instruments Incorporated nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef TI_R5FMATH_TRIG_H_ +#define TI_R5FMATH_TRIG_H_ + +#define TI_R5FMATH_PI 3.141592653589793238f +#define TI_R5FMATH_2PI 6.28318530717959f +#define TI_R5FMATH_PIOVER2 1.5707963267948966f +#define TI_R5FMATH_3PIOVER2 4.71238898f +#define TI_R5FMATH_PIOVER4 0.78539816f +#define TI_R5FMATH_ONEOVERPIOVER4 1.273239545f +#define TI_R5FMATH_PIOVER6 0.5235987755f +#define TI_R5FMATH_TANPIOVER6 0.577350269f +#define TI_R5FMATH_TANPIOVER12 0.26794919f +#define TI_R5FMATH_PIOVER180 0.017453292519943295769f + +void ti_r5fmath_sincos(float inputRadians, float *PIconstants, float *sincosCoefficients, float *returnValues); + +// globals +extern float ti_r5fmath_sincosCoef[8]; +extern float ti_r5fmath_sincosPIconst[2]; + +#endif /* TI_R5FMATH_TRIG.H */ diff --git a/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-1_nortos/tisddf_pruss_intc_mapping.h b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-1_nortos/tisddf_pruss_intc_mapping.h new file mode 100644 index 0000000..9fc85a1 --- /dev/null +++ b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss0-1_nortos/tisddf_pruss_intc_mapping.h @@ -0,0 +1,201 @@ +/* + * Copyright (c) 2021, Texas Instruments Incorporated + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of Texas Instruments Incorporated nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * +*/ + +/** +* @file ti_uart_pruss_intc_mapping.h +* +* @brief Pruss interrupt mapping related macros +* +*/ + +#ifndef TI_UART_PRUSS_INTC_MAPPING_H +#define TI_UART_PRUSS_INTC_MAPPING_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define IEP_TIM_CAP_CMP_EVENT 7 +#define SYNC1_OUT_EVENT 13 +#define SYNC0_OUT_EVENT 14 + +/* SYS_EVT_16-31 can be used for generating interrupts for IPC with hosts/prus etc */ +#define PRU_ARM_EVENT00 16 +#define PRU_ARM_EVENT01 17 +#define PRU_ARM_EVENT02 18 +#define PRU_ARM_EVENT03 19 +#define PRU_ARM_EVENT04 20 +#define PRU_ARM_EVENT05 21 +#define PRU_ARM_EVENT06 22 +#define PRU_ARM_EVENT07 23 +#define PRU_ARM_EVENT08 24 +#define PRU_ARM_EVENT09 25 +#define PRU_ARM_EVENT10 26 +#define PRU_ARM_EVENT11 27 +#define PRU_ARM_EVENT12 28 +#define PRU_ARM_EVENT13 29 +#define PRU_ARM_EVENT14 30 +#define PRU_ARM_EVENT15 31 + +#define PRU0_RX_ERR32_EVENT 33 +#define PORT1_TX_UNDERFLOW 39 +#define PORT1_TX_OVERFLOW 40 +#define MII_LINK0_EVENT 41 +#define PORT1_RX_EOF_EVENT 42 +#define PRU1_RX_ERR32_EVENT 45 +#define PORT2_TX_UNDERFLOW 51 +#define PORT2_TX_OVERFLOW 53 +#define PORT2_RX_EOF_EVENT 54 +#define MII_LINK1_EVENT 53 + +#define CHANNEL0 0 +#define CHANNEL1 1 +#define CHANNEL2 2 +#define CHANNEL3 3 +#define CHANNEL4 4 +#define CHANNEL5 5 +#define CHANNEL6 6 +#define CHANNEL7 7 +#define CHANNEL8 8 +#define CHANNEL9 9 + +#define PRU0 0 +#define PRU1 1 +#define PRU_EVTOUT0 2 +#define PRU_EVTOUT1 3 +#define PRU_EVTOUT2 4 +#define PRU_EVTOUT3 5 +#define PRU_EVTOUT4 6 +#define PRU_EVTOUT5 7 +#define PRU_EVTOUT6 8 +#define PRU_EVTOUT7 9 + +#define PRU0_HOSTEN_MASK ((uint32_t)0x0001) +#define PRU1_HOSTEN_MASK ((uint32_t)0x0002) +#define PRU_EVTOUT0_HOSTEN_MASK ((uint32_t)0x0004) +#define PRU_EVTOUT1_HOSTEN_MASK ((uint32_t)0x0008) +#define PRU_EVTOUT2_HOSTEN_MASK ((uint32_t)0x0010) +#define PRU_EVTOUT3_HOSTEN_MASK ((uint32_t)0x0020) +#define PRU_EVTOUT4_HOSTEN_MASK ((uint32_t)0x0040) +#define PRU_EVTOUT5_HOSTEN_MASK ((uint32_t)0x0080) +#define PRU_EVTOUT6_HOSTEN_MASK ((uint32_t)0x0100) +#define PRU_EVTOUT7_HOSTEN_MASK ((uint32_t)0x0200) + +#define SYS_EVT_POLARITY_LOW 0 +#define SYS_EVT_POLARITY_HIGH 1 + +#define SYS_EVT_TYPE_PULSE 0 +#define SYS_EVT_TYPE_EDGE 1 + +#define PRUICSS_INTC_INITDATA { \ +{ IEP_TIM_CAP_CMP_EVENT, PRU_ARM_EVENT02, PRU_ARM_EVENT03, PRU_ARM_EVENT04, PRU_ARM_EVENT05, PRU_ARM_EVENT06, \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* initializing member [6-15] for Misra C standards */ \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* initializing member [16-31] for Misra C standards */ \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* initializing member [32-47] for Misra C standards */ \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, /* initializing member [48-63] for Misra C standards */ \ +{ {IEP_TIM_CAP_CMP_EVENT, CHANNEL1, SYS_EVT_POLARITY_HIGH, SYS_EVT_TYPE_PULSE},\ + {PRU_ARM_EVENT02, CHANNEL2, SYS_EVT_POLARITY_HIGH, SYS_EVT_TYPE_PULSE},\ + {PRU_ARM_EVENT03, CHANNEL3, SYS_EVT_POLARITY_HIGH, SYS_EVT_TYPE_PULSE},\ + {PRU_ARM_EVENT04, CHANNEL4, SYS_EVT_POLARITY_HIGH, SYS_EVT_TYPE_PULSE},\ + {PRU_ARM_EVENT05, CHANNEL5, SYS_EVT_POLARITY_HIGH, SYS_EVT_TYPE_PULSE},\ + {PRU_ARM_EVENT06, CHANNEL6, SYS_EVT_POLARITY_HIGH, SYS_EVT_TYPE_PULSE},\ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [6] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [7] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [8] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [9] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [10] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [11] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [12] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [13] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [14] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [15] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [16] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [17] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [18] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [19] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [20] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [21] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [22] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [23] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [24] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [25] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [26] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [27] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [28] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [29] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [30] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [31] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [32] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [33] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [34] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [35] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [36] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [37] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [38] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [39] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [40] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [41] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [42] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [43] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [44] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [45] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [46] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [47] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [48] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [49] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [50] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [51] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [52] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [53] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [54] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [55] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [56] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [57] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [58] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [59] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [60] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [61] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}, /* initializing member [62] for Misra C standards */ \ + {0xFF,0xFF,0xFF,0xFF}}, /* initializing member [63] for Misra C standards */ \ + { {CHANNEL1, PRU1}, {CHANNEL2, PRU_EVTOUT0}, {CHANNEL3, PRU_EVTOUT1},\ + {CHANNEL4, PRU_EVTOUT2}, {CHANNEL5, PRU_EVTOUT3}, {CHANNEL6, PRU_EVTOUT4}, \ + {0xFF, 0xFF}, {0xFF, 0xFF}, {0xFF, 0xFF}, {0xFF, 0xFF} }, /* Initializing members [6,7,8,9] of array for Misra C standards */ \ + (PRU1_HOSTEN_MASK | PRU_EVTOUT0_HOSTEN_MASK | PRU_EVTOUT1_HOSTEN_MASK | PRU_EVTOUT2_HOSTEN_MASK | PRU_EVTOUT3_HOSTEN_MASK | PRU_EVTOUT4_HOSTEN_MASK) /* PRU_EVTOUT0 */ \ +} + +#ifdef __cplusplus +} +#endif + + +#endif /* TI_UART_PRUSS_INTC_MAPPING_H */ diff --git a/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss1-0_freertos/ESL_BOARD_OS_config.c b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss1-0_freertos/ESL_BOARD_OS_config.c new file mode 100644 index 0000000..38cd40d --- /dev/null +++ b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss1-0_freertos/ESL_BOARD_OS_config.c @@ -0,0 +1,298 @@ +/*! + * \file ESL_BOARD_OS_config.c + * + * \brief + * Board OS dependent configuration for FreeRTOS AM243X Launchpad. + * + * \author + * KUNBUS GmbH + * + * \copyright + * Copyright (c) 2021, KUNBUS GmbH

+ * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (c) 2023 KUNBUS GmbH. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + *
    + *
  1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer./
  2. + *
  3. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution.
  4. + *
  5. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission.
  6. + *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY + * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#include +#include +#include + +#include "ti_board_config.h" +#include "ti_board_open_close.h" + +const ESL_GPIO_STestPinCfg_t ESL_GPIO_testPinCfg_g[] = { +#if (defined CONFIG_GPIO_TEST0_PIN) + { .baseAddress = CONFIG_GPIO_TEST0_BASE_ADDR, .pinNumber = CONFIG_GPIO_TEST0_PIN, .pinDirection = CONFIG_GPIO_TEST0_DIR}, +#endif +#if (defined CONFIG_GPIO_TEST1_PIN) + { .baseAddress = CONFIG_GPIO_TEST1_BASE_ADDR, .pinNumber = CONFIG_GPIO_TEST1_PIN, .pinDirection = CONFIG_GPIO_TEST1_DIR}, +#endif +#if (defined CONFIG_GPIO_TEST2_PIN) + { .baseAddress = CONFIG_GPIO_TEST2_BASE_ADDR, .pinNumber = CONFIG_GPIO_TEST2_PIN, .pinDirection = CONFIG_GPIO_TEST2_DIR}, +#endif +#if (defined CONFIG_GPIO_TEST3_PIN) + { .baseAddress = CONFIG_GPIO_TEST3_BASE_ADDR, .pinNumber = CONFIG_GPIO_TEST3_PIN, .pinDirection = CONFIG_GPIO_TEST3_DIR}, +#endif +}; + +/*! + * + * + * \brief + * Initialize board status LED + * + * + * + * \param[in] pGpioHandle_p GPIO handle + * \param[in] selectedPru_p Pru Instance index + * + * + * + * \par Example + * \code{.c} + * + * // the Call + * ESL_BOARD_OS_initStatusLED(gpioHandle, EC_API_SLV_ePRUICSS_INSTANCE_ONE); + * \endcode + * + * + * + * \ingroup ESL_OS + * + * */ +void ESL_BOARD_OS_initStatusLED(void* pGpioHandle_p, uint32_t selectedPru_p) +{ + OSALUNREF_PARM(selectedPru_p); + +#if (defined GPIO_BANK_LEDSTATUS) && (defined GPIO_PIN_LEDSTATUS) + ESL_GPIO_setConfigMode(pGpioHandle_p, GPIO_BANK_LEDSTATUS, GPIO_PIN_LEDSTATUS, ESL_GPIO_enDIRECTION_MODE_OUTPUT, ESL_GPIO_enIRQ_MODE_NONE); +#endif +#if (defined GPIO_BANK_LEDERROR) && (defined GPIO_PIN_LEDERROR) + ESL_GPIO_setConfigMode(pGpioHandle_p, GPIO_BANK_LEDERROR, GPIO_PIN_LEDERROR, ESL_GPIO_enDIRECTION_MODE_OUTPUT, ESL_GPIO_enIRQ_MODE_NONE); +#endif +} + +/*! + * + * + * \brief + * Configure/control board status LED + * + * + * + * \param[in] pGpioHandle_p GPIO handle + * \param[in] selectedPru_p Pru Instance index + * \param[in] runLed_p Status LED on/off + * \param[in] errLed_p Error LED on/off + * + * + * + * \par Example + * \code{.c} + * + * // the Call + * ESL_BOARD_OS_statusLED(gpioHandle, EC_API_SLV_ePRUICSS_INSTANCE_ONE, true, false); + * \endcode + * + * + * + * \ingroup ESL_OS + * + * */ +void ESL_BOARD_OS_statusLED(void* pGpioHandle_p, uint32_t selectedPru_p, bool runLed_p, bool errLed_p) +{ + OSALUNREF_PARM(selectedPru_p); + OSALUNREF_PARM(pGpioHandle_p); + +#if !(defined FBTLPROVIDER) || (FBTLPROVIDER==0) + if (runLed_p) /* ioexp port 0 */ + { + ///LED_on(gLedHandle[CONFIG_LED_STATUS], 0); + } + else + { + ///LED_off(gLedHandle[CONFIG_LED_STATUS], 0); + } + + if (errLed_p) /* gpio */ + { + LED_on(gLedHandle[CONFIG_LED_ERROR], 0); + } + else + { + LED_off(gLedHandle[CONFIG_LED_ERROR], 0); + } +#endif +} + +/*! + * + * + * \brief + * Configure PHY reset lines + * + * + * + * \param[in] pGpioHandle_p GPIO driver handle. + * \param[in] selectedPru_p PRU instance number. + * + * + * + * \par Example + * \code{.c} + * #include + * + * // the call + * ESL_BOARD_OS_configureResets(gpioHandle, EC_API_SLV_ePRUICSS_INSTANCE_ONE); + * \endcode + * + * + * + * \ingroup ESL_OS + * + * */ +void ESL_BOARD_OS_configureResets(void* pGpioHandle_p, uint32_t selectedPru_p) +{ + OSALUNREF_PARM(selectedPru_p); + +#if (defined APP_PHYIN_RESET_MODULE) && (defined APP_PHYIN_RESET_PIN) && (defined APP_PHYOUT_RESET_MODULE) && (defined APP_PHYOUT_RESET_PIN) + ESL_GPIO_setConfigMode(pGpioHandle_p, APP_PHYIN_RESET_MODULE, APP_PHYIN_RESET_PIN, + ESL_GPIO_enDIRECTION_MODE_OUTPUT, ESL_GPIO_enIRQ_MODE_NONE); + ESL_GPIO_setConfigMode(pGpioHandle_p, APP_PHYOUT_RESET_MODULE, APP_PHYOUT_RESET_PIN, + ESL_GPIO_enDIRECTION_MODE_OUTPUT, ESL_GPIO_enIRQ_MODE_NONE); +#else +#error "No PHY reset pins defined" +#endif +} + +/*! + * + * + * \brief + * Issue PHY reset + * + * + * + * \param[in] pGpioHandle_p GPIO driver handle. + * \param[in] selectedPru_p PRU instance number. + * \param[in] phyIdx_p PHY identifier. + * \param[in] reset_p true: reset, false: run + * + * + * + * \par Example + * \code{.c} + * #include + * + * // the call + * ESL_BOARD_OS_phyReset(gpioHandle, EC_API_SLV_ePRUICSS_INSTANCE_ONE, EC_API_SLV_ePHY_IN, true); + * \endcode + * + * + * + * \ingroup ESL_OS + * + * */ +void ESL_BOARD_OS_phyReset(void* pGpioHandle_p, uint32_t selectedPru_p, uint8_t phyIdx_p, bool reset_p) +{ + uint8_t module = (uint8_t)~0; + uint8_t pin = (uint8_t)~0; + + OSALUNREF_PARM(selectedPru_p); + + switch(phyIdx_p) + { + case EC_API_SLV_ePHY_IN: + module = APP_PHYIN_RESET_MODULE; + pin = APP_PHYIN_RESET_PIN; + break; + case EC_API_SLV_ePHY_OUT: + module = APP_PHYOUT_RESET_MODULE; + pin = APP_PHYOUT_RESET_PIN; + break; + default: + return; + } + + if ((uint8_t)-1 == pin || (uint8_t)-1 == module) + { + OSAL_printf("Invalid PHY config %u\r\n", phyIdx_p); + OSAL_error(__func__, __LINE__, OSAL_STACK_PHYDETECT_ERROR, true, 0); + } + + if (reset_p) + { + OSAL_printf("Phy Reset: %u.%u\r\n", module, pin); + ESL_GPIO_write(pGpioHandle_p, (ESL_GPIO_EModule_t)module, (ESL_GPIO_EPin_t)pin, ESL_GPIO_enPINSTATE_LOW); + } + else + { + OSAL_printf("Phy UnReset: %u.%u\r\n", module, pin); + ESL_GPIO_write(pGpioHandle_p, (ESL_GPIO_EModule_t)module, (ESL_GPIO_EPin_t)pin, ESL_GPIO_enPINSTATE_HIGH); + } +} + +/*! + * + * + * \brief + * Register PHY descriptor to DTK + * + * + * + * \param[in] selectedPru_p PRU instance number. + * + * + * + * \par Example + * \code{.c} + * #include + * + * // the call + * ESL_BOARD_OS_registerPhys(EC_API_SLV_ePRUICSS_INSTANCE_ONE); + * \endcode + * + * + * + * \ingroup ESL_OS + * + * */ +void ESL_BOARD_OS_registerPhys(EC_API_SLV_SHandle_t *pHandle, uint32_t selectedPru_p) +{ +#if !(defined ECAT_PHYADDR_IN) && !(defined ECAT_PHYADDR_OUT) +#error "EtherCAT without PHY is useless" +#endif +#if !(defined DPRAM_REMOTE) && !(defined FBTL_REMOTE) + EC_API_SLV_registerPhy(pHandle, EC_API_SLV_ePHY_IN, ECAT_PHYADDR_IN, ECAT_PHYPOLINVERT_IN, ECAT_PHYUSERXLINK_IN); + EC_API_SLV_registerPhy(pHandle, EC_API_SLV_ePHY_OUT, ECAT_PHYADDR_OUT, ECAT_PHYPOLINVERT_OUT, ECAT_PHYUSERXLINK_OUT); +#endif +} + +//************************************************************************************************* diff --git a/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss1-0_freertos/ESL_cia402Demo.c b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss1-0_freertos/ESL_cia402Demo.c new file mode 100644 index 0000000..855373a --- /dev/null +++ b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss1-0_freertos/ESL_cia402Demo.c @@ -0,0 +1,1331 @@ +/*! + * \example ESL_cia402Demo.c + * + * \brief + * CiA 402 Callbacks Example. + * + * \author + * KUNBUS GmbH + * + * \copyright + * Copyright (c) 2020, KUNBUS GmbH

+ * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (c) 2023 KUNBUS GmbH. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + *
    + *
  1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer./
  2. + *
  3. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution.
  4. + *
  5. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission.
  6. + *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY + * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#include + +#include +#include + +#include "ecSlvCiA402.h" + +#include "ESL_cia402Demo.h" +#include "ESL_cia402Obd.h" +#include "ESL_gpioHelper.h" + +#if !(defined BIT2BYTE) +#define BIT2BYTE(x) (((x)+7) >> 3) +#endif + +/* if dynamic value change while OP is required, this costs 15usec per cycle ! */ +#define ENABLE_DYNAMIC_POSITION_LIMITS 0 + +/*! + * + * + * \brief + * Read CiA402 Axis value + * + * \details + * If objects are mapped and known (on SafeOP/OP) use direct access to linear process data memory + * when not mapped, use traditional PDO data API. + * + * + * + * \param[in] type_p Type of variable. + * \param[out] target_p Target to read value to. + * \param[in] axisDesc_p Axis variable descriptor. + * + * + * + * \ingroup CiA402 + * + */ +/* @cppcheck_justify{misra-c2012-20.7} brackets around type result in compile error */ +/* cppcheck-suppress misra-c2012-20.7 */ +#define EC_SLV_APP_CIA_GETAXISVALUE(gav_type, gav_target, gav_axisDesc) \ + { if (gotInOffset && (NULL != (gav_axisDesc).pdoObject)) { \ + (gav_target) = ((gav_type*)&(pApplication_p->pdRxBuffer[(gav_axisDesc).pdoOffset]))[0]; } else { \ + (void)EC_SLV_APP_getCiA402ObjectValue(pApplication_p, (gav_axisDesc).pSdo, sizeof(gav_type), (uint16_t*)&(gav_target)); } } + +/*! + * + * + * \brief + * Write CiA402 Axis value + * + * \details + * If objects are mapped and known (on SafeOP/OP) use direct access to linear process data memory + * when not mapped, use traditional PDO data API. + * + * + * + * \param[in] type_p Type of variable. + * \param[in] axisDesc_p Axis variable descriptor. + * \param[in] value_p Variable to write value from. + * + * + * + * \ingroup CiA402 + * + */ +/* @cppcheck_justify{misra-c2012-20.7} brackets around type result in compile error */ +/* cppcheck-suppress misra-c2012-20.7 */ +#define EC_SLV_APP_CIA_SETAXISVALUE(sav_type, sav_axisDesc, sav_value) \ + { if (gotOutOffset && (NULL != (sav_axisDesc).pdoObject)) { \ + ((sav_type*)&(pApplication_p->pdTxBuffer[(sav_axisDesc).pdoOffset]))[0] = (sav_value); } else { \ + (void)EC_SLV_APP_setCiA402ObjectValue(pApplication_p, &(sav_axisDesc), sizeof(sav_type), (uint16_t*)&(sav_value)); } } + +/** \brief Data structure to handle an CiA 402 axis */ +typedef struct EC_SLV_APP_CiA402_SAxis +{ + uint8_t id; /**< \brief Axis Identification */ + bool axisIsActive; /**< \brief Axis is active */ + bool brakeApplied; /**< \brief Motor brake is applied */ + bool lowLevelPowerApplied; /**< \brief Low-level power applied*/ + bool highLevelPowerApplied; /**< \brief High-level power applied*/ + bool axisFunctionEnabled; /**< \brief Axis functions enabled*/ + bool configurationAllowed; /**< \brief Configuration allowed*/ + double positionActualValue; /**< \brief Actual position within control loop*/ + uint32_t cycleTime; /**< \brief Motion controller cycletime in us*/ +} EC_SLV_APP_CiA402_SAxis_t; + +/*----------------------------------------------------------------------------------------- +------ +------ local variables and constants +------ +-----------------------------------------------------------------------------------------*/ +static EC_SLV_APP_CiA402_SAxis_t localAxes_s[AXES_NUMBER]; + +//Supported drive modes: ETG6010 6.8.1 +#define SUPPORTED_DRIVE_MODE_CSP_BIT (7u) +#define SUPPORTED_DRIVE_MODE_CSV_BIT (8u) +#define SUPPORTED_DRIVE_MODE_CST_BIT (9u) +#define DRIVE_MODE_CSP ((uint32_t)(1u << SUPPORTED_DRIVE_MODE_CSP_BIT)) +#define DRIVE_MODE_CSV ((uint32_t)(1u << SUPPORTED_DRIVE_MODE_CSV_BIT)) +#define DRIVE_MODE_CST ((uint32_t)(1u << SUPPORTED_DRIVE_MODE_CST_BIT)) + +#define DRIVE_GEAR_RELATION 0.0010922 +#define POSITION_MAX_LIMIT (0xFFFFFFFFu) + +#define NON_DC_DEFAULT_CYCLE_TIME_USEC (4000u) +#define NSEC_TO_USEC (1000u) +#define ESC_DC_SYNC0_CYCLETIME_REG (0x09A0u) + +/*! + * + * + * \brief + * Read CiA402 Objects + * \details + * + * + * + * \param[in] pApplication_p application Instance. + * \param[in] pObject_p CiA402 Object. + * \param[in] length_p Object length. + * \param[out] pValue_p Object Value. + * \return ErrorCode SDK Error code. + * + * + * + * \par Example + * \code{.c} + * #include + * + * // required variables + * void* pAppInstance; + * uint16_t index; + * uint8_t axis; + * int16_t* value; + * + * // the Call + * retVal = EC_SLV_APP_getCiA402ObjectValue(pAppInstance, index, axis, sizeof(value), &value); + * \endcode + * + * + * + * \ingroup CiA402 + * + */ +static uint32_t EC_SLV_APP_getCiA402ObjectValue(EC_SLV_APP_CIA_Application_t* pApplication_p, EC_API_SLV_SCoE_Object_t* pObject_p, uint16_t length_p, uint16_t* pValue_p) +{ + EC_API_SLV_SHandle_t* pEcApiSlv = NULL; + uint32_t err = EC_API_eERR_INVALID; + + if((NULL == pApplication_p) || (NULL == pObject_p)) + { + /* @cppcheck_justify{misra-c2012-15.1} goto is used to assure single point of exit */ + /* cppcheck-suppress misra-c2012-15.1 */ + goto Exit; + } + + pEcApiSlv = pApplication_p->ptEcSlvApi; + + err = EC_API_SLV_CoE_getObjectData(pEcApiSlv, pObject_p, length_p, pValue_p); + +Exit: + return err; +} + +/*! + * + * + * \brief + * Write CiA402 Object value. + * \remark + * Use OBD indexes described in ETG6010 Chapter 16. axis_p parameter calculates the axis object index. + * + * + * \param[in] pApplication_p application Instance. + * \param[in] pCiaObject_p CiA402 application object descriptor. + * \param[in] length_p Object length. + * \param[in] pValue_p Object Value. + * \return ErrorCode SDK Error code. + * + * + * + * \par Example + * \code{.c} + * #include + * + * // required variables + * EC_SLV_APP_Application_t* S_appInstance; + * EC_SLV_APP_sCIA_object_t object; + * int16_t* value; + * + * // the Call + * retVal = EC_SLV_APP_setCiA402ObjectValue(S_appInstance, &object, sizeof(value), &value); + * \endcode + * + * + * + * \ingroup CiA402 + * + */ +static uint32_t EC_SLV_APP_setCiA402ObjectValue(EC_SLV_APP_CIA_Application_t* pApplication_p, EC_SLV_APP_sCIA_object_t* pCiaObject_p, uint16_t length_p, uint16_t* pValue_p) +{ + uint32_t err; + EC_API_SLV_SCoE_Object_t* pObject = NULL; + + if (NULL != pCiaObject_p->pSdo) + { + pObject = pCiaObject_p->pSdo; + } + else + { + err = EC_API_SLV_CoE_getObject(pApplication_p->ptEcSlvApi, pCiaObject_p->objectIndex, &pObject); + if (0u != err) + { + /* @cppcheck_justify{misra-c2012-15.1} goto is used to assure single point of exit */ + /* cppcheck-suppress misra-c2012-15.1 */ + goto Exit; + } + } + + err = EC_API_SLV_CoE_setObjectData(pApplication_p->ptEcSlvApi, pObject, length_p, pValue_p); + +Exit: + return err; +} + +/*! + * + * + * \brief + * Read CiA402 Object entry. + * \details + * + * + * + * \param[in] pAppCtxt_p Application Instance. + * \param[in] pObjectEntry_p CiA402 Object entry. + * \param[in] length_p Object entry length. + * \param[in] pValue_p Object entry value. + * \return ErrorCode SDK Error code. + * + * + * + * \par Example + * \code{.c} + * #include + * + * // required variables + * EC_API_SLV_SCoE_Object_t* pObject; + * EC_API_SLV_SCoE_ObjEntry_t* pObjectEntry; + * int16_t* value; + * + * // the Call + * retVal = EC_SLV_APP_getCiA402ObjectEntryValue(appInst, pObjectEnry, sizeof(value), &value); + * \endcode + * + * + * + * \ingroup CiA402 + * + */ +uint32_t EC_SLV_APP_getCiA402ObjectEntryValue(void* pAppCtxt_p, EC_API_SLV_SCoE_ObjEntry_t* pObjectEntry_p, uint16_t length_p, uint16_t* pValue_p) +{ + uint32_t error = EC_API_eERR_INVALID; + EC_API_SLV_SHandle_t* pEcSlvApi = NULL; + /* @cppcheck_justify{misra-c2012-11.5} generic API requires cast */ + /* cppcheck-suppress misra-c2012-11.5 */ + EC_SLV_APP_CIA_Application_t* pApplication = (EC_SLV_APP_CIA_Application_t*)pAppCtxt_p; + + if (!pApplication || !pObjectEntry_p) + { + error = EC_API_eERR_NULLPTR; + /* @cppcheck_justify{misra-c2012-15.1} goto is used to assure single point of exit */ + /* cppcheck-suppress misra-c2012-15.1 */ + goto Exit; + } + + pEcSlvApi = pApplication->ptEcSlvApi; + + error = EC_API_SLV_CoE_getObjectEntryData(pEcSlvApi, pObjectEntry_p, length_p, pValue_p); + +Exit: + return error; +} + +/*! + * + * + * \brief + * Write CiA402 Object entry. + * \details + * + * + * + * \param[in] pEcApiSlv_p SDK Instance. + * \param[in] index_p CiA402 Object index. + * \param[in] subIndex_p CiA402 Object entry subIndex. + * \param[in] length_p Object entry length. + * \param[in] pValue_p Object entry value. + * \return ErrorCode SDK Error code. + * + * + * + * \par Example + * \code{.c} + * #include + * + * // required variables + * EC_API_SLV_SHandle_t* S_ecSlvApiHdl; + * uint16_t index; + * uint8_t subIndex; + * uint8_t axis; + * int16_t* value; + * + * // the Call + * retVal = EC_SLV_APP_setCiA402ObjectEntryValue(S_ecSlvApiHdl, index, subIndex, axis, sizeof(value), &value); + * \endcode + * + * + * + * \ingroup CiA402 + * + */ +static uint32_t EC_SLV_APP_setCiA402ObjectEntryValue(EC_API_SLV_SHandle_t* pEcApiSlv_p, uint16_t index_p, uint8_t subIndex_p, uint16_t length_p, uint16_t* pValue_p) +{ + EC_API_SLV_SCoE_ObjEntry_t* pObjEntry; + uint32_t err; + err = EC_API_SLV_CoE_getObjectEntry(pEcApiSlv_p,index_p, subIndex_p, &pObjEntry); + if (err == EC_API_eERR_NONE) + { + err = EC_API_SLV_CoE_setObjectEntryData(pEcApiSlv_p, pObjEntry, length_p, pValue_p); + } + return err; +} + +/*! + * + * + * \brief + * Set supported drive modes. + * + * \details + * Set object 0x6502 (Supported drive modes). Activate support for CSP and CSV profiles. + * Check ETG6010 Object Definitions for more information. + * + * + * \param[in] pApplication_p Application Instance. + * + * + * + * \par Example + * \code{.c} + * #include + * + * // required variables + * EC_API_SLV_SHandle_t* S_ecSlvApiHdl; + * + * // the call + * EC_SLV_APP_setCiA402ObjectValue(S_ecSlvApiHdl); + * \endcode + * + * + * + * \ingroup CiA402 + * + * */ +static uint32_t EC_SLV_APP_setSupportedDriveModes(EC_SLV_APP_CIA_Application_t* pApplication_p) +{ + uint32_t err; + /* @cppcheck_justify{misra-c2012-10.8} false positive on type conversion */ + /* cppcheck-suppress misra-c2012-10.8 */ + /* @cppcheck_justify{misra-c2012-12.2} false positive, assignment correct */ + /* cppcheck-suppress misra-c2012-12.2 */ + uint32_t driveMode = (uint32_t)(DRIVE_MODE_CSP | DRIVE_MODE_CSV | DRIVE_MODE_CST); + uint8_t axisNo; + + for(axisNo = 0u; axisNo < AXES_NUMBER; axisNo++) + { + err = EC_SLV_APP_setCiA402ObjectValue(pApplication_p, + &pApplication_p->CiA402_axisData[axisNo].supportedDriveModesIndex, + sizeof (driveMode), + /* @cppcheck_justify{misra-c2012-11.3} cast required for geeric API */ + /* cppcheck-suppress misra-c2012-11.3 */ + (uint16_t*) &driveMode); + } + return err; +} + + + +/*! + * + * + * \brief + * Set default values for CiA 402 object dictionary + * \details + * + * + * + * \param[in] pCtxt_p function context. + * + * + * + * \par Example + * \code{.c} + * #include + * + * // required variables + * EC_API_SLV_SHandle_t* S_ecSlvApiHdl; + * + * // the Call + * EC_SLV_APP_setObdValues(S_ecSlvApiHdl); + * \endcode + * + * + * + * \ingroup CiA402 + * + */ +void EC_SLV_APP_setObdValues(void* ctxt) +{ + /* @cppcheck_justify{misra-c2012-11.5} generic API requires cast */ + /* cppcheck-suppress misra-c2012-11.5 */ + EC_SLV_APP_CIA_Application_t* pApplicationInstance = (EC_SLV_APP_CIA_Application_t*)ctxt; + int32_t posMaxLimit = POSITION_MAX_LIMIT; + uint8_t axisNo; + + OSAL_printf("+%s\r\n", __func__); + + (void)EC_SLV_APP_setSupportedDriveModes(pApplicationInstance); + + for(axisNo = 0u; axisNo < AXES_NUMBER; axisNo++) + { + (void)EC_SLV_APP_setCiA402ObjectEntryValue( + pApplicationInstance->ptEcSlvApi, + OBD_SW_POSITION_LIMIT_INDEX(axisNo), + 2, + sizeof(posMaxLimit), + /* @cppcheck_justify{misra-c2012-11.3} generic API requires cast */ + /* cppcheck-suppress misra-c2012-11.3 */ + (uint16_t*) &posMaxLimit); + } +} + +/*! + * + * + * \brief + * Get cycle time information + * \details + * + * + * + * \param[in] pCtxt_p Callback context. + * \param[in] pIntMask_p Register 0x204 value. + * \return ErrorCode Closer description of ErrorCode, if required. + * + * + * + * \par Example + * \code{.c} + * #include + * + * // required variables + * EC_API_SLV_SHandle_t* S_ecSlvApiHdl; + * uint16_t intMask; + * + * // the Call + * retVal = EC_SLV_APP_CIA_startInputHandler(S_ecSlvApiHdl, &intMask); + * \endcode + * + * + * + * \ingroup CiA402 + * + */ +uint16_t EC_SLV_APP_CIA_startInputHandler(void* ctxt, uint16_t* intMask) +{ + /* @cppcheck_justify{misra-c2012-11.5} generic API requires cast */ + /* cppcheck-suppress misra-c2012-11.5 */ + EC_SLV_APP_CIA_Application_t* pApplicationInstance = (EC_SLV_APP_CIA_Application_t*)ctxt; + EC_API_SLV_SHandle_t* pEcApiSlv = NULL; + uint32_t sync0CycleTime = 0; + EC_API_SLV_EUserRetCodes_t retVal = EC_USR_eRET_ERROR; + uint8_t axisNo; + + OSALUNREF_PARM(intMask); + + if (NULL == pApplicationInstance) + { + /* @cppcheck_justify{misra-c2012-15.1} goto is used to assure single point of exit */ + /* cppcheck-suppress misra-c2012-15.1 */ + goto Exit; + } + + pEcApiSlv = pApplicationInstance->ptEcSlvApi; + + EC_API_SLV_readDoubleWordEscRegister(pEcApiSlv, ESC_DC_SYNC0_CYCLETIME_REG, &sync0CycleTime); + + sync0CycleTime = sync0CycleTime / NSEC_TO_USEC; //get cycle time in us + + for(axisNo = 0u; axisNo < AXES_NUMBER; axisNo++) + { + localAxes_s[axisNo].id = axisNo; + + if (localAxes_s[axisNo].axisIsActive) + { + localAxes_s[axisNo].cycleTime = sync0CycleTime; + } + if(!localAxes_s[axisNo].cycleTime) + { + localAxes_s[axisNo].cycleTime = NON_DC_DEFAULT_CYCLE_TIME_USEC; + } + OSALUNREF_PARM(localAxes_s[axisNo].brakeApplied); + OSALUNREF_PARM(localAxes_s[axisNo].lowLevelPowerApplied); + OSALUNREF_PARM(localAxes_s[axisNo].highLevelPowerApplied); + OSALUNREF_PARM(localAxes_s[axisNo].axisFunctionEnabled); + OSALUNREF_PARM(localAxes_s[axisNo].configurationAllowed); + } + + retVal = EC_USR_eRET_OK; +Exit: + return retVal; +} + +/*! + * + * + * \brief + * This function shall calculate the desired Axis input values to move on a predefined ramp. + * \details + * + * + * + * \param[in] characteristic_p Ramp description. + * \return bool True if transition finished. + * + * + * + * \par Example + * \code{.c} + * + * // required variables + * int16_t characteristic + * + * // the Call + * retVal = EC_SLV_APP_transitionAction(characteristic); + * \endcode + * + * + * + * \ingroup CiA402 + * + */ +static bool EC_SLV_APP_transitionAction(int16_t characteristic_p) +{ + switch(characteristic_p) + { + case SLOW_DOWN_RAMP: + //do stuff + break; + case QUICKSTOP_RAMP: + //do stuff + break; + case STOP_ON_CURRENT_LIMIT: + //do stuff + break; + case STOP_ON_VOLTAGE_LIMIT: + //do stuff + break; + default: + break; + } + + return true; +} + +/*! + * + * \brief + * Cyclic synchronous torque mode. ETG6010 6.4 + * + * + * + * \param[in] pApplication_p Application instance. + * \param[in] pCiA402Axis_p Servo Axis description structure. + * \param[in] gotInOffset got input offsets + * \param[in] gotOutOffset got output offsets + * + * + * + * \par Example + * \code{.c} + * #include + * + * // required variables + * EC_API_SLV_SHandle_t* S_ecSlvApiHdl; + * EC_SLV_APP_CiA402_SAxis_t* pCiA402Axis; + * + * // the Call + * EC_SLV_APP_CST(S_ecSlvApiHdl, pCiA402Axis); + * \endcode + * + * + * + * \ingroup CiA402 + * + * */ +static void EC_SLV_APP_CST( + EC_SLV_APP_CIA_Application_t *pApplication_p, + EC_SLV_APP_CiA402_SAxis_t *pCiA402Axis_p, + bool gotInOffset, + bool gotOutOffset) +{ + int16_t targetTorque; + + //Read target torque value + /* @cppcheck_justify{misra-c2012-11.3} type cast required */ + /* cppcheck-suppress misra-c2012-11.3 */ + EC_SLV_APP_CIA_GETAXISVALUE(int16_t, targetTorque, pApplication_p->CiA402_axisData[pCiA402Axis_p->id].targetTorqueIndex); + + //Update torque value + /* @cppcheck_justify{misra-c2012-11.3} type cast required */ + /* cppcheck-suppress misra-c2012-11.3 */ + EC_SLV_APP_CIA_SETAXISVALUE(int16_t, pApplication_p->CiA402_axisData[pCiA402Axis_p->id].torqueActualValueIndex, targetTorque); +} + +/*! + * + * + * \brief + * Cyclic synchronous velocity mode. ETG6010 6.3 + * + * + * + * \param[in] pApplication_p Application instance. + * \param[in] pCiA402Axis Servo Axis description structure. + * \param[in] gotInOffset got PDO in offset + * \param[in] gotOutOffset got PDO out offset + * + * + * + * \par Example + * \code{.c} + * #include + * + * // required variables + * EC_API_SLV_SHandle_t* S_ecSlvApiHdl; + * EC_SLV_API_CiA402_SAxis_t* pCiA402Axis; + * + * // the Call + * EC_SLV_APP_CSV(S_ecSlvApiHdl, pCiA402Axis); + * \endcode + * + * + * + * \ingroup CiA402 + * + * */ +__attribute__((section(".gEtherCatCia402"))) int32_t gCurTargetVelocity[3]; +__attribute__((section(".gEtherCatCia402"))) int32_t gCurActualVelocity[3]; +static void EC_SLV_APP_CSV( + EC_SLV_APP_CIA_Application_t *pApplication_p, + EC_SLV_APP_CiA402_SAxis_t *pCiA402Axis_p, + bool gotInOffset, + bool gotOutOffset) +{ + int32_t targetVelocity; + int32_t actualVelocity; + + //Read target velocity value + /* @cppcheck_justify{misra-c2012-11.3} type cast required */ + /* cppcheck-suppress misra-c2012-11.3 */ + EC_SLV_APP_CIA_GETAXISVALUE(int32_t, targetVelocity, pApplication_p->CiA402_axisData[pCiA402Axis_p->id].targetVelocityIndex); + + // Update the target velocity + gCurTargetVelocity[pCiA402Axis_p->id] = targetVelocity; + + // Update actual velocity + actualVelocity = gCurActualVelocity[pCiA402Axis_p->id]; + + // Write actual velocity value + EC_SLV_APP_CIA_SETAXISVALUE(int32_t, pApplication_p->CiA402_axisData[pCiA402Axis_p->id].velocityActualValueIndex, actualVelocity); +} + +/*! + * + * + * \brief + * Cyclic synchronous position mode. ETG6010 6.2 + * + * + * + * \param[in] pApplication_p application instance. + * \param[in] pCiA402Axis Servo Axis description structure. + * \param[in] gotOffsets got PDO offsets + * + * + * + * \par Example + * \code{.c} + * #include + * + * // required variables + * EC_API_SLV_SHandle_t* S_ecSlvApiHdl; + * EC_SLV_APP_CiA402_SAxis_t* pCiA402Axis; + * + * // the Call + * EC_SLV_APP_CSP(S_ecSlvApiHdl, pCiA402Axis); + * \endcode + * + * + * + * \ingroup CiA402 + * + * */ +static void EC_SLV_APP_CSP( + EC_SLV_APP_CIA_Application_t *pApplication_p, + EC_SLV_APP_CiA402_SAxis_t *pCiA402Axis_p, + bool gotInOffset, + bool gotOutOffset) +{ + uint32_t targetPosition = 0; + uint32_t actualPosition = 0; + int32_t targetVelocity = 0; + int32_t actualVelocity = 0; + int16_t targetTorque = 0; + int16_t actualTorque = 0; + + float incFactor = (float) (DRIVE_GEAR_RELATION * pCiA402Axis_p->cycleTime); + + //Read target position, velocity and torque values + /* @cppcheck_justify{misra-c2012-11.3} type cast required */ + /* cppcheck-suppress misra-c2012-11.3 */ + EC_SLV_APP_CIA_GETAXISVALUE(uint32_t, targetPosition, pApplication_p->CiA402_axisData[pCiA402Axis_p->id].targetPositionIndex); + /* @cppcheck_justify{misra-c2012-11.3} type cast required */ + /* cppcheck-suppress misra-c2012-11.3 */ + EC_SLV_APP_CIA_GETAXISVALUE(int32_t, targetVelocity, pApplication_p->CiA402_axisData[pCiA402Axis_p->id].targetVelocityIndex); + /* @cppcheck_justify{misra-c2012-11.3} type cast required */ + /* cppcheck-suppress misra-c2012-11.3 */ + EC_SLV_APP_CIA_GETAXISVALUE(int16_t, targetTorque, pApplication_p->CiA402_axisData[pCiA402Axis_p->id].targetTorqueIndex); + + OSALUNREF_PARM(targetVelocity); + OSALUNREF_PARM(targetTorque); + + //Read actual position, velocity and torque values + /* @cppcheck_justify{misra-c2012-11.3} type cast required */ + /* cppcheck-suppress misra-c2012-11.3 */ + EC_SLV_APP_CIA_GETAXISVALUE(uint32_t, actualPosition, pApplication_p->CiA402_axisData[pCiA402Axis_p->id].positionActualValueIndex); + /* @cppcheck_justify{misra-c2012-11.3} type cast required */ + /* cppcheck-suppress misra-c2012-11.3 */ + EC_SLV_APP_CIA_GETAXISVALUE(int32_t, actualVelocity, pApplication_p->CiA402_axisData[pCiA402Axis_p->id].velocityActualValueIndex); + /* @cppcheck_justify{misra-c2012-11.3} type cast required */ + /* cppcheck-suppress misra-c2012-11.3 */ + EC_SLV_APP_CIA_GETAXISVALUE(int16_t, actualTorque, pApplication_p->CiA402_axisData[pCiA402Axis_p->id].torqueActualValueIndex); + + OSALUNREF_PARM(actualTorque); + + if(0.0 != incFactor) + { + actualVelocity = (int32_t)(((targetPosition - actualPosition) * 1.0) / incFactor); + pCiA402Axis_p->positionActualValue = (double)(1.0*((int32_t)actualPosition + actualVelocity)); + } + + //Update position and velocity value + /* @cppcheck_justify{misra-c2012-11.3} type cast required */ + /* cppcheck-suppress misra-c2012-11.3 */ + EC_SLV_APP_CIA_SETAXISVALUE(int32_t, pApplication_p->CiA402_axisData[pCiA402Axis_p->id].velocityActualValueIndex, actualVelocity); + /* @cppcheck_justify{misra-c2012-11.3} type cast required */ + /* cppcheck-suppress misra-c2012-11.3 */ + EC_SLV_APP_CIA_SETAXISVALUE(uint32_t, pApplication_p->CiA402_axisData[pCiA402Axis_p->id].positionActualValueIndex, pCiA402Axis_p->positionActualValue); +} + +/*! + * + * + * \brief + * This functions provides a simple feedback functionality. + * \remarks + * Motion Controller shall only be triggered if application is trigger by DC Sync Signals + * and a valid mode of operation is set + * + * + * + * \param[in] pApplication_p application instance. + * \param[in] pCiA402Axis Servo Axis description structure. + * \param[in] gotInOffset got PDO in offsets + * \param[in] gotOutOffset got PDO out offsets + * + * + * + * \par Example + * \code{.c} + * #include + * + * // required variables + * EC_API_SLV_SHandle_t* S_ecSlvApiHdl; + * EC_SLV_APP_CiA402_SAxis_t* pCiA402Axis; + * + * // the Call + * retVal = EC_SLV_APP_motionControl(S_ecSlvApiHdl, pCiA402Axis); + * \endcode + * + * + * + * \ingroup CiA402 + * + * */ +static void EC_SLV_APP_motionControl( + EC_SLV_APP_CIA_Application_t *pApplication_p, + EC_SLV_APP_CiA402_SAxis_t *pCiA402Axis_p, + bool gotInOffset, + bool gotOutOffset) +{ + uint16_t statusWord = 0; + uint16_t controlWord = 0; + uint32_t targetPosition = 0; + uint32_t posMaxLimit = 0; + uint32_t posMinLimit = 0; + uint8_t operationModeDisplay = 0; + + if (!pApplication_p) + { + /* @cppcheck_justify{misra-c2012-15.1} goto is used to assure single point of exit */ + /* cppcheck-suppress misra-c2012-15.1 */ + goto Exit; + } + + //Read control, status and drive operation mode objects + /* @cppcheck_justify{misra-c2012-11.3} type cast required */ + /* cppcheck-suppress misra-c2012-11.3 */ + EC_SLV_APP_CIA_GETAXISVALUE(uint16_t, controlWord, pApplication_p->CiA402_axisData[pCiA402Axis_p->id].controlWordIndex); + /* @cppcheck_justify{misra-c2012-11.3} type cast required */ + /* cppcheck-suppress misra-c2012-11.3 */ + EC_SLV_APP_CIA_GETAXISVALUE(uint16_t, statusWord, pApplication_p->CiA402_axisData[pCiA402Axis_p->id].statusWordIndex); + /* @cppcheck_justify{misra-c2012-11.3} type cast required */ + /* cppcheck-suppress misra-c2012-11.3 */ + EC_SLV_APP_CIA_GETAXISVALUE(uint8_t, operationModeDisplay, pApplication_p->CiA402_axisData[pCiA402Axis_p->id].modesOfOperationDisplayIndex); + + //Read target position + /* @cppcheck_justify{misra-c2012-11.3} type cast required */ + /* cppcheck-suppress misra-c2012-11.3 */ + EC_SLV_APP_CIA_GETAXISVALUE(uint32_t, targetPosition, pApplication_p->CiA402_axisData[pCiA402Axis_p->id].targetPositionIndex); + + //Get software position limits +#if (defined ENABLE_DYNAMIC_POSITION_LIMITS) && (1==ENABLE_DYNAMIC_POSITION_LIMITS) /* if dynamic value change while OP is required, this costs 15usec per cycle ! */ + EC_SLV_APP_getCiA402ObjectEntryValue(pApplication_p, + pApplication_p->CiA402_axisData[pCiA402Axis_p->id].positionLimitMin.pObjetEntry, + sizeof(pApplication_p->CiA402_axisData[pCiA402Axis_p->id].posLimitMin), + (uint16_t *) &pApplication_p->CiA402_axisData[pCiA402Axis_p->id].posLimitMin); + EC_SLV_APP_getCiA402ObjectEntryValue(pApplication_p, + pApplication_p->CiA402_axisData[pCiA402Axis_p->id].positionLimitMax.pObjetEntry, + sizeof(pApplication_p->CiA402_axisData[pCiA402Axis_p->id].posLimitMax), + (uint16_t *) &pApplication_p->CiA402_axisData[pCiA402Axis_p->id].posLimitMax); +#endif + posMinLimit = pApplication_p->CiA402_axisData[pCiA402Axis_p->id].posLimitMin; + posMaxLimit = pApplication_p->CiA402_axisData[pCiA402Axis_p->id].posLimitMax; + + //Calculate new targets for CSP, CSV or CST modes + if(controlWord == CONTROLWORD_COMMAND_ENABLEOPERATION) + { + if(((posMaxLimit >= pCiA402Axis_p->positionActualValue) || (pCiA402Axis_p->positionActualValue >= targetPosition)) + &&((posMinLimit <= pCiA402Axis_p->positionActualValue) || (pCiA402Axis_p->positionActualValue <= targetPosition))) + { + statusWord &= ~STATUSWORD_INTERNAL_LIMIT; + + switch(operationModeDisplay) + { + case CYCLIC_SYNC_POSITION_MODE: + EC_SLV_APP_CSP(pApplication_p, pCiA402Axis_p, gotInOffset, gotOutOffset); + break; + case CYCLIC_SYNC_VELOCITY_MODE: + //nothing + EC_SLV_APP_CSV(pApplication_p, pCiA402Axis_p, gotInOffset, gotOutOffset); + break; + case CYCLIC_SYNC_TORQUE_MODE: + //nothing + EC_SLV_APP_CST(pApplication_p, pCiA402Axis_p, gotInOffset, gotOutOffset); + break; + default: + break; + } + } + else + { + statusWord |= STATUSWORD_INTERNAL_LIMIT; + } + } + + //Update drive status + /* @cppcheck_justify{misra-c2012-11.3} type cast required */ + /* cppcheck-suppress misra-c2012-11.3 */ + EC_SLV_APP_CIA_SETAXISVALUE(uint16_t, pApplication_p->CiA402_axisData[pCiA402Axis_p->id].statusWordIndex, statusWord); + + //Accept new mode of operation + /* @cppcheck_justify{misra-c2012-11.3} type cast required */ + /* cppcheck-suppress misra-c2012-11.3 */ + EC_SLV_APP_CIA_GETAXISVALUE(uint8_t, operationModeDisplay, pApplication_p->CiA402_axisData[pCiA402Axis_p->id].modesOfOperationIndex); + /* @cppcheck_justify{misra-c2012-11.3} type cast required */ + /* cppcheck-suppress misra-c2012-11.3 */ + EC_SLV_APP_CIA_SETAXISVALUE(uint8_t, pApplication_p->CiA402_axisData[pCiA402Axis_p->id].modesOfOperationDisplayIndex, operationModeDisplay); + +Exit: + return; +} + +/*! + * + * + * \brief + * CiA402 Application function. + * + * \details + * Write Control Word RxPDO to activate axis with value 7. + * Write to Operation Mode RxPDO the position, velocity or torque modes (8, 9, 10). + * Write Control Word RxPDO to enable axis operation with value 15. + * Write a target torque, velocity or position value to the RxPDO mapping. + * Read the TxPDO or OBD values of the actual position, velocity or torque. + * Read the TxPDO or OBD values of the status word and the operation mode display. + * + * \remarks + * If device goes into OP state without activating the axis, status goes into quickstop mode (4096). + * Reset quickstop status by activating the axis in control word object. + * + * + * + * \param[in] pCtxt_p EtherCAT slave handle. + * + * + * + * \par Example + * \code{.c} + * #include + * + * // required variables + * EC_API_SLV_SHandle_t* S_ecSlvApiHdl; + * + * // the Call + * EC_SLV_APP_cia402Application(ctxt); + * \endcode + * + * + * + * \ingroup CiA402 + * + * */ +void EC_SLV_APP_cia402Application(void* ctxt) +{ + /* @cppcheck_justify{misra-c2012-11.5} type cast required */ + /* cppcheck-suppress misra-c2012-11.5 */ + EC_SLV_APP_CIA_Application_t* pApplication_p = (EC_SLV_APP_CIA_Application_t*)ctxt; + EC_API_SLV_SHandle_t* pEcApiSlv = NULL; + /* @cppcheck_justify{threadsafety-threadsafety} not called re-entrant */ + /* cppcheck-suppress threadsafety-threadsafety */ + static bool gotInOffset = false; + static bool gotOutOffset = false; + bool gotOffsets = false; + uint8_t axisNo; + + uint16_t controlWord = 0; + uint16_t statusWord = 0; + uint16_t errorCode = 0; + int16_t quickStopOptionCode = 0; + int16_t shutdownOptionCode = 0; + int16_t disableOperationCode = 0; + int16_t faultReactionCode = 0; + uint8_t operationDisplayCode = 0; + + uint16_t driveRamp = DISABLE_DRIVE; + + EC_API_SLV_EEsmState_t curState = EC_API_SLV_eESM_uninit; + uint16_t alErrorCode = ALSTATUSCODE_NOERROR; + + uint32_t apiError; + + if (!pApplication_p) + { + /* @cppcheck_justify{misra-c2012-15.1} goto is used to assure single point of exit */ + /* cppcheck-suppress misra-c2012-15.1 */ + goto Exit; + } + + pEcApiSlv = pApplication_p->ptEcSlvApi; + +#if (defined GPIO_TEST_PINS) && (1==GPIO_TEST_PINS) +#if (defined GPIO_TEST_PROFILE_SEL) && (defined GPIO_TEST_PROFILE_1) && (GPIO_TEST_PROFILE_1 == GPIO_TEST_PROFILE_SEL) + ESL_GPIO_testPins_set(ESL_TESTPIN_STATE_REG_BANK, ESL_TESTPIN_2_MASK); +#endif +#endif + + EC_API_SLV_getState(pEcApiSlv, &curState, &alErrorCode); + + //OSAL_printf("0x%02x|0x%04x\r\n", curState, alErrorCode); + + curState &= ~EC_API_SLV_eESM_errState; + + if ((EC_API_SLV_eESM_op != curState) && (EC_API_SLV_eESM_safeop != curState) && (gotInOffset || gotOutOffset)) + { + (void)EC_SLV_APP_CiA_dropPDOffsets(pApplication_p); + pApplication_p->pdoOutLen = ~0; + pApplication_p->pdoInLen = ~0; + gotInOffset = gotOutOffset = false; + } + + if (((EC_API_SLV_eESM_op == curState) || (EC_API_SLV_eESM_safeop == curState)) && !gotInOffset) + { + (void)EC_SLV_APP_CiA_fetchPDOffsets(pApplication_p); + + EC_API_SLV_getInputProcDataLength(pApplication_p->ptEcSlvApi, &pApplication_p->pdoInLen); + pApplication_p->pdoInLen = BIT2BYTE(pApplication_p->pdoInLen); + + OSAL_printf( + "PDO size In:0x%x/0x%x\r\n", + pApplication_p->pdoInLen, + pApplication_p->realPdoInLen + ); + gotInOffset = true; + } + + if ((EC_API_SLV_eESM_op == curState) && !gotOutOffset) + { + gotOffsets = (gotInOffset && gotOutOffset); + (void)EC_SLV_APP_CiA_fetchPDOffsets(pApplication_p); + + EC_API_SLV_getOutputProcDataLength(pApplication_p->ptEcSlvApi, &pApplication_p->pdoOutLen); + pApplication_p->pdoOutLen = BIT2BYTE(pApplication_p->pdoOutLen); + + OSAL_printf( + "PDO size Out:0x%x/0x%x, In:0x%x/0x%x\r\n", + pApplication_p->pdoOutLen, + pApplication_p->realPdoOutLen, + pApplication_p->pdoInLen, + pApplication_p->realPdoInLen + ); + gotOutOffset = true; + } + +#if (defined GPIO_TEST_PINS) && (1==GPIO_TEST_PINS) +#if (defined GPIO_TEST_PROFILE_SEL) && (defined GPIO_TEST_PROFILE_1) && (GPIO_TEST_PROFILE_1 == GPIO_TEST_PROFILE_SEL) + ESL_GPIO_testPins_clear(ESL_TESTPIN_STATE_REG_BANK, ESL_TESTPIN_2_MASK); +#endif +#endif + +#if (defined GPIO_TEST_PINS) && (1==GPIO_TEST_PINS) +#if (defined GPIO_TEST_PROFILE_SEL) && (defined GPIO_TEST_PROFILE_1) && (GPIO_TEST_PROFILE_1 == GPIO_TEST_PROFILE_SEL) + ESL_GPIO_testPins_set(ESL_TESTPIN_STATE_REG_BANK, ESL_TESTPIN_2_MASK); +#endif +#endif + + if(((EC_API_SLV_eESM_op == curState) || (EC_API_SLV_eESM_safeop == curState)) && gotInOffset) + { + apiError = EC_API_SLV_preSeqInputPDBuffer( + pApplication_p->ptEcSlvApi, + pApplication_p->realPdoInLen, + (void**)&(pApplication_p->pdTxBuffer) + ); + + if(EC_API_eERR_BUSY == apiError) + { + goto Exit; + } + } + + if((EC_API_SLV_eESM_op == curState) && gotOutOffset) + { + apiError = EC_API_SLV_preSeqOutputPDBuffer( + pApplication_p->ptEcSlvApi, + pApplication_p->realPdoOutLen, + (void**)&(pApplication_p->pdRxBuffer) + ); + + if(EC_API_eERR_BUSY == apiError) + { + goto Exit; + } + } + + for(axisNo = 0; axisNo < AXES_NUMBER; axisNo++) + { + //Read drive control and status objects + /* @cppcheck_justify{misra-c2012-11.3} type cast required */ + /* cppcheck-suppress misra-c2012-11.3 */ + EC_SLV_APP_CIA_GETAXISVALUE(uint16_t, controlWord, pApplication_p->CiA402_axisData[axisNo].controlWordIndex); + /* @cppcheck_justify{misra-c2012-11.3} type cast required */ + /* cppcheck-suppress misra-c2012-11.3 */ + EC_SLV_APP_CIA_GETAXISVALUE(uint16_t, statusWord, pApplication_p->CiA402_axisData[axisNo].statusWordIndex); + + //Enable high level power, no torque on the motor. + if(controlWord == CONTROLWORD_COMMAND_SWITCHON) + { + OSAL_printf("Axis %d Activated\n\r", axisNo); + EC_API_SLV_CiA402_activateAxis(pEcApiSlv, axisNo, true); + } + + //Read drive's operation mode + /* @cppcheck_justify{misra-c2012-11.3} type cast required */ + /* cppcheck-suppress misra-c2012-11.3 */ + EC_SLV_APP_CIA_GETAXISVALUE(uint8_t, operationDisplayCode, pApplication_p->CiA402_axisData[axisNo].modesOfOperationDisplayIndex); + + //Read supported error option codes (ETG6010 Chapter 4). + EC_API_SLV_CiA402_SM_getErrorCode(pEcApiSlv, axisNo, &errorCode); + + if(errorCode && + ((operationDisplayCode == CYCLIC_SYNC_POSITION_MODE) || + (operationDisplayCode == CYCLIC_SYNC_VELOCITY_MODE) || + (operationDisplayCode == CYCLIC_SYNC_TORQUE_MODE))) + { + statusWord &= ~ STATUSWORD_DRIVE_FOLLOWS_COMMAND; + } + else + { + statusWord |= STATUSWORD_DRIVE_FOLLOWS_COMMAND; + } + + //Analyse error codes + switch(errorCode) + { + case OBD_QUICKSTOP_INDEX(0): + /*State transition 11 is pending analyse shutdown option code (0x605A)*/ + { + /* @cppcheck_justify{misra-c2012-11.3} type cast required */ + /* cppcheck-suppress misra-c2012-11.3 */ + EC_SLV_APP_CIA_GETAXISVALUE(uint16_t, quickStopOptionCode, pApplication_p->CiA402_axisData[axisNo].quickStopIndex); + + /*Masked and execute specified quick stop ramp characteristic */ + if((quickStopOptionCode >= SLOWDOWN_RAMP_NO_TRANSIT) && (quickStopOptionCode <= VOLTAGE_LIMIT_NO_TRANSIT)) + { + if (quickStopOptionCode == SLOWDOWN_RAMP_NO_TRANSIT) + { + driveRamp = SLOW_DOWN_RAMP; + } + if (quickStopOptionCode == QUICKSTOP_RAMP_NO_TRANSIT) + { + driveRamp = QUICKSTOP_RAMP; + } + if (quickStopOptionCode == CURRENT_LIMIT_NO_TRANSIT) + { + driveRamp = STOP_ON_CURRENT_LIMIT; + } + if (quickStopOptionCode == VOLTAGE_LIMIT_NO_TRANSIT) + { + driveRamp = STOP_ON_VOLTAGE_LIMIT; + } + } + + if(EC_SLV_APP_transitionAction(driveRamp)) + { + /*Quick stop ramp is finished complete state transition*/ + EC_API_SLV_CiA402_SM_clearErrorCode(pEcApiSlv, axisNo); + if ((quickStopOptionCode >= SLOWDOWN_RAMP_NO_TRANSIT) && (quickStopOptionCode <= VOLTAGE_LIMIT_NO_TRANSIT)) + { + statusWord |= STATUSWORD_TARGET_REACHED; + } + } + } + break; + case OBD_SHUTDOWN_INDEX(0): + /*State transition 8 is pending analyse shutdown option code (0x605B)*/ + { + /* @cppcheck_justify{misra-c2012-11.3} type cast required */ + /* cppcheck-suppress misra-c2012-11.3 */ + EC_SLV_APP_CIA_GETAXISVALUE(uint16_t, shutdownOptionCode, pApplication_p->CiA402_axisData[axisNo].shutdownIndex); + + if(EC_SLV_APP_transitionAction(shutdownOptionCode)) + { + /*shutdown ramp is finished complete state transition*/ + EC_API_SLV_CiA402_SM_clearErrorCode(pEcApiSlv, axisNo); + } + } + break; + case OBD_DISABLE_OPERATION_INDEX(0): + /*State transition 5 is pending analyse Disable operation option code (0x605C)*/ + { + /* @cppcheck_justify{misra-c2012-11.3} type cast required */ + /* cppcheck-suppress misra-c2012-11.3 */ + EC_SLV_APP_CIA_GETAXISVALUE(uint16_t, disableOperationCode, pApplication_p->CiA402_axisData[axisNo].disableOperationIndex); + + if(EC_SLV_APP_transitionAction(disableOperationCode)) + { + /*disable operation ramp is finished complete state transition*/ + EC_API_SLV_CiA402_SM_clearErrorCode(pEcApiSlv, axisNo); + } + } + break; + + case OBD_FAULT_REACTION_INDEX(0): + /*State transition 14 is pending analyse Fault reaction option code (0x605E)*/ + { + /* @cppcheck_justify{misra-c2012-11.3} type cast required */ + /* cppcheck-suppress misra-c2012-11.3 */ + EC_SLV_APP_CIA_GETAXISVALUE(uint16_t, faultReactionCode, pApplication_p->CiA402_axisData[axisNo].faultReactionIndex); + + if(EC_SLV_APP_transitionAction(faultReactionCode)) + { + /*fault reaction ramp is finished complete state transition*/ + EC_API_SLV_CiA402_SM_clearErrorCode(pEcApiSlv, axisNo); + } + } + break; + default: + //Pending transition code is invalid => values from the master are used + statusWord |= STATUSWORD_DRIVE_FOLLOWS_COMMAND; + break; + } + + /* @cppcheck_justify{misra-c2012-11.3} type cast required */ + /* cppcheck-suppress misra-c2012-11.3 */ + EC_SLV_APP_CIA_SETAXISVALUE(uint16_t, pApplication_p->CiA402_axisData[axisNo].statusWordIndex, statusWord); + +#if (defined GPIO_TEST_PINS) && (1==GPIO_TEST_PINS) +#if (defined GPIO_TEST_PROFILE_SEL) && (defined GPIO_TEST_PROFILE_1) && (GPIO_TEST_PROFILE_1 == GPIO_TEST_PROFILE_SEL) + ESL_GPIO_testPins_set(ESL_TESTPIN_STATE_REG_BANK, ESL_TESTPIN_1_MASK); +#endif +#endif + + EC_SLV_APP_motionControl(pApplication_p, &localAxes_s[axisNo], gotInOffset, gotOutOffset); + +#if (defined GPIO_TEST_PINS) && (1==GPIO_TEST_PINS) +#if (defined GPIO_TEST_PROFILE_SEL) && (defined GPIO_TEST_PROFILE_1) && (GPIO_TEST_PROFILE_1 == GPIO_TEST_PROFILE_SEL) + ESL_GPIO_testPins_clear(ESL_TESTPIN_STATE_REG_BANK, ESL_TESTPIN_1_MASK); +#endif +#endif + } + +Exit: + if((EC_API_SLV_eESM_op == curState) && gotOutOffset) + { + EC_API_SLV_postSeqOutputPDBuffer( + pApplication_p->ptEcSlvApi, + pApplication_p->realPdoOutLen, + pApplication_p->pdRxBuffer + ); + } + if(((EC_API_SLV_eESM_op == curState) || (EC_API_SLV_eESM_safeop == curState)) && gotInOffset) + { + EC_API_SLV_postSeqInputPDBuffer( + pApplication_p->ptEcSlvApi, + pApplication_p->realPdoInLen, + pApplication_p->pdTxBuffer + ); + } + +#if (defined GPIO_TEST_PINS) && (1==GPIO_TEST_PINS) +#if (defined GPIO_TEST_PROFILE_SEL) && (defined GPIO_TEST_PROFILE_1) && (GPIO_TEST_PROFILE_1 == GPIO_TEST_PROFILE_SEL) + ESL_GPIO_testPins_clear(ESL_TESTPIN_STATE_REG_BANK, ESL_TESTPIN_2_MASK); +#endif +#endif + return; +} + +/*! + * + * + * \brief + * Local Error function handler. + * \details + * Called if CiA402 state machine changes to an error state. + * + * + * \param[in] pCtxt_p function context. + * \param[in] errorCode_p error code. + * + * + * + * \par Example + * \code{.c} + * #include + * + * // required variables + * EC_API_SLV_SHandle_t* S_ecSlvApiHdl; + * uint16_t errorCode; + * + * // the Call + * retVal = EC_SLV_APP_cia402LocalError(S_ecSlvApiHdl, errorCode); + * \endcode + * + * + * + * \ingroup CiA402 + * + * */ +void EC_SLV_APP_cia402LocalError(void* ctxt, uint16_t errorCode) +{ + OSALUNREF_PARM(ctxt); + OSAL_printf("Local error triggered: 0x%04x\r\n", errorCode); +} + +//************************************************************************************************* diff --git a/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss1-0_freertos/example.syscfg b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss1-0_freertos/example.syscfg new file mode 100644 index 0000000..3c4d2c0 --- /dev/null +++ b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss1-0_freertos/example.syscfg @@ -0,0 +1,171 @@ +/** + * These arguments were used when this file was generated. They will be automatically applied on subsequent loads + * via the GUI or CLI. Run CLI with '--help' for additional information on how to override these arguments. + * @cliArgs --device "AM243x_ALX_beta" --package "ALX" --part "ALX" --context "r5fss1-0" --product "MOTOR_CONTROL_SDK_AM243x@09.01.00" + * @versions {"tool":"1.18.0+3266"} + */ + +/** + * Import the modules used in this configuration. + */ +const flash = scripting.addModule("/board/flash/flash", {}, false); +const flash1 = flash.addInstance(); +const led = scripting.addModule("/board/led/led", {}, false); +const led1 = led.addInstance(); +const gpio = scripting.addModule("/drivers/gpio/gpio", {}, false); +const gpio1 = gpio.addInstance(); +const gpio2 = gpio.addInstance(); +const gpio3 = gpio.addInstance(); +const pruicss = scripting.addModule("/drivers/pruicss/pruicss", {}, false); +const pruicss1 = pruicss.addInstance(); +const uart = scripting.addModule("/drivers/uart/uart", {}, false); +const uart1 = uart.addInstance(); +const ethercat = scripting.addModule("/industrial_comms/ethercat/ethercat", {}, false); +const ethercat1 = ethercat.addInstance(); +const clock = scripting.addModule("/kernel/dpl/clock"); +const debug_log = scripting.addModule("/kernel/dpl/debug_log"); +const mpu_armv7 = scripting.addModule("/kernel/dpl/mpu_armv7", {}, false); +const mpu_armv71 = mpu_armv7.addInstance(); +const mpu_armv72 = mpu_armv7.addInstance(); +const mpu_armv73 = mpu_armv7.addInstance(); +const mpu_armv74 = mpu_armv7.addInstance(); +const mpu_armv75 = mpu_armv7.addInstance(); +const mpu_armv76 = mpu_armv7.addInstance(); +const timer = scripting.addModule("/kernel/dpl/timer", {}, false); +const timer1 = timer.addInstance(); + +/** + * Write custom configuration values to the imported modules. + */ +flash1.$name = "CONFIG_FLASH0"; +flash1.peripheralDriver.$name = "CONFIG_OSPI0"; +flash1.peripheralDriver.inputClkFreq = 200000000; + +led1.$name = "CONFIG_LED_ERROR"; + +led1.peripheralDriver = gpio1; +gpio1.$name = "CONFIG_GPIO_LED_ERROR"; +gpio1.pinDir = "OUTPUT"; +gpio1.GPIO.gpioPin.rx = false; +gpio1.GPIO.gpioPin.$assign = "UART0_RTSn"; + +gpio2.$name = "CONFIG_GPIO0_PHYRESET0"; +gpio2.pinDir = "OUTPUT"; +gpio2.GPIO.gpioPin.rx = false; +gpio2.GPIO.gpioPin.$assign = "GPMC0_AD13"; + +gpio3.$name = "CONFIG_GPIO0_PHYRESET1"; +gpio3.pinDir = "OUTPUT"; +gpio3.GPIO.gpioPin.rx = false; +gpio3.GPIO.gpioPin.$assign = "PRG1_PRU1_GPO18"; + +uart1.$name = "CONFIG_UART_CONSOLE"; + +ethercat1.$name = "CONFIG_ETHERCAT0"; +ethercat1.instance = "ICSSG1"; +ethercat1.ethphy[0].$name = "CONFIG_ETHPHY0"; +ethercat1.ethphy[0].mdioPort = 3; +ethercat1.ethphy[1].$name = "CONFIG_ETHPHY1"; + +ethercat1.icss = pruicss1; +pruicss1.$name = "CONFIG_PRU_ICSS1"; +pruicss1.AdditionalICSSSettings[0].$name = "CONFIG_PRU_ICSS_IO0"; + +debug_log.enableLogZoneInfo = true; + +mpu_armv71.$name = "CONFIG_MPU_REGION0"; +mpu_armv71.size = 31; +mpu_armv71.attributes = "Device"; +mpu_armv71.allowExecute = false; + +mpu_armv72.$name = "CONFIG_MPU_REGION1"; +mpu_armv72.size = 15; +mpu_armv72.accessPermissions = "Supervisor RD+WR, User RD"; + +mpu_armv73.$name = "CONFIG_MPU_REGION2"; +mpu_armv73.baseAddr = 0x41010000; +mpu_armv73.size = 15; +mpu_armv73.accessPermissions = "Supervisor RD+WR, User RD"; + +mpu_armv74.$name = "CONFIG_MPU_REGION3"; +mpu_armv74.baseAddr = 0x70000000; +mpu_armv74.size = 21; +mpu_armv74.accessPermissions = "Supervisor RD+WR, User RD"; + +mpu_armv75.$name = "CONFIG_MPU_MSRAM_NOCACHE0"; +mpu_armv75.baseAddr = 0x701C0000; +mpu_armv75.size = 16; +mpu_armv75.allowExecute = false; +mpu_armv75.attributes = "NonCached"; + +mpu_armv76.baseAddr = 0x701D0000; +mpu_armv76.size = 16; +mpu_armv76.attributes = "NonCached"; +mpu_armv76.allowExecute = false; +mpu_armv76.$name = "CONFIG_MPU_MSRAM_NOCACHE1"; + +timer1.$name = "CONFIG_TIMER0"; +timer1.startTimer = true; +timer1.usecPerTick = 100; +timer1.timerCallback = "OSAL_FREERTOS_callbackTimer"; +timer1.TIMER.$assign = "DMTIMER4"; + +/** + * Pinmux solution for unlocked pins/peripherals. This ensures that minor changes to the automatic solver in a future + * version of the tool will not impact the pinmux you originally saw. These lines can be completely deleted in order to + * re-solve from scratch. + */ +flash1.peripheralDriver.OSPI.$suggestSolution = "OSPI0"; +flash1.peripheralDriver.OSPI.CLK.$suggestSolution = "OSPI0_CLK"; +flash1.peripheralDriver.OSPI.CSn0.$suggestSolution = "OSPI0_CSn0"; +flash1.peripheralDriver.OSPI.D3.$suggestSolution = "OSPI0_D3"; +flash1.peripheralDriver.OSPI.D2.$suggestSolution = "OSPI0_D2"; +flash1.peripheralDriver.OSPI.D1.$suggestSolution = "OSPI0_D1"; +flash1.peripheralDriver.OSPI.D0.$suggestSolution = "OSPI0_D0"; +gpio1.GPIO.$suggestSolution = "GPIO1"; +gpio2.GPIO.$suggestSolution = "GPIO0"; +gpio3.GPIO.$suggestSolution = "GPIO0"; +uart1.UART.$suggestSolution = "USART0"; +uart1.UART.RXD.$suggestSolution = "UART0_RXD"; +uart1.UART.TXD.$suggestSolution = "UART0_TXD"; +ethercat1.PRU_ICSSG1_MDIO.$suggestSolution = "PRU_ICSSG1_MDIO0"; +ethercat1.PRU_ICSSG1_MDIO.MDC.$suggestSolution = "PRG1_MDIO0_MDC"; +ethercat1.PRU_ICSSG1_MDIO.MDIO.$suggestSolution = "PRG1_MDIO0_MDIO"; +ethercat1.PRU_ICSSG1_IEP.$suggestSolution = "PRU_ICSSG1_IEP0"; +ethercat1.PRU_ICSSG1_IEP.EDC_LATCH_IN0.$suggestSolution = "PRG1_PRU0_GPO18"; +ethercat1.PRU_ICSSG1_IEP.EDC_LATCH_IN1.$suggestSolution = "PRG1_PRU0_GPO7"; +ethercat1.PRU_ICSSG1_IEP.EDC_SYNC_OUT0.$suggestSolution = "PRG1_PRU0_GPO19"; +ethercat1.PRU_ICSSG1_IEP.EDC_SYNC_OUT1.$suggestSolution = "PRG1_PRU0_GPO17"; +ethercat1.PRU_ICSSG1_IEP.EDIO_DATA_IN_OUT28.$suggestSolution = "PRG1_PRU0_GPO9"; +ethercat1.PRU_ICSSG1_IEP.EDIO_DATA_IN_OUT29.$suggestSolution = "PRG1_PRU0_GPO10"; +ethercat1.PRU_ICSSG1_IEP.EDIO_DATA_IN_OUT30.$suggestSolution = "PRG1_PRU1_GPO9"; +ethercat1.PRU_ICSSG1_IEP.EDIO_DATA_IN_OUT31.$suggestSolution = "PRG1_PRU1_GPO10"; +ethercat1.PRU_ICSSG1_MII_G_RT.$suggestSolution = "PRU_ICSSG1_MII_G_RT"; +ethercat1.PRU_ICSSG1_MII_G_RT.MII0_RXD0.$suggestSolution = "PRG1_PRU0_GPO0"; +ethercat1.PRU_ICSSG1_MII_G_RT.MII0_RXD1.$suggestSolution = "PRG1_PRU0_GPO1"; +ethercat1.PRU_ICSSG1_MII_G_RT.MII0_RXD2.$suggestSolution = "PRG1_PRU0_GPO2"; +ethercat1.PRU_ICSSG1_MII_G_RT.MII0_RXD3.$suggestSolution = "PRG1_PRU0_GPO3"; +ethercat1.PRU_ICSSG1_MII_G_RT.MII0_RXDV.$suggestSolution = "PRG1_PRU0_GPO4"; +ethercat1.PRU_ICSSG1_MII_G_RT.MII0_RXER.$suggestSolution = "PRG1_PRU0_GPO5"; +ethercat1.PRU_ICSSG1_MII_G_RT.MII0_RXLINK.$suggestSolution = "PRG1_PRU0_GPO8"; +ethercat1.PRU_ICSSG1_MII_G_RT.MII0_TXD0.$suggestSolution = "PRG1_PRU0_GPO11"; +ethercat1.PRU_ICSSG1_MII_G_RT.MII0_TXD1.$suggestSolution = "PRG1_PRU0_GPO12"; +ethercat1.PRU_ICSSG1_MII_G_RT.MII0_TXD2.$suggestSolution = "PRG1_PRU0_GPO13"; +ethercat1.PRU_ICSSG1_MII_G_RT.MII0_TXD3.$suggestSolution = "PRG1_PRU0_GPO14"; +ethercat1.PRU_ICSSG1_MII_G_RT.MII0_TXEN.$suggestSolution = "PRG1_PRU0_GPO15"; +ethercat1.PRU_ICSSG1_MII_G_RT.MII1_RXD0.$suggestSolution = "PRG1_PRU1_GPO0"; +ethercat1.PRU_ICSSG1_MII_G_RT.MII1_RXD1.$suggestSolution = "PRG1_PRU1_GPO1"; +ethercat1.PRU_ICSSG1_MII_G_RT.MII1_RXD2.$suggestSolution = "PRG1_PRU1_GPO2"; +ethercat1.PRU_ICSSG1_MII_G_RT.MII1_RXD3.$suggestSolution = "PRG1_PRU1_GPO3"; +ethercat1.PRU_ICSSG1_MII_G_RT.MII1_RXDV.$suggestSolution = "PRG1_PRU1_GPO4"; +ethercat1.PRU_ICSSG1_MII_G_RT.MII1_RXER.$suggestSolution = "PRG1_PRU1_GPO5"; +ethercat1.PRU_ICSSG1_MII_G_RT.MII1_RXLINK.$suggestSolution = "PRG1_PRU1_GPO8"; +ethercat1.PRU_ICSSG1_MII_G_RT.MII1_TXD0.$suggestSolution = "PRG1_PRU1_GPO11"; +ethercat1.PRU_ICSSG1_MII_G_RT.MII1_TXD1.$suggestSolution = "PRG1_PRU1_GPO12"; +ethercat1.PRU_ICSSG1_MII_G_RT.MII1_TXD2.$suggestSolution = "PRG1_PRU1_GPO13"; +ethercat1.PRU_ICSSG1_MII_G_RT.MII1_TXD3.$suggestSolution = "PRG1_PRU1_GPO14"; +ethercat1.PRU_ICSSG1_MII_G_RT.MII1_TXEN.$suggestSolution = "PRG1_PRU1_GPO15"; +ethercat1.PRU_ICSSG1_MII_G_RT.MII_MR0_CLK.$suggestSolution = "PRG1_PRU0_GPO6"; +ethercat1.PRU_ICSSG1_MII_G_RT.MII_MR1_CLK.$suggestSolution = "PRG1_PRU1_GPO6"; +ethercat1.PRU_ICSSG1_MII_G_RT.MII_MT0_CLK.$suggestSolution = "PRG1_PRU0_GPO16"; +ethercat1.PRU_ICSSG1_MII_G_RT.MII_MT1_CLK.$suggestSolution = "PRG1_PRU1_GPO16"; diff --git a/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss1-0_freertos/project.h b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss1-0_freertos/project.h new file mode 100644 index 0000000..ebc3ca1 --- /dev/null +++ b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss1-0_freertos/project.h @@ -0,0 +1,127 @@ +/*! + * \example project.h + * + * \brief + * EtherCAT_Slave_Simple project defines example. + * + * \author + * KUNBUS GmbH + * + * \copyright + * Copyright (c) 2021, KUNBUS GmbH

+ * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (c) 2023 KUNBUS GmbH. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + *
    + *
  1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer./
  2. + *
  3. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution.
  4. + *
  5. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission.
  6. + *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY + * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#if !(defined PROTECT_PROJECT_H) +#define PROTECT_PROJECT_H 1 + +/* @cppcheck_justify{misra-c2012-21.6} we need stdio for snprintf */ +/* cppcheck-suppress misra-c2012-21.6 */ +#include + +/* Brief description of purpose and functionality*/ + +#define EC_MAX_PD_LEN 1024 +#define EC_DEFAULT_PD_LEN 256 + +#define EC_REVISION 0x00010000 +#define EC_DEVICE_SERIALNUMBER 0xFFFFFFFF //replace with serial number from uboot + +#define ESC_EE_PDI_CONTROL 0x0C80 // 0x80 = On Chip PDI Type +#define ESC_EE_PDI_CONFIG 0x88E0 // ?? copy from TI + +#define COE_SDO_INFO_SUPPORTED 0x02 +#define COE_PDO_ASSIGN_SUPPORTED 0x04 +#define COE_PDO_CONFIG_SUPPORTED 0x08 +#define COE_PDO_UPLOAD_SUPPORTED 0x10 +#define COE_SDO_COMPLETE_ACCESS_SUPPORTED 0x20 + +#define EC_BOOTSTRAP_MBXOUT_START 0x1000 +#define EC_BOOTSTRAP_MBXOUT_DEF_LENGTH 256 + +#define EC_BOOTSTRAP_MBXIN_START 0x1200 +#define EC_BOOTSTRAP_MBXIN_DEF_LENGTH 256 + +#define EC_MBXOUT_START 0x1000 +#define EC_MBXOUT_DEF_LENGTH 256 +#define EC_MBXOUT_CONTROLREG 0x26 +#define EC_MBXOUT_ENABLE 1 + +#define EC_MBXIN_START EC_MBXOUT_START + EC_MBXOUT_DEF_LENGTH +#define EC_MBXIN_DEF_LENGTH 256 +#define EC_MBXIN_CONTROLREG 0x22 +#define EC_MBXIN_ENABLE 1 + +#define EC_OUTPUT_START EC_MBXIN_START + EC_MBXIN_DEF_LENGTH +#define EC_OUTPUT_CONTROLREG 0x64 +#define EC_OUTPUT_DEF_LENGTH (EC_MAX_PD_LEN * 3) //in Bytes +#define EC_OUTPUT_ENABLE 1 + +#define EC_INPUT_START EC_OUTPUT_START + EC_OUTPUT_DEF_LENGTH +#define EC_INPUT_CONTROLREG 0x20 +#define EC_INPUT_DEF_LENGTH (EC_MAX_PD_LEN * 3) //in Bytes +#define EC_INPUT_ENABLE 1 + +/* pru/ecat address settings of shared ram */ +#define MIN_PD_READ_ADDRESS 0x1000 // ti register offset +#define MIN_PD_WRITE_ADDRESS 0x1000 +#define MIN_MBX_WRITE_ADDRESS 0x1000 +#define MIN_MBX_READ_ADDRESS 0x1000 + +/*#define OS_TICKS_IN_MILLI_SEC 10 // 100us tick */ +#define OS_TICKS_IN_MILLI_SEC 1 /* 1000us tick */ +/* task priorities */ +#ifndef BSP_OS_MAX_TASKS +#define BSP_OS_MAX_TASKS 20 +#endif + +#define KBECSLV_PRIO_PDI OSAL_TASK_Prio_ECPDI +#define KBECSLV_PRIO_SYNC0 OSAL_TASK_Prio_ECSync +#define KBECSLV_PRIO_SYNC1 OSAL_TASK_Prio_ECSync +#define KBECSLV_PRIO_EOE OSAL_TASK_Prio_ECEoE +#define KBECSLV_PRIO_LED OSAL_TASK_Prio_ECLED + +#define OSPIFLASH_APP_STARTMAGIC \ +/* @cppcheck_justify{misra-c2012-11.6} void cast required for signature */ \ + /* cppcheck-suppress misra-c2012-11.6 */ \ + ((void*)0xEE11AA44u) + +#if (defined __cplusplus) +extern "C" { +#endif + +/* extern void func(void); */ + +#if (defined __cplusplus) +} +#endif + +#endif /* PROTECT_PROJECT_H */ diff --git a/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss1-0_freertos/ti-arm-clang/example.projectspec b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss1-0_freertos/ti-arm-clang/example.projectspec new file mode 100644 index 0000000..261a10d --- /dev/null +++ b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss1-0_freertos/ti-arm-clang/example.projectspec @@ -0,0 +1,171 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss1-0_freertos/ti-arm-clang/linker.cmd b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss1-0_freertos/ti-arm-clang/linker.cmd new file mode 100644 index 0000000..94ab158 --- /dev/null +++ b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss1-0_freertos/ti-arm-clang/linker.cmd @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2020, Texas Instruments Incorporated + * Copyright (c) 2023, KUNBUS GmbH + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * + * Neither the name of Texas Instruments Incorporated nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +--stack_size=0x8000 +--heap_size=0x30000 + +-e_vectors + +__IRQ_STACK_SIZE = 0x200; +__FIQ_STACK_SIZE = 0x200; +__SVC_STACK_SIZE = 0x200; +__ABORT_STACK_SIZE = 512; +__UNDEFINED_STACK_SIZE = 0x200; + +SECTIONS +{ + .vectors:{} palign(8) > R5F_VECS + .init_array: palign(8) > MSRAM_1_0 + .fini_array: palign(8) > MSRAM_1_0 + + GROUP { + .text.hwi: palign(8) + .text.cache: palign(8) + .text.mpu: palign(8) + .text.boot: palign(8) + .text:abort: palign(8) /* this helps in loading symbols when using XIP mode */ + } > MSRAM_1_0 + + GROUP { + .text: {} palign(8) + .rodata: {} palign(8) + } > MSRAM_1_0 + + GROUP { + .data: {} palign(8) + } > MSRAM_1_0 + + GROUP { + .bss: {} palign(8) FILL(0x00000000) + RUN_START(__BSS_START) + RUN_END(__BSS_END) + .threadstack: {} palign(8) FILL(0x00000000) + .stack: {} palign(8) FILL(0x00000000) + } > MSRAM_1_0 + + GROUP { + .sysmem: {} palign(8) + } > EXTRAHEAP + + GROUP { + .irqstack: {. = . + __IRQ_STACK_SIZE;} align(8) + RUN_START(__IRQ_STACK_START) + RUN_END(__IRQ_STACK_END) + .fiqstack: {. = . + __FIQ_STACK_SIZE;} align(8) + RUN_START(__FIQ_STACK_START) + RUN_END(__FIQ_STACK_END) + .svcstack: {. = . + __SVC_STACK_SIZE;} align(8) + RUN_START(__SVC_STACK_START) + RUN_END(__SVC_STACK_END) + .abortstack: {. = . + __ABORT_STACK_SIZE;} align(8) + RUN_START(__ABORT_STACK_START) + RUN_END(__ABORT_STACK_END) + .undefinedstack: {. = . + __UNDEFINED_STACK_SIZE;} align(8) + RUN_START(__UNDEFINED_STACK_START) + RUN_END(__UNDEFINED_STACK_END) + } > MSRAM_1_0 + + /* General purpose user shared memory */ + .bss.user_shared_mem (NOLOAD) : {} > USER_SHM_MEM + /* this is used when Debug log's to shared memory are enabled, else this is not used */ + .bss.log_shared_mem (NOLOAD) : {} > LOG_SHM_MEM + /* this is used only when IPC RPMessage is enabled, else this is not used */ + .bss.ipc_vring_mem (NOLOAD) : {} > RTOS_NORTOS_IPC_SHM_MEM + //.bss.nocache (NOLOAD) : {} > NON_CACHE_MEM + .gEtherCatCia402 (NOLOAD) : {} palign(4) > MSRAM_NO_CACHE +} + +/* +NOTE: Below memory is reserved for DMSC usage + - During Boot till security handoff is complete + 0x701E0000 - 0x701FFFFF (128KB) + - After "Security Handoff" is complete (i.e at run time) + 0x701FC000 - 0x701FFFFF (16KB) + + Security handoff is complete when this message is sent to the DMSC, + TISCI_MSG_SEC_HANDOVER + + This should be sent once all cores are loaded and all application + specific firewall calls are setup. +*/ + +MEMORY +{ + R5F_VECS : ORIGIN = 0x00000000 , LENGTH = 0x00000040 + R5F_TCMA : ORIGIN = 0x00000040 , LENGTH = 0x00007FC0 + R5F_TCMB0: ORIGIN = 0x41010000 , LENGTH = 0x00008000 + + MSRAM_1_0 : ORIGIN = 0x700C0000 , LENGTH = 0x00070000 + EXTRAHEAP: ORIGIN = 0x70008000 , LENGTH = 0x00038000 + + /* shared memories that are used by all cores */ + /* On R5F, + * - make sure there is a MPU entry which maps below regions as non-cache + */ + USER_SHM_MEM : ORIGIN = 0x701D0000, LENGTH = 0x00004000 + LOG_SHM_MEM : ORIGIN = 0x701D4000, LENGTH = 0x00004000 + RTOS_NORTOS_IPC_SHM_MEM : ORIGIN = 0x701D8000, LENGTH = 0x00008000 + MSRAM_NO_CACHE : ORIGIN = 0x701C0000, LENGTH = 0x100 + +} diff --git a/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss1-0_freertos/ti-arm-clang/makefile b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss1-0_freertos/ti-arm-clang/makefile new file mode 100644 index 0000000..7d3ac70 --- /dev/null +++ b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss1-0_freertos/ti-arm-clang/makefile @@ -0,0 +1,326 @@ +# +# Auto generated makefile +# + +export MOTOR_CONTROL_SDK_PATH?=$(abspath ../../../../../..) +include $(MOTOR_CONTROL_SDK_PATH)/imports.mak +include $(MOTOR_CONTROL_SDK_PATH)/devconfig/devconfig.mak + +CG_TOOL_ROOT=$(CGT_TI_ARM_CLANG_PATH) + +CC=$(CG_TOOL_ROOT)/bin/tiarmclang +LNK=$(CG_TOOL_ROOT)/bin/tiarmclang +STRIP=$(CG_TOOL_ROOT)/bin/tiarmstrip +OBJCOPY=$(CG_TOOL_ROOT)/bin/tiarmobjcopy +ifeq ($(OS), Windows_NT) + PYTHON=python +else + PYTHON=python3 +endif + +PROFILE?=release +ConfigName:=$(PROFILE) + +OUTNAME:=single_chip_servo.$(PROFILE).out + +BOOTIMAGE_PATH=$(abspath .) +BOOTIMAGE_NAME:=single_chip_servo.$(PROFILE).appimage +BOOTIMAGE_NAME_XIP:=single_chip_servo.$(PROFILE).appimage_xip +BOOTIMAGE_NAME_SIGNED:=single_chip_servo.$(PROFILE).appimage.signed +BOOTIMAGE_RPRC_NAME:=single_chip_servo.$(PROFILE).rprc +BOOTIMAGE_RPRC_NAME_XIP:=single_chip_servo.$(PROFILE).rprc_xip +BOOTIMAGE_RPRC_NAME_TMP:=single_chip_servo.$(PROFILE).rprc_tmp + +FILES_common := \ + ind_comms_sdk/examples/industrial_comms/ethercat_slave_demo/common/ESL_version.c \ + ind_comms_sdk/examples/industrial_comms/ethercat_slave_demo/common/os/freertos/ESL_OS_os.c \ + ind_comms_sdk/examples/industrial_comms/ethercat_slave_demo/common/os/freertos/ESL_eeprom.c \ + ind_comms_sdk/examples/industrial_comms/ethercat_slave_demo/common/os/freertos/ESL_fileHandling.c \ + ind_comms_sdk/examples/industrial_comms/ethercat_slave_demo/common/os/freertos/ESL_foeDemo.c \ + ind_comms_sdk/examples/industrial_comms/ethercat_slave_demo/common/os/freertos/ESL_soeDemo.c \ + ind_comms_sdk/examples/industrial_comms/ethercat_slave_demo/common/os/freertos/ESL_gpioHelper.c \ + ind_comms_sdk/examples/industrial_comms/custom_phy/src/CUST_PHY_base.c \ + ind_comms_sdk/examples/industrial_comms/custom_phy/src/CUST_PHY_dp83869.c \ + ind_comms_sdk/examples/industrial_comms/ethercat_slave_demo/device_profiles/402_cia/ecSlvCiA402.c \ + ind_comms_sdk/examples/industrial_comms/ethercat_slave_demo/device_profiles/402_cia/ESL_cia402Obd.c \ + ind_comms_sdk/examples/industrial_comms/ethercat_slave_demo/device_profiles/402_cia/EtherCAT_Slave_CiA402.c \ + ESL_cia402Demo.c \ + ESL_BOARD_OS_config.c \ + ti_drivers_config.c \ + ti_drivers_open_close.c \ + ti_board_config.c \ + ti_board_open_close.c \ + ti_dpl_config.c \ + ti_pinmux_config.c \ + ti_power_clock_config.c \ + +FILES_PATH_common = \ + .. \ + ../../.. \ + ../../../../../.. \ + generated \ + +INCLUDES_common := \ + -I${CG_TOOL_ROOT}/include/c \ + -I${MOTOR_CONTROL_SDK_PATH}/mcu_plus_sdk/source \ + -I${MOTOR_CONTROL_SDK_PATH}/source \ + -I${CG_TOOL_ROOT}/include/c \ + -I${MOTOR_CONTROL_SDK_PATH}/mcu_plus_sdk/source \ + -I${MOTOR_CONTROL_SDK_PATH}/ind_comms_sdk/source \ + -I${MOTOR_CONTROL_SDK_PATH}/mcu_plus_sdk/source/kernel/freertos/FreeRTOS-Kernel/include \ + -I${MOTOR_CONTROL_SDK_PATH}/mcu_plus_sdk/source/kernel/freertos/portable/TI_ARM_CLANG/ARM_CR5F \ + -I${MOTOR_CONTROL_SDK_PATH}/mcu_plus_sdk/source/kernel/freertos/config/am243x/r5f \ + -I${MOTOR_CONTROL_SDK_PATH}/ind_comms_sdk/examples/industrial_comms/ethercat_slave_demo/device_profiles/402_cia \ + -I${MOTOR_CONTROL_SDK_PATH}/ind_comms_sdk/examples/industrial_comms/ethercat_slave_demo/common \ + -I${MOTOR_CONTROL_SDK_PATH}/ind_comms_sdk/examples/industrial_comms/ethercat_slave_demo/common/os \ + -I${MOTOR_CONTROL_SDK_PATH}/ind_comms_sdk/examples/industrial_comms/ethercat_slave_demo/common/os/freertos \ + -I${MOTOR_CONTROL_SDK_PATH}/ind_comms_sdk/examples/industrial_comms/ethercat_slave_demo/common/board/am243lp \ + -I${MOTOR_CONTROL_SDK_PATH}/ind_comms_sdk/examples/industrial_comms/ethercat_slave_demo/common/board/am243lp/freertos \ + -I${MOTOR_CONTROL_SDK_PATH}/ind_comms_sdk/examples/industrial_comms/custom_phy/inc \ + -I${MOTOR_CONTROL_SDK_PATH}/ind_comms_sdk/source/industrial_comms/ethercat_slave/stack/inc \ + -I${MOTOR_CONTROL_SDK_PATH}/ind_comms_sdk/source/industrial_comms/common/inc \ + -Igenerated \ + +DEFINES_common := \ + -DSOC_AM243X \ + -DSOC_AM243X=1 \ + -DOSAL_FREERTOS=1 \ + -Dcore0 \ + -Dam243x \ + -Dam243x_lp \ + -DSSC_CHECKTIMER=1 \ + -DUSE_ECAT_TIMER=1 \ + +CFLAGS_common := \ + -mcpu=cortex-r5 \ + -mfloat-abi=hard \ + -mfpu=vfpv3-d16 \ + -mthumb \ + -Wall \ + -Werror \ + -g \ + -Wno-gnu-variable-sized-type-not-at-end \ + -Wno-unused-function \ + -Wno-unused-but-set-variable \ + +CFLAGS_debug := \ + -D_DEBUG_=1 \ + -O0 \ + +CFLAGS_cpp_common := \ + -Wno-c99-designator \ + -Wno-extern-c-compat \ + -Wno-c++11-narrowing \ + -Wno-reorder-init-list \ + -Wno-deprecated-register \ + -Wno-writable-strings \ + -Wno-enum-compare \ + -Wno-reserved-user-defined-literal \ + -Wno-unused-const-variable \ + -x c++ \ + +CFLAGS_release := \ + -Os \ + +LNK_FILES_common = \ + linker.cmd \ + +LIBS_PATH_common = \ + -Wl,-i${CG_TOOL_ROOT}/lib \ + -Wl,-i${MOTOR_CONTROL_SDK_PATH}/mcu_plus_sdk/source/kernel/freertos/lib \ + -Wl,-i${MOTOR_CONTROL_SDK_PATH}/mcu_plus_sdk/source/drivers/lib \ + -Wl,-i${MOTOR_CONTROL_SDK_PATH}/mcu_plus_sdk/source/board/lib \ + -Wl,-i${MOTOR_CONTROL_SDK_PATH}/ind_comms_sdk/source/industrial_comms/ethercat_slave/stack/lib \ + -Wl,-i${CG_TOOL_ROOT}/lib \ + +LIBS_common = \ + -llibc.a \ + -llibsysbm.a \ + -lfreertos.am243x.r5f.ti-arm-clang.${ConfigName}.lib \ + -ldrivers.am243x.r5f.ti-arm-clang.${ConfigName}.lib \ + -lboard.am243x.r5f.ti-arm-clang.${ConfigName}.lib \ + -lethercat_slave.am243x_lp.r5f.ti-arm-clang.${ConfigName}.lib \ + -lethercat_slave_bkhfSsc.am243x_lp.r5f.ti-arm-clang.${ConfigName}.lib \ + -llibc.a \ + -llibsysbm.a \ + +LFLAGS_common = \ + -Wl,--diag_suppress=10063 \ + -Wl,--ram_model \ + -Wl,--reread_libs \ + -Wl,--use_memcpy=fast \ + -Wl,--use_memset=fast \ + + +LIBS_NAME = \ + libc.a \ + libsysbm.a \ + freertos.am243x.r5f.ti-arm-clang.${ConfigName}.lib \ + drivers.am243x.r5f.ti-arm-clang.${ConfigName}.lib \ + board.am243x.r5f.ti-arm-clang.${ConfigName}.lib \ + ethercat_slave.am243x_lp.r5f.ti-arm-clang.${ConfigName}.lib \ + ethercat_slave_bkhfSsc.am243x_lp.r5f.ti-arm-clang.${ConfigName}.lib \ + libc.a \ + libsysbm.a \ + +LIBS_PATH_NAME = \ + ${CG_TOOL_ROOT}/lib \ + ${MOTOR_CONTROL_SDK_PATH}/mcu_plus_sdk/source/kernel/freertos/lib \ + ${MOTOR_CONTROL_SDK_PATH}/mcu_plus_sdk/source/drivers/lib \ + ${MOTOR_CONTROL_SDK_PATH}/mcu_plus_sdk/source/board/lib \ + ${MOTOR_CONTROL_SDK_PATH}/ind_comms_sdk/source/industrial_comms/ethercat_slave/stack/lib \ + ${CG_TOOL_ROOT}/lib \ + +FILES := $(FILES_common) $(FILES_$(PROFILE)) +ASMFILES := $(ASMFILES_common) $(ASMFILES_$(PROFILE)) +FILES_PATH := $(FILES_PATH_common) $(FILES_PATH_$(PROFILE)) +CFLAGS := $(CFLAGS_common) $(CFLAGS_$(PROFILE)) +DEFINES := $(DEFINES_common) $(DEFINES_$(PROFILE)) +INCLUDES := $(INCLUDES_common) $(INCLUDE_$(PROFILE)) +LIBS := $(LIBS_common) $(LIBS_$(PROFILE)) +LIBS_PATH := $(LIBS_PATH_common) $(LIBS_PATH_$(PROFILE)) +LFLAGS := $(LFLAGS_common) $(LFLAGS_$(PROFILE)) +LNKOPTFLAGS := $(LNKOPTFLAGS_common) $(LNKOPTFLAGS_$(PROFILE)) +LNK_FILES := $(LNK_FILES_common) $(LNK_FILES_$(PROFILE)) + +OBJDIR := obj/$(PROFILE)/ +OBJS := $(FILES:%.c=%.obj) +OBJS += $(ASMFILES:%.S=%.obj) +DEPS := $(FILES:%.c=%.d) + +vpath %.obj $(OBJDIR) +vpath %.c $(FILES_PATH) +vpath %.S $(FILES_PATH) +vpath %.lib $(LIBS_PATH_NAME) +vpath %.a $(LIBS_PATH_NAME) + +$(OBJDIR)/%.obj %.obj: %.c + @echo Compiling: am243x:r5fss1-0:freertos:ti-arm-clang $(OUTNAME): $< + $(CC) -c $(CFLAGS) $(INCLUDES) $(DEFINES) -MMD -o $(OBJDIR)/$@ $< + +$(OBJDIR)/%.obj %.obj: %.S + @echo Compiling: am243x:r5fss1-0:freertos:ti-arm-clang $(LIBNAME): $< + $(CC) -c $(CFLAGS) -o $(OBJDIR)/$@ $< + +all: $(BOOTIMAGE_NAME) + +SYSCFG_GEN_FILES=generated/ti_drivers_config.c generated/ti_drivers_config.h +SYSCFG_GEN_FILES+=generated/ti_drivers_open_close.c generated/ti_drivers_open_close.h +SYSCFG_GEN_FILES+=generated/ti_dpl_config.c generated/ti_dpl_config.h +SYSCFG_GEN_FILES+=generated/ti_pinmux_config.c generated/ti_power_clock_config.c +SYSCFG_GEN_FILES+=generated/ti_board_config.c generated/ti_board_config.h +SYSCFG_GEN_FILES+=generated/ti_board_open_close.c generated/ti_board_open_close.h + +$(OUTNAME): syscfg $(SYSCFG_GEN_FILES) $(OBJS) $(LNK_FILES) $(LIBS_NAME) + @echo . + @echo Linking: am243x:r5fss1-0:freertos:ti-arm-clang $@ ... + $(LNK) $(LNKOPTFLAGS) $(LFLAGS) $(LIBS_PATH) -Wl,-m=$(basename $@).map -o $@ $(addprefix $(OBJDIR), $(OBJS)) $(LIBS) $(LNK_FILES) + @echo Linking: am243x:r5fss1-0:freertos:ti-arm-clang $@ Done !!! + @echo . + +clean: + @echo Cleaning: am243x:r5fss1-0:freertos:ti-arm-clang $(OUTNAME) ... + $(RMDIR) $(OBJDIR) + $(RM) $(OUTNAME) + $(RM) $(BOOTIMAGE_NAME) + $(RM) $(BOOTIMAGE_NAME_XIP) + $(RM) $(BOOTIMAGE_NAME_SIGNED) + $(RM) $(BOOTIMAGE_NAME_HS) + $(RM) $(BOOTIMAGE_NAME_HS_FS) + $(RM) $(BOOTIMAGE_RPRC_NAME) + $(RM) $(BOOTIMAGE_RPRC_NAME_XIP) + $(RMDIR) generated/ + +scrub: + @echo Scrubing: am243x:r5fss1-0:freertos:ti-arm-clang single_chip_servo ... + $(RMDIR) obj +ifeq ($(OS),Windows_NT) + $(RM) \*.out + $(RM) \*.map + $(RM) \*.appimage* + $(RM) \*.rprc* + $(RM) \*.tiimage* + $(RM) \*.bin +else + $(RM) *.out + $(RM) *.map + $(RM) *.appimage* + $(RM) *.rprc* + $(RM) *.tiimage* + $(RM) *.bin +endif + $(RMDIR) generated + +$(OBJS): | $(OBJDIR) + +$(OBJDIR): + $(MKDIR) $@ + + +.NOTPARALLEL: + +.INTERMEDIATE: syscfg +$(SYSCFG_GEN_FILES): syscfg + +syscfg: ../example.syscfg + @echo Generating SysConfig files ... + $(SYSCFG_NODE) $(SYSCFG_CLI_PATH)/dist/cli.js --product $(SYSCFG_SDKPRODUCT) --context r5fss1-0 --part ALX --package ALX --output generated/ ../example.syscfg + +syscfg-gui: + $(SYSCFG_NWJS) $(SYSCFG_PATH) --product $(SYSCFG_SDKPRODUCT) --device AM243x_ALX_beta --context r5fss1-0 --part ALX --package ALX --output generated/ ../example.syscfg + +# +# Generation of boot image which can be loaded by Secondary Boot Loader (SBL) +# +ifeq ($(OS),Windows_NT) +EXE_EXT=.exe +endif +ifeq ($(OS),Windows_NT) + BOOTIMAGE_CERT_GEN_CMD=powershell -executionpolicy unrestricted -command $(MOTOR_CONTROL_SDK_PATH)/mcu_plus_sdk/tools/boot/signing/x509CertificateGen.ps1 +else + BOOTIMAGE_CERT_GEN_CMD=$(MOTOR_CONTROL_SDK_PATH)/mcu_plus_sdk/tools/boot/signing/x509CertificateGen.sh +endif +BOOTIMAGE_TEMP_OUT_FILE=temp_stdout_$(PROFILE).txt + +BOOTIMAGE_CERT_KEY=$(APP_SIGNING_KEY) + +BOOTIMAGE_CORE_ID_r5fss0-0 = 4 +BOOTIMAGE_CORE_ID_r5fss0-1 = 5 +BOOTIMAGE_CORE_ID_r5fss1-0 = 6 +BOOTIMAGE_CORE_ID_r5fss1-1 = 7 +BOOTIMAGE_CORE_ID_m4fss0-0 = 14 +SBL_RUN_ADDRESS=0x70000000 +SBL_DEV_ID=55 + +MULTI_CORE_IMAGE_GEN = $(SYSCFG_NODE) $(MOTOR_CONTROL_SDK_PATH)/mcu_plus_sdk/tools/boot/multicoreImageGen/multicoreImageGen.js +OUTRPRC_CMD = $(SYSCFG_NODE) $(MOTOR_CONTROL_SDK_PATH)/mcu_plus_sdk/tools/boot/out2rprc/elf2rprc.js + +ifeq ($(OS),Windows_NT) + XIPGEN_CMD=$(MOTOR_CONTROL_SDK_PATH)/mcu_plus_sdk/tools/boot/xipGen/xipGen.exe +else + XIPGEN_CMD=$(MOTOR_CONTROL_SDK_PATH)/mcu_plus_sdk/tools/boot/xipGen/xipGen.out +endif + +MULTI_CORE_IMAGE_PARAMS = \ + $(BOOTIMAGE_RPRC_NAME)@$(BOOTIMAGE_CORE_ID_r5fss1-0) \ + +MULTI_CORE_IMAGE_PARAMS_XIP = \ + $(BOOTIMAGE_RPRC_NAME_XIP)@$(BOOTIMAGE_CORE_ID_r5fss1-0) \ + +$(BOOTIMAGE_NAME): $(OUTNAME) + @echo Boot image: am243x:r5fss1-0:freertos:ti-arm-clang $(BOOTIMAGE_PATH)/$@ ... +ifneq ($(OS),Windows_NT) + $(CHMOD) a+x $(XIPGEN_CMD) +endif + $(OUTRPRC_CMD) $(OUTNAME) >> $(BOOTIMAGE_TEMP_OUT_FILE) + $(COPY) $(BOOTIMAGE_RPRC_NAME) $(BOOTIMAGE_RPRC_NAME_TMP) + $(RM) $(BOOTIMAGE_RPRC_NAME) + $(XIPGEN_CMD) -i $(BOOTIMAGE_RPRC_NAME_TMP) -o $(BOOTIMAGE_RPRC_NAME) -x $(BOOTIMAGE_RPRC_NAME_XIP) --flash-start-addr 0x60000000 -v > $(BOOTIMAGE_TEMP_OUT_FILE) + $(MULTI_CORE_IMAGE_GEN) --devID $(SBL_DEV_ID) --out $(BOOTIMAGE_NAME) $(MULTI_CORE_IMAGE_PARAMS) >> $(BOOTIMAGE_TEMP_OUT_FILE) + $(MULTI_CORE_IMAGE_GEN) --devID $(SBL_DEV_ID) --out $(BOOTIMAGE_NAME_XIP) $(MULTI_CORE_IMAGE_PARAMS_XIP) >> $(BOOTIMAGE_TEMP_OUT_FILE) + $(RM) $(BOOTIMAGE_RPRC_NAME_TMP) + $(RM) $(BOOTIMAGE_TEMP_OUT_FILE) + @echo Boot image: am243x:r5fss1-0:freertos:ti-arm-clang $(BOOTIMAGE_PATH)/$@ Done !!! + @echo . + +-include $(addprefix $(OBJDIR)/, $(DEPS)) diff --git a/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss1-0_freertos/ti-arm-clang/makefile_ccs_bootimage_gen b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss1-0_freertos/ti-arm-clang/makefile_ccs_bootimage_gen new file mode 100644 index 0000000..c75865e --- /dev/null +++ b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss1-0_freertos/ti-arm-clang/makefile_ccs_bootimage_gen @@ -0,0 +1,85 @@ +# +# Auto generated makefile +# + +# Below variables need to be defined outside this file or via command line +# - MOTOR_CONTROL_SDK_PATH +# - PROFILE +# - CG_TOOL_ROOT +# - OUTNAME +# - CCS_INSTALL_DIR +# - CCS_IDE_MODE + +CCS_PATH=$(CCS_INSTALL_DIR) +include ${MOTOR_CONTROL_SDK_PATH}/imports.mak +include ${MOTOR_CONTROL_SDK_PATH}/devconfig/devconfig.mak + +STRIP=$(CG_TOOL_ROOT)/bin/tiarmstrip +OBJCOPY=$(CG_TOOL_ROOT)/bin/tiarmobjcopy +ifeq ($(OS), Windows_NT) + PYTHON=python +else + PYTHON=python3 +endif + +OUTFILE=$(PROFILE)/$(OUTNAME).out +BOOTIMAGE_PATH=$(abspath ${PROFILE}) +BOOTIMAGE_NAME:=$(BOOTIMAGE_PATH)/$(OUTNAME).appimage +BOOTIMAGE_NAME_XIP:=$(BOOTIMAGE_PATH)/$(OUTNAME).appimage_xip +BOOTIMAGE_NAME_SIGNED:=$(BOOTIMAGE_PATH)/$(OUTNAME).appimage.signed +BOOTIMAGE_RPRC_NAME:=$(BOOTIMAGE_PATH)/$(OUTNAME).rprc +BOOTIMAGE_RPRC_NAME_XIP:=$(BOOTIMAGE_PATH)/$(OUTNAME).rprc_xip +BOOTIMAGE_RPRC_NAME_TMP:=$(BOOTIMAGE_PATH)/$(OUTNAME).rprc_tmp + +# +# Generation of boot image which can be loaded by Secondary Boot Loader (SBL) +# +ifeq ($(OS),Windows_NT) +EXE_EXT=.exe +endif +ifeq ($(OS),Windows_NT) + BOOTIMAGE_CERT_GEN_CMD=powershell -executionpolicy unrestricted -command $(MOTOR_CONTROL_SDK_PATH)/mcu_plus_sdk/tools/boot/signing/x509CertificateGen.ps1 +else + BOOTIMAGE_CERT_GEN_CMD=$(MOTOR_CONTROL_SDK_PATH)/mcu_plus_sdk/tools/boot/signing/x509CertificateGen.sh +endif +BOOTIMAGE_TEMP_OUT_FILE=$(PROFILE)/temp_stdout_$(PROFILE).txt + +BOOTIMAGE_CORE_ID_r5fss0-0 = 4 +BOOTIMAGE_CORE_ID_r5fss0-1 = 5 +BOOTIMAGE_CORE_ID_r5fss1-0 = 6 +BOOTIMAGE_CORE_ID_r5fss1-1 = 7 +BOOTIMAGE_CORE_ID_m4fss0-0 = 14 +SBL_RUN_ADDRESS=0x70000000 +SBL_DEV_ID=55 + +MULTI_CORE_IMAGE_GEN = $(CCS_NODE) $(MOTOR_CONTROL_SDK_PATH)/mcu_plus_sdk/tools/boot/multicoreImageGen/multicoreImageGen.js +OUTRPRC_CMD = $(CCS_NODE) $(MOTOR_CONTROL_SDK_PATH)/mcu_plus_sdk/tools/boot/out2rprc/elf2rprc.js + +ifeq ($(OS),Windows_NT) + XIPGEN_CMD=$(MOTOR_CONTROL_SDK_PATH)/mcu_plus_sdk/tools/boot/xipGen/xipGen.exe +else + XIPGEN_CMD=$(MOTOR_CONTROL_SDK_PATH)/mcu_plus_sdk/tools/boot/xipGen/xipGen.out +endif + +MULTI_CORE_IMAGE_PARAMS = \ + $(BOOTIMAGE_RPRC_NAME)@$(BOOTIMAGE_CORE_ID_r5fss1-0) \ + +MULTI_CORE_IMAGE_PARAMS_XIP = \ + $(BOOTIMAGE_RPRC_NAME_XIP)@$(BOOTIMAGE_CORE_ID_r5fss1-0) \ + +all: +ifeq ($(CCS_IDE_MODE),cloud) +# No post build steps +else + @echo Boot image: am243x:r5fss1-0:freertos:ti-arm-clang $(BOOTIMAGE_NAME) ... + $(OUTRPRC_CMD) $(OUTFILE) >> $(BOOTIMAGE_TEMP_OUT_FILE) + $(COPY) $(OUTNAME).rprc $(BOOTIMAGE_RPRC_NAME) + $(COPY) $(BOOTIMAGE_RPRC_NAME) $(BOOTIMAGE_RPRC_NAME_TMP) + $(RM) $(BOOTIMAGE_RPRC_NAME) + $(XIPGEN_CMD) -i $(BOOTIMAGE_RPRC_NAME_TMP) -o $(BOOTIMAGE_RPRC_NAME) -x $(BOOTIMAGE_RPRC_NAME_XIP) --flash-start-addr 0x60000000 -v > $(BOOTIMAGE_TEMP_OUT_FILE) + $(MULTI_CORE_IMAGE_GEN) --devID $(SBL_DEV_ID) --out $(BOOTIMAGE_NAME) $(MULTI_CORE_IMAGE_PARAMS) >> $(BOOTIMAGE_TEMP_OUT_FILE) + $(MULTI_CORE_IMAGE_GEN) --devID $(SBL_DEV_ID) --out $(BOOTIMAGE_NAME_XIP) $(MULTI_CORE_IMAGE_PARAMS_XIP) >> $(BOOTIMAGE_TEMP_OUT_FILE) + $(RM) $(BOOTIMAGE_RPRC_NAME_TMP) + @echo Boot image: am243x:r5fss1-0:freertos:ti-arm-clang $(BOOTIMAGE_NAME) Done !!! + @echo . +endif diff --git a/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss1-0_freertos/ti-arm-clang/makefile_projectspec b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss1-0_freertos/ti-arm-clang/makefile_projectspec new file mode 100644 index 0000000..e1c395b --- /dev/null +++ b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss1-0_freertos/ti-arm-clang/makefile_projectspec @@ -0,0 +1,20 @@ +# +# Auto generated makefile +# + +export MOTOR_CONTROL_SDK_PATH?=$(abspath ../../../../../..) +include $(MOTOR_CONTROL_SDK_PATH)/imports.mak + +PROFILE?=Release + +PROJECT_NAME=single_chip_servo_am243x-lp_r5fss1-0_freertos_ti-arm-clang + +all: + $(CCS_ECLIPSE) -noSplash -data $(MOTOR_CONTROL_SDK_PATH)/ccs_projects -application com.ti.ccstudio.apps.projectBuild -ccs.projects $(PROJECT_NAME) -ccs.configuration $(PROFILE) + +clean: + $(CCS_ECLIPSE) -noSplash -data $(MOTOR_CONTROL_SDK_PATH)/ccs_projects -application com.ti.ccstudio.apps.projectBuild -ccs.projects $(PROJECT_NAME) -ccs.configuration $(PROFILE) -ccs.clean + +export: + $(MKDIR) $(MOTOR_CONTROL_SDK_PATH)/ccs_projects + $(CCS_ECLIPSE) -noSplash -data $(MOTOR_CONTROL_SDK_PATH)/ccs_projects -application com.ti.ccstudio.apps.projectCreate -ccs.projectSpec example.projectspec -ccs.overwrite full diff --git a/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss1-0_freertos/ti-arm-clang/syscfg_c.rov.xs b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss1-0_freertos/ti-arm-clang/syscfg_c.rov.xs new file mode 100644 index 0000000..d46875e --- /dev/null +++ b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss1-0_freertos/ti-arm-clang/syscfg_c.rov.xs @@ -0,0 +1,8 @@ +/* + * ======== syscfg_c.rov.xs ======== + * This file contains the information needed by the Runtime Object + * View (ROV) tool. + */ +var crovFiles = [ + "mcu_plus_sdk/source/kernel/freertos/rov/FreeRTOS.rov.js", +]; diff --git a/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss1-0_freertos/version.h b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss1-0_freertos/version.h new file mode 100644 index 0000000..4940f80 --- /dev/null +++ b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/r5fss1-0_freertos/version.h @@ -0,0 +1,59 @@ +/*! + * \example version.h + * + * \brief + * EtherCAT_Slave_Simple version defines example. + * + * \author + * KUNBUS GmbH + * + * \copyright + * Copyright (c) 2021, KUNBUS GmbH

+ * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (c) 2023 KUNBUS GmbH. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + *
    + *
  1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer./
  2. + *
  3. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution.
  4. + *
  5. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission.
  6. + *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY + * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#if !(defined __VERSION_H__) +#define __VERSION_H__ 1 + +#define IND_PKG_VERSION "EtherCAT Slave 01.00.06.01" +#define OLED_DISPLAY_VERSION_STRING "EtherCAT App 1.0.6" + +#if (defined __cplusplus) +extern "C" { +#endif + +/* extern void func(void); */ + +#if (defined __cplusplus) +} +#endif + +#endif /* __VERSION_H__ */ diff --git a/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/readme.txt b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/readme.txt new file mode 100644 index 0000000..7ff1b8c --- /dev/null +++ b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/readme.txt @@ -0,0 +1,2 @@ +This folder contains the reference design software for the TIDEP-01032 (EtherCAT-Connected, Single-Chip, Dual-Servo Motor Drive Reference Design for AM243x Systems). It will be release as part of the Motor Control SDK 09.01.00. Currently the FOC loop used for Closed Speed (Velocity) Control is based on the CMSIS library. We will switch to the RTLib functions and DCL functions in the near future. + diff --git a/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/system_freertos_nortos/makefile b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/system_freertos_nortos/makefile new file mode 100644 index 0000000..671a877 --- /dev/null +++ b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/system_freertos_nortos/makefile @@ -0,0 +1,134 @@ +# +# Auto generated makefile +# + +export MOTOR_CONTROL_SDK_PATH?=$(abspath ../../../../..) +include $(MOTOR_CONTROL_SDK_PATH)/imports.mak +include $(MOTOR_CONTROL_SDK_PATH)/devconfig/devconfig.mak + +ifeq ($(OS), Windows_NT) + PYTHON=python +else + PYTHON=python3 +endif + +PROFILE?=release + +MULTI_CORE_BOOTIMAGE_PATH=$(abspath .) +MULTI_CORE_BOOTIMAGE_NAME:=single_chip_servo_system.$(PROFILE).appimage +MULTI_CORE_BOOTIMAGE_NAME_SIGNED:=$(MULTI_CORE_BOOTIMAGE_NAME).signed +MULTI_CORE_BOOTIMAGE_NAME_XIP:=single_chip_servo_system.$(PROFILE).appimage_xip +MULTI_CORE_BOOTIMAGE_NAME_HS:=$(MULTI_CORE_BOOTIMAGE_NAME).hs + +CORE_0=--script ../r5fss0-0_nortos/example.syscfg --context r5fss0-0 --output ../r5fss0-0_nortos/ti-arm-clang/generated +CORE_1=--script ../r5fss0-1_nortos/example.syscfg --context r5fss0-1 --output ../r5fss0-1_nortos/ti-arm-clang/generated +CORE_2=--script ../r5fss1-0_freertos/example.syscfg --context r5fss1-0 --output ../r5fss1-0_freertos/ti-arm-clang/generated + +CORES = \ + $(CORE_2) \ + $(CORE_1) \ + $(CORE_0) \ + +all: syscfg + $(MAKE) -C ../r5fss0-0_nortos/ti-arm-clang/ all + $(MAKE) -C ../r5fss0-1_nortos/ti-arm-clang/ all + $(MAKE) -C ../r5fss1-0_freertos/ti-arm-clang/ all + $(MAKE) $(MULTI_CORE_BOOTIMAGE_NAME) +ifeq ($(DEVICE_TYPE), HS) + $(MAKE) $(MULTI_CORE_BOOTIMAGE_NAME_HS) +endif + +clean: + $(MAKE) -C ../r5fss0-0_nortos/ti-arm-clang/ clean + $(MAKE) -C ../r5fss0-1_nortos/ti-arm-clang/ clean + $(MAKE) -C ../r5fss1-0_freertos/ti-arm-clang/ clean + $(RM) $(MULTI_CORE_BOOTIMAGE_NAME) + $(RM) $(MULTI_CORE_BOOTIMAGE_NAME_SIGNED) + $(RM) $(MULTI_CORE_BOOTIMAGE_NAME_XIP) + +scrub: + $(MAKE) -C ../r5fss0-0_nortos/ti-arm-clang/ scrub + $(MAKE) -C ../r5fss0-1_nortos/ti-arm-clang/ scrub + $(MAKE) -C ../r5fss1-0_freertos/ti-arm-clang/ scrub +ifeq ($(OS),Windows_NT) + $(RM) \*.appimage + $(RM) \*.appimage.signed + $(RM) \*.appimage.hs + $(RM) \*.appimage_xip +else + $(RM) *.appimage + $(RM) *.appimage.signed + $(RM) \*.appimage.hs + $(RM) *.appimage_xip +endif + +syscfg: + @echo Generating SysConfig files ... + $(SYSCFG_NODE) $(SYSCFG_CLI_PATH)/dist/cli.js --product $(SYSCFG_SDKPRODUCT) $(CORES) + +syscfg-gui: + $(SYSCFG_NWJS) $(SYSCFG_PATH) --product $(SYSCFG_SDKPRODUCT) --device AM243x_ALX_beta --part ALX --package ALX $(CORES) + +# +# Generation of multi-core boot image which can be loaded by Secondary Boot Loader (SBL) +# +ifeq ($(OS),Windows_NT) +EXE_EXT=.exe +endif +BOOTIMAGE_TEMP_OUT_FILE=temp_stdout_$(PROFILE).txt + +BOOTIMAGE_CORE_ID_r5fss0-0 = 4 +BOOTIMAGE_CORE_ID_r5fss0-1 = 5 +BOOTIMAGE_CORE_ID_r5fss1-0 = 6 +BOOTIMAGE_CORE_ID_r5fss1-1 = 7 +BOOTIMAGE_CORE_ID_m4fss0-0 = 14 +SBL_RUN_ADDRESS=0x70000000 +SBL_DEV_ID=55 + +MULTI_CORE_IMAGE_GEN = $(SYSCFG_NODE) $(MOTOR_CONTROL_SDK_PATH)/mcu_plus_sdk/tools/boot/multicoreImageGen/multicoreImageGen.js +OUTRPRC_CMD = $(SYSCFG_NODE) $(MOTOR_CONTROL_SDK_PATH)/mcu_plus_sdk/tools/boot/out2rprc/elf2rprc.js +APP_IMAGE_SIGN_CMD = $(MOTOR_CONTROL_SDK_PATH)/mcu_plus_sdk/tools/boot/signing/appimage_x509_cert_gen.py + +MULTI_CORE_APP_PARAMS = \ + ../r5fss0-0_nortos/ti-arm-clang/single_chip_servo.$(PROFILE).rprc@$(BOOTIMAGE_CORE_ID_r5fss0-0) \ + ../r5fss0-1_nortos/ti-arm-clang/single_chip_servo.$(PROFILE).rprc@$(BOOTIMAGE_CORE_ID_r5fss0-1) \ + ../r5fss1-0_freertos/ti-arm-clang/single_chip_servo.$(PROFILE).rprc@$(BOOTIMAGE_CORE_ID_r5fss1-0) \ + +MULTI_CORE_APP_PARAMS_XIP = \ + ../r5fss0-0_nortos/ti-arm-clang/single_chip_servo.$(PROFILE).rprc_xip@$(BOOTIMAGE_CORE_ID_r5fss0-0) \ + ../r5fss0-1_nortos/ti-arm-clang/single_chip_servo.$(PROFILE).rprc_xip@$(BOOTIMAGE_CORE_ID_r5fss0-1) \ + ../r5fss1-0_freertos/ti-arm-clang/single_chip_servo.$(PROFILE).rprc_xip@$(BOOTIMAGE_CORE_ID_r5fss1-0) \ + +MULTI_CORE_BOOTIMAGE_DEPENDENCY = \ + ../r5fss0-0_nortos/ti-arm-clang/single_chip_servo.$(PROFILE).rprc \ + ../r5fss0-1_nortos/ti-arm-clang/single_chip_servo.$(PROFILE).rprc \ + ../r5fss1-0_freertos/ti-arm-clang/single_chip_servo.$(PROFILE).rprc \ + +$(MULTI_CORE_BOOTIMAGE_DEPENDENCY): + +$(MULTI_CORE_BOOTIMAGE_NAME): $(MULTI_CORE_BOOTIMAGE_DEPENDENCY) + @echo Boot multi-core image: $@ ... + $(MULTI_CORE_IMAGE_GEN) --devID $(SBL_DEV_ID) --out $(MULTI_CORE_BOOTIMAGE_NAME) $(MULTI_CORE_APP_PARAMS) >> $(BOOTIMAGE_TEMP_OUT_FILE) + $(MULTI_CORE_IMAGE_GEN) --devID $(SBL_DEV_ID) --out $(MULTI_CORE_BOOTIMAGE_NAME_XIP) $(MULTI_CORE_APP_PARAMS_XIP) >> $(BOOTIMAGE_TEMP_OUT_FILE) + $(RM) $(BOOTIMAGE_TEMP_OUT_FILE) + @echo Boot multi-core image: $(MULTI_CORE_BOOTIMAGE_PATH)/$@ Done !!! + @echo . + $(PYTHON) $(APP_IMAGE_SIGN_CMD) --bin $(MULTI_CORE_BOOTIMAGE_NAME) --authtype 1 --key $(APP_SIGNING_KEY) --output $(MULTI_CORE_BOOTIMAGE_NAME).hs_fs + @echo Boot multi-core image: $(MULTI_CORE_BOOTIMAGE_PATH)/$(MULTI_CORE_BOOTIMAGE_NAME).hs_fs Done !!! + @echo . + +$(MULTI_CORE_BOOTIMAGE_NAME_HS): $(MULTI_CORE_BOOTIMAGE_NAME) +ifeq ($(DEVICE_TYPE),HS) +# Sign the appimage using appimage signing script +ifeq ($(ENC_ENABLED),no) + @echo Boot image signing: Encryption is disabled. + $(PYTHON) $(APP_IMAGE_SIGN_CMD) --bin $(MULTI_CORE_BOOTIMAGE_NAME) --authtype 1 --key $(APP_SIGNING_KEY) --output $(MULTI_CORE_BOOTIMAGE_NAME_HS) +else + @echo Boot image signing: Encryption is enabled. + $(PYTHON) $(APP_IMAGE_SIGN_CMD) --bin $(MULTI_CORE_BOOTIMAGE_NAME) --authtype 1 --key $(APP_SIGNING_KEY) --enc y --enckey $(APP_ENCRYPTION_KEY) --output $(MULTI_CORE_BOOTIMAGE_NAME_HS) + $(RM) $(MULTI_CORE_BOOTIMAGE_NAME)-enc +endif + @echo Boot multi-core image: $(MULTI_CORE_BOOTIMAGE_PATH)/$@ Done !!! + @echo Boot multi-core image: $(MULTI_CORE_BOOTIMAGE_PATH)/$(MULTI_CORE_BOOTIMAGE_NAME_HS) Done !!! + @echo . +endif diff --git a/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/system_freertos_nortos/makefile_projectspec b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/system_freertos_nortos/makefile_projectspec new file mode 100644 index 0000000..39630d7 --- /dev/null +++ b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/system_freertos_nortos/makefile_projectspec @@ -0,0 +1,23 @@ +# +# Auto generated makefile +# + +export MOTOR_CONTROL_SDK_PATH?=$(abspath ../../../../..) +include $(MOTOR_CONTROL_SDK_PATH)/imports.mak + +export PROFILE?=Release + +PROJECT_NAME=single_chip_servo_am243x-lp_system_freertos_nortos + +all: + $(CCS_ECLIPSE) -noSplash -data $(MOTOR_CONTROL_SDK_PATH)/ccs_projects -application com.ti.ccstudio.apps.projectBuild -ccs.projects $(PROJECT_NAME) -ccs.configuration $(PROFILE) + +clean: + $(CCS_ECLIPSE) -noSplash -data $(MOTOR_CONTROL_SDK_PATH)/ccs_projects -application com.ti.ccstudio.apps.projectBuild -ccs.projects $(PROJECT_NAME) -ccs.configuration $(PROFILE) -ccs.clean + $(MAKE) -C ../r5fss0-0_nortos/ti-arm-clang/ -f makefile_projectspec clean + $(MAKE) -C ../r5fss0-1_nortos/ti-arm-clang/ -f makefile_projectspec clean + $(MAKE) -C ../r5fss1-0_freertos/ti-arm-clang/ -f makefile_projectspec clean + +export: + $(MKDIR) $(MOTOR_CONTROL_SDK_PATH)/ccs_projects + $(CCS_ECLIPSE) -noSplash -data $(MOTOR_CONTROL_SDK_PATH)/ccs_projects -application com.ti.ccstudio.apps.projectCreate -ccs.projectSpec system.projectspec -ccs.overwrite full diff --git a/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/system_freertos_nortos/makefile_system_ccs_bootimage_gen b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/system_freertos_nortos/makefile_system_ccs_bootimage_gen new file mode 100644 index 0000000..9370deb --- /dev/null +++ b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/system_freertos_nortos/makefile_system_ccs_bootimage_gen @@ -0,0 +1,83 @@ +# +# Auto generated makefile +# + +# Below variables need to be defined outside this file or via command line +# - MOTOR_CONTROL_SDK_PATH +# - PROFILE +# - OUTNAME +# - CCS_INSTALL_DIR + +CCS_PATH=$(CCS_INSTALL_DIR) +include $(MOTOR_CONTROL_SDK_PATH)/imports.mak +include $(MOTOR_CONTROL_SDK_PATH)/devconfig/devconfig.mak + +ifeq ($(OS), Windows_NT) + PYTHON=python +else + PYTHON=python3 +endif + +MULTI_CORE_BOOTIMAGE_PATH=$(abspath $(PROFILE)) +MULTI_CORE_BOOTIMAGE_NAME:=$(PROFILE)/$(OUTNAME).appimage +MULTI_CORE_BOOTIMAGE_NAME_SIGNED:=$(PROFILE)/$(OUTNAME).appimage.signed +MULTI_CORE_BOOTIMAGE_NAME_XIP:=$(PROFILE)/$(OUTNAME).appimage_xip + +# +# Generation of multi-core boot image which can be loaded by Secondary Boot Loader (SBL) +# +ifeq ($(OS),Windows_NT) +EXE_EXT=.exe +endif +BOOTIMAGE_TEMP_OUT_FILE=$(PROFILE)/temp_stdout_$(PROFILE).txt + +BOOTIMAGE_CORE_ID_r5fss0-0 = 4 +BOOTIMAGE_CORE_ID_r5fss0-1 = 5 +BOOTIMAGE_CORE_ID_r5fss1-0 = 6 +BOOTIMAGE_CORE_ID_r5fss1-1 = 7 +BOOTIMAGE_CORE_ID_m4fss0-0 = 14 +SBL_RUN_ADDRESS=0x70000000 +SBL_DEV_ID=55 + +MULTI_CORE_IMAGE_GEN = $(CCS_NODE) $(MOTOR_CONTROL_SDK_PATH)/mcu_plus_sdk/tools/boot/multicoreImageGen/multicoreImageGen.js +OUTRPRC_CMD = $(CCS_NODE) $(MOTOR_CONTROL_SDK_PATH)/mcu_plus_sdk/tools/boot/out2rprc/elf2rprc.js +APP_IMAGE_SIGN_CMD = $(MOTOR_CONTROL_SDK_PATH)/mcu_plus_sdk/tools/boot/signing/appimage_x509_cert_gen.py + +MULTI_CORE_APP_PARAMS = \ + ../single_chip_servo_am243x-lp_r5fss0-0_nortos_ti-arm-clang/$(PROFILE)/single_chip_servo_am243x-lp_r5fss0-0_nortos_ti-arm-clang.rprc@$(BOOTIMAGE_CORE_ID_r5fss0-0) \ + ../single_chip_servo_am243x-lp_r5fss0-1_nortos_ti-arm-clang/$(PROFILE)/single_chip_servo_am243x-lp_r5fss0-1_nortos_ti-arm-clang.rprc@$(BOOTIMAGE_CORE_ID_r5fss0-1) \ + ../single_chip_servo_am243x-lp_r5fss1-0_freertos_ti-arm-clang/$(PROFILE)/single_chip_servo_am243x-lp_r5fss1-0_freertos_ti-arm-clang.rprc@$(BOOTIMAGE_CORE_ID_r5fss1-0) \ + +MULTI_CORE_APP_PARAMS_XIP = \ + ../single_chip_servo_am243x-lp_r5fss0-0_nortos_ti-arm-clang/$(PROFILE)/single_chip_servo_am243x-lp_r5fss0-0_nortos_ti-arm-clang.rprc_xip@$(BOOTIMAGE_CORE_ID_r5fss0-0) \ + ../single_chip_servo_am243x-lp_r5fss0-1_nortos_ti-arm-clang/$(PROFILE)/single_chip_servo_am243x-lp_r5fss0-1_nortos_ti-arm-clang.rprc_xip@$(BOOTIMAGE_CORE_ID_r5fss0-1) \ + ../single_chip_servo_am243x-lp_r5fss1-0_freertos_ti-arm-clang/$(PROFILE)/single_chip_servo_am243x-lp_r5fss1-0_freertos_ti-arm-clang.rprc_xip@$(BOOTIMAGE_CORE_ID_r5fss1-0) \ + +all: +ifeq ($(CCS_IDE_MODE),cloud) +# No post build steps +else + @echo Boot multi-core image: $(MULTI_CORE_BOOTIMAGE_NAME) ... + $(MULTI_CORE_IMAGE_GEN) --devID $(SBL_DEV_ID) --out $(MULTI_CORE_BOOTIMAGE_NAME) $(MULTI_CORE_APP_PARAMS) >> $(BOOTIMAGE_TEMP_OUT_FILE) + $(MULTI_CORE_IMAGE_GEN) --devID $(SBL_DEV_ID) --out $(MULTI_CORE_BOOTIMAGE_NAME_XIP) $(MULTI_CORE_APP_PARAMS_XIP) >> $(BOOTIMAGE_TEMP_OUT_FILE) +# Sign the appimage for HS-FS using appimage signing script + $(PYTHON) $(APP_IMAGE_SIGN_CMD) --bin $(MULTI_CORE_BOOTIMAGE_NAME) --authtype 1 --key $(APP_SIGNING_KEY) --output $(MULTI_CORE_BOOTIMAGE_NAME).hs_fs +ifeq ($(DEVICE_TYPE),HS) +# Sign the appimage using appimage signing script +ifeq ($(ENC_ENABLED),no) + @echo Boot image signing: Encryption is disabled. + $(PYTHON) $(APP_IMAGE_SIGN_CMD) --bin $(MULTI_CORE_BOOTIMAGE_NAME) --authtype 1 --key $(APP_SIGNING_KEY) --output $(MULTI_CORE_BOOTIMAGE_NAME).hs +else + @echo Boot image signing: Encryption is enabled. + $(PYTHON) $(APP_IMAGE_SIGN_CMD) --bin $(MULTI_CORE_BOOTIMAGE_NAME) --authtype 1 --key $(APP_SIGNING_KEY) --enc y --enckey $(APP_ENCRYPTION_KEY) --output $(MULTI_CORE_BOOTIMAGE_NAME).hs + $(RM) $(MULTI_CORE_BOOTIMAGE_NAME)-enc +endif +endif +ifeq ($(DEVICE_TYPE),HS) + @echo Boot multi-core image: $(MULTI_CORE_BOOTIMAGE_NAME).hs Done !!! +else + @echo Boot multi-core image: $(MULTI_CORE_BOOTIMAGE_NAME) Done !!! + @echo Boot multi-core image: $(MULTI_CORE_BOOTIMAGE_NAME).hs_fs Done !!! +endif + @echo . +endif diff --git a/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/system_freertos_nortos/system.projectspec b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/system_freertos_nortos/system.projectspec new file mode 100644 index 0000000..c3c022a --- /dev/null +++ b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/system_freertos_nortos/system.projectspec @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + diff --git a/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/system_freertos_nortos/system.xml b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/system_freertos_nortos/system.xml new file mode 100644 index 0000000..bffc39f --- /dev/null +++ b/examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/system_freertos_nortos/system.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/makefile.am243x b/makefile.am243x index 94b8ce6..cde500a 100644 --- a/makefile.am243x +++ b/makefile.am243x @@ -121,6 +121,7 @@ help: @echo . @echo System Example build targets, @echo ============================= + @echo $(MAKE) -s -C examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/system_freertos_nortos [all clean syscfg-gui syscfg] @echo . # Various Component Targets @@ -284,6 +285,7 @@ BUILD_COMBO_EXAMPLE_ALL += pruicss_pwm_duty_cycle_am243x-evm_r5fss0-0_freertos_t BUILD_COMBO_EXAMPLE_ALL += pruicss_pwm_duty_cycle_am243x-lp_r5fss0-0_freertos_ti-arm-clang BUILD_COMBO_EXAMPLE_ALL += pruicss_pwm_epwm_sync_am243x-lp_r5fss0-0_freertos_ti-arm-clang # Various System Example Targets +BUILD_COMBO_EXAMPLE_ALL += single_chip_servo_am243x-lp_system_freertos_nortos BUILD_COMBO_EXAMPLE_PRIVATE_ALL = # Various Private Example Targets @@ -523,6 +525,9 @@ examples-private: $(BUILD_COMBO_EXAMPLE_PRIVATE_ALL) bissc_peripheral_interface_multi_ch_am243x-evm_icssg0-pru1_fw_ti-pru-cgt: $(MAKE) -C source/position_sense/bissc/firmware/multi_channel_single_pru/am243x-evm/icssg0-pru1_fw/ti-pru-cgt -f makefile all + single_chip_servo_am243x-lp_system_freertos_nortos: + $(MAKE) -C examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/system_freertos_nortos -f makefile all + BUILD_COMBO_EXAMPLE_CLEAN_ALL = # Various Example Clean Targets @@ -569,6 +574,7 @@ BUILD_COMBO_EXAMPLE_CLEAN_ALL += pruicss_pwm_duty_cycle_am243x-evm_r5fss0-0_free BUILD_COMBO_EXAMPLE_CLEAN_ALL += pruicss_pwm_duty_cycle_am243x-lp_r5fss0-0_freertos_ti-arm-clang_clean BUILD_COMBO_EXAMPLE_CLEAN_ALL += pruicss_pwm_epwm_sync_am243x-lp_r5fss0-0_freertos_ti-arm-clang_clean # Various System Example Clean Targets +BUILD_COMBO_EXAMPLE_CLEAN_ALL += single_chip_servo_am243x-lp_system_freertos_nortos_clean BUILD_COMBO_EXAMPLE_PRIVATE_CLEAN_ALL = # Various Private Example Targets @@ -808,6 +814,9 @@ examples-private-clean: $(BUILD_COMBO_EXAMPLE_PRIVATE_CLEAN_ALL) bissc_peripheral_interface_multi_ch_am243x-evm_icssg0-pru1_fw_ti-pru-cgt_clean: $(MAKE) -C source/position_sense/bissc/firmware/multi_channel_single_pru/am243x-evm/icssg0-pru1_fw/ti-pru-cgt -f makefile clean + single_chip_servo_am243x-lp_system_freertos_nortos_clean: + $(MAKE) -C examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/system_freertos_nortos -f makefile clean + BUILD_COMBO_EXAMPLE_SCRUB_ALL = # Various Example Scrub Targets @@ -854,6 +863,7 @@ BUILD_COMBO_EXAMPLE_SCRUB_ALL += pruicss_pwm_duty_cycle_am243x-evm_r5fss0-0_free BUILD_COMBO_EXAMPLE_SCRUB_ALL += pruicss_pwm_duty_cycle_am243x-lp_r5fss0-0_freertos_ti-arm-clang_scrub BUILD_COMBO_EXAMPLE_SCRUB_ALL += pruicss_pwm_epwm_sync_am243x-lp_r5fss0-0_freertos_ti-arm-clang_scrub # Various System Example Scrub Targets +BUILD_COMBO_EXAMPLE_SCRUB_ALL += single_chip_servo_am243x-lp_system_freertos_nortos_scrub BUILD_COMBO_EXAMPLE_PRIVATE_SCRUB_ALL = # Various Private Example Targets @@ -1093,6 +1103,9 @@ examples-scrub-private: $(BUILD_COMBO_EXAMPLE_PRIVATE_SCRUB_ALL) bissc_peripheral_interface_multi_ch_am243x-evm_icssg0-pru1_fw_ti-pru-cgt_scrub: $(MAKE) -C source/position_sense/bissc/firmware/multi_channel_single_pru/am243x-evm/icssg0-pru1_fw/ti-pru-cgt -f makefile scrub + single_chip_servo_am243x-lp_system_freertos_nortos_scrub: + $(MAKE) -C examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/system_freertos_nortos -f makefile scrub + .PHONY: all clean scrub help .PHONY: libs libs-clean libs-scrub diff --git a/makefile_projectspec.am243x b/makefile_projectspec.am243x index c73b54e..23cd256 100644 --- a/makefile_projectspec.am243x +++ b/makefile_projectspec.am243x @@ -50,6 +50,7 @@ BUILD_COMBO_EXAMPLE_PROJECTSPEC_BUILD_ALL += pruicss_pwm_duty_cycle_am243x-evm_r BUILD_COMBO_EXAMPLE_PROJECTSPEC_BUILD_ALL += pruicss_pwm_duty_cycle_am243x-lp_r5fss0-0_freertos_ti-arm-clang_build BUILD_COMBO_EXAMPLE_PROJECTSPEC_BUILD_ALL += pruicss_pwm_epwm_sync_am243x-lp_r5fss0-0_freertos_ti-arm-clang_build # Various System Example Projectspec Build Targets +BUILD_COMBO_EXAMPLE_PROJECTSPEC_BUILD_ALL += single_chip_servo_am243x-lp_system_freertos_nortos_build BUILD_COMBO_EXAMPLE_PROJECTSPEC_BUILD_PRIVATE_ALL = # Various Private Example Projectspec Build Targets @@ -289,6 +290,9 @@ all-private: $(BUILD_COMBO_EXAMPLE_PROJECTSPEC_BUILD_PRIVATE_ALL) bissc_peripheral_interface_multi_ch_am243x-evm_icssg0-pru1_fw_ti-pru-cgt_build: $(MAKE) -C source/position_sense/bissc/firmware/multi_channel_single_pru/am243x-evm/icssg0-pru1_fw/ti-pru-cgt -f makefile_projectspec all + single_chip_servo_am243x-lp_system_freertos_nortos_build: + $(MAKE) -C examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/system_freertos_nortos -f makefile_projectspec all + BUILD_COMBO_EXAMPLE_PROJECTSPEC_CLEAN_ALL = @@ -336,6 +340,7 @@ BUILD_COMBO_EXAMPLE_PROJECTSPEC_CLEAN_ALL += pruicss_pwm_duty_cycle_am243x-evm_r BUILD_COMBO_EXAMPLE_PROJECTSPEC_CLEAN_ALL += pruicss_pwm_duty_cycle_am243x-lp_r5fss0-0_freertos_ti-arm-clang_clean BUILD_COMBO_EXAMPLE_PROJECTSPEC_CLEAN_ALL += pruicss_pwm_epwm_sync_am243x-lp_r5fss0-0_freertos_ti-arm-clang_clean # Various System Example Projectspec Clean Targets +BUILD_COMBO_EXAMPLE_PROJECTSPEC_CLEAN_ALL += single_chip_servo_am243x-lp_system_freertos_nortos_clean BUILD_COMBO_EXAMPLE_PROJECTSPEC_CLEAN_PRIVATE_ALL = # Various Private Example Projectspec Clean Targets @@ -575,6 +580,9 @@ clean-private: $(BUILD_COMBO_EXAMPLE_PROJECTSPEC_CLEAN_PRIVATE_ALL) bissc_peripheral_interface_multi_ch_am243x-evm_icssg0-pru1_fw_ti-pru-cgt_clean: $(MAKE) -C source/position_sense/bissc/firmware/multi_channel_single_pru/am243x-evm/icssg0-pru1_fw/ti-pru-cgt -f makefile_projectspec clean + single_chip_servo_am243x-lp_system_freertos_nortos_clean: + $(MAKE) -C examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/system_freertos_nortos -f makefile_projectspec clean + BUILD_COMBO_EXAMPLE_PROJECTSPEC_EXPORT_ALL = @@ -622,6 +630,7 @@ BUILD_COMBO_EXAMPLE_PROJECTSPEC_EXPORT_ALL += pruicss_pwm_duty_cycle_am243x-evm_ BUILD_COMBO_EXAMPLE_PROJECTSPEC_EXPORT_ALL += pruicss_pwm_duty_cycle_am243x-lp_r5fss0-0_freertos_ti-arm-clang_export BUILD_COMBO_EXAMPLE_PROJECTSPEC_EXPORT_ALL += pruicss_pwm_epwm_sync_am243x-lp_r5fss0-0_freertos_ti-arm-clang_export # Various System Example Projectspec Export Targets +BUILD_COMBO_EXAMPLE_PROJECTSPEC_EXPORT_ALL += single_chip_servo_am243x-lp_system_freertos_nortos_export BUILD_COMBO_EXAMPLE_PROJECTSPEC_EXPORT_PRIVATE_ALL = # Various Private Example Projectspec Export Targets @@ -861,6 +870,9 @@ export-private: $(BUILD_COMBO_EXAMPLE_PROJECTSPEC_EXPORT_PRIVATE_ALL) bissc_peripheral_interface_multi_ch_am243x-evm_icssg0-pru1_fw_ti-pru-cgt_export: $(MAKE) -C source/position_sense/bissc/firmware/multi_channel_single_pru/am243x-evm/icssg0-pru1_fw/ti-pru-cgt -f makefile_projectspec export + single_chip_servo_am243x-lp_system_freertos_nortos_export: + $(MAKE) -C examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/system_freertos_nortos -f makefile_projectspec export + # Import extra components into CCS workspace before creating a project # Setup dependency separately so that it runs if one or all projects are built via the makefile @@ -961,6 +973,7 @@ help: @echo . @echo System Example ProjectSpec build targets, @echo ========================================= + @echo $(MAKE) -s -C examples/tidep_01032_dual_motor_drive/single_chip_servo/am243x-lp/system_freertos_nortos -f makefile_projectspec [export all clean] @echo . .PHONY: all all-private