mirror of
https://github.com/odriverobotics/ODrive.git
synced 2026-09-21 23:44:48 +08:00
Merge branch 'devel' into preroll
This commit is contained in:
+1
-1
@@ -33,7 +33,7 @@ install:
|
||||
|
||||
- export TUP_DIR=$HOME/dl/tup_0.7.5-0~16.04.york0_amd64
|
||||
- export TUP_ARCHIVE=$HOME/dl/tup_0.7.5-0~16.04.york0_amd64.deb
|
||||
- export TUP_URL=http://ppa.launchpad.net/jonathonf/tup/ubuntu/pool/main/t/tup/tup_0.7.5-0~16.04.york0_amd64.deb
|
||||
- export TUP_URL=http://ppa.launchpad.net/jonathonf/tup/ubuntu/pool/main/t/tup/tup_0.7.8-2~16.04.york0_amd64.deb
|
||||
- if [ ! -e $TUP_DIR/bin/tup ]; then wget $TUP_URL -O $TUP_ARCHIVE; dpkg-deb -R $TUP_ARCHIVE $TUP_DIR; fi
|
||||
- export PATH=$PATH:$TUP_DIR/usr/bin
|
||||
|
||||
|
||||
@@ -38,6 +38,10 @@ void ODriveArduino::SetVelocity(int motor_number, float velocity, float current_
|
||||
serial_ << "v " << motor_number << " " << velocity << " " << current_feedforward << "\n";
|
||||
}
|
||||
|
||||
void ODriveArduino::SetCurrent(int motor_number, float current) {
|
||||
serial_ << "c " << motor_number << " " << current << "\n";
|
||||
}
|
||||
|
||||
float ODriveArduino::readFloat() {
|
||||
return readString().toFloat();
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ public:
|
||||
void SetPosition(int motor_number, float position, float velocity_feedforward, float current_feedforward);
|
||||
void SetVelocity(int motor_number, float velocity);
|
||||
void SetVelocity(int motor_number, float velocity, float current_feedforward);
|
||||
void SetCurrent(int motor_number, float current);
|
||||
|
||||
// General params
|
||||
float readFloat();
|
||||
|
||||
@@ -8,6 +8,7 @@ template<> inline Print& operator <<(Print &obj, float arg) { obj.print(a
|
||||
|
||||
// Serial to the ODrive
|
||||
SoftwareSerial odrive_serial(8, 9); //RX (ODrive TX), TX (ODrive RX)
|
||||
// Note: you must also connect GND on ODrive to GND on Arduino!
|
||||
|
||||
// ODrive object
|
||||
ODriveArduino odrive(odrive_serial);
|
||||
|
||||
+24
-2
@@ -1,10 +1,32 @@
|
||||
# Unreleased Features
|
||||
Please add a note of your changes below this heading if you make a Pull Request.
|
||||
|
||||
## Fixed
|
||||
* Would ERROR_CONTROL_DEADLINE_MISSED along with every ERROR_PHASE_RESISTANCE_OUT_OF_RANGE.
|
||||
### Added
|
||||
* `dump_errors()` utility function in odrivetool to dump, decode and optionally clear errors.
|
||||
* `q` command to ascii protocol. It is like the old `p` command, but velocity and current mean limits, not feed-forward.
|
||||
* Voltage limit soft clamping instead of ERROR_MODULATION_MAGNITUDE in gimbal motor closed loop.
|
||||
* Thermal current limit with linear derating.
|
||||
|
||||
# Releases
|
||||
## [0.4.7] - 2018-11-28
|
||||
### Added
|
||||
* Overspeed fault
|
||||
* Current sense saturation fault.
|
||||
* Supress startup transients by sampling encoder estimate into position setpoint when entering closed loop control.
|
||||
* Make step dir gpio pins configurable.
|
||||
* Configuration variable `encoder.config.zero_count_on_find_idx`, true by default. Set to false to leave the initial encoder count to be where the axis was at boot.
|
||||
* Circular position setpoint mode: position setpoints wrapped [0, cpr). Useful for infinite incremental position control.
|
||||
* Velocity setpoint ramping. Use velocity control mode, and set `controller.vel_ramp_enable` to true. This will ramp `controller.vel_setpoint` towards `controller.vel_ramp_target` at a ramp rate of `controller.config.vel_ramp_rate`.
|
||||
|
||||
### Changed
|
||||
* Increased switching frequency from around 8kHz to 24kHz. Control loops still run at 8kHz.
|
||||
* Renamed `axis.enable_step_dir` to `axis.step_dir_active`
|
||||
* New process for working with STM32CubeMX.
|
||||
|
||||
### Fixed
|
||||
* Would get ERROR_CONTROL_DEADLINE_MISSED along with every ERROR_PHASE_RESISTANCE_OUT_OF_RANGE.
|
||||
* ODrive tool can now run interactive nested scripts with "%run -i script.py"
|
||||
|
||||
## [0.4.6] - 2018-10-07
|
||||
### Fixed
|
||||
* Broken printing of floats on ascii protocol
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
From b7ea3f500fbfc187a0a7112282ae6b1eee4555d0 Mon Sep 17 00:00:00 2001
|
||||
From: Samuel Sadok <samuel.sadok@bluewin.ch>
|
||||
Date: Tue, 13 Mar 2018 20:05:07 -0700
|
||||
Subject: [PATCH] display correct ODrive version in USB descriptor
|
||||
|
||||
---
|
||||
Firmware/Board/v3/Src/usbd_desc.c | 8 +++++---
|
||||
1 file changed, 5 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/Firmware/Board/v3/Src/usbd_desc.c b/Firmware/Board/v3/Src/usbd_desc.c
|
||||
index 94dc49b..37b4302 100644
|
||||
--- a/Firmware/Board/v3/Src/usbd_desc.c
|
||||
+++ b/Firmware/Board/v3/Src/usbd_desc.c
|
||||
@@ -96,7 +96,9 @@
|
||||
#define USBD_LANGID_STRING 1033
|
||||
#define USBD_MANUFACTURER_STRING "ODrive Robotics"
|
||||
#define USBD_PID_FS 0x0D32
|
||||
-#define USBD_PRODUCT_STRING_FS "ODrive v3.3"
|
||||
+#define USBD_PRODUCT_XSTR(s) USBD_PRODUCT_STR(s)
|
||||
+#define USBD_PRODUCT_STR(s) #s
|
||||
+#define USBD_PRODUCT_STRING_FS ODrive version HW_VERSION_MAJOR.HW_VERSION_MINOR
|
||||
#define USBD_SERIALNUMBER_STRING_FS "000000000001"
|
||||
#define USBD_CONFIGURATION_STRING_FS "CDC Config"
|
||||
#define USBD_INTERFACE_STRING_FS "CDC Interface"
|
||||
@@ -299,11 +301,11 @@ uint8_t * USBD_FS_ProductStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length
|
||||
{
|
||||
if(speed == 0)
|
||||
{
|
||||
- USBD_GetString((uint8_t *)USBD_PRODUCT_STRING_FS, USBD_StrDesc, length);
|
||||
+ USBD_GetString((uint8_t *)USBD_PRODUCT_XSTR(USBD_PRODUCT_STRING_FS), USBD_StrDesc, length);
|
||||
}
|
||||
else
|
||||
{
|
||||
- USBD_GetString((uint8_t *)USBD_PRODUCT_STRING_FS, USBD_StrDesc, length);
|
||||
+ USBD_GetString((uint8_t *)USBD_PRODUCT_XSTR(USBD_PRODUCT_STRING_FS), USBD_StrDesc, length);
|
||||
}
|
||||
return USBD_StrDesc;
|
||||
}
|
||||
--
|
||||
2.16.2
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
From 0867a92f742b312a0ebaafe94cade6f57be22170 Mon Sep 17 00:00:00 2001
|
||||
From: Samuel Sadok <samuel.sadok@bluewin.ch>
|
||||
Date: Mon, 12 Mar 2018 23:49:32 -0700
|
||||
Subject: [PATCH] expose correct serial number on USB
|
||||
|
||||
---
|
||||
Firmware/Board/v3/Src/usbd_desc.c | 9 +++++++++-------
|
||||
1 file changed, 1 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/Firmware/Board/v3/Src/usbd_desc.c b/Firmware/Board/v3/Src/usbd_desc.c
|
||||
index b9c7bd0..94dc49b 100644
|
||||
--- a/Firmware/Board/v3/Src/usbd_desc.c
|
||||
+++ b/Firmware/Board/v3/Src/usbd_desc.c
|
||||
@@ -327,14 +327,7 @@ uint8_t * USBD_FS_ManufacturerStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *l
|
||||
*/
|
||||
uint8_t * USBD_FS_SerialStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
|
||||
{
|
||||
- if(speed == USBD_SPEED_HIGH)
|
||||
- {
|
||||
- USBD_GetString((uint8_t *)USBD_SERIALNUMBER_STRING_FS, USBD_StrDesc, length);
|
||||
- }
|
||||
- else
|
||||
- {
|
||||
- USBD_GetString((uint8_t *)USBD_SERIALNUMBER_STRING_FS, USBD_StrDesc, length);
|
||||
- }
|
||||
+ USBD_GetString ((uint8_t *)serial_number_str, USBD_StrDesc, length);
|
||||
return USBD_StrDesc;
|
||||
}
|
||||
|
||||
--
|
||||
2.16.2
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
From 49353ccb7023c02c2bc6e3b6f14fac02a13fe599 Mon Sep 17 00:00:00 2001
|
||||
From: Samuel Sadok <samuel.sadok@bluewin.ch>
|
||||
Date: Mon, 26 Feb 2018 14:55:17 -0800
|
||||
Subject: [PATCH] fix return type of osSemaphoreWait
|
||||
|
||||
---
|
||||
.../Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS/cmsis_os.c | 6 +++---
|
||||
.../Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS/cmsis_os.h | 6 +++---
|
||||
2 files changed, 6 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/Firmware/Board/v3/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS/cmsis_os.c b/Firmware/Board/v3/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS/cmsis_os.c
|
||||
index d0e0fd7..e764cbc 100644
|
||||
--- a/Firmware/Board/v3/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS/cmsis_os.c
|
||||
+++ b/Firmware/Board/v3/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS/cmsis_os.c
|
||||
@@ -816,10 +816,10 @@ osSemaphoreId osSemaphoreCreate (const osSemaphoreDef_t *semaphore_def, int32_t
|
||||
* @brief Wait until a Semaphore token becomes available
|
||||
* @param semaphore_id semaphore object referenced with \ref osSemaphore.
|
||||
* @param millisec timeout value or 0 in case of no time-out.
|
||||
-* @retval number of available tokens, or -1 in case of incorrect parameters.
|
||||
+* @retval status code that indicates the execution status of the function.
|
||||
* @note MUST REMAIN UNCHANGED: \b osSemaphoreWait shall be consistent in every CMSIS-RTOS.
|
||||
*/
|
||||
-int32_t osSemaphoreWait (osSemaphoreId semaphore_id, uint32_t millisec)
|
||||
+osStatus osSemaphoreWait (osSemaphoreId semaphore_id, uint32_t millisec)
|
||||
{
|
||||
TickType_t ticks;
|
||||
portBASE_TYPE taskWoken = pdFALSE;
|
||||
diff --git a/Firmware/Board/v3/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS/cmsis_os.h b/Firmware/Board/v3/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS/cmsis_os.h
|
||||
index 15e25b9..5223f8e 100644
|
||||
--- a/Firmware/Board/v3/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS/cmsis_os.h
|
||||
+++ b/Firmware/Board/v3/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS/cmsis_os.h
|
||||
@@ -719,9 +719,9 @@ osSemaphoreId osSemaphoreCreate (const osSemaphoreDef_t *semaphore_def, int32_t
|
||||
/// Wait until a Semaphore token becomes available.
|
||||
/// \param[in] semaphore_id semaphore object referenced with \ref osSemaphoreCreate.
|
||||
/// \param[in] millisec timeout value or 0 in case of no time-out.
|
||||
-/// \return number of available tokens, or -1 in case of incorrect parameters.
|
||||
+/// \return status code that indicates the execution status of the function.
|
||||
/// \note MUST REMAIN UNCHANGED: \b osSemaphoreWait shall be consistent in every CMSIS-RTOS.
|
||||
-int32_t osSemaphoreWait (osSemaphoreId semaphore_id, uint32_t millisec);
|
||||
+osStatus osSemaphoreWait (osSemaphoreId semaphore_id, uint32_t millisec);
|
||||
|
||||
/// Release a Semaphore token.
|
||||
/// \param[in] semaphore_id semaphore object referenced with \ref osSemaphoreCreate.
|
||||
--
|
||||
2.16.1
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
From 965f7f2c80e30d7a66dcac7abaa9bdc371d9ea51 Mon Sep 17 00:00:00 2001
|
||||
From: Samuel Sadok <samuel.sadok@bluewin.ch>
|
||||
Date: Mon, 26 Feb 2018 14:53:52 -0800
|
||||
Subject: [PATCH] release sem_usb_tx in usbd_cdc.c
|
||||
|
||||
---
|
||||
.../Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Src/usbd_cdc.c | 5 +++--
|
||||
1 file changed, 3 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/Firmware/Board/v3/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Src/usbd_cdc.c b/Firmware/Board/v3.3/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Src/usbd_cdc.c
|
||||
index b2ca5f1..6ae33e8 100644
|
||||
--- a/Firmware/Board/v3/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Src/usbd_cdc.c
|
||||
+++ b/Firmware/Board/v3/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Src/usbd_cdc.c
|
||||
@@ -62,7 +62,8 @@
|
||||
#include "usbd_cdc.h"
|
||||
#include "usbd_desc.h"
|
||||
#include "usbd_ctlreq.h"
|
||||
-
|
||||
+#include <cmsis_os.h>
|
||||
+#include <freertos_vars.h>
|
||||
|
||||
/** @addtogroup STM32_USB_DEVICE_LIBRARY
|
||||
* @{
|
||||
@@ -669,7 +670,7 @@ static uint8_t USBD_CDC_DataIn (USBD_HandleTypeDef *pdev, uint8_t epnum)
|
||||
{
|
||||
|
||||
hcdc->TxState = 0;
|
||||
-
|
||||
+ osSemaphoreRelease(sem_usb_tx);
|
||||
return USBD_OK;
|
||||
}
|
||||
else
|
||||
--
|
||||
2.16.1
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,64 +0,0 @@
|
||||
From 510ead2b159e1d8116e5241066c54a7bf8b7bfbe Mon Sep 17 00:00:00 2001
|
||||
From: Samuel Sadok <samuel.sadok@bluewin.ch>
|
||||
Date: Mon, 26 Mar 2018 15:29:44 -0700
|
||||
Subject: [PATCH] FreeRTOS constness fixes
|
||||
|
||||
- make thread names const char *
|
||||
- make thread argument non-const void*
|
||||
---
|
||||
.../Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS/cmsis_os.h | 6 +++---
|
||||
Firmware/Board/v3/Src/freertos.c | 4 ++--
|
||||
2 files changed, 5 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/Firmware/Board/v3/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS/cmsis_os.h b/Firmware/Board/v3/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS/cmsis_os.h
|
||||
index 09cdf27..754be24 100644
|
||||
--- a/Firmware/Board/v3/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS/cmsis_os.h
|
||||
+++ b/Firmware/Board/v3/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS/cmsis_os.h
|
||||
@@ -270,11 +270,11 @@ typedef enum {
|
||||
|
||||
/// Entry point of a thread.
|
||||
/// \note MUST REMAIN UNCHANGED: \b os_pthread shall be consistent in every CMSIS-RTOS.
|
||||
-typedef void (*os_pthread) (void const *argument);
|
||||
+typedef void (*os_pthread) (void *argument);
|
||||
|
||||
/// Entry point of a timer call back function.
|
||||
/// \note MUST REMAIN UNCHANGED: \b os_ptimer shall be consistent in every CMSIS-RTOS.
|
||||
-typedef void (*os_ptimer) (void const *argument);
|
||||
+typedef void (*os_ptimer) (void *argument);
|
||||
|
||||
// >>> the following data type definitions may shall adapted towards a specific RTOS
|
||||
|
||||
@@ -323,7 +323,7 @@ typedef StaticQueue_t osStaticMessageQDef_t;
|
||||
/// Thread Definition structure contains startup information of a thread.
|
||||
/// \note CAN BE CHANGED: \b os_thread_def is implementation specific in every CMSIS-RTOS.
|
||||
typedef struct os_thread_def {
|
||||
- char *name; ///< Thread name
|
||||
+ const char *name; ///< Thread name
|
||||
os_pthread pthread; ///< start address of thread function
|
||||
osPriority tpriority; ///< initial thread priority
|
||||
uint32_t instances; ///< maximum number of instances of that thread function
|
||||
diff --git a/Firmware/Board/v3/Src/freertos.c b/Firmware/Board/v3/Src/freertos.c
|
||||
index 6eaea82..b247994 100644
|
||||
--- a/Firmware/Board/v3/Src/freertos.c
|
||||
+++ b/Firmware/Board/v3/Src/freertos.c
|
||||
@@ -75,7 +75,7 @@ uint8_t ucHeap[configTOTAL_HEAP_SIZE];
|
||||
/* USER CODE END Variables */
|
||||
|
||||
/* Function prototypes -------------------------------------------------------*/
|
||||
-void StartDefaultTask(void const * argument);
|
||||
+void StartDefaultTask(void * argument);
|
||||
|
||||
extern void MX_USB_DEVICE_Init(void);
|
||||
void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) */
|
||||
@@ -147,7 +147,7 @@ void MX_FREERTOS_Init(void) {
|
||||
}
|
||||
|
||||
/* StartDefaultTask function */
|
||||
-void StartDefaultTask(void const * argument)
|
||||
+void StartDefaultTask(void * argument)
|
||||
{
|
||||
/* init code for USB_DEVICE */
|
||||
MX_USB_DEVICE_Init();
|
||||
--
|
||||
2.16.2
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
From ab5ca860b3729d76a9c43c485776147ab69d2342 Mon Sep 17 00:00:00 2001
|
||||
From: Samuel Sadok <samuel.sadok@bluewin.ch>
|
||||
Date: Mon, 26 Mar 2018 19:02:45 -0700
|
||||
Subject: [PATCH] disable IRQ for DMA2_Stream0
|
||||
|
||||
This DMA stream is used to read values from ADC1
|
||||
while ADC1 cycles through it's sequence of input
|
||||
channels. No interrupts are required to make
|
||||
this work.
|
||||
---
|
||||
Firmware/Board/v3/Src/dma.c | 6 ++++--
|
||||
1 file changed, 4 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/Firmware/Board/v3/Src/dma.c b/Firmware/Board/v3/Src/dma.c
|
||||
index 55d5e03..3de873a 100644
|
||||
--- a/Firmware/Board/v3/Src/dma.c
|
||||
+++ b/Firmware/Board/v3/Src/dma.c
|
||||
@@ -78,8 +78,10 @@ void MX_DMA_Init(void)
|
||||
HAL_NVIC_SetPriority(DMA1_Stream4_IRQn, 5, 0);
|
||||
HAL_NVIC_EnableIRQ(DMA1_Stream4_IRQn);
|
||||
/* DMA2_Stream0_IRQn interrupt configuration */
|
||||
- HAL_NVIC_SetPriority(DMA2_Stream0_IRQn, 5, 0);
|
||||
- HAL_NVIC_EnableIRQ(DMA2_Stream0_IRQn);
|
||||
+ // Dear STM, no we _don't_ want to fire an interrupt for this DMA
|
||||
+ // (it's not possible to deselect this in CubeMX)
|
||||
+ //HAL_NVIC_SetPriority(DMA2_Stream0_IRQn, 5, 0);
|
||||
+ //HAL_NVIC_EnableIRQ(DMA2_Stream0_IRQn);
|
||||
|
||||
}
|
||||
|
||||
--
|
||||
2.16.2
|
||||
|
||||
@@ -70,6 +70,9 @@ typedef enum
|
||||
} HAL_LockTypeDef;
|
||||
|
||||
/* Exported macro ------------------------------------------------------------*/
|
||||
|
||||
#define UNUSED(X) (void)X /* To avoid gcc/g++ warnings */
|
||||
|
||||
#define HAL_MAX_DELAY 0xFFFFFFFFU
|
||||
|
||||
#define HAL_IS_BIT_SET(REG, BIT) (((REG) & (BIT)) != RESET)
|
||||
@@ -79,9 +82,7 @@ typedef enum
|
||||
do{ \
|
||||
(__HANDLE__)->__PPP_DMA_FIELD__ = &(__DMA_HANDLE__); \
|
||||
(__DMA_HANDLE__).Parent = (__HANDLE__); \
|
||||
} while(0)
|
||||
|
||||
#define UNUSED(x) ((void)(x))
|
||||
} while(0U)
|
||||
|
||||
/** @brief Reset the Handle's State field.
|
||||
* @param __HANDLE__ specifies the Peripheral Handle.
|
||||
@@ -135,7 +136,7 @@ typedef enum
|
||||
/* Macro to get variable aligned on 4-bytes, for __ICCARM__ the directive "#pragma data_alignment=4" must be used instead */
|
||||
#if defined ( __GNUC__ ) && !defined (__CC_ARM) /* GNU Compiler */
|
||||
#ifndef __ALIGN_END
|
||||
#define __ALIGN_END __attribute__ ((aligned (4)))
|
||||
#define __ALIGN_END __attribute__ ((aligned (4)))
|
||||
#endif /* __ALIGN_END */
|
||||
#ifndef __ALIGN_BEGIN
|
||||
#define __ALIGN_BEGIN
|
||||
@@ -146,7 +147,7 @@ typedef enum
|
||||
#endif /* __ALIGN_END */
|
||||
#ifndef __ALIGN_BEGIN
|
||||
#if defined (__CC_ARM) /* ARM Compiler */
|
||||
#define __ALIGN_BEGIN __align(4)
|
||||
#define __ALIGN_BEGIN __align(4)
|
||||
#elif defined (__ICCARM__) /* IAR Compiler */
|
||||
#define __ALIGN_BEGIN
|
||||
#endif /* __CC_ARM */
|
||||
@@ -167,14 +168,14 @@ typedef enum
|
||||
Available memory areas are declared in the 'Target' tab of the 'Options for Target'
|
||||
dialog.
|
||||
*/
|
||||
#define __RAM_FUNC HAL_StatusTypeDef
|
||||
#define __RAM_FUNC
|
||||
|
||||
#elif defined ( __ICCARM__ )
|
||||
/* ICCARM Compiler
|
||||
---------------
|
||||
RAM functions are defined using a specific toolchain keyword "__ramfunc".
|
||||
*/
|
||||
#define __RAM_FUNC __ramfunc HAL_StatusTypeDef
|
||||
#define __RAM_FUNC __ramfunc
|
||||
|
||||
#elif defined ( __GNUC__ )
|
||||
/* GNU Compiler
|
||||
@@ -182,7 +183,7 @@ typedef enum
|
||||
RAM functions are defined using a specific toolchain attribute
|
||||
"__attribute__((section(".RamFunc")))".
|
||||
*/
|
||||
#define __RAM_FUNC HAL_StatusTypeDef __attribute__((section(".RamFunc")))
|
||||
#define __RAM_FUNC __attribute__((section(".RamFunc")))
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -64,10 +64,10 @@
|
||||
/** @addtogroup FLASH_RAMFUNC_Exported_Functions_Group1
|
||||
* @{
|
||||
*/
|
||||
__RAM_FUNC HAL_FLASHEx_StopFlashInterfaceClk(void);
|
||||
__RAM_FUNC HAL_FLASHEx_StartFlashInterfaceClk(void);
|
||||
__RAM_FUNC HAL_FLASHEx_EnableFlashSleepMode(void);
|
||||
__RAM_FUNC HAL_FLASHEx_DisableFlashSleepMode(void);
|
||||
__RAM_FUNC HAL_StatusTypeDef HAL_FLASHEx_StopFlashInterfaceClk(void);
|
||||
__RAM_FUNC HAL_StatusTypeDef HAL_FLASHEx_StartFlashInterfaceClk(void);
|
||||
__RAM_FUNC HAL_StatusTypeDef HAL_FLASHEx_EnableFlashSleepMode(void);
|
||||
__RAM_FUNC HAL_StatusTypeDef HAL_FLASHEx_DisableFlashSleepMode(void);
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
@@ -66,11 +66,11 @@
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @brief STM32F4xx HAL Driver version number V1.7.3
|
||||
* @brief STM32F4xx HAL Driver version number V1.7.4
|
||||
*/
|
||||
#define __STM32F4xx_HAL_VERSION_MAIN (0x01U) /*!< [31:24] main version */
|
||||
#define __STM32F4xx_HAL_VERSION_SUB1 (0x07U) /*!< [23:16] sub1 version */
|
||||
#define __STM32F4xx_HAL_VERSION_SUB2 (0x03U) /*!< [15:8] sub2 version */
|
||||
#define __STM32F4xx_HAL_VERSION_SUB2 (0x04U) /*!< [15:8] sub2 version */
|
||||
#define __STM32F4xx_HAL_VERSION_RC (0x00U) /*!< [7:0] release candidate */
|
||||
#define __STM32F4xx_HAL_VERSION ((__STM32F4xx_HAL_VERSION_MAIN << 24U)\
|
||||
|(__STM32F4xx_HAL_VERSION_SUB1 << 16U)\
|
||||
|
||||
@@ -107,9 +107,9 @@
|
||||
* @note This mode is only available for STM32F41xxx/STM32F446xx devices.
|
||||
* @note This mode couldn't be set while executing with the flash itself.
|
||||
* It should be done with specific routine executed from RAM.
|
||||
* @retval None
|
||||
* @retval HAL status
|
||||
*/
|
||||
__RAM_FUNC HAL_FLASHEx_StopFlashInterfaceClk(void)
|
||||
__RAM_FUNC HAL_StatusTypeDef HAL_FLASHEx_StopFlashInterfaceClk(void)
|
||||
{
|
||||
/* Enable Power ctrl clock */
|
||||
__HAL_RCC_PWR_CLK_ENABLE();
|
||||
@@ -124,9 +124,9 @@ __RAM_FUNC HAL_FLASHEx_StopFlashInterfaceClk(void)
|
||||
* @note This mode is only available for STM32F411xx/STM32F446xx devices.
|
||||
* @note This mode couldn't be set while executing with the flash itself.
|
||||
* It should be done with specific routine executed from RAM.
|
||||
* @retval None
|
||||
* @retval HAL status
|
||||
*/
|
||||
__RAM_FUNC HAL_FLASHEx_StartFlashInterfaceClk(void)
|
||||
__RAM_FUNC HAL_StatusTypeDef HAL_FLASHEx_StartFlashInterfaceClk(void)
|
||||
{
|
||||
/* Enable Power ctrl clock */
|
||||
__HAL_RCC_PWR_CLK_ENABLE();
|
||||
@@ -141,9 +141,9 @@ __RAM_FUNC HAL_FLASHEx_StartFlashInterfaceClk(void)
|
||||
* @note This mode is only available for STM32F41xxx/STM32F446xx devices.
|
||||
* @note This mode could n't be set while executing with the flash itself.
|
||||
* It should be done with specific routine executed from RAM.
|
||||
* @retval None
|
||||
* @retval HAL status
|
||||
*/
|
||||
__RAM_FUNC HAL_FLASHEx_EnableFlashSleepMode(void)
|
||||
__RAM_FUNC HAL_StatusTypeDef HAL_FLASHEx_EnableFlashSleepMode(void)
|
||||
{
|
||||
/* Enable Power ctrl clock */
|
||||
__HAL_RCC_PWR_CLK_ENABLE();
|
||||
@@ -158,9 +158,9 @@ __RAM_FUNC HAL_FLASHEx_EnableFlashSleepMode(void)
|
||||
* @note This mode is only available for STM32F41xxx/STM32F446xx devices.
|
||||
* @note This mode couldn't be set while executing with the flash itself.
|
||||
* It should be done with specific routine executed from RAM.
|
||||
* @retval None
|
||||
* @retval HAL status
|
||||
*/
|
||||
__RAM_FUNC HAL_FLASHEx_DisableFlashSleepMode(void)
|
||||
__RAM_FUNC HAL_StatusTypeDef HAL_FLASHEx_DisableFlashSleepMode(void)
|
||||
{
|
||||
/* Enable Power ctrl clock */
|
||||
__HAL_RCC_PWR_CLK_ENABLE();
|
||||
|
||||
@@ -89,7 +89,6 @@
|
||||
/* Ensure stdint is only used by the compiler, and not the assembler. */
|
||||
#if defined(__ICCARM__) || defined(__CC_ARM) || defined(__GNUC__)
|
||||
#include <stdint.h>
|
||||
#include "main.h"
|
||||
extern uint32_t SystemCoreClock;
|
||||
#endif
|
||||
|
||||
@@ -153,7 +152,7 @@ See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */
|
||||
|
||||
/* Normal assert() semantics without relying on the provision of an assert.h
|
||||
header file. */
|
||||
/* USER CODE BEGIN 1 */
|
||||
/* USER CODE BEGIN 1 */
|
||||
#define configASSERT( x ) if ((x) == 0) {taskDISABLE_INTERRUPTS(); for( ;; );}
|
||||
/* USER CODE END 1 */
|
||||
|
||||
@@ -168,6 +167,7 @@ standard names. */
|
||||
|
||||
/* USER CODE BEGIN Defines */
|
||||
/* Section where parameter definitions can be added (for instance, to override default ones in FreeRTOS.h) */
|
||||
#define configAPPLICATION_ALLOCATED_HEAP 1 // ucHeap allocated in freertos.c
|
||||
/* USER CODE END Defines */
|
||||
|
||||
#endif /* FREERTOS_CONFIG_H */
|
||||
|
||||
@@ -67,12 +67,12 @@
|
||||
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
#define TIM_1_8_CLOCK_HZ 168000000
|
||||
#define TIM_1_8_PERIOD_CLOCKS 10192
|
||||
#define TIM_1_8_PERIOD_CLOCKS 3500
|
||||
#define TIM_1_8_DEADTIME_CLOCKS 20
|
||||
#define TIM_APB1_CLOCK_HZ 84000000
|
||||
#define TIM_APB1_PERIOD_CLOCKS 4096
|
||||
#define TIM_APB1_DEADTIME_CLOCKS 40
|
||||
#define configAPPLICATION_ALLOCATED_HEAP 1
|
||||
#define TIM_1_8_RCR 2
|
||||
|
||||
#define M0_nCS_Pin GPIO_PIN_13
|
||||
#define M0_nCS_GPIO_Port GPIOC
|
||||
@@ -168,8 +168,8 @@
|
||||
//TODO: make this come automatically out of CubeMX somehow
|
||||
#define TIM_TIME_BASE TIM14
|
||||
|
||||
#define CURRENT_MEAS_PERIOD ((float)(2*TIM_1_8_PERIOD_CLOCKS)/(float)TIM_1_8_CLOCK_HZ)
|
||||
#define CURRENT_MEAS_HZ (TIM_1_8_CLOCK_HZ/(2*TIM_1_8_PERIOD_CLOCKS))
|
||||
#define CURRENT_MEAS_PERIOD ( (float)2*TIM_1_8_PERIOD_CLOCKS*(TIM_1_8_RCR+1) / (float)TIM_1_8_CLOCK_HZ )
|
||||
#define CURRENT_MEAS_HZ ( (float)(TIM_1_8_CLOCK_HZ) / (float)(2*TIM_1_8_PERIOD_CLOCKS*(TIM_1_8_RCR+1)) )
|
||||
|
||||
#if HW_VERSION_VOLTAGE == 48
|
||||
#define VBUS_S_DIVIDER_RATIO 19.0f
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
#define TIM_1_8_CLOCK_HZ 168000000
|
||||
#define TIM_1_8_PERIOD_CLOCKS 10192
|
||||
#define TIM_1_8_PERIOD_CLOCKS 3500
|
||||
#define TIM_1_8_DEADTIME_CLOCKS 20
|
||||
#define TIM_APB1_CLOCK_HZ 84000000
|
||||
#define TIM_APB1_PERIOD_CLOCKS 4096
|
||||
#define TIM_APB1_DEADTIME_CLOCKS 40
|
||||
#define configAPPLICATION_ALLOCATED_HEAP 1
|
||||
#define TIM_1_8_RCR 2
|
||||
|
||||
#define M0_nCS_Pin GPIO_PIN_13
|
||||
#define M0_nCS_GPIO_Port GPIOC
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
#define TIM_1_8_CLOCK_HZ 168000000
|
||||
#define TIM_1_8_PERIOD_CLOCKS 10192
|
||||
#define TIM_1_8_PERIOD_CLOCKS 3500
|
||||
#define TIM_1_8_DEADTIME_CLOCKS 20
|
||||
#define TIM_APB1_CLOCK_HZ 84000000
|
||||
#define TIM_APB1_PERIOD_CLOCKS 4096
|
||||
#define TIM_APB1_DEADTIME_CLOCKS 40
|
||||
#define configAPPLICATION_ALLOCATED_HEAP 1
|
||||
#define TIM_1_8_RCR 2
|
||||
|
||||
#define M0_nCS_Pin GPIO_PIN_13
|
||||
#define M0_nCS_GPIO_Port GPIOC
|
||||
|
||||
@@ -91,6 +91,7 @@
|
||||
/* #define HAL_SPDIFRX_MODULE_ENABLED */
|
||||
/* #define HAL_DFSDM_MODULE_ENABLED */
|
||||
/* #define HAL_LPTIM_MODULE_ENABLED */
|
||||
/* #define HAL_EXTI_MODULE_ENABLED */
|
||||
#define HAL_GPIO_MODULE_ENABLED
|
||||
#define HAL_DMA_MODULE_ENABLED
|
||||
#define HAL_RCC_MODULE_ENABLED
|
||||
@@ -244,6 +245,10 @@
|
||||
#include "stm32f4xx_hal_rcc.h"
|
||||
#endif /* HAL_RCC_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_EXTI_MODULE_ENABLED
|
||||
#include "stm32f4xx_hal_exti.h"
|
||||
#endif /* HAL_EXTI_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_GPIO_MODULE_ENABLED
|
||||
#include "stm32f4xx_hal_gpio.h"
|
||||
#endif /* HAL_GPIO_MODULE_ENABLED */
|
||||
|
||||
@@ -54,8 +54,10 @@ void BusFault_Handler(void);
|
||||
void UsageFault_Handler(void);
|
||||
void DebugMon_Handler(void);
|
||||
void SysTick_Handler(void);
|
||||
void DMA1_Stream0_IRQHandler(void);
|
||||
void DMA1_Stream2_IRQHandler(void);
|
||||
void DMA1_Stream4_IRQHandler(void);
|
||||
void DMA1_Stream5_IRQHandler(void);
|
||||
void ADC_IRQHandler(void);
|
||||
void CAN1_TX_IRQHandler(void);
|
||||
void CAN1_RX0_IRQHandler(void);
|
||||
@@ -63,6 +65,7 @@ void CAN1_RX1_IRQHandler(void);
|
||||
void CAN1_SCE_IRQHandler(void);
|
||||
void TIM8_TRG_COM_TIM14_IRQHandler(void);
|
||||
void TIM5_IRQHandler(void);
|
||||
void SPI3_IRQHandler(void);
|
||||
void UART4_IRQHandler(void);
|
||||
void OTG_FS_IRQHandler(void);
|
||||
|
||||
|
||||
@@ -67,6 +67,7 @@ extern TIM_HandleTypeDef htim3;
|
||||
extern TIM_HandleTypeDef htim4;
|
||||
extern TIM_HandleTypeDef htim5;
|
||||
extern TIM_HandleTypeDef htim8;
|
||||
extern TIM_HandleTypeDef htim13;
|
||||
|
||||
/* USER CODE BEGIN Private defines */
|
||||
|
||||
@@ -80,10 +81,10 @@ void MX_TIM3_Init(void);
|
||||
void MX_TIM4_Init(void);
|
||||
void MX_TIM5_Init(void);
|
||||
void MX_TIM8_Init(void);
|
||||
|
||||
void MX_TIM13_Init(void);
|
||||
|
||||
void HAL_TIM_MspPostInit(TIM_HandleTypeDef *htim);
|
||||
|
||||
|
||||
|
||||
/* USER CODE BEGIN Prototypes */
|
||||
|
||||
void OC4_PWM_Override(TIM_HandleTypeDef* htim);
|
||||
|
||||
@@ -89,7 +89,7 @@
|
||||
* @brief Defines for configuration of the Usb device.
|
||||
* @{
|
||||
*/
|
||||
#define MS_VendorCode 'P'
|
||||
#define MS_VendorCode 'P'
|
||||
|
||||
/*---------- -----------*/
|
||||
#define USBD_MAX_NUM_INTERFACES 1
|
||||
|
||||
+1
-1
@@ -26,7 +26,7 @@
|
||||
*
|
||||
*----------------------------------------------------------------------------
|
||||
*
|
||||
* Portions Copyright © 2016 STMicroelectronics International N.V. All rights reserved.
|
||||
* Portions Copyright � 2016 STMicroelectronics International N.V. All rights reserved.
|
||||
* Portions Copyright (c) 2013 ARM LIMITED
|
||||
* All rights reserved.
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
||||
@@ -76,9 +76,11 @@ ADC3.SamplingTime-7\#ChannelRegularConversion=ADC_SAMPLETIME_3CYCLES
|
||||
ADC3.SamplingTime-8\#ChannelInjectedConversion=ADC_SAMPLETIME_3CYCLES
|
||||
ADC3.ScanConvMode=DISABLE
|
||||
CAN1.AutoWakeUp=ENABLE
|
||||
CAN1.CalculateTimeBit=2000
|
||||
CAN1.BS1=CAN_BS1_6TQ
|
||||
CAN1.BS2=CAN_BS2_5TQ
|
||||
CAN1.CalculateTimeBit=500
|
||||
CAN1.CalculateTimeQuantum=166.66666666666669
|
||||
CAN1.IPParameters=CalculateTimeQuantum,CalculateTimeBit,Prescaler,TimeSeg1,TimeSeg2,AutoWakeUp
|
||||
CAN1.IPParameters=CalculateTimeQuantum,CalculateTimeBit,Prescaler,TimeSeg1,TimeSeg2,AutoWakeUp,BS1,BS2
|
||||
CAN1.Prescaler=7
|
||||
CAN1.TimeSeg1=CAN_BS1_6TQ
|
||||
CAN1.TimeSeg2=CAN_BS2_5TQ
|
||||
@@ -95,7 +97,29 @@ Dma.ADC1.2.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlign
|
||||
Dma.Request0=UART4_RX
|
||||
Dma.Request1=UART4_TX
|
||||
Dma.Request2=ADC1
|
||||
Dma.RequestsNb=3
|
||||
Dma.Request3=SPI3_TX
|
||||
Dma.Request4=SPI3_RX
|
||||
Dma.RequestsNb=5
|
||||
Dma.SPI3_RX.4.Direction=DMA_PERIPH_TO_MEMORY
|
||||
Dma.SPI3_RX.4.FIFOMode=DMA_FIFOMODE_DISABLE
|
||||
Dma.SPI3_RX.4.Instance=DMA1_Stream0
|
||||
Dma.SPI3_RX.4.MemDataAlignment=DMA_MDATAALIGN_HALFWORD
|
||||
Dma.SPI3_RX.4.MemInc=DMA_MINC_ENABLE
|
||||
Dma.SPI3_RX.4.Mode=DMA_NORMAL
|
||||
Dma.SPI3_RX.4.PeriphDataAlignment=DMA_PDATAALIGN_HALFWORD
|
||||
Dma.SPI3_RX.4.PeriphInc=DMA_PINC_DISABLE
|
||||
Dma.SPI3_RX.4.Priority=DMA_PRIORITY_MEDIUM
|
||||
Dma.SPI3_RX.4.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority,FIFOMode
|
||||
Dma.SPI3_TX.3.Direction=DMA_MEMORY_TO_PERIPH
|
||||
Dma.SPI3_TX.3.FIFOMode=DMA_FIFOMODE_DISABLE
|
||||
Dma.SPI3_TX.3.Instance=DMA1_Stream5
|
||||
Dma.SPI3_TX.3.MemDataAlignment=DMA_MDATAALIGN_HALFWORD
|
||||
Dma.SPI3_TX.3.MemInc=DMA_MINC_ENABLE
|
||||
Dma.SPI3_TX.3.Mode=DMA_NORMAL
|
||||
Dma.SPI3_TX.3.PeriphDataAlignment=DMA_PDATAALIGN_HALFWORD
|
||||
Dma.SPI3_TX.3.PeriphInc=DMA_PINC_DISABLE
|
||||
Dma.SPI3_TX.3.Priority=DMA_PRIORITY_MEDIUM
|
||||
Dma.SPI3_TX.3.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority,FIFOMode
|
||||
Dma.UART4_RX.0.Direction=DMA_PERIPH_TO_MEMORY
|
||||
Dma.UART4_RX.0.FIFOMode=DMA_FIFOMODE_DISABLE
|
||||
Dma.UART4_RX.0.Instance=DMA1_Stream2
|
||||
@@ -135,9 +159,10 @@ Mcu.IP12=TIM3
|
||||
Mcu.IP13=TIM4
|
||||
Mcu.IP14=TIM5
|
||||
Mcu.IP15=TIM8
|
||||
Mcu.IP16=UART4
|
||||
Mcu.IP17=USB_DEVICE
|
||||
Mcu.IP18=USB_OTG_FS
|
||||
Mcu.IP16=TIM13
|
||||
Mcu.IP17=UART4
|
||||
Mcu.IP18=USB_DEVICE
|
||||
Mcu.IP19=USB_OTG_FS
|
||||
Mcu.IP2=ADC3
|
||||
Mcu.IP3=CAN1
|
||||
Mcu.IP4=DMA
|
||||
@@ -146,7 +171,7 @@ Mcu.IP6=NVIC
|
||||
Mcu.IP7=RCC
|
||||
Mcu.IP8=SPI3
|
||||
Mcu.IP9=SYS
|
||||
Mcu.IPNb=19
|
||||
Mcu.IPNb=20
|
||||
Mcu.Name=STM32F405RGTx
|
||||
Mcu.Package=LQFP64
|
||||
Mcu.Pin0=PC13-ANTI_TAMP
|
||||
@@ -200,25 +225,28 @@ Mcu.Pin51=VP_FREERTOS_VS_ENABLE
|
||||
Mcu.Pin52=VP_SYS_VS_tim14
|
||||
Mcu.Pin53=VP_TIM1_VS_ClockSourceINT
|
||||
Mcu.Pin54=VP_TIM1_VS_no_output4
|
||||
Mcu.Pin55=VP_USB_DEVICE_VS_USB_DEVICE_CDC_FS
|
||||
Mcu.Pin55=VP_TIM13_VS_ClockSourceINT
|
||||
Mcu.Pin56=VP_USB_DEVICE_VS_USB_DEVICE_CDC_FS
|
||||
Mcu.Pin6=PC1
|
||||
Mcu.Pin7=PC2
|
||||
Mcu.Pin8=PC3
|
||||
Mcu.Pin9=PA0-WKUP
|
||||
Mcu.PinsNb=56
|
||||
Mcu.PinsNb=57
|
||||
Mcu.ThirdPartyNb=0
|
||||
Mcu.UserConstants=TIM_1_8_CLOCK_HZ,168000000;TIM_1_8_PERIOD_CLOCKS,10192;TIM_1_8_DEADTIME_CLOCKS,20;TIM_APB1_CLOCK_HZ,84000000;TIM_APB1_PERIOD_CLOCKS,4096;TIM_APB1_DEADTIME_CLOCKS,40;configAPPLICATION_ALLOCATED_HEAP,1
|
||||
Mcu.UserConstants=TIM_1_8_CLOCK_HZ,168000000;TIM_1_8_PERIOD_CLOCKS,3500;TIM_1_8_DEADTIME_CLOCKS,20;TIM_APB1_CLOCK_HZ,84000000;TIM_APB1_PERIOD_CLOCKS,4096;TIM_APB1_DEADTIME_CLOCKS,40;TIM_1_8_RCR,2
|
||||
Mcu.UserName=STM32F405RGTx
|
||||
MxCube.Version=4.24.0
|
||||
MxDb.Version=DB.4.0.240
|
||||
MxCube.Version=4.27.0
|
||||
MxDb.Version=DB.4.0.270
|
||||
NVIC.ADC_IRQn=true\:5\:0\:false\:false\:true\:true\:true
|
||||
NVIC.BusFault_IRQn=true\:0\:0\:false\:false\:true\:false\:true
|
||||
NVIC.CAN1_RX0_IRQn=true\:6\:0\:true\:false\:true\:true\:true
|
||||
NVIC.CAN1_RX1_IRQn=true\:6\:0\:true\:false\:true\:true\:true
|
||||
NVIC.CAN1_SCE_IRQn=true\:6\:0\:true\:false\:true\:true\:true
|
||||
NVIC.CAN1_TX_IRQn=true\:6\:0\:true\:false\:true\:true\:true
|
||||
NVIC.DMA1_Stream0_IRQn=true\:5\:0\:false\:false\:true\:true\:false
|
||||
NVIC.DMA1_Stream2_IRQn=true\:5\:0\:false\:false\:true\:true\:true
|
||||
NVIC.DMA1_Stream4_IRQn=true\:5\:0\:false\:false\:true\:true\:false
|
||||
NVIC.DMA1_Stream5_IRQn=true\:5\:0\:false\:false\:true\:true\:false
|
||||
NVIC.DMA2_Stream0_IRQn=true\:5\:0\:false\:false\:false\:true\:false
|
||||
NVIC.DebugMonitor_IRQn=true\:0\:0\:false\:false\:true\:false\:true
|
||||
NVIC.HardFault_IRQn=true\:0\:0\:false\:false\:true\:false\:true
|
||||
@@ -227,6 +255,7 @@ NVIC.NonMaskableInt_IRQn=true\:0\:0\:false\:false\:true\:false\:true
|
||||
NVIC.OTG_FS_IRQn=true\:5\:0\:false\:false\:true\:true\:true
|
||||
NVIC.PendSV_IRQn=true\:15\:0\:false\:false\:false\:true\:true
|
||||
NVIC.PriorityGroup=NVIC_PRIORITYGROUP_4
|
||||
NVIC.SPI3_IRQn=true\:5\:0\:false\:false\:true\:true\:true
|
||||
NVIC.SVCall_IRQn=true\:0\:0\:false\:false\:false\:false\:true
|
||||
NVIC.SysTick_IRQn=true\:15\:0\:false\:false\:true\:true\:true
|
||||
NVIC.TIM1_UP_TIM10_IRQn=true\:0\:0\:false\:false\:false\:false\:true
|
||||
@@ -443,13 +472,15 @@ ProjectManager.CustomerFirmwarePackage=
|
||||
ProjectManager.DefaultFWLocation=true
|
||||
ProjectManager.DeletePrevious=true
|
||||
ProjectManager.DeviceId=STM32F405RGTx
|
||||
ProjectManager.FirmwarePackage=STM32Cube FW_F4 V1.19.0
|
||||
ProjectManager.FirmwarePackage=STM32Cube FW_F4 V1.21.0
|
||||
ProjectManager.FreePins=false
|
||||
ProjectManager.HalAssertFull=false
|
||||
ProjectManager.HeapSize=0x3C00
|
||||
ProjectManager.KeepUserCode=true
|
||||
ProjectManager.LastFirmware=true
|
||||
ProjectManager.LibraryCopy=1
|
||||
ProjectManager.MainLocation=Src
|
||||
ProjectManager.NoMain=false
|
||||
ProjectManager.PreviousToolchain=SW4STM32
|
||||
ProjectManager.ProjectBuild=false
|
||||
ProjectManager.ProjectFileName=Odrive.ioc
|
||||
@@ -458,7 +489,7 @@ ProjectManager.StackSize=0x800
|
||||
ProjectManager.TargetToolchain=Makefile
|
||||
ProjectManager.ToolChainLocation=
|
||||
ProjectManager.UnderRoot=false
|
||||
ProjectManager.functionlistsort=1-MX_GPIO_Init-GPIO-false-HAL-true,2-MX_DMA_Init-DMA-false-HAL-true,3-MX_ADC1_Init-ADC1-false-HAL-true,4-MX_ADC2_Init-ADC2-false-HAL-true,5-MX_CAN1_Init-CAN1-false-HAL-true,6-MX_TIM1_Init-TIM1-false-HAL-true,7-MX_TIM8_Init-TIM8-false-HAL-true,8-MX_TIM3_Init-TIM3-false-HAL-true,9-MX_TIM4_Init-TIM4-false-HAL-true,10-MX_SPI3_Init-SPI3-false-HAL-true,11-MX_ADC3_Init-ADC3-false-HAL-true,12-SystemClock_Config-RCC-false-HAL-true,13-MX_TIM2_Init-TIM2-false-HAL-true,14-MX_USB_DEVICE_Init-USB_DEVICE-false-HAL-true,15-MX_UART4_Init-UART4-false-HAL-true,16-MX_TIM5_Init-TIM5-false-HAL-true
|
||||
ProjectManager.functionlistsort=1-MX_GPIO_Init-GPIO-false-HAL-true,2-MX_DMA_Init-DMA-false-HAL-true,3-MX_ADC1_Init-ADC1-false-HAL-true,4-MX_ADC2_Init-ADC2-false-HAL-true,5-MX_CAN1_Init-CAN1-false-HAL-true,6-MX_TIM1_Init-TIM1-false-HAL-true,7-MX_TIM8_Init-TIM8-false-HAL-true,8-MX_TIM3_Init-TIM3-false-HAL-true,9-MX_TIM4_Init-TIM4-false-HAL-true,10-MX_SPI3_Init-SPI3-false-HAL-true,11-MX_ADC3_Init-ADC3-false-HAL-true,12-SystemClock_Config-RCC-false-HAL-true,13-MX_TIM2_Init-TIM2-false-HAL-true,14-MX_USB_DEVICE_Init-USB_DEVICE-false-HAL-true,15-MX_UART4_Init-UART4-false-HAL-true,16-MX_TIM5_Init-TIM5-false-HAL-true,17-MX_TIM13_Init-TIM13-false-HAL-true
|
||||
RCC.48MHZClocksFreq_Value=48000000
|
||||
RCC.AHBFreq_Value=168000000
|
||||
RCC.APB1CLKDivider=RCC_HCLK_DIV4
|
||||
@@ -576,7 +607,7 @@ TIM1.Channel-PWM\ Generation2\ CH2\ CH2N=TIM_CHANNEL_2
|
||||
TIM1.Channel-PWM\ Generation3\ CH3\ CH3N=TIM_CHANNEL_3
|
||||
TIM1.CounterMode=TIM_COUNTERMODE_CENTERALIGNED3
|
||||
TIM1.DeadTime=TIM_1_8_DEADTIME_CLOCKS
|
||||
TIM1.IPParameters=Channel-PWM Generation2 CH2 CH2N,Channel-PWM Generation3 CH3 CH3N,OCNPolarity_1,OCNPolarity_2,OCNPolarity_3,CounterMode,OCMode_PWM-PWM Generation1 CH1 CH1N,OCMode_PWM-PWM Generation2 CH2 CH2N,OCMode_PWM-PWM Generation3 CH3 CH3N,Period,DeadTime,OffStateRunMode,OffStateIDLEMode,Channel-Output Compare4 No Output,TIM_MasterOutputTrigger,Channel-PWM Generation1 CH1 CH1N
|
||||
TIM1.IPParameters=Channel-PWM Generation2 CH2 CH2N,Channel-PWM Generation3 CH3 CH3N,OCNPolarity_1,OCNPolarity_2,OCNPolarity_3,CounterMode,OCMode_PWM-PWM Generation1 CH1 CH1N,OCMode_PWM-PWM Generation2 CH2 CH2N,OCMode_PWM-PWM Generation3 CH3 CH3N,Period,DeadTime,OffStateRunMode,OffStateIDLEMode,Channel-Output Compare4 No Output,TIM_MasterOutputTrigger,Channel-PWM Generation1 CH1 CH1N,RepetitionCounter
|
||||
TIM1.OCMode_PWM-PWM\ Generation1\ CH1\ CH1N=TIM_OCMODE_PWM2
|
||||
TIM1.OCMode_PWM-PWM\ Generation2\ CH2\ CH2N=TIM_OCMODE_PWM2
|
||||
TIM1.OCMode_PWM-PWM\ Generation3\ CH3\ CH3N=TIM_OCMODE_PWM2
|
||||
@@ -586,7 +617,10 @@ TIM1.OCNPolarity_3=TIM_OCNPOLARITY_HIGH
|
||||
TIM1.OffStateIDLEMode=TIM_OSSI_ENABLE
|
||||
TIM1.OffStateRunMode=TIM_OSSR_ENABLE
|
||||
TIM1.Period=TIM_1_8_PERIOD_CLOCKS
|
||||
TIM1.RepetitionCounter=TIM_1_8_RCR
|
||||
TIM1.TIM_MasterOutputTrigger=TIM_TRGO_UPDATE
|
||||
TIM13.IPParameters=Period
|
||||
TIM13.Period=(2 * TIM_1_8_PERIOD_CLOCKS * (TIM_1_8_RCR+1)) * (TIM_APB1_CLOCK_HZ / TIM_1_8_CLOCK_HZ)
|
||||
TIM2.Channel-PWM\ Generation3\ CH3=TIM_CHANNEL_3
|
||||
TIM2.Channel-PWM\ Generation4\ CH4=TIM_CHANNEL_4
|
||||
TIM2.CounterMode=TIM_COUNTERMODE_CENTERALIGNED3
|
||||
@@ -624,13 +658,14 @@ TIM8.Channel-PWM\ Generation2\ CH2\ CH2N=TIM_CHANNEL_2
|
||||
TIM8.Channel-PWM\ Generation3\ CH3\ CH3N=TIM_CHANNEL_3
|
||||
TIM8.CounterMode=TIM_COUNTERMODE_CENTERALIGNED3
|
||||
TIM8.DeadTime=TIM_1_8_DEADTIME_CLOCKS
|
||||
TIM8.IPParameters=Channel-PWM Generation3 CH3 CH3N,Channel-PWM Generation2 CH2 CH2N,CounterMode,Period,OffStateRunMode,OffStateIDLEMode,DeadTime,OCMode_PWM-PWM Generation1 CH1 CH1N,OCMode_PWM-PWM Generation2 CH2 CH2N,OCMode_PWM-PWM Generation3 CH3 CH3N,Channel-Output Compare4 No Output,TIM_MasterOutputTrigger,Channel-PWM Generation1 CH1 CH1N
|
||||
TIM8.IPParameters=Channel-PWM Generation3 CH3 CH3N,Channel-PWM Generation2 CH2 CH2N,CounterMode,Period,OffStateRunMode,OffStateIDLEMode,DeadTime,OCMode_PWM-PWM Generation1 CH1 CH1N,OCMode_PWM-PWM Generation2 CH2 CH2N,OCMode_PWM-PWM Generation3 CH3 CH3N,Channel-Output Compare4 No Output,TIM_MasterOutputTrigger,Channel-PWM Generation1 CH1 CH1N,RepetitionCounter
|
||||
TIM8.OCMode_PWM-PWM\ Generation1\ CH1\ CH1N=TIM_OCMODE_PWM2
|
||||
TIM8.OCMode_PWM-PWM\ Generation2\ CH2\ CH2N=TIM_OCMODE_PWM2
|
||||
TIM8.OCMode_PWM-PWM\ Generation3\ CH3\ CH3N=TIM_OCMODE_PWM2
|
||||
TIM8.OffStateIDLEMode=TIM_OSSI_ENABLE
|
||||
TIM8.OffStateRunMode=TIM_OSSR_ENABLE
|
||||
TIM8.Period=TIM_1_8_PERIOD_CLOCKS
|
||||
TIM8.RepetitionCounter=TIM_1_8_RCR
|
||||
TIM8.TIM_MasterOutputTrigger=TIM_TRGO_UPDATE
|
||||
UART4.IPParameters=VirtualMode
|
||||
UART4.VirtualMode=Asynchronous
|
||||
@@ -652,6 +687,8 @@ VP_FREERTOS_VS_ENABLE.Mode=Enabled
|
||||
VP_FREERTOS_VS_ENABLE.Signal=FREERTOS_VS_ENABLE
|
||||
VP_SYS_VS_tim14.Mode=TIM14
|
||||
VP_SYS_VS_tim14.Signal=SYS_VS_tim14
|
||||
VP_TIM13_VS_ClockSourceINT.Mode=Enable_Timer
|
||||
VP_TIM13_VS_ClockSourceINT.Signal=TIM13_VS_ClockSourceINT
|
||||
VP_TIM1_VS_ClockSourceINT.Mode=Internal
|
||||
VP_TIM1_VS_ClockSourceINT.Signal=TIM1_VS_ClockSourceINT
|
||||
VP_TIM1_VS_no_output4.Mode=Output Compare4 No Output
|
||||
|
||||
@@ -134,9 +134,10 @@ SECTIONS
|
||||
*
|
||||
* IMPORTANT NOTE!
|
||||
* If initialized variables will be placed in this section,
|
||||
* the startup code needs to be modified to copy the init-values.
|
||||
* the startup code needs to be modified to copy the init-values.
|
||||
* Oskar: Added NOLOAD to remove this section from .bin outputs
|
||||
*/
|
||||
.ccmram :
|
||||
.ccmram (NOLOAD):
|
||||
{
|
||||
. = ALIGN(4);
|
||||
_sccmram = .; /* create a global symbol at ccmram start */
|
||||
|
||||
@@ -71,12 +71,18 @@ void MX_DMA_Init(void)
|
||||
__HAL_RCC_DMA2_CLK_ENABLE();
|
||||
|
||||
/* DMA interrupt init */
|
||||
/* DMA1_Stream0_IRQn interrupt configuration */
|
||||
HAL_NVIC_SetPriority(DMA1_Stream0_IRQn, 5, 0);
|
||||
HAL_NVIC_EnableIRQ(DMA1_Stream0_IRQn);
|
||||
/* DMA1_Stream2_IRQn interrupt configuration */
|
||||
HAL_NVIC_SetPriority(DMA1_Stream2_IRQn, 5, 0);
|
||||
HAL_NVIC_EnableIRQ(DMA1_Stream2_IRQn);
|
||||
/* DMA1_Stream4_IRQn interrupt configuration */
|
||||
HAL_NVIC_SetPriority(DMA1_Stream4_IRQn, 5, 0);
|
||||
HAL_NVIC_EnableIRQ(DMA1_Stream4_IRQn);
|
||||
/* DMA1_Stream5_IRQn interrupt configuration */
|
||||
HAL_NVIC_SetPriority(DMA1_Stream5_IRQn, 5, 0);
|
||||
HAL_NVIC_EnableIRQ(DMA1_Stream5_IRQn);
|
||||
/* DMA2_Stream0_IRQn interrupt configuration */
|
||||
// Dear STM, no we _don't_ want to fire an interrupt for this DMA
|
||||
// (it's not possible to deselect this in CubeMX)
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* USER CODE BEGIN Header */
|
||||
/**
|
||||
******************************************************************************
|
||||
* File Name : freertos.c
|
||||
@@ -45,12 +46,15 @@
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
/* USER CODE END Header */
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "main.h"
|
||||
#include "cmsis_os.h"
|
||||
|
||||
/* Private includes ----------------------------------------------------------*/
|
||||
/* USER CODE BEGIN Includes */
|
||||
#include "freertos_vars.h"
|
||||
#include "usb_device.h"
|
||||
@@ -58,9 +62,22 @@ extern PCD_HandleTypeDef hpcd_USB_OTG_FS;
|
||||
int odrive_main(void);
|
||||
/* USER CODE END Includes */
|
||||
|
||||
/* Variables -----------------------------------------------------------------*/
|
||||
osThreadId defaultTaskHandle;
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* USER CODE BEGIN PTD */
|
||||
|
||||
/* USER CODE END PTD */
|
||||
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/* USER CODE BEGIN PD */
|
||||
|
||||
/* USER CODE END PD */
|
||||
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* USER CODE BEGIN PM */
|
||||
|
||||
/* USER CODE END PM */
|
||||
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* USER CODE BEGIN Variables */
|
||||
// List of semaphores
|
||||
osSemaphoreId sem_usb_irq;
|
||||
@@ -74,17 +91,18 @@ osThreadId usb_irq_thread;
|
||||
__attribute__((section(".ccmram")))
|
||||
uint8_t ucHeap[configTOTAL_HEAP_SIZE];
|
||||
/* USER CODE END Variables */
|
||||
osThreadId defaultTaskHandle;
|
||||
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/* USER CODE BEGIN FunctionPrototypes */
|
||||
|
||||
/* USER CODE END FunctionPrototypes */
|
||||
|
||||
/* Function prototypes -------------------------------------------------------*/
|
||||
void StartDefaultTask(void * argument);
|
||||
|
||||
extern void MX_USB_DEVICE_Init(void);
|
||||
void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) */
|
||||
|
||||
/* USER CODE BEGIN FunctionPrototypes */
|
||||
|
||||
/* USER CODE END FunctionPrototypes */
|
||||
|
||||
/* Hook prototypes */
|
||||
void vApplicationIdleHook(void);
|
||||
void vApplicationStackOverflowHook(xTaskHandle xTask, signed char *pcTaskName);
|
||||
@@ -135,8 +153,11 @@ void init_deferred_interrupts(void) {
|
||||
|
||||
/* USER CODE END 4 */
|
||||
|
||||
/* Init FreeRTOS */
|
||||
|
||||
/**
|
||||
* @brief FreeRTOS initialization
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
void MX_FREERTOS_Init(void) {
|
||||
/* USER CODE BEGIN Init */
|
||||
|
||||
@@ -186,7 +207,13 @@ void MX_FREERTOS_Init(void) {
|
||||
/* USER CODE END RTOS_QUEUES */
|
||||
}
|
||||
|
||||
/* StartDefaultTask function */
|
||||
/* USER CODE BEGIN Header_StartDefaultTask */
|
||||
/**
|
||||
* @brief Function implementing the defaultTask thread.
|
||||
* @param argument: Not used
|
||||
* @retval None
|
||||
*/
|
||||
/* USER CODE END Header_StartDefaultTask */
|
||||
void StartDefaultTask(void * argument)
|
||||
{
|
||||
/* init code for USB_DEVICE */
|
||||
@@ -202,6 +229,7 @@ void StartDefaultTask(void * argument)
|
||||
/* USER CODE END StartDefaultTask */
|
||||
}
|
||||
|
||||
/* Private application code --------------------------------------------------*/
|
||||
/* USER CODE BEGIN Application */
|
||||
|
||||
/* USER CODE END Application */
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file : main.c
|
||||
@@ -179,7 +180,7 @@ int main(void)
|
||||
MX_DMA_Init();
|
||||
MX_ADC1_Init();
|
||||
MX_ADC2_Init();
|
||||
MX_CAN1_Init();
|
||||
// MX_CAN1_Init(); // CAN or I2C called in main.cpp instead
|
||||
MX_TIM1_Init();
|
||||
MX_TIM8_Init();
|
||||
MX_TIM3_Init();
|
||||
@@ -189,6 +190,7 @@ int main(void)
|
||||
MX_TIM2_Init();
|
||||
MX_UART4_Init();
|
||||
MX_TIM5_Init();
|
||||
MX_TIM13_Init();
|
||||
/* USER CODE BEGIN 2 */
|
||||
|
||||
//Required to use OC4 for ADC triggering.
|
||||
|
||||
@@ -51,12 +51,15 @@
|
||||
#include "spi.h"
|
||||
|
||||
#include "gpio.h"
|
||||
#include "dma.h"
|
||||
|
||||
/* USER CODE BEGIN 0 */
|
||||
|
||||
/* USER CODE END 0 */
|
||||
|
||||
SPI_HandleTypeDef hspi3;
|
||||
DMA_HandleTypeDef hdma_spi3_tx;
|
||||
DMA_HandleTypeDef hdma_spi3_rx;
|
||||
|
||||
/* SPI3 init function */
|
||||
void MX_SPI3_Init(void)
|
||||
@@ -105,6 +108,46 @@ void HAL_SPI_MspInit(SPI_HandleTypeDef* spiHandle)
|
||||
GPIO_InitStruct.Alternate = GPIO_AF6_SPI3;
|
||||
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
|
||||
|
||||
/* SPI3 DMA Init */
|
||||
/* SPI3_TX Init */
|
||||
hdma_spi3_tx.Instance = DMA1_Stream5;
|
||||
hdma_spi3_tx.Init.Channel = DMA_CHANNEL_0;
|
||||
hdma_spi3_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
|
||||
hdma_spi3_tx.Init.PeriphInc = DMA_PINC_DISABLE;
|
||||
hdma_spi3_tx.Init.MemInc = DMA_MINC_ENABLE;
|
||||
hdma_spi3_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
|
||||
hdma_spi3_tx.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
|
||||
hdma_spi3_tx.Init.Mode = DMA_NORMAL;
|
||||
hdma_spi3_tx.Init.Priority = DMA_PRIORITY_MEDIUM;
|
||||
hdma_spi3_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
|
||||
if (HAL_DMA_Init(&hdma_spi3_tx) != HAL_OK)
|
||||
{
|
||||
_Error_Handler(__FILE__, __LINE__);
|
||||
}
|
||||
|
||||
__HAL_LINKDMA(spiHandle,hdmatx,hdma_spi3_tx);
|
||||
|
||||
/* SPI3_RX Init */
|
||||
hdma_spi3_rx.Instance = DMA1_Stream0;
|
||||
hdma_spi3_rx.Init.Channel = DMA_CHANNEL_0;
|
||||
hdma_spi3_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
|
||||
hdma_spi3_rx.Init.PeriphInc = DMA_PINC_DISABLE;
|
||||
hdma_spi3_rx.Init.MemInc = DMA_MINC_ENABLE;
|
||||
hdma_spi3_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
|
||||
hdma_spi3_rx.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
|
||||
hdma_spi3_rx.Init.Mode = DMA_NORMAL;
|
||||
hdma_spi3_rx.Init.Priority = DMA_PRIORITY_MEDIUM;
|
||||
hdma_spi3_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
|
||||
if (HAL_DMA_Init(&hdma_spi3_rx) != HAL_OK)
|
||||
{
|
||||
_Error_Handler(__FILE__, __LINE__);
|
||||
}
|
||||
|
||||
__HAL_LINKDMA(spiHandle,hdmarx,hdma_spi3_rx);
|
||||
|
||||
/* SPI3 interrupt Init */
|
||||
HAL_NVIC_SetPriority(SPI3_IRQn, 5, 0);
|
||||
HAL_NVIC_EnableIRQ(SPI3_IRQn);
|
||||
/* USER CODE BEGIN SPI3_MspInit 1 */
|
||||
|
||||
/* USER CODE END SPI3_MspInit 1 */
|
||||
@@ -129,6 +172,12 @@ void HAL_SPI_MspDeInit(SPI_HandleTypeDef* spiHandle)
|
||||
*/
|
||||
HAL_GPIO_DeInit(GPIOC, GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12);
|
||||
|
||||
/* SPI3 DMA DeInit */
|
||||
HAL_DMA_DeInit(spiHandle->hdmatx);
|
||||
HAL_DMA_DeInit(spiHandle->hdmarx);
|
||||
|
||||
/* SPI3 interrupt Deinit */
|
||||
HAL_NVIC_DisableIRQ(SPI3_IRQn);
|
||||
/* USER CODE BEGIN SPI3_MspDeInit 1 */
|
||||
|
||||
/* USER CODE END SPI3_MspDeInit 1 */
|
||||
|
||||
@@ -48,7 +48,6 @@
|
||||
*/
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f4xx_hal.h"
|
||||
|
||||
extern void _Error_Handler(char *, int);
|
||||
/* USER CODE BEGIN 0 */
|
||||
|
||||
@@ -62,6 +61,9 @@ void HAL_MspInit(void)
|
||||
|
||||
/* USER CODE END MspInit 0 */
|
||||
|
||||
__HAL_RCC_SYSCFG_CLK_ENABLE();
|
||||
__HAL_RCC_PWR_CLK_ENABLE();
|
||||
|
||||
HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);
|
||||
|
||||
/* System interrupt init*/
|
||||
|
||||
@@ -63,6 +63,9 @@ extern ADC_HandleTypeDef hadc1;
|
||||
extern ADC_HandleTypeDef hadc2;
|
||||
extern ADC_HandleTypeDef hadc3;
|
||||
extern CAN_HandleTypeDef hcan1;
|
||||
extern DMA_HandleTypeDef hdma_spi3_tx;
|
||||
extern DMA_HandleTypeDef hdma_spi3_rx;
|
||||
extern SPI_HandleTypeDef hspi3;
|
||||
extern TIM_HandleTypeDef htim5;
|
||||
extern TIM_HandleTypeDef htim8;
|
||||
extern DMA_HandleTypeDef hdma_uart4_rx;
|
||||
@@ -206,6 +209,20 @@ void SysTick_Handler(void)
|
||||
/* please refer to the startup file (startup_stm32f4xx.s). */
|
||||
/******************************************************************************/
|
||||
|
||||
/**
|
||||
* @brief This function handles DMA1 stream0 global interrupt.
|
||||
*/
|
||||
void DMA1_Stream0_IRQHandler(void)
|
||||
{
|
||||
/* USER CODE BEGIN DMA1_Stream0_IRQn 0 */
|
||||
|
||||
/* USER CODE END DMA1_Stream0_IRQn 0 */
|
||||
HAL_DMA_IRQHandler(&hdma_spi3_rx);
|
||||
/* USER CODE BEGIN DMA1_Stream0_IRQn 1 */
|
||||
|
||||
/* USER CODE END DMA1_Stream0_IRQn 1 */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles DMA1 stream2 global interrupt.
|
||||
*/
|
||||
@@ -234,6 +251,20 @@ void DMA1_Stream4_IRQHandler(void)
|
||||
/* USER CODE END DMA1_Stream4_IRQn 1 */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles DMA1 stream5 global interrupt.
|
||||
*/
|
||||
void DMA1_Stream5_IRQHandler(void)
|
||||
{
|
||||
/* USER CODE BEGIN DMA1_Stream5_IRQn 0 */
|
||||
|
||||
/* USER CODE END DMA1_Stream5_IRQn 0 */
|
||||
HAL_DMA_IRQHandler(&hdma_spi3_tx);
|
||||
/* USER CODE BEGIN DMA1_Stream5_IRQn 1 */
|
||||
|
||||
/* USER CODE END DMA1_Stream5_IRQn 1 */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles ADC1, ADC2 and ADC3 global interrupts.
|
||||
*/
|
||||
@@ -348,6 +379,20 @@ void TIM5_IRQHandler(void)
|
||||
/* USER CODE END TIM5_IRQn 1 */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles SPI3 global interrupt.
|
||||
*/
|
||||
void SPI3_IRQHandler(void)
|
||||
{
|
||||
/* USER CODE BEGIN SPI3_IRQn 0 */
|
||||
|
||||
/* USER CODE END SPI3_IRQn 0 */
|
||||
HAL_SPI_IRQHandler(&hspi3);
|
||||
/* USER CODE BEGIN SPI3_IRQn 1 */
|
||||
|
||||
/* USER CODE END SPI3_IRQn 1 */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles UART4 global interrupt.
|
||||
*/
|
||||
|
||||
@@ -80,6 +80,7 @@ TIM_HandleTypeDef htim3;
|
||||
TIM_HandleTypeDef htim4;
|
||||
TIM_HandleTypeDef htim5;
|
||||
TIM_HandleTypeDef htim8;
|
||||
TIM_HandleTypeDef htim13;
|
||||
|
||||
/* TIM1 init function */
|
||||
void MX_TIM1_Init(void)
|
||||
@@ -94,7 +95,7 @@ void MX_TIM1_Init(void)
|
||||
htim1.Init.CounterMode = TIM_COUNTERMODE_CENTERALIGNED3;
|
||||
htim1.Init.Period = TIM_1_8_PERIOD_CLOCKS;
|
||||
htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
|
||||
htim1.Init.RepetitionCounter = 0;
|
||||
htim1.Init.RepetitionCounter = TIM_1_8_RCR;
|
||||
if (HAL_TIM_Base_Init(&htim1) != HAL_OK)
|
||||
{
|
||||
_Error_Handler(__FILE__, __LINE__);
|
||||
@@ -324,7 +325,7 @@ void MX_TIM8_Init(void)
|
||||
htim8.Init.CounterMode = TIM_COUNTERMODE_CENTERALIGNED3;
|
||||
htim8.Init.Period = TIM_1_8_PERIOD_CLOCKS;
|
||||
htim8.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
|
||||
htim8.Init.RepetitionCounter = 0;
|
||||
htim8.Init.RepetitionCounter = TIM_1_8_RCR;
|
||||
if (HAL_TIM_PWM_Init(&htim8) != HAL_OK)
|
||||
{
|
||||
_Error_Handler(__FILE__, __LINE__);
|
||||
@@ -373,6 +374,21 @@ void MX_TIM8_Init(void)
|
||||
|
||||
HAL_TIM_MspPostInit(&htim8);
|
||||
|
||||
}
|
||||
/* TIM13 init function */
|
||||
void MX_TIM13_Init(void)
|
||||
{
|
||||
|
||||
htim13.Instance = TIM13;
|
||||
htim13.Init.Prescaler = 0;
|
||||
htim13.Init.CounterMode = TIM_COUNTERMODE_UP;
|
||||
htim13.Init.Period = (2 * TIM_1_8_PERIOD_CLOCKS * (TIM_1_8_RCR+1)) * ((float)TIM_APB1_CLOCK_HZ / (float)TIM_1_8_CLOCK_HZ) - 1;
|
||||
htim13.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
|
||||
if (HAL_TIM_Base_Init(&htim13) != HAL_OK)
|
||||
{
|
||||
_Error_Handler(__FILE__, __LINE__);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* tim_baseHandle)
|
||||
@@ -393,6 +409,21 @@ void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* tim_baseHandle)
|
||||
|
||||
/* USER CODE END TIM1_MspInit 1 */
|
||||
}
|
||||
else if(tim_baseHandle->Instance==TIM13)
|
||||
{
|
||||
/* USER CODE BEGIN TIM13_MspInit 0 */
|
||||
|
||||
/* USER CODE END TIM13_MspInit 0 */
|
||||
/* TIM13 clock enable */
|
||||
__HAL_RCC_TIM13_CLK_ENABLE();
|
||||
|
||||
/* TIM13 interrupt Init */
|
||||
HAL_NVIC_SetPriority(TIM8_UP_TIM13_IRQn, 0, 0);
|
||||
HAL_NVIC_EnableIRQ(TIM8_UP_TIM13_IRQn);
|
||||
/* USER CODE BEGIN TIM13_MspInit 1 */
|
||||
|
||||
/* USER CODE END TIM13_MspInit 1 */
|
||||
}
|
||||
}
|
||||
|
||||
void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef* tim_pwmHandle)
|
||||
@@ -626,6 +657,27 @@ void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef* tim_baseHandle)
|
||||
|
||||
/* USER CODE END TIM1_MspDeInit 1 */
|
||||
}
|
||||
else if(tim_baseHandle->Instance==TIM13)
|
||||
{
|
||||
/* USER CODE BEGIN TIM13_MspDeInit 0 */
|
||||
|
||||
/* USER CODE END TIM13_MspDeInit 0 */
|
||||
/* Peripheral clock disable */
|
||||
__HAL_RCC_TIM13_CLK_DISABLE();
|
||||
|
||||
/* TIM13 interrupt Deinit */
|
||||
/* USER CODE BEGIN TIM13:TIM8_UP_TIM13_IRQn disable */
|
||||
/**
|
||||
* Uncomment the line below to disable the "TIM8_UP_TIM13_IRQn" interrupt
|
||||
* Be aware, disabling shared interrupt may affect other IPs
|
||||
*/
|
||||
/* HAL_NVIC_DisableIRQ(TIM8_UP_TIM13_IRQn); */
|
||||
/* USER CODE END TIM13:TIM8_UP_TIM13_IRQn disable */
|
||||
|
||||
/* USER CODE BEGIN TIM13_MspDeInit 1 */
|
||||
|
||||
/* USER CODE END TIM13_MspDeInit 1 */
|
||||
}
|
||||
}
|
||||
|
||||
void HAL_TIM_PWM_MspDeInit(TIM_HandleTypeDef* tim_pwmHandle)
|
||||
@@ -651,7 +703,14 @@ void HAL_TIM_PWM_MspDeInit(TIM_HandleTypeDef* tim_pwmHandle)
|
||||
__HAL_RCC_TIM8_CLK_DISABLE();
|
||||
|
||||
/* TIM8 interrupt Deinit */
|
||||
HAL_NVIC_DisableIRQ(TIM8_UP_TIM13_IRQn);
|
||||
/* USER CODE BEGIN TIM8:TIM8_UP_TIM13_IRQn disable */
|
||||
/**
|
||||
* Uncomment the line below to disable the "TIM8_UP_TIM13_IRQn" interrupt
|
||||
* Be aware, disabling shared interrupt may affect other IPs
|
||||
*/
|
||||
/* HAL_NVIC_DisableIRQ(TIM8_UP_TIM13_IRQn); */
|
||||
/* USER CODE END TIM8:TIM8_UP_TIM13_IRQn disable */
|
||||
|
||||
HAL_NVIC_DisableIRQ(TIM8_TRG_COM_TIM14_IRQn);
|
||||
/* USER CODE BEGIN TIM8_MspDeInit 1 */
|
||||
|
||||
|
||||
@@ -66,7 +66,7 @@ void MX_UART4_Init(void)
|
||||
{
|
||||
|
||||
huart4.Instance = UART4;
|
||||
huart4.Init.BaudRate = 115200;
|
||||
huart4.Init.BaudRate = 115200; // Provisionally this can be changed to 921600 for faster transfers, the low power Arduinos will not keep up.
|
||||
huart4.Init.WordLength = UART_WORDLENGTH_8B;
|
||||
huart4.Init.StopBits = UART_STOPBITS_1;
|
||||
huart4.Init.Parity = UART_PARITY_NONE;
|
||||
|
||||
@@ -26,6 +26,8 @@ Axis::Axis(const AxisHardwareConfig_t& hw_config,
|
||||
controller_.axis_ = this;
|
||||
motor_.axis_ = this;
|
||||
trap_.axis_ = this;
|
||||
|
||||
decode_step_dir_pins();
|
||||
}
|
||||
|
||||
static void step_cb_wrapper(void* ctx) {
|
||||
@@ -66,33 +68,46 @@ bool Axis::wait_for_current_meas() {
|
||||
|
||||
// step/direction interface
|
||||
void Axis::step_cb() {
|
||||
if (enable_step_dir_) {
|
||||
GPIO_PinState dir_pin = HAL_GPIO_ReadPin(hw_config_.dir_port, hw_config_.dir_pin);
|
||||
if (step_dir_active_) {
|
||||
GPIO_PinState dir_pin = HAL_GPIO_ReadPin(dir_port_, dir_pin_);
|
||||
float dir = (dir_pin == GPIO_PIN_SET) ? 1.0f : -1.0f;
|
||||
controller_.pos_setpoint_ += dir * config_.counts_per_step;
|
||||
}
|
||||
};
|
||||
|
||||
// @brief Enables or disables step/dir input
|
||||
void Axis::set_step_dir_enabled(bool enable) {
|
||||
if (enable) {
|
||||
void Axis::load_default_step_dir_pin_config(
|
||||
const AxisHardwareConfig_t& hw_config, Config_t* config) {
|
||||
config->step_gpio_pin = hw_config.step_gpio_pin;
|
||||
config->dir_gpio_pin = hw_config.dir_gpio_pin;
|
||||
}
|
||||
|
||||
void Axis::decode_step_dir_pins() {
|
||||
step_port_ = get_gpio_port_by_pin(config_.step_gpio_pin);
|
||||
step_pin_ = get_gpio_pin_by_pin(config_.step_gpio_pin);
|
||||
dir_port_ = get_gpio_port_by_pin(config_.dir_gpio_pin);
|
||||
dir_pin_ = get_gpio_pin_by_pin(config_.dir_gpio_pin);
|
||||
}
|
||||
|
||||
// @brief (de)activates step/dir input
|
||||
void Axis::set_step_dir_active(bool active) {
|
||||
if (active) {
|
||||
// Set up the direction GPIO as input
|
||||
GPIO_InitTypeDef GPIO_InitStruct;
|
||||
GPIO_InitStruct.Pin = hw_config_.dir_pin;
|
||||
GPIO_InitStruct.Pin = dir_pin_;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
|
||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
HAL_GPIO_Init(hw_config_.dir_port, &GPIO_InitStruct);
|
||||
HAL_GPIO_Init(dir_port_, &GPIO_InitStruct);
|
||||
|
||||
// Subscribe to rising edges of the step GPIO
|
||||
GPIO_subscribe(hw_config_.step_port, hw_config_.step_pin, GPIO_PULLDOWN,
|
||||
GPIO_subscribe(step_port_, step_pin_, GPIO_PULLDOWN,
|
||||
step_cb_wrapper, this);
|
||||
|
||||
enable_step_dir_ = true;
|
||||
step_dir_active_ = true;
|
||||
} else {
|
||||
enable_step_dir_ = false;
|
||||
step_dir_active_ = false;
|
||||
|
||||
// Unsubscribe from step GPIO
|
||||
GPIO_unsubscribe(hw_config_.step_port, hw_config_.step_pin);
|
||||
GPIO_unsubscribe(step_port_, step_pin_);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,12 +141,6 @@ bool Axis::do_updates() {
|
||||
return check_for_errors();
|
||||
}
|
||||
|
||||
float Axis::get_temp() {
|
||||
float adc = adc_measurements_[hw_config_.thermistor_adc_ch];
|
||||
float normalized_voltage = adc / adc_full_scale;
|
||||
return horner_fma(normalized_voltage, thermistor_poly_coeffs, thermistor_num_coeffs);
|
||||
}
|
||||
|
||||
bool Axis::run_lockin_spin() {
|
||||
// Spiral up current for softer rotor lock-in
|
||||
lockin_state_ = LOCKIN_STATE_RAMP;
|
||||
@@ -140,7 +149,7 @@ bool Axis::run_lockin_spin() {
|
||||
float phase = wrap_pm_pi(config_.lockin_ramp_distance * x);
|
||||
float I_mag = config_.lockin_current * x;
|
||||
x += current_meas_period / config_.lockin_ramp_time;
|
||||
if (!motor_.update(I_mag, phase))
|
||||
if (!motor_.update(I_mag, phase, 0.0f))
|
||||
return false;
|
||||
return x < 1.0f;
|
||||
});
|
||||
@@ -169,7 +178,7 @@ bool Axis::run_lockin_spin() {
|
||||
distance += vel * current_meas_period;
|
||||
phase = wrap_pm_pi(phase + vel * current_meas_period);
|
||||
|
||||
if (!motor_.update(config_.lockin_current, phase))
|
||||
if (!motor_.update(config_.lockin_current, phase, vel))
|
||||
return false;
|
||||
return !spin_done(true); //vel_override to go to next phase
|
||||
});
|
||||
@@ -194,7 +203,6 @@ bool Axis::run_lockin_spin() {
|
||||
|
||||
// Note run_sensorless_control_loop and run_closed_loop_control_loop are very similar and differ only in where we get the estimate from.
|
||||
bool Axis::run_sensorless_control_loop() {
|
||||
set_step_dir_enabled(config_.enable_step_dir);
|
||||
run_control_loop([this](){
|
||||
if (controller_.config_.control_mode >= Controller::CTRL_MODE_POSITION_CONTROL)
|
||||
return error_ |= ERROR_POS_CTRL_DURING_SENSORLESS, false;
|
||||
@@ -203,26 +211,28 @@ bool Axis::run_sensorless_control_loop() {
|
||||
float current_setpoint;
|
||||
if (!controller_.update(sensorless_estimator_.pll_pos_, sensorless_estimator_.vel_estimate_, ¤t_setpoint))
|
||||
return error_ |= ERROR_CONTROLLER_FAILED, false;
|
||||
if (!motor_.update(current_setpoint, sensorless_estimator_.phase_))
|
||||
if (!motor_.update(current_setpoint, sensorless_estimator_.phase_, sensorless_estimator_.vel_estimate_))
|
||||
return false; // set_error should update axis.error_
|
||||
return true;
|
||||
});
|
||||
set_step_dir_enabled(false);
|
||||
return check_for_errors();
|
||||
}
|
||||
|
||||
bool Axis::run_closed_loop_control_loop() {
|
||||
set_step_dir_enabled(config_.enable_step_dir);
|
||||
// To avoid any transient on startup, we intialize the setpoint to be the current position
|
||||
controller_.pos_setpoint_ = encoder_.pos_estimate_;
|
||||
set_step_dir_active(config_.enable_step_dir);
|
||||
run_control_loop([this](){
|
||||
// Note that all estimators are updated in the loop prefix in run_control_loop
|
||||
float current_setpoint;
|
||||
if (!controller_.update(encoder_.pos_estimate_, encoder_.vel_estimate_, ¤t_setpoint))
|
||||
return error_ |= ERROR_CONTROLLER_FAILED, false; //TODO: Make controller.set_error
|
||||
if (!motor_.update(current_setpoint, encoder_.phase_))
|
||||
float phase_vel = 2*M_PI * encoder_.vel_estimate_ / (float)encoder_.config_.cpr * motor_.config_.pole_pairs;
|
||||
if (!motor_.update(current_setpoint, encoder_.phase_, phase_vel))
|
||||
return false; // set_error should update axis.error_
|
||||
return true;
|
||||
});
|
||||
set_step_dir_enabled(false);
|
||||
set_step_dir_active(false);
|
||||
return check_for_errors();
|
||||
}
|
||||
|
||||
|
||||
@@ -45,9 +45,12 @@ public:
|
||||
bool startup_sensorless_control = false; //<! enable sensorless control after calibration/startup
|
||||
bool enable_step_dir = false; //<! enable step/dir input after calibration
|
||||
// For M0 this has no effect if enable_uart is true
|
||||
|
||||
float counts_per_step = 2.0f;
|
||||
|
||||
// Defaults loaded from hw_config in load_configuration in main.cpp
|
||||
uint16_t step_gpio_pin = 0;
|
||||
uint16_t dir_gpio_pin = 0;
|
||||
|
||||
// Spinup settings
|
||||
float lockin_current = 10.0f; // [A]
|
||||
float lockin_ramp_time = 0.4f; // [s]
|
||||
@@ -85,13 +88,15 @@ public:
|
||||
bool wait_for_current_meas();
|
||||
|
||||
void step_cb();
|
||||
void set_step_dir_enabled(bool enable);
|
||||
void set_step_dir_active(bool enable);
|
||||
void decode_step_dir_pins();
|
||||
static void load_default_step_dir_pin_config(
|
||||
const AxisHardwareConfig_t& hw_config, Config_t* config);
|
||||
|
||||
bool check_DRV_fault();
|
||||
bool check_PSU_brownout();
|
||||
bool do_checks();
|
||||
bool do_updates();
|
||||
float get_temp();
|
||||
|
||||
// True if there are no errors
|
||||
bool inline check_for_errors() {
|
||||
@@ -177,7 +182,14 @@ public:
|
||||
|
||||
// variables exposed on protocol
|
||||
Error_t error_ = ERROR_NONE;
|
||||
bool enable_step_dir_ = false; // auto enabled after calibration, based on config.enable_step_dir
|
||||
bool step_dir_active_ = false; // auto enabled after calibration, based on config.enable_step_dir
|
||||
|
||||
// updated from config in constructor, and on protocol hook
|
||||
GPIO_TypeDef* step_port_;
|
||||
uint16_t step_pin_;
|
||||
GPIO_TypeDef* dir_port_;
|
||||
uint16_t dir_pin_;
|
||||
|
||||
State_t requested_state_ = AXIS_STATE_STARTUP_SEQUENCE;
|
||||
State_t task_chain_[10] = { AXIS_STATE_UNDEFINED };
|
||||
State_t& current_state_ = task_chain_[0];
|
||||
@@ -188,7 +200,7 @@ public:
|
||||
auto make_protocol_definitions() {
|
||||
return make_protocol_member_list(
|
||||
make_protocol_property("error", &error_),
|
||||
make_protocol_property("enable_step_dir", &enable_step_dir_),
|
||||
make_protocol_ro_property("step_dir_active", &step_dir_active_),
|
||||
make_protocol_ro_property("current_state", ¤t_state_),
|
||||
make_protocol_property("requested_state", &requested_state_),
|
||||
make_protocol_ro_property("loop_counter", &loop_counter_),
|
||||
@@ -209,9 +221,12 @@ public:
|
||||
make_protocol_property("lockin_finish_distance", &config_.lockin_finish_distance),
|
||||
make_protocol_property("lockin_finish_on_vel", &config_.lockin_finish_on_vel),
|
||||
make_protocol_property("lockin_finish_on_distance", &config_.lockin_finish_on_distance),
|
||||
make_protocol_property("lockin_finish_on_enc_idx", &config_.lockin_finish_on_enc_idx)
|
||||
make_protocol_property("lockin_finish_on_enc_idx", &config_.lockin_finish_on_enc_idx),
|
||||
make_protocol_property("step_gpio_pin", &config_.step_gpio_pin,
|
||||
[](void* ctx) { static_cast<Axis*>(ctx)->decode_step_dir_pins(); }, this),
|
||||
make_protocol_property("dir_gpio_pin", &config_.dir_gpio_pin,
|
||||
[](void* ctx) { static_cast<Axis*>(ctx)->decode_step_dir_pins(); }, this)
|
||||
),
|
||||
make_protocol_function("get_temp", *this, &Axis::get_temp),
|
||||
make_protocol_object("motor", motor_.make_protocol_definitions()),
|
||||
make_protocol_object("controller", controller_.make_protocol_definitions()),
|
||||
make_protocol_object("encoder", encoder_.make_protocol_definitions()),
|
||||
|
||||
@@ -21,11 +21,8 @@
|
||||
|
||||
|
||||
typedef struct {
|
||||
GPIO_TypeDef* step_port;
|
||||
uint16_t step_pin;
|
||||
GPIO_TypeDef* dir_port;
|
||||
uint16_t dir_pin;
|
||||
size_t thermistor_adc_ch;
|
||||
uint16_t step_gpio_pin;
|
||||
uint16_t dir_gpio_pin;
|
||||
osPriority thread_priority;
|
||||
} AxisHardwareConfig_t;
|
||||
|
||||
@@ -44,6 +41,7 @@ typedef struct {
|
||||
TIM_HandleTypeDef* timer;
|
||||
uint16_t control_deadline;
|
||||
float shunt_conductance;
|
||||
size_t inverter_thermistor_adc_ch;
|
||||
} MotorHardwareConfig_t;
|
||||
typedef struct {
|
||||
SPI_HandleTypeDef* spi;
|
||||
@@ -68,17 +66,14 @@ extern const size_t thermistor_num_coeffs;
|
||||
//TODO stick this in a C file
|
||||
#ifdef __MAIN_CPP__
|
||||
const float thermistor_poly_coeffs[] =
|
||||
{363.0172658f, -459.19773008f, 308.29273921f, -28.12731452f};
|
||||
{363.93910201f, -462.15369634f, 307.55129571f, -27.72569531f};
|
||||
const size_t thermistor_num_coeffs = sizeof(thermistor_poly_coeffs)/sizeof(thermistor_poly_coeffs[1]);
|
||||
|
||||
const BoardHardwareConfig_t hw_configs[2] = { {
|
||||
//M0
|
||||
.axis_config = {
|
||||
.step_port = GPIO_1_GPIO_Port,
|
||||
.step_pin = GPIO_1_Pin,
|
||||
.dir_port = GPIO_2_GPIO_Port,
|
||||
.dir_pin = GPIO_2_Pin,
|
||||
.thermistor_adc_ch = 15,
|
||||
.step_gpio_pin = 1,
|
||||
.dir_gpio_pin = 2,
|
||||
.thread_priority = (osPriority)(osPriorityHigh + (osPriority)1),
|
||||
},
|
||||
.encoder_config = {
|
||||
@@ -96,6 +91,7 @@ const BoardHardwareConfig_t hw_configs[2] = { {
|
||||
.timer = &htim1,
|
||||
.control_deadline = TIM_1_8_PERIOD_CLOCKS,
|
||||
.shunt_conductance = 1.0f / SHUNT_RESISTANCE, //[S]
|
||||
.inverter_thermistor_adc_ch = 15,
|
||||
},
|
||||
.gate_driver_config = {
|
||||
.spi = &hspi3,
|
||||
@@ -111,20 +107,11 @@ const BoardHardwareConfig_t hw_configs[2] = { {
|
||||
//M1
|
||||
.axis_config = {
|
||||
#if HW_VERSION_MAJOR == 3 && HW_VERSION_MINOR >= 5
|
||||
.step_port = GPIO_7_GPIO_Port,
|
||||
.step_pin = GPIO_7_Pin,
|
||||
.dir_port = GPIO_8_GPIO_Port,
|
||||
.dir_pin = GPIO_8_Pin,
|
||||
.step_gpio_pin = 7,
|
||||
.dir_gpio_pin = 8,
|
||||
#else
|
||||
.step_port = GPIO_3_GPIO_Port,
|
||||
.step_pin = GPIO_3_Pin,
|
||||
.dir_port = GPIO_4_GPIO_Port,
|
||||
.dir_pin = GPIO_4_Pin,
|
||||
#endif
|
||||
#if HW_VERSION_MAJOR == 3 && HW_VERSION_MINOR >= 3
|
||||
.thermistor_adc_ch = 4,
|
||||
#else
|
||||
.thermistor_adc_ch = 1,
|
||||
.step_gpio_pin = 3,
|
||||
.dir_gpio_pin = 4,
|
||||
#endif
|
||||
.thread_priority = osPriorityHigh,
|
||||
},
|
||||
@@ -143,6 +130,11 @@ const BoardHardwareConfig_t hw_configs[2] = { {
|
||||
.timer = &htim8,
|
||||
.control_deadline = (3 * TIM_1_8_PERIOD_CLOCKS) / 2,
|
||||
.shunt_conductance = 1.0f / SHUNT_RESISTANCE, //[S]
|
||||
#if HW_VERSION_MAJOR == 3 && HW_VERSION_MINOR >= 3
|
||||
.inverter_thermistor_adc_ch = 4,
|
||||
#else
|
||||
.inverter_thermistor_adc_ch = 1,
|
||||
#endif
|
||||
},
|
||||
.gate_driver_config = {
|
||||
.spi = &hspi3,
|
||||
|
||||
@@ -13,6 +13,11 @@ void Controller::reset() {
|
||||
current_setpoint_ = 0.0f;
|
||||
}
|
||||
|
||||
void Controller::set_error(Error_t error) {
|
||||
error_ |= error;
|
||||
axis_->error_ |= Axis::ERROR_CONTROLLER_FAILED;
|
||||
}
|
||||
|
||||
//--------------------------------
|
||||
// Command Handling
|
||||
//--------------------------------
|
||||
@@ -113,11 +118,36 @@ bool Controller::update(float pos_estimate, float vel_estimate, float* current_s
|
||||
anticogging_pos = pos_setpoint_; // FF the position setpoint instead of the pos_estimate
|
||||
}
|
||||
|
||||
// Ramp rate limited velocity setpoint
|
||||
if (config_.control_mode == CTRL_MODE_VELOCITY_CONTROL && vel_ramp_enable_) {
|
||||
float max_step_size = current_meas_period * config_.vel_ramp_rate;
|
||||
float full_step = vel_ramp_target_ - vel_setpoint_;
|
||||
float step;
|
||||
if (fabsf(full_step) > max_step_size) {
|
||||
step = std::copysignf(max_step_size, full_step);
|
||||
} else {
|
||||
step = full_step;
|
||||
}
|
||||
vel_setpoint_ += step;
|
||||
}
|
||||
|
||||
// Position control
|
||||
// TODO Decide if we want to use encoder or pll position here
|
||||
float vel_des = vel_setpoint_;
|
||||
if (config_.control_mode >= CTRL_MODE_POSITION_CONTROL) {
|
||||
float pos_err = pos_setpoint_ - pos_estimate;
|
||||
float pos_err;
|
||||
if (config_.setpoints_in_cpr) {
|
||||
// TODO this breaks the semantics that estimates come in on the arguments.
|
||||
// It's probably better to call a get_estimate that will arbitrate (enc vs sensorless) instead.
|
||||
float cpr = (float)(axis_->encoder_.config_.cpr);
|
||||
// Keep pos setpoint from drifting
|
||||
pos_setpoint_ = fmodf_pos(pos_setpoint_, cpr);
|
||||
// Circular delta
|
||||
pos_err = pos_setpoint_ - axis_->encoder_.pos_cpr_;
|
||||
pos_err = wrap_pm(pos_err, 0.5f * cpr);
|
||||
} else {
|
||||
pos_err = pos_setpoint_ - pos_estimate;
|
||||
}
|
||||
vel_des += config_.pos_gain * pos_err;
|
||||
}
|
||||
|
||||
@@ -126,6 +156,14 @@ bool Controller::update(float pos_estimate, float vel_estimate, float* current_s
|
||||
if (vel_des > vel_lim) vel_des = vel_lim;
|
||||
if (vel_des < -vel_lim) vel_des = -vel_lim;
|
||||
|
||||
// Check for overspeed fault (done in this module (controller) for cohesion with vel_lim)
|
||||
if (config_.vel_limit_tolerance > 0.0f) { // 0.0f to disable
|
||||
if (fabsf(vel_estimate) > config_.vel_limit_tolerance * vel_lim) {
|
||||
set_error(ERROR_OVERSPEED);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Velocity control
|
||||
float Iq = current_setpoint_;
|
||||
|
||||
@@ -145,8 +183,8 @@ bool Controller::update(float pos_estimate, float vel_estimate, float* current_s
|
||||
Iq += vel_integrator_current_;
|
||||
|
||||
// Current limiting
|
||||
float Ilim = std::min(axis_->motor_.config_.current_lim, axis_->motor_.current_control_.max_allowed_current);
|
||||
bool limited = false;
|
||||
float Ilim = axis_->motor_.effective_current_lim();
|
||||
if (Iq > Ilim) {
|
||||
limited = true;
|
||||
Iq = Ilim;
|
||||
|
||||
@@ -7,6 +7,11 @@
|
||||
|
||||
class Controller {
|
||||
public:
|
||||
enum Error_t {
|
||||
ERROR_NONE = 0,
|
||||
ERROR_OVERSPEED = 0x01,
|
||||
};
|
||||
|
||||
// Note: these should be sorted from lowest level of control to
|
||||
// highest level of control, to allow "<" style comparisons.
|
||||
enum ControlMode_t{
|
||||
@@ -23,11 +28,15 @@ public:
|
||||
float vel_gain = 5.0f / 10000.0f; // [A/(counts/s)]
|
||||
// float vel_gain = 5.0f / 200.0f, // [A/(rad/s)] <sensorless example>
|
||||
float vel_integrator_gain = 10.0f / 10000.0f; // [A/(counts/s * s)]
|
||||
float vel_limit = 20000.0f; // [counts/s]
|
||||
float vel_limit = 20000.0f; // [counts/s]
|
||||
float vel_limit_tolerance = 1.2f; // ratio to vel_lim. 0.0f to disable
|
||||
float vel_ramp_rate = 10000.0f; // [(counts/s) / s]
|
||||
bool setpoints_in_cpr = false;
|
||||
};
|
||||
|
||||
Controller(Config_t& config);
|
||||
void reset();
|
||||
void set_error(Error_t error);
|
||||
|
||||
void set_pos_setpoint(float pos_setpoint, float vel_feed_forward, float current_feed_forward);
|
||||
void set_vel_setpoint(float vel_setpoint, float current_feed_forward);
|
||||
@@ -68,28 +77,37 @@ public:
|
||||
.calib_vel_threshold = 1.0f,
|
||||
};
|
||||
|
||||
Error_t error_ = ERROR_NONE;
|
||||
// variables exposed on protocol
|
||||
float pos_setpoint_ = 0.0f;
|
||||
float vel_setpoint_ = 0.0f;
|
||||
// float vel_setpoint = 800.0f; <sensorless example>
|
||||
float vel_integrator_current_ = 0.0f; // [A]
|
||||
float current_setpoint_ = 0.0f; // [A]
|
||||
float vel_ramp_target_ = 0.0f;
|
||||
bool vel_ramp_enable_ = false;
|
||||
|
||||
uint32_t traj_start_loop_count_ = 0;
|
||||
|
||||
// Communication protocol definitions
|
||||
auto make_protocol_definitions() {
|
||||
return make_protocol_member_list(
|
||||
make_protocol_property("error", &error_),
|
||||
make_protocol_property("pos_setpoint", &pos_setpoint_),
|
||||
make_protocol_property("vel_setpoint", &vel_setpoint_),
|
||||
make_protocol_property("vel_integrator_current", &vel_integrator_current_),
|
||||
make_protocol_property("current_setpoint", ¤t_setpoint_),
|
||||
make_protocol_property("vel_ramp_target", &vel_ramp_target_),
|
||||
make_protocol_property("vel_ramp_enable", &vel_ramp_enable_),
|
||||
make_protocol_object("config",
|
||||
make_protocol_property("control_mode", &config_.control_mode),
|
||||
make_protocol_property("pos_gain", &config_.pos_gain),
|
||||
make_protocol_property("vel_gain", &config_.vel_gain),
|
||||
make_protocol_property("vel_integrator_gain", &config_.vel_integrator_gain),
|
||||
make_protocol_property("vel_limit", &config_.vel_limit)
|
||||
make_protocol_property("vel_limit", &config_.vel_limit),
|
||||
make_protocol_property("vel_limit_tolerance", &config_.vel_limit_tolerance),
|
||||
make_protocol_property("vel_ramp_rate", &config_.vel_ramp_rate),
|
||||
make_protocol_property("setpoints_in_cpr", &config_.setpoints_in_cpr)
|
||||
),
|
||||
make_protocol_function("set_pos_setpoint", *this, &Controller::set_pos_setpoint,
|
||||
"pos_setpoint", "vel_feed_forward", "current_feed_forward"),
|
||||
@@ -103,4 +121,6 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
DEFINE_ENUM_FLAG_OPERATORS(Controller::Error_t)
|
||||
|
||||
#endif // __CONTROLLER_HPP
|
||||
|
||||
@@ -24,7 +24,7 @@ void Encoder::setup() {
|
||||
enc_index_cb_wrapper, this);
|
||||
}
|
||||
|
||||
void Encoder::set_error(Encoder::Error_t error) {
|
||||
void Encoder::set_error(Error_t error) {
|
||||
error_ |= error;
|
||||
axis_->error_ |= Axis::ERROR_ENCODER_FAILED;
|
||||
}
|
||||
@@ -46,7 +46,8 @@ void Encoder::enc_index_cb() {
|
||||
if (config_.find_idx_on_lockin && axis_->lockin_state_ != Axis::LOCKIN_STATE_CONST_VEL)
|
||||
return;
|
||||
set_circular_count(0, false);
|
||||
set_linear_count(0); // Avoid position control transient after search
|
||||
if (config_.zero_count_on_find_idx)
|
||||
set_linear_count(0); // Avoid position control transient after search
|
||||
if (config_.pre_calibrated) {
|
||||
is_ready_ = true;
|
||||
} else {
|
||||
@@ -221,6 +222,27 @@ void Encoder::update_pll_gains() {
|
||||
}
|
||||
}
|
||||
|
||||
void Encoder::sample_now() {
|
||||
switch (config_.mode) {
|
||||
case MODE_INCREMENTAL: {
|
||||
tim_cnt_sample_ = (int16_t)hw_config_.timer->Instance->CNT;
|
||||
} break;
|
||||
|
||||
case MODE_HALL: {
|
||||
// do nothing: samples already captured in general GPIO capture
|
||||
} break;
|
||||
|
||||
case MODE_SINCOS: {
|
||||
sincos_sample_s_ = get_adc_voltage(GPIO_3_GPIO_Port, GPIO_3_Pin) / 3.3f;
|
||||
sincos_sample_c_ = get_adc_voltage(GPIO_4_GPIO_Port, GPIO_4_Pin) / 3.3f;
|
||||
} break;
|
||||
|
||||
default: {
|
||||
set_error(ERROR_UNSUPPORTED_ENCODER_MODE);
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
bool Encoder::update() {
|
||||
// update internal encoder state.
|
||||
int32_t delta_enc = 0;
|
||||
@@ -228,7 +250,7 @@ bool Encoder::update() {
|
||||
case MODE_INCREMENTAL: {
|
||||
//TODO: use count_in_cpr_ instead as shadow_count_ can overflow
|
||||
//or use 64 bit
|
||||
int16_t delta_enc_16 = (int16_t)hw_config_.timer->Instance->CNT - (int16_t)shadow_count_;
|
||||
int16_t delta_enc_16 = (int16_t)tim_cnt_sample_ - (int16_t)shadow_count_;
|
||||
delta_enc = (int32_t)delta_enc_16; //sign extend
|
||||
} break;
|
||||
|
||||
@@ -240,10 +262,23 @@ bool Encoder::update() {
|
||||
if (delta_enc > 3)
|
||||
delta_enc -= 6;
|
||||
} else {
|
||||
set_error(ERROR_ILLEGAL_HALL_STATE);
|
||||
return false;
|
||||
if (!config_.ignore_illegal_hall_state) {
|
||||
set_error(ERROR_ILLEGAL_HALL_STATE);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
case MODE_SINCOS: {
|
||||
float phase = fast_atan2(sincos_sample_s_, sincos_sample_c_);
|
||||
int fake_count = (int)(1000.0f * phase);
|
||||
//CPR = 6283 = 2pi * 1k
|
||||
|
||||
delta_enc = fake_count - count_in_cpr_;
|
||||
delta_enc = mod(delta_enc, 6283);
|
||||
if (delta_enc > 6283/2)
|
||||
delta_enc -= 6283;
|
||||
} break;
|
||||
|
||||
default: {
|
||||
set_error(ERROR_UNSUPPORTED_ENCODER_MODE);
|
||||
|
||||
@@ -20,7 +20,8 @@ public:
|
||||
|
||||
enum Mode_t {
|
||||
MODE_INCREMENTAL,
|
||||
MODE_HALL
|
||||
MODE_HALL,
|
||||
MODE_SINCOS
|
||||
};
|
||||
|
||||
struct Config_t {
|
||||
@@ -32,6 +33,7 @@ public:
|
||||
// In this case the encoder will enter ready
|
||||
// state as soon as the index is found.
|
||||
float idx_search_speed = 10.0f; // [rad/s electrical]
|
||||
bool zero_count_on_find_idx = true;
|
||||
int32_t cpr = (2048 * 4); // Default resolution of CUI-AMT102 encoder,
|
||||
int32_t offset = 0; // Offset between encoder count and rotor electrical phase
|
||||
float offset_float = 0.0f; // Sub-count phase alignment offset
|
||||
@@ -40,6 +42,7 @@ public:
|
||||
float overspeed_fault_ratio = 1.2f; // ratio of vel_lim, 0.0f = disabled
|
||||
bool find_idx_on_lockin = false;
|
||||
bool idx_search_unidirectional = false;
|
||||
bool ignore_illegal_hall_state = false;
|
||||
};
|
||||
|
||||
Encoder(const EncoderHardwareConfig_t& hw_config,
|
||||
@@ -57,6 +60,7 @@ public:
|
||||
|
||||
bool run_index_search();
|
||||
bool run_offset_calibration();
|
||||
void sample_now();
|
||||
bool update();
|
||||
|
||||
void update_pll_gains();
|
||||
@@ -71,15 +75,18 @@ public:
|
||||
int32_t shadow_count_ = 0;
|
||||
int32_t count_in_cpr_ = 0;
|
||||
float interpolation_ = 0.0f;
|
||||
float phase_ = 0.0f; // [rad]
|
||||
float pos_estimate_ = 0.0f; // [rad]
|
||||
float pos_cpr_ = 0.0f; // [rad]
|
||||
float vel_estimate_ = 0.0f; // [rad/s]
|
||||
float pll_kp_ = 0.0f; // [rad/s / rad]
|
||||
float pll_ki_ = 0.0f; // [(rad/s^2) / rad]
|
||||
float phase_ = 0.0f; // [count]
|
||||
float pos_estimate_ = 0.0f; // [count]
|
||||
float pos_cpr_ = 0.0f; // [count]
|
||||
float vel_estimate_ = 0.0f; // [count/s]
|
||||
float pll_kp_ = 0.0f; // [count/s / count]
|
||||
float pll_ki_ = 0.0f; // [(count/s^2) / count]
|
||||
|
||||
int16_t tim_cnt_sample_ = 0; //
|
||||
// Updated by low_level pwm_adc_cb
|
||||
uint8_t hall_state_ = 0x0; // bit[0] = HallA, .., bit[2] = HallC
|
||||
float sincos_sample_s_ = 0.0f;
|
||||
float sincos_sample_c_ = 0.0f;
|
||||
|
||||
// Communication protocol definitions
|
||||
auto make_protocol_definitions() {
|
||||
@@ -103,6 +110,7 @@ public:
|
||||
make_protocol_property("pre_calibrated", &config_.pre_calibrated),
|
||||
make_protocol_property("overspeed_fault_ratio", &config_.overspeed_fault_ratio),
|
||||
make_protocol_property("idx_search_speed", &config_.idx_search_speed),
|
||||
make_protocol_property("zero_count_on_find_idx", &config_.zero_count_on_find_idx),
|
||||
make_protocol_property("cpr", &config_.cpr),
|
||||
make_protocol_property("offset", &config_.offset),
|
||||
make_protocol_property("offset_float", &config_.offset_float),
|
||||
@@ -110,7 +118,8 @@ public:
|
||||
[](void* ctx) { static_cast<Encoder*>(ctx)->update_pll_gains(); }, this),
|
||||
make_protocol_property("calib_range", &config_.calib_range),
|
||||
make_protocol_property("find_idx_on_lockin", &config_.find_idx_on_lockin),
|
||||
make_protocol_property("idx_search_unidirectional", &config_.idx_search_unidirectional)
|
||||
make_protocol_property("idx_search_unidirectional", &config_.idx_search_unidirectional),
|
||||
make_protocol_property("ignore_illegal_hall_state", &config_.ignore_illegal_hall_state)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -125,7 +125,7 @@ bool safety_critical_disarm_motor_pwm(Motor& motor) {
|
||||
void safety_critical_apply_motor_pwm_timings(Motor& motor, uint16_t timings[3]) {
|
||||
uint32_t mask = cpu_enter_critical();
|
||||
if (!brake_resistor_armed) {
|
||||
motor.armed_state_ = Motor::ARMED_STATE_ARMED;
|
||||
motor.armed_state_ = Motor::ARMED_STATE_DISARMED;
|
||||
}
|
||||
|
||||
motor.hw_config_.timer->Instance->CCR1 = timings[0];
|
||||
@@ -216,7 +216,8 @@ void start_adc_pwm() {
|
||||
start_pwm(&htim1);
|
||||
start_pwm(&htim8);
|
||||
// TODO: explain why this offset
|
||||
sync_timers(&htim1, &htim8, TIM_CLOCKSOURCE_ITR0, TIM_1_8_PERIOD_CLOCKS / 2 - 1 * 128);
|
||||
sync_timers(&htim1, &htim8, TIM_CLOCKSOURCE_ITR0, TIM_1_8_PERIOD_CLOCKS / 2 - 1 * 128,
|
||||
&htim13);
|
||||
|
||||
// Motor output starts in the disabled state
|
||||
__HAL_TIM_MOE_DISABLE_UNCONDITIONALLY(&htim1);
|
||||
@@ -259,7 +260,8 @@ void start_pwm(TIM_HandleTypeDef* htim) {
|
||||
}
|
||||
|
||||
void sync_timers(TIM_HandleTypeDef* htim_a, TIM_HandleTypeDef* htim_b,
|
||||
uint16_t TIM_CLOCKSOURCE_ITRx, uint16_t count_offset) {
|
||||
uint16_t TIM_CLOCKSOURCE_ITRx, uint16_t count_offset,
|
||||
TIM_HandleTypeDef* htim_refbase) {
|
||||
// Store intial timer configs
|
||||
uint16_t MOE_store_a = htim_a->Instance->BDTR & (TIM_BDTR_MOE);
|
||||
uint16_t MOE_store_b = htim_b->Instance->BDTR & (TIM_BDTR_MOE);
|
||||
@@ -294,6 +296,11 @@ void sync_timers(TIM_HandleTypeDef* htim_a, TIM_HandleTypeDef* htim_b,
|
||||
// set counter offset
|
||||
htim_a->Instance->CNT = count_offset;
|
||||
htim_b->Instance->CNT = 0;
|
||||
// Set and start reference timebase timer (if used)
|
||||
if (htim_refbase) {
|
||||
htim_refbase->Instance->CNT = count_offset;
|
||||
htim_refbase->Instance->CR1 |= (TIM_CR1_CEN); // start
|
||||
}
|
||||
// Start Timer a
|
||||
htim_a->Instance->CR1 |= (TIM_CR1_CEN);
|
||||
// Restore timer configs
|
||||
@@ -475,8 +482,14 @@ void pwm_trig_adc_cb(ADC_HandleTypeDef* hadc, bool injected) {
|
||||
int axis_num = injected ? 0 : 1;
|
||||
Axis& other_axis = injected ? *axes[1] : *axes[0];
|
||||
bool counting_down = axis.motor_.hw_config_.timer->Instance->CR1 & TIM_CR1_DIR;
|
||||
|
||||
bool current_meas_not_DC_CAL = !counting_down;
|
||||
|
||||
// Check the timing of the sequencing
|
||||
if (current_meas_not_DC_CAL)
|
||||
axis.motor_.log_timing(Motor::TIMING_LOG_ADC_CB_I);
|
||||
else
|
||||
axis.motor_.log_timing(Motor::TIMING_LOG_ADC_CB_DC);
|
||||
|
||||
bool update_timings = false;
|
||||
if (hadc == &hadc2) {
|
||||
if (&axis == axes[1] && counting_down)
|
||||
@@ -503,12 +516,6 @@ void pwm_trig_adc_cb(ADC_HandleTypeDef* hadc, bool injected) {
|
||||
update_brake_current();
|
||||
}
|
||||
|
||||
// Check the timing of the sequencing
|
||||
if (current_meas_not_DC_CAL)
|
||||
axis.motor_.log_timing(Motor::TIMING_LOG_ADC_CB_I);
|
||||
else
|
||||
axis.motor_.log_timing(Motor::TIMING_LOG_ADC_CB_DC);
|
||||
|
||||
uint32_t ADCValue;
|
||||
if (injected) {
|
||||
ADCValue = HAL_ADCEx_InjectedGetValue(hadc, ADC_INJECTED_RANK_1);
|
||||
@@ -532,6 +539,7 @@ void pwm_trig_adc_cb(ADC_HandleTypeDef* hadc, bool injected) {
|
||||
axis.motor_.current_meas_.phC = current - axis.motor_.DC_calib_.phC;
|
||||
}
|
||||
// Prepare hall readings
|
||||
// TODO move this to inside encoder update function
|
||||
decode_hall_samples(axis.encoder_, GPIO_port_samples[axis_num]);
|
||||
// Trigger axis thread
|
||||
axis.signal_current_meas();
|
||||
@@ -546,18 +554,30 @@ void pwm_trig_adc_cb(ADC_HandleTypeDef* hadc, bool injected) {
|
||||
}
|
||||
|
||||
void tim_update_cb(TIM_HandleTypeDef* htim) {
|
||||
int portsamples_arr;
|
||||
|
||||
// If the corresponding timer is counting up, we just sampled in SVM vector 0, i.e. real current
|
||||
// If we are counting down, we just sampled in SVM vector 7, with zero current
|
||||
bool counting_down = htim->Instance->CR1 & TIM_CR1_DIR;
|
||||
if (counting_down)
|
||||
return;
|
||||
|
||||
int sample_ch;
|
||||
Axis* axis;
|
||||
if (htim == &htim1) {
|
||||
portsamples_arr = 0;
|
||||
sample_ch = 0;
|
||||
axis = axes[0];
|
||||
} else if (htim == &htim8) {
|
||||
portsamples_arr = 1;
|
||||
sample_ch = 1;
|
||||
axis = axes[1];
|
||||
} else {
|
||||
low_level_fault(Motor::ERROR_UNEXPECTED_TIMER_CALLBACK);
|
||||
return;
|
||||
}
|
||||
|
||||
axis->encoder_.sample_now();
|
||||
|
||||
for (int i = 0; i < num_GPIO; ++i) {
|
||||
GPIO_port_samples[portsamples_arr][i] = GPIOs_to_samp[i]->IDR;
|
||||
GPIO_port_samples[sample_ch][i] = GPIOs_to_samp[i]->IDR;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -660,6 +680,7 @@ void pwm_in_init() {
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: These expressions have integer division by 1MHz, so it will be incorrect for clock speeds of not-integer MHz
|
||||
#define TIM_2_5_CLOCK_HZ TIM_APB1_CLOCK_HZ
|
||||
#define PWM_MIN_HIGH_TIME ((TIM_2_5_CLOCK_HZ / 1000000UL) * 1000UL) // 1ms high is considered full reverse
|
||||
#define PWM_MAX_HIGH_TIME ((TIM_2_5_CLOCK_HZ / 1000000UL) * 2000UL) // 2ms high is considered full forward
|
||||
@@ -705,4 +726,33 @@ void pwm_in_cb(int channel, uint32_t timestamp) {
|
||||
last_timestamp[gpio_num - 1] = timestamp;
|
||||
last_pin_state[gpio_num - 1] = current_pin_state;
|
||||
last_sample_valid[gpio_num - 1] = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Analog speed control input */
|
||||
|
||||
static void update_analog_endpoint(const struct PWMMapping_t *map, int gpio)
|
||||
{
|
||||
float fraction = get_adc_voltage(get_gpio_port_by_pin(gpio), get_gpio_pin_by_pin(gpio)) / 3.3f;
|
||||
float value = map->min + (fraction * (map->max - map->min));
|
||||
get_endpoint(map->endpoint)->set_from_float(value);
|
||||
}
|
||||
|
||||
static void analog_polling_thread(void *)
|
||||
{
|
||||
while (true) {
|
||||
for (int i = 0; i < GPIO_COUNT; i++) {
|
||||
struct PWMMapping_t *map = &board_config.analog_mappings[i];
|
||||
|
||||
if (is_endpoint_ref_valid(map->endpoint))
|
||||
update_analog_endpoint(map, i + 1);
|
||||
}
|
||||
osDelay(10);
|
||||
}
|
||||
}
|
||||
|
||||
void start_analog_thread()
|
||||
{
|
||||
osThreadDef(thread_def, analog_polling_thread, osPriorityLow, 0, 4*512);
|
||||
osThreadCreate(osThread(thread_def), NULL);
|
||||
}
|
||||
|
||||
@@ -46,16 +46,19 @@ void pwm_in_cb(int channel, uint32_t timestamp);
|
||||
void start_adc_pwm();
|
||||
void start_pwm(TIM_HandleTypeDef* htim);
|
||||
void sync_timers(TIM_HandleTypeDef* htim_a, TIM_HandleTypeDef* htim_b,
|
||||
uint16_t TIM_CLOCKSOURCE_ITRx, uint16_t count_offset);
|
||||
uint16_t TIM_CLOCKSOURCE_ITRx, uint16_t count_offset,
|
||||
TIM_HandleTypeDef* htim_refbase = nullptr);
|
||||
void start_general_purpose_adc();
|
||||
float get_adc_voltage(GPIO_TypeDef* GPIO_port, uint16_t GPIO_pin);
|
||||
void pwm_in_init();
|
||||
void start_analog_thread();
|
||||
|
||||
void update_brake_current();
|
||||
|
||||
inline uint32_t cpu_enter_critical() {
|
||||
return __get_PRIMASK();
|
||||
uint32_t primask = __get_PRIMASK();
|
||||
__disable_irq();
|
||||
return primask;
|
||||
}
|
||||
|
||||
inline void cpu_exit_critical(uint32_t priority_mask) {
|
||||
|
||||
@@ -65,6 +65,8 @@ void load_configuration(void) {
|
||||
motor_configs[i] = Motor::Config_t();
|
||||
trap_configs[i] = TrapezoidalTrajectory::Config_t();
|
||||
axis_configs[i] = Axis::Config_t();
|
||||
// Default step/dir pins are different, so we need to explicitly load them
|
||||
Axis::load_default_step_dir_pin_config(hw_configs[i].axis_config, &axis_configs[i]);
|
||||
}
|
||||
} else {
|
||||
user_config_loaded_ = true;
|
||||
@@ -178,8 +180,6 @@ int odrive_main(void) {
|
||||
// TODO: make dynamically reconfigurable
|
||||
#if HW_VERSION_MAJOR == 3 && HW_VERSION_MINOR >= 3
|
||||
if (board_config.enable_uart) {
|
||||
axes[0]->config_.enable_step_dir = false;
|
||||
axes[0]->set_step_dir_enabled(false);
|
||||
SetGPIO12toUART();
|
||||
}
|
||||
#endif
|
||||
@@ -214,6 +214,8 @@ int odrive_main(void) {
|
||||
axes[i]->start_thread();
|
||||
}
|
||||
|
||||
start_analog_thread();
|
||||
|
||||
system_stats_.fully_booted = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -73,7 +73,8 @@ void Motor::DRV8301_setup() {
|
||||
// Solve for exact gain, then snap down to have equal or larger range as requested
|
||||
// or largest possible range otherwise
|
||||
static const float kMargin = 0.90f;
|
||||
static const float max_output_swing = 1.6f; // [V] out of amplifier
|
||||
static const float kTripMargin = 1.0f; // Trip level is at edge of linear range of amplifer
|
||||
static const float max_output_swing = 1.35f; // [V] out of amplifier
|
||||
float max_unity_gain_current = kMargin * max_output_swing * hw_config_.shunt_conductance; // [A]
|
||||
float requested_gain = max_unity_gain_current / config_.requested_current_range; // [V/V]
|
||||
|
||||
@@ -99,6 +100,8 @@ void Motor::DRV8301_setup() {
|
||||
phase_current_rev_gain_ = 1.0f / gain_snap_down->first;
|
||||
// Clip all current control to actual usable range
|
||||
current_control_.max_allowed_current = max_unity_gain_current * phase_current_rev_gain_;
|
||||
// Set trip level
|
||||
current_control_.overcurrent_trip_level = (kTripMargin / kMargin) * current_control_.max_allowed_current;
|
||||
|
||||
// We now have the gain settings we want to use, lets set up DRV chip
|
||||
DRV_SPI_8301_Vars_t* local_regs = &gate_driver_regs_;
|
||||
@@ -140,22 +143,57 @@ void Motor::set_error(Motor::Error_t error){
|
||||
update_brake_current();
|
||||
}
|
||||
|
||||
bool Motor::do_checks() {
|
||||
if (!check_DRV_fault()) {
|
||||
set_error(ERROR_DRV_FAULT);
|
||||
float Motor::get_inverter_temp() {
|
||||
float adc = adc_measurements_[hw_config_.inverter_thermistor_adc_ch];
|
||||
float normalized_voltage = adc / adc_full_scale;
|
||||
return horner_fma(normalized_voltage, thermistor_poly_coeffs, thermistor_num_coeffs);
|
||||
}
|
||||
|
||||
bool Motor::update_thermal_limits() {
|
||||
float fet_temp = get_inverter_temp();
|
||||
float temp_margin = config_.inverter_temp_limit_upper - fet_temp;
|
||||
float derating_range = config_.inverter_temp_limit_upper - config_.inverter_temp_limit_lower;
|
||||
thermal_current_lim_ = config_.current_lim * (temp_margin / derating_range);
|
||||
if (!(thermal_current_lim_ >= 0.0f)) { //Funny polarity to also catch NaN
|
||||
thermal_current_lim_ = 0.0f;
|
||||
}
|
||||
if (fet_temp > config_.inverter_temp_limit_upper + 5) {
|
||||
set_error(ERROR_INVERTER_OVER_TEMP);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Motor::log_timing(TimingLog_t log_idx) {
|
||||
TIM_HandleTypeDef* htim = hw_config_.timer;
|
||||
uint16_t timing = htim->Instance->CNT;
|
||||
bool down = htim->Instance->CR1 & TIM_CR1_DIR;
|
||||
if (down) {
|
||||
uint16_t delta = TIM_1_8_PERIOD_CLOCKS - timing;
|
||||
timing = TIM_1_8_PERIOD_CLOCKS + delta;
|
||||
bool Motor::do_checks() {
|
||||
if (!check_DRV_fault()) {
|
||||
set_error(ERROR_DRV_FAULT);
|
||||
return false;
|
||||
}
|
||||
if (!update_thermal_limits()) {
|
||||
//error already set in function
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
float Motor::effective_current_lim() {
|
||||
// Configured limit
|
||||
float current_lim = config_.current_lim;
|
||||
// Hardware limit
|
||||
if (axis_->motor_.config_.motor_type == Motor::MOTOR_TYPE_GIMBAL) {
|
||||
current_lim = std::min(current_lim, 0.98f*one_by_sqrt3*vbus_voltage);
|
||||
} else {
|
||||
current_lim = std::min(current_lim, axis_->motor_.current_control_.max_allowed_current);
|
||||
}
|
||||
// Thermal limit
|
||||
current_lim = std::min(current_lim, thermal_current_lim_);
|
||||
|
||||
return current_lim;
|
||||
}
|
||||
|
||||
void Motor::log_timing(TimingLog_t log_idx) {
|
||||
static const uint16_t clocks_per_cnt = (uint16_t)((float)TIM_1_8_CLOCK_HZ / (float)TIM_APB1_CLOCK_HZ);
|
||||
uint16_t timing = clocks_per_cnt * htim13.Instance->CNT; // TODO: Use a hw_config
|
||||
|
||||
if (log_idx < TIMING_LOG_NUM_SLOTS) {
|
||||
timing_log_[log_idx] = timing;
|
||||
@@ -238,7 +276,7 @@ bool Motor::measure_phase_inductance(float voltage_low, float voltage_high) {
|
||||
|
||||
config_.phase_inductance = L;
|
||||
// TODO arbitrary values set for now
|
||||
if (L < 1e-6f || L > 2500e-6f)
|
||||
if (L < 2e-6f || L > 4000e-6f)
|
||||
return set_error(ERROR_PHASE_INDUCTANCE_OUT_OF_RANGE), false;
|
||||
return true;
|
||||
}
|
||||
@@ -284,33 +322,39 @@ bool Motor::enqueue_voltage_timings(float v_alpha, float v_beta) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO: This doesn't update brake current
|
||||
// We should probably make FOC Current call FOC Voltage to avoid duplication.
|
||||
bool Motor::FOC_voltage(float v_d, float v_q, float phase) {
|
||||
float c = our_arm_cos_f32(phase);
|
||||
float s = our_arm_sin_f32(phase);
|
||||
bool Motor::FOC_voltage(float v_d, float v_q, float pwm_phase) {
|
||||
float c = our_arm_cos_f32(pwm_phase);
|
||||
float s = our_arm_sin_f32(pwm_phase);
|
||||
float v_alpha = c*v_d - s*v_q;
|
||||
float v_beta = c*v_q + s*v_d;
|
||||
return enqueue_voltage_timings(v_alpha, v_beta);
|
||||
}
|
||||
|
||||
bool Motor::FOC_current(float Id_des, float Iq_des, float phase) {
|
||||
bool Motor::FOC_current(float Id_des, float Iq_des, float I_phase, float pwm_phase) {
|
||||
// Syntactic sugar
|
||||
CurrentControl_t& ictrl = current_control_;
|
||||
|
||||
// For Reporting
|
||||
ictrl.Iq_setpoint = Iq_des;
|
||||
|
||||
// Check for current sense saturation
|
||||
if (fabsf(current_meas_.phB) > ictrl.overcurrent_trip_level
|
||||
|| fabsf(current_meas_.phC) > ictrl.overcurrent_trip_level) {
|
||||
set_error(ERROR_CURRENT_SENSE_SATURATION);
|
||||
}
|
||||
|
||||
// Clarke transform
|
||||
float Ialpha = -current_meas_.phB - current_meas_.phC;
|
||||
float Ibeta = one_by_sqrt3 * (current_meas_.phB - current_meas_.phC);
|
||||
|
||||
// Park transform
|
||||
float c = our_arm_cos_f32(phase);
|
||||
float s = our_arm_sin_f32(phase);
|
||||
float Id = c * Ialpha + s * Ibeta;
|
||||
float Iq = c * Ibeta - s * Ialpha;
|
||||
ictrl.Iq_measured = Iq;
|
||||
float c_I = our_arm_cos_f32(I_phase);
|
||||
float s_I = our_arm_sin_f32(I_phase);
|
||||
float Id = c_I * Ialpha + s_I * Ibeta;
|
||||
float Iq = c_I * Ibeta - s_I * Ialpha;
|
||||
ictrl.Iq_measured += ictrl.I_measured_report_filter_k * (Iq - ictrl.Iq_measured);
|
||||
ictrl.Id_measured += ictrl.I_measured_report_filter_k * (Id - ictrl.Id_measured);
|
||||
|
||||
// Current error
|
||||
float Ierr_d = Id_des - Id;
|
||||
@@ -344,8 +388,10 @@ bool Motor::FOC_current(float Id_des, float Iq_des, float phase) {
|
||||
ictrl.Ibus = mod_d * Id + mod_q * Iq;
|
||||
|
||||
// Inverse park transform
|
||||
float mod_alpha = c * mod_d - s * mod_q;
|
||||
float mod_beta = c * mod_q + s * mod_d;
|
||||
float c_p = our_arm_cos_f32(pwm_phase);
|
||||
float s_p = our_arm_sin_f32(pwm_phase);
|
||||
float mod_alpha = c_p * mod_d - s_p * mod_q;
|
||||
float mod_beta = c_p * mod_q + s_p * mod_d;
|
||||
|
||||
// Report final applied voltage in stationary frame (for sensorles estimator)
|
||||
ictrl.final_v_alpha = mod_to_V * mod_alpha;
|
||||
@@ -360,19 +406,22 @@ bool Motor::FOC_current(float Id_des, float Iq_des, float phase) {
|
||||
}
|
||||
|
||||
|
||||
bool Motor::update(float current_setpoint, float phase) {
|
||||
bool Motor::update(float current_setpoint, float phase, float phase_vel) {
|
||||
current_setpoint *= config_.direction;
|
||||
phase *= config_.direction;
|
||||
phase_vel *= config_.direction;
|
||||
|
||||
float pwm_phase = phase + 1.5f * current_meas_period * phase_vel;
|
||||
|
||||
// Execute current command
|
||||
// TODO: move this into the mot
|
||||
if (config_.motor_type == MOTOR_TYPE_HIGH_CURRENT) {
|
||||
if(!FOC_current(0.0f, current_setpoint, phase)){
|
||||
if(!FOC_current(0.0f, current_setpoint, phase, pwm_phase)){
|
||||
return false;
|
||||
}
|
||||
} else if (config_.motor_type == MOTOR_TYPE_GIMBAL) {
|
||||
//In gimbal motor mode, current is reinterptreted as voltage.
|
||||
if(!FOC_voltage(0.0f, current_setpoint, phase))
|
||||
if(!FOC_voltage(0.0f, current_setpoint, pwm_phase))
|
||||
return false;
|
||||
} else {
|
||||
set_error(ERROR_NOT_IMPLEMENTED_MOTOR_TYPE);
|
||||
|
||||
@@ -20,7 +20,9 @@ public:
|
||||
ERROR_BRAKE_CURRENT_OUT_OF_RANGE = 0x0040,
|
||||
ERROR_MODULATION_MAGNITUDE = 0x0080,
|
||||
ERROR_BRAKE_DEADTIME_VIOLATION = 0x0100,
|
||||
ERROR_UNEXPECTED_TIMER_CALLBACK = 0x0200
|
||||
ERROR_UNEXPECTED_TIMER_CALLBACK = 0x0200,
|
||||
ERROR_CURRENT_SENSE_SATURATION = 0x0400,
|
||||
ERROR_INVERTER_OVER_TEMP = 0x0800
|
||||
};
|
||||
|
||||
enum MotorType_t {
|
||||
@@ -43,9 +45,12 @@ public:
|
||||
// Voltage applied at end of cycle:
|
||||
float final_v_alpha; // [V]
|
||||
float final_v_beta; // [V]
|
||||
float Iq_setpoint;
|
||||
float Iq_measured;
|
||||
float max_allowed_current;
|
||||
float Iq_setpoint; // [A]
|
||||
float Iq_measured; // [A]
|
||||
float Id_measured; // [A]
|
||||
float I_measured_report_filter_k;
|
||||
float max_allowed_current; // [A]
|
||||
float overcurrent_trip_level; // [A]
|
||||
};
|
||||
|
||||
// NOTE: for gimbal motors, all units of A are instead V.
|
||||
@@ -64,8 +69,10 @@ public:
|
||||
// float current_lim = 70.0f; //[A]
|
||||
float current_lim = 10.0f; //[A]
|
||||
// Value used to compute shunt amplifier gains
|
||||
float requested_current_range = 70.0f; // [A]
|
||||
float requested_current_range = 60.0f; // [A]
|
||||
float current_control_bandwidth = 1000.0f; // [rad/s]
|
||||
float inverter_temp_limit_lower = 100;
|
||||
float inverter_temp_limit_upper = 120;
|
||||
};
|
||||
|
||||
enum TimingLog_t {
|
||||
@@ -104,6 +111,9 @@ public:
|
||||
bool check_DRV_fault();
|
||||
void set_error(Error_t error);
|
||||
bool do_checks();
|
||||
float get_inverter_temp();
|
||||
bool update_thermal_limits();
|
||||
float effective_current_lim();
|
||||
void log_timing(TimingLog_t log_idx);
|
||||
float phase_current_from_adcval(uint32_t ADCValue);
|
||||
bool measure_phase_resistance(float test_current, float max_voltage);
|
||||
@@ -111,9 +121,9 @@ public:
|
||||
bool run_calibration();
|
||||
bool enqueue_modulation_timings(float mod_alpha, float mod_beta);
|
||||
bool enqueue_voltage_timings(float v_alpha, float v_beta);
|
||||
bool FOC_voltage(float v_d, float v_q, float phase);
|
||||
bool FOC_current(float Id_des, float Iq_des, float phase);
|
||||
bool update(float current_setpoint, float phase);
|
||||
bool FOC_voltage(float v_d, float v_q, float pwm_phase);
|
||||
bool FOC_current(float Id_des, float Iq_des, float I_phase, float pwm_phase);
|
||||
bool update(float current_setpoint, float phase, float phase_vel);
|
||||
|
||||
const MotorHardwareConfig_t& hw_config_;
|
||||
const GateDriverHardwareConfig_t gate_driver_config_;
|
||||
@@ -152,10 +162,14 @@ public:
|
||||
.final_v_beta = 0.0f,
|
||||
.Iq_setpoint = 0.0f,
|
||||
.Iq_measured = 0.0f,
|
||||
.Id_measured = 0.0f,
|
||||
.I_measured_report_filter_k = 1.0f,
|
||||
.max_allowed_current = 0.0f,
|
||||
.overcurrent_trip_level = 0.0f,
|
||||
};
|
||||
DRV8301_FaultType_e drv_fault_ = DRV8301_FaultType_NoFault;
|
||||
DRV_SPI_8301_Vars_t gate_driver_regs_; //Local view of DRV registers (initialized by DRV8301_setup)
|
||||
float thermal_current_lim_ = 10.0f; //[A]
|
||||
|
||||
// Communication protocol definitions
|
||||
auto make_protocol_definitions() {
|
||||
@@ -168,6 +182,8 @@ public:
|
||||
make_protocol_property("DC_calib_phB", &DC_calib_.phB),
|
||||
make_protocol_property("DC_calib_phC", &DC_calib_.phC),
|
||||
make_protocol_property("phase_current_rev_gain", &phase_current_rev_gain_),
|
||||
make_protocol_ro_property("thermal_current_lim", &thermal_current_lim_),
|
||||
make_protocol_function("get_inverter_temp", *this, &Motor::get_inverter_temp),
|
||||
make_protocol_object("current_control",
|
||||
make_protocol_property("p_gain", ¤t_control_.p_gain),
|
||||
make_protocol_property("i_gain", ¤t_control_.i_gain),
|
||||
@@ -178,7 +194,10 @@ public:
|
||||
make_protocol_property("final_v_beta", ¤t_control_.final_v_beta),
|
||||
make_protocol_property("Iq_setpoint", ¤t_control_.Iq_setpoint),
|
||||
make_protocol_property("Iq_measured", ¤t_control_.Iq_measured),
|
||||
make_protocol_property("max_allowed_current", ¤t_control_.max_allowed_current)
|
||||
make_protocol_property("Id_measured", ¤t_control_.Id_measured),
|
||||
make_protocol_property("I_measured_report_filter_k", ¤t_control_.I_measured_report_filter_k),
|
||||
make_protocol_ro_property("max_allowed_current", ¤t_control_.max_allowed_current),
|
||||
make_protocol_ro_property("overcurrent_trip_level", ¤t_control_.overcurrent_trip_level)
|
||||
),
|
||||
make_protocol_object("gate_driver",
|
||||
make_protocol_ro_property("drv_fault", &drv_fault_)
|
||||
@@ -208,6 +227,8 @@ public:
|
||||
make_protocol_property("direction", &config_.direction),
|
||||
make_protocol_property("motor_type", &config_.motor_type),
|
||||
make_protocol_property("current_lim", &config_.current_lim),
|
||||
make_protocol_property("inverter_temp_limit_lower", &config_.inverter_temp_limit_lower),
|
||||
make_protocol_property("inverter_temp_limit_upper", &config_.inverter_temp_limit_upper),
|
||||
make_protocol_property("requested_current_range", &config_.requested_current_range),
|
||||
make_protocol_property("current_control_bandwidth", &config_.current_control_bandwidth,
|
||||
[](void* ctx) { static_cast<Motor*>(ctx)->update_current_controller_gains(); }, this)
|
||||
|
||||
@@ -82,6 +82,7 @@ struct BoardConfig_t {
|
||||
//<! the brake power if the brake resistor is disabled.
|
||||
//<! The default is 26V for the 24V board version and 52V for the 48V board version.
|
||||
PWMMapping_t pwm_mappings[GPIO_COUNT];
|
||||
PWMMapping_t analog_mappings[GPIO_COUNT];
|
||||
};
|
||||
extern BoardConfig_t board_config;
|
||||
extern bool user_config_loaded_;
|
||||
|
||||
@@ -51,9 +51,8 @@ int SVM(float alpha, float beta, float* tA, float* tB, float* tC) {
|
||||
*tA = (1.0f - t1 - t2) * 0.5f;
|
||||
*tB = *tA + t1;
|
||||
*tC = *tB + t2;
|
||||
} break;
|
||||
|
||||
break;
|
||||
}
|
||||
// sextant v2-v3
|
||||
case 2: {
|
||||
// Vector on-times
|
||||
@@ -64,9 +63,8 @@ int SVM(float alpha, float beta, float* tA, float* tB, float* tC) {
|
||||
*tB = (1.0f - t2 - t3) * 0.5f;
|
||||
*tA = *tB + t3;
|
||||
*tC = *tA + t2;
|
||||
} break;
|
||||
|
||||
break;
|
||||
}
|
||||
// sextant v3-v4
|
||||
case 3: {
|
||||
// Vector on-times
|
||||
@@ -77,9 +75,8 @@ int SVM(float alpha, float beta, float* tA, float* tB, float* tC) {
|
||||
*tB = (1.0f - t3 - t4) * 0.5f;
|
||||
*tC = *tB + t3;
|
||||
*tA = *tC + t4;
|
||||
} break;
|
||||
|
||||
break;
|
||||
}
|
||||
// sextant v4-v5
|
||||
case 4: {
|
||||
// Vector on-times
|
||||
@@ -90,9 +87,8 @@ int SVM(float alpha, float beta, float* tA, float* tB, float* tC) {
|
||||
*tC = (1.0f - t4 - t5) * 0.5f;
|
||||
*tB = *tC + t5;
|
||||
*tA = *tB + t4;
|
||||
} break;
|
||||
|
||||
break;
|
||||
}
|
||||
// sextant v5-v6
|
||||
case 5: {
|
||||
// Vector on-times
|
||||
@@ -103,9 +99,8 @@ int SVM(float alpha, float beta, float* tA, float* tB, float* tC) {
|
||||
*tC = (1.0f - t5 - t6) * 0.5f;
|
||||
*tA = *tC + t5;
|
||||
*tB = *tA + t6;
|
||||
} break;
|
||||
|
||||
break;
|
||||
}
|
||||
// sextant v6-v1
|
||||
case 6: {
|
||||
// Vector on-times
|
||||
@@ -116,9 +111,7 @@ int SVM(float alpha, float beta, float* tA, float* tB, float* tC) {
|
||||
*tA = (1.0f - t6 - t1) * 0.5f;
|
||||
*tC = *tA + t1;
|
||||
*tB = *tC + t6;
|
||||
|
||||
break;
|
||||
}
|
||||
} break;
|
||||
}
|
||||
|
||||
// if any of the results becomes NaN, result_valid will evaluate to false
|
||||
|
||||
@@ -15,6 +15,7 @@ export CONFIG_STRICT=true
|
||||
rm -rdf build
|
||||
mkdir -p build
|
||||
env | grep ^CONFIG > tup.config
|
||||
tup init
|
||||
tup generate ./tup_build.sh
|
||||
bash -xe ./tup_build.sh
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user