merged the MVBMS repos, prob fucked both
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Software/.cache/clangd/index/PWM_control.h.4ED8B589A47755CF.idx
Normal file
BIN
Software/.cache/clangd/index/PWM_control.h.4ED8B589A47755CF.idx
Normal file
Binary file not shown.
BIN
Software/.cache/clangd/index/TMP1075.h.4B89CD0655BBDEEC.idx
Normal file
BIN
Software/.cache/clangd/index/TMP1075.h.4B89CD0655BBDEEC.idx
Normal file
Binary file not shown.
BIN
Software/.cache/clangd/index/can-halal.h.D8D9CD5568814F4E.idx
Normal file
BIN
Software/.cache/clangd/index/can-halal.h.D8D9CD5568814F4E.idx
Normal file
Binary file not shown.
BIN
Software/.cache/clangd/index/can.h.2BCB4E0C7FC5BD86.idx
Normal file
BIN
Software/.cache/clangd/index/can.h.2BCB4E0C7FC5BD86.idx
Normal file
Binary file not shown.
Binary file not shown.
BIN
Software/.cache/clangd/index/cmsis_gcc.h.03D4AFF6E036D3BC.idx
Normal file
BIN
Software/.cache/clangd/index/cmsis_gcc.h.03D4AFF6E036D3BC.idx
Normal file
Binary file not shown.
Binary file not shown.
BIN
Software/.cache/clangd/index/common_defs.h.0ED637FEC38C86B2.idx
Normal file
BIN
Software/.cache/clangd/index/common_defs.h.0ED637FEC38C86B2.idx
Normal file
Binary file not shown.
BIN
Software/.cache/clangd/index/core_cm4.h.8B7ACB8EE768AA52.idx
Normal file
BIN
Software/.cache/clangd/index/core_cm4.h.8B7ACB8EE768AA52.idx
Normal file
Binary file not shown.
BIN
Software/.cache/clangd/index/eeprom.h.64E531ECA863C41B.idx
Normal file
BIN
Software/.cache/clangd/index/eeprom.h.64E531ECA863C41B.idx
Normal file
Binary file not shown.
BIN
Software/.cache/clangd/index/errors.h.E4C0A0233E37601D.idx
Normal file
BIN
Software/.cache/clangd/index/errors.h.E4C0A0233E37601D.idx
Normal file
Binary file not shown.
BIN
Software/.cache/clangd/index/main.c.B4D309D46B27403A.idx
Normal file
BIN
Software/.cache/clangd/index/main.c.B4D309D46B27403A.idx
Normal file
Binary file not shown.
BIN
Software/.cache/clangd/index/main.h.56D4208CB2DDBED8.idx
Normal file
BIN
Software/.cache/clangd/index/main.h.56D4208CB2DDBED8.idx
Normal file
Binary file not shown.
BIN
Software/.cache/clangd/index/mpu_armv7.h.1B06708C585C9C94.idx
Normal file
BIN
Software/.cache/clangd/index/mpu_armv7.h.1B06708C585C9C94.idx
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Software/.cache/clangd/index/status_LED.h.EC943067FA39EA93.idx
Normal file
BIN
Software/.cache/clangd/index/status_LED.h.EC943067FA39EA93.idx
Normal file
Binary file not shown.
Binary file not shown.
BIN
Software/.cache/clangd/index/stm32f302xc.h.FA8A34C434A1DB29.idx
Normal file
BIN
Software/.cache/clangd/index/stm32f302xc.h.FA8A34C434A1DB29.idx
Normal file
Binary file not shown.
BIN
Software/.cache/clangd/index/stm32f3xx.h.BC05578F3657727D.idx
Normal file
BIN
Software/.cache/clangd/index/stm32f3xx.h.BC05578F3657727D.idx
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
25
Software/.mxproject
Normal file
25
Software/.mxproject
Normal file
File diff suppressed because one or more lines are too long
22
Software/.vscode/c_cpp_properties.json
vendored
Normal file
22
Software/.vscode/c_cpp_properties.json
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"configurations": [
|
||||
{
|
||||
"name": "STM32",
|
||||
"includePath": [
|
||||
"Core/Inc",
|
||||
"Core/Lib/can-halal",
|
||||
"Drivers/CMSIS/Device/ST/STM32F3xx/Include",
|
||||
"Drivers/CMSIS/Include",
|
||||
"Drivers/STM32F3xx_HAL_Driver/Inc",
|
||||
"Drivers/STM32F3xx_HAL_Driver/Inc/Legacy"
|
||||
],
|
||||
"defines": [
|
||||
"STM32F302xC",
|
||||
"STM32F3xx",
|
||||
"USE_HAL_DRIVER"
|
||||
],
|
||||
"compilerPath": "/run/current-system/sw/bin/arm-none-eabi-gcc"
|
||||
}
|
||||
],
|
||||
"version": 4
|
||||
}
|
||||
32
Software/.vscode/launch.json
vendored
Normal file
32
Software/.vscode/launch.json
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
{
|
||||
"configurations": [
|
||||
{
|
||||
"showDevDebugOutput": "parsed",
|
||||
"cwd": "${workspaceRoot}",
|
||||
"executable": "./build/mvbms-test-24.elf",
|
||||
"name": "Debug STM32",
|
||||
"request": "launch",
|
||||
"type": "cortex-debug",
|
||||
"servertype": "openocd",
|
||||
"preLaunchTask": "Build STM",
|
||||
"device": "stm32f302xc.s",
|
||||
"configFiles": [
|
||||
"openocd.cfg"
|
||||
]
|
||||
},
|
||||
{
|
||||
"showDevDebugOutput": "parsed",
|
||||
"cwd": "${workspaceRoot}",
|
||||
"executable": "./build/mvbms-test-24.elf",
|
||||
"name": "Attach STM32",
|
||||
"request": "attach",
|
||||
"type": "cortex-debug",
|
||||
"servertype": "openocd",
|
||||
"preLaunchTask": "Build STM",
|
||||
"device": "stm32f302xc.s",
|
||||
"configFiles": [
|
||||
"openocd.cfg"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
5
Software/.vscode/settings.json
vendored
Normal file
5
Software/.vscode/settings.json
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"cortex-debug.armToolchainPath": "/run/current-system/sw/bin",
|
||||
"cortex-debug.openocdPath": "/run/current-system/sw/bin/openocd",
|
||||
"makefile.makefilePath": "STM32Make.make"
|
||||
}
|
||||
50
Software/.vscode/tasks.json
vendored
Normal file
50
Software/.vscode/tasks.json
vendored
Normal file
@ -0,0 +1,50 @@
|
||||
{
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"label": "Build STM",
|
||||
"type": "process",
|
||||
"command": "${command:stm32-for-vscode.build}",
|
||||
"options": {
|
||||
"cwd": "${workspaceRoot}"
|
||||
},
|
||||
"group": {
|
||||
"kind": "build",
|
||||
"isDefault": true
|
||||
},
|
||||
"problemMatcher": [
|
||||
"$gcc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": "Build Clean STM",
|
||||
"type": "process",
|
||||
"command": "${command:stm32-for-vscode.cleanBuild}",
|
||||
"options": {
|
||||
"cwd": "${workspaceRoot}"
|
||||
},
|
||||
"group": {
|
||||
"kind": "build",
|
||||
"isDefault": true
|
||||
},
|
||||
"problemMatcher": [
|
||||
"$gcc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": "Flash STM",
|
||||
"type": "process",
|
||||
"command": "${command:stm32-for-vscode.flash}",
|
||||
"options": {
|
||||
"cwd": "${workspaceRoot}"
|
||||
},
|
||||
"group": {
|
||||
"kind": "build",
|
||||
"isDefault": true
|
||||
},
|
||||
"problemMatcher": [
|
||||
"$gcc"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
110
Software/CHANGELOG.txt
Normal file
110
Software/CHANGELOG.txt
Normal file
@ -0,0 +1,110 @@
|
||||
V1.0
|
||||
- merged mvbms-test to main
|
||||
- made the changes needed for the project to compile
|
||||
|
||||
V1.1
|
||||
- changed PWM settings in mxcube for ESC_L/R_PWM
|
||||
- add pwm_calibrate_powerground
|
||||
- precharge and discharge are now timer dependent instead of voltage dependent
|
||||
- remove the transitions (precharge -> discharge) to stop weird interactions
|
||||
|
||||
V1.2
|
||||
- change auxvoltages and cellvoltages to float to achieve higher precision
|
||||
- added void sm_calibrate_powerground(); void sm_precharge_discharge_manager();
|
||||
- fixed the clock in mxcube
|
||||
- cleaned up PWM_powerground_control()
|
||||
- cleaned up the state machine
|
||||
|
||||
V1.3
|
||||
- added eeprom.h and eeprom.c, is still WIP
|
||||
- void sm_check_charging(); was removed, you need to call 0xF1XX to enter charging mode, precharge is then 3 seconds then the relay closes. call 0x0000 to exit charging
|
||||
- removed some variables and some functions
|
||||
|
||||
V1.4
|
||||
- replaced ADBMS code with the newest version from the Slaves
|
||||
- added the Author to things i made
|
||||
- error_source is now set in the state_machine.c
|
||||
|
||||
V1.5
|
||||
- int16_t auxVoltages[MAXIMUM_AUX_VOLTAGES] to float
|
||||
- errors out when no messages are recieved for CAN_TIMEOUT messages
|
||||
- void set_error_source(int source); -> void set_error_source(SlaveErrorKind source);
|
||||
|
||||
V1.6
|
||||
- set temperature limit to 59
|
||||
- precharge and discharge durations are now 5 seconds
|
||||
- RELAY_BAT/ESC_SIDE and CURRENT_MEASUREMENT to int32_t
|
||||
- CAN messages are now correctly formated
|
||||
- minimum cell voltage is now set to 3200 mV
|
||||
- powerground calibration is now done in STATE_PRECHARGE (well yes but actually no)
|
||||
|
||||
V1.7
|
||||
- added eeprom functions
|
||||
- fixed(tm) voltage and CURRENT_MEASUREMENT
|
||||
- changed the CAN message a bit
|
||||
- added soc_estimation.c soc_estimation.h
|
||||
- added MIN/MAX_CELL_VOLTAGE for AMS_HighLevel
|
||||
- cleaned up state_machine code
|
||||
- changed the format of the CAN message.
|
||||
|
||||
V1.8
|
||||
- removed macros from can.h
|
||||
- added documentation to PWM_control.h
|
||||
- the MVBMS only reacts to messages if they are different from the previous message
|
||||
- powerground calibration now starts at STATE_PRECHARGE
|
||||
- moved header files from state_machine.c to h
|
||||
- added status_LED.c, changed the ioc file accordingly
|
||||
|
||||
V1.9
|
||||
- switched ~CSB and ~WC to high speed GPIO
|
||||
- cleaned up the includes in most files
|
||||
- wrote some code for the eeprom
|
||||
|
||||
V1.10
|
||||
- PWM_control now has some macros and the method PWM_powerground_softcontrol()
|
||||
- added void sm_powerground_manager() to state_machine.c
|
||||
|
||||
V1.11
|
||||
- added can_handle_dump() to dump the logging data from the EEPROM to CAN
|
||||
- rewrote eeprom_read() and eeprom_write
|
||||
- added void sm_program_powerground() and void sm_eeprom_write_status()
|
||||
-
|
||||
|
||||
V1.12
|
||||
- added some TODOs as warnings
|
||||
- added AMS_Balancing_Loop() to AMS_HighLevel
|
||||
- added current_soc to logging data
|
||||
- removed void sm_balancing() (the AMS should do it automatically if we set it to charging state)
|
||||
- changed the colors for the states in status_LED
|
||||
|
||||
V1.13
|
||||
- moved macros and libraries from eeprom.c to h
|
||||
- added can.h to state_machine.h
|
||||
- added balancing to AMS_HighLevel.c (hopefully)
|
||||
- fixed can_handle_dump()
|
||||
|
||||
V1.14
|
||||
- added programming mode to program the ESCs
|
||||
- removed void status_led_blink_sequence(uint8_t blinks, color color) and added proper blinking
|
||||
- fixed the bit shift of temperature in the can message
|
||||
- moved tmp1075_measure() and can_handle_send_status() to the state_machine
|
||||
|
||||
V1.15
|
||||
- changed max temperature to 55 from 60 according to the data sheet of the cell
|
||||
- changed ocv_soc_pairs to something close to the curve of other swaytronics batteries
|
||||
- the can messages uses roundf to round the values
|
||||
- made the pwm spool up in 300ms
|
||||
- increased MIN_CELL_VOLTAGE
|
||||
- the STM32 wait 1s for the BMS to finish its measurements
|
||||
- added debugging mode (turns off error checking)
|
||||
- added and ERROR_LATCH_TIME
|
||||
- added different blink speeds for different states
|
||||
|
||||
V1.16
|
||||
- TIME_BLINK_SLOW: 1000 -> 2000
|
||||
- moved can.c timers to can.h to detec
|
||||
- added logging of cells on can ID 0x503
|
||||
- eeprom gets initialized in main
|
||||
- startup delay is now 500ms
|
||||
- removed a zero from ocv_soc_pairs
|
||||
- changed precharge and discharge timers to 8000ms
|
||||
106
Software/Core/Inc/ADBMS_Abstraction.h
Executable file
106
Software/Core/Inc/ADBMS_Abstraction.h
Executable file
@ -0,0 +1,106 @@
|
||||
/*
|
||||
* ADBMS_Abstraction.h
|
||||
*
|
||||
* Created on: 14.07.2022
|
||||
* Author: max
|
||||
*/
|
||||
|
||||
#ifndef INC_ADBMS_ABSTRACTION_H_
|
||||
#define INC_ADBMS_ABSTRACTION_H_
|
||||
|
||||
#include "ADBMS_CMD_MAKROS.h"
|
||||
#include "ADBMS_LL_Driver.h"
|
||||
#include "main.h"
|
||||
|
||||
|
||||
#define MAXIMUM_CELL_VOLTAGES 16
|
||||
#define MAXIMUM_AUX_VOLTAGES 10
|
||||
#define MAXIMUM_GPIO 10
|
||||
|
||||
//see table 103 in datasheet (page 71)
|
||||
#define DEFAULT_UV 417 //VUV * 16 * 150 uV + 1.5 V Default Setting 2.5V
|
||||
#define DEFAULT_OV 1125 //VOV * 16 * 150 uV + 1.5 V Default Setting 4.2V
|
||||
|
||||
#define mV_from_ADBMS6830(x) (((((int16_t) (x))) * 0.150) + 1500)
|
||||
|
||||
struct ADBMS6830_Internal_Status {
|
||||
uint16 CS_FLT : 16; //ADC fault - mismatch between S- and C-ADC
|
||||
uint16 : 3;
|
||||
uint16 CCTS : 13; //Conversion counter
|
||||
uint16 VA_OV : 1; //5V analog supply overvoltage
|
||||
uint16 VA_UV : 1; //5V analog supply undervoltage
|
||||
uint16 VD_OV : 1; //3V digital supply overvoltage
|
||||
uint16 VD_UV : 1; //3V digital supply undervoltage
|
||||
uint16 CED : 1; //C-ADC single trim error (correctable)
|
||||
uint16 CMED : 1; //C-ADC multiple trim error (uncorrectable)
|
||||
uint16 SED : 1; //S-ADC single trim error (correctable)
|
||||
uint16 SMED : 1; //S-ADC multiple trim error (uncorrectable)
|
||||
uint16 VDEL : 1; //Latent supply voltage error
|
||||
uint16 VDE : 1; //Supply voltage error
|
||||
uint16 COMPARE : 1; //Comparasion between S- and C-ADC active
|
||||
uint16 SPIFLT : 1; //SPI fault
|
||||
uint16 SLEEP : 1; //Sleep mode previously entered
|
||||
uint16 THSD : 1; //Thermal shutdown
|
||||
uint16 TMODCHK : 1; //Test mode check
|
||||
uint16 OSCCHK : 1; //Oscillator check
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
int16_t cellVoltages[MAXIMUM_CELL_VOLTAGES];
|
||||
float auxVoltages[MAXIMUM_AUX_VOLTAGES];
|
||||
|
||||
struct ADBMS6830_Internal_Status status;
|
||||
uint16 internalDieTemp;
|
||||
uint16 analogSupplyVoltage;
|
||||
uint16 digitalSupplyVoltage;
|
||||
uint16 sumOfCellMeasurements;
|
||||
uint16 refVoltage;
|
||||
|
||||
uint16 GPIO_Values[MAXIMUM_GPIO];
|
||||
|
||||
uint32 overVoltage;
|
||||
uint32 underVoltage;
|
||||
|
||||
} Cell_Module;
|
||||
|
||||
uint8 amsReset();
|
||||
|
||||
uint8 initAMS(SPI_HandleTypeDef* hspi, uint8 numofcells, uint8 numofaux);
|
||||
uint8 amsWakeUp();
|
||||
|
||||
uint8 amsCellMeasurement(Cell_Module* module);
|
||||
uint8 amsConfigCellMeasurement(uint8 numberofChannels);
|
||||
|
||||
uint8 amsAuxAndStatusMeasurement(Cell_Module* module);
|
||||
uint8 amsConfigAuxMeasurement(uint16 Channels);
|
||||
|
||||
uint8 amsConfigGPIO(uint16 gpios);
|
||||
uint8 amsSetGPIO(uint16 gpios);
|
||||
uint8 readGPIO(Cell_Module* module);
|
||||
|
||||
uint8 amsConfigBalancing(uint32 Channels, uint8 dutyCycle);
|
||||
uint8 amsStartBalancing(uint8 dutyCycle);
|
||||
uint8 amsStopBalancing();
|
||||
|
||||
uint8 amsSelfTest();
|
||||
|
||||
uint8 amsConfigOverUnderVoltage(uint16 overVoltage, uint16 underVoltage);
|
||||
|
||||
uint8 amsCheckUnderOverVoltage(Cell_Module* module);
|
||||
uint8 amsConfigOverVoltage(uint16 overVoltage);
|
||||
|
||||
uint8 amscheckOpenCellWire(Cell_Module* module);
|
||||
|
||||
uint8 amsClearStatus();
|
||||
uint8 amsClearAux();
|
||||
uint8 amsClearCells();
|
||||
|
||||
uint8 amsSendWarning();
|
||||
uint8 amsSendError();
|
||||
|
||||
uint8 amsClearWarning();
|
||||
uint8 amsClearError();
|
||||
|
||||
uint8 amsReadCellVoltages(Cell_Module* module);
|
||||
|
||||
#endif /* INC_ADBMS_ABSTRACTION_H_ */
|
||||
171
Software/Core/Inc/ADBMS_CMD_MAKROS.h
Executable file
171
Software/Core/Inc/ADBMS_CMD_MAKROS.h
Executable file
@ -0,0 +1,171 @@
|
||||
/*
|
||||
* ADBMS_CMD_MAKROS.h
|
||||
*
|
||||
* Created on: 14.07.2022
|
||||
* Author: max
|
||||
*/
|
||||
|
||||
#ifndef INC_ADBMS_CMD_MAKROS_H_
|
||||
#define INC_ADBMS_CMD_MAKROS_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#define WRCFGA 0x0001 // Write Configuration Register Group A
|
||||
#define RDCFGA 0x0002 // Read Configuration Register Group A
|
||||
#define WRCFGB 0x0024 // Write Configuration Register Group B
|
||||
#define RDCFGB 0x0026 // Read Configuration Register Group B
|
||||
|
||||
#define WRPWMA 0x0020 // Write PWM Register Group A
|
||||
#define RDPWMA 0x0022 // Read PWM Register Group A
|
||||
#define WRPWMB 0x0021 // Write PWM Register Group B
|
||||
#define RDPWMB 0x0023 // Read PWM Register Group B
|
||||
|
||||
#define RDCVA 0x0004 // Read Cell Voltage Register Group A
|
||||
#define RDCVB 0x0006 // Read Cell Voltage Register Group B
|
||||
#define RDCVC 0x0008 // Read Cell Voltage Register Group C
|
||||
#define RDCVD 0x000A // Read Cell Voltage Register Group D
|
||||
#define RDCVE 0x0009 // Read Cell Voltage Register Group E
|
||||
#define RDCVF 0x000B // Read Cell Voltage Register Group F
|
||||
#define RDCVALL 0x000C // Read All Cell Voltage Register Groups
|
||||
|
||||
#define RDACA 0x0044 // Read averaged Cell Voltage Register Group A
|
||||
#define RDACB 0x0046 // Read averaged Cell Voltage Register Group B
|
||||
#define RDACC 0x0048 // Read averaged Cell Voltage Register Group C
|
||||
#define RDACD 0x004A // Read averaged Cell Voltage Register Group D
|
||||
#define RDACE 0x0049 // Read averaged Cell Voltage Register Group E
|
||||
#define RDACF 0x004B // Read averaged Cell Voltage Register Group F
|
||||
#define RDACALL 0x004C // Read averaged All Cell Voltage Register Groups
|
||||
|
||||
#define RDAUXA 0x0019 // Read Auxilliary Register Group A
|
||||
#define RDAUXB 0x001A // Read Auxilliary Register Group B
|
||||
#define RDAUXC 0x001B // Read Auxilliary Register Group C
|
||||
#define RDAUXD 0x001F // Read Auxilliary Register Group D
|
||||
|
||||
#define RDAUXALL 0x0035 // Read All Auxilliary and Status Register Groups
|
||||
|
||||
#define RDSTATA 0x0030 // Read Status Register Group A
|
||||
#define RDSTATB 0x0031 // Read Status Register Group B
|
||||
#define RDSTATC 0x0032 // Read Status Register Group C
|
||||
#define RDSTATD 0x0033 // Read Status Register Group D
|
||||
#define RDSTATE 0x0034 // Read Status Register Group E
|
||||
|
||||
#define ADCV 0x0260 // Start Cell Voltage Conversion with C-ADC
|
||||
#define ADCV_OW_0 (1u << 0)
|
||||
#define ADCV_OW_1 (1u << 1)
|
||||
#define ADCV_RSTF (1u << 2)
|
||||
#define ADCV_DCP (1u << 4)
|
||||
#define ADCV_CONT (1u << 7) // Continuous Mode
|
||||
#define ADCV_RD (1u << 8) // Redundancy Mode
|
||||
|
||||
#define ADSV 0x0168 // Start Cell Voltage Conversion with S-ADC
|
||||
#define ADSV_OW_0 (1u << 0)
|
||||
#define ADSV_OW_1 (1u << 1)
|
||||
#define ADSV_DCP (1u << 4)
|
||||
#define ADSV_CONT (1u << 7) // Continuous Mode
|
||||
|
||||
#define ADAX 0x0410 // Start GPIOs and Vref2 Conversion
|
||||
#define ADAX_CONV_ALL 0x0000 // Convert all GPIOs, VREF2, VD, VA, ITEMP
|
||||
#define ADAX_OW (1u << 8)
|
||||
|
||||
#define CLRCELL 0x0711 // Clear Cell Voltage Register Groups
|
||||
#define CLRAUX 0x0712 // Clear Auxiliary Register Groups
|
||||
#define CLOVUV 0x0715 // Clear Overvoltage and Undervoltage Flags
|
||||
#define CLRFLAG 0x0717 // Clear all Flags
|
||||
|
||||
#define PLADC 0x0718 // Poll ADC Conversion Status
|
||||
#define PLAUX 0x071E // Poll AUX Conversion Status
|
||||
|
||||
#define SRST 0x0027 //Soft reset
|
||||
|
||||
#define DIAGN 0x0715 // Diagnos MUX and Poll Status
|
||||
#define WRCOMM 0x0721 // Write COMM Register Group
|
||||
#define RDCOMM 0x0722 // Read COMM Register Group
|
||||
#define STCOMM 0x0723 // Start I2C/SPI Communication
|
||||
#define MUTE 0x0028 // Mute Discharge
|
||||
#define UNMUTE 0x0029 // Unmute Discharge
|
||||
|
||||
|
||||
|
||||
/* GPIO Selection for ADC Converion
|
||||
* 000: GPIO1 to 5, 2nd Reference, GPIO 6 to 9
|
||||
* 001: GPIO1 and GPIO6
|
||||
* 010 GPIO2 and GPIO7
|
||||
* 011 GPIO3 and GPIO8
|
||||
* 100 GPIO4 and GPIO9
|
||||
* 101 GPIO5
|
||||
* 110 2nd Reference
|
||||
*/
|
||||
|
||||
#define CHG000 (0x00)
|
||||
#define CHG001 (0x01)
|
||||
#define CHG010 (0x02)
|
||||
#define CHG011 (0x03)
|
||||
#define CHG100 (0x04)
|
||||
#define CHG101 (0x05)
|
||||
#define CHG110 (0x06)
|
||||
|
||||
/* Status Group Selection
|
||||
* 000: SC,ITMP,VA,VD
|
||||
* 001: SC
|
||||
* 010: ITMP
|
||||
* 011: VA
|
||||
* 100: VD
|
||||
*/
|
||||
|
||||
#define CHST000 (0x00)
|
||||
#define CHST001 (0x01)
|
||||
#define CHST010 (0x02)
|
||||
#define CHST011 (0x03)
|
||||
#define CHST100 (0x04)
|
||||
|
||||
#define PEC_FIELD_SIZE 2
|
||||
|
||||
#define CFG_GROUP_A_SIZE 6
|
||||
#define CFG_GROUP_B_SIZE 6
|
||||
|
||||
#define PWM_GROUP_A_SIZE 6
|
||||
#define PWM_GROUP_B_SIZE 2
|
||||
|
||||
#define CV_GROUP_A_SIZE 6
|
||||
#define CV_GROUP_B_SIZE 6
|
||||
#define CV_GROUP_C_SIZE 6
|
||||
#define CV_GROUP_D_SIZE 6
|
||||
#define CV_GROUP_E_SIZE 6
|
||||
#define CV_GROUP_F_SIZE 6
|
||||
|
||||
#define AUX_GROUP_A_SIZE 6
|
||||
#define AUX_GROUP_B_SIZE 6
|
||||
#define AUX_GROUP_C_SIZE 6
|
||||
#define AUX_GROUP_D_SIZE 6
|
||||
|
||||
#define STATUS_GROUP_A_SIZE 6
|
||||
#define STATUS_GROUP_B_SIZE 6
|
||||
#define STATUS_GROUP_C_SIZE 6
|
||||
#define STATUS_GROUP_D_SIZE 6
|
||||
#define STATUS_GROUP_E_SIZE 6
|
||||
#define COMM_GROUP_SIZE 6
|
||||
#define S_CONTROL_GROUP_SIZE 6
|
||||
#define PWM_GROUP_SIZE 6
|
||||
#define PWM_S_CONTROL_GROUP_B_SIZE 6
|
||||
|
||||
#define CFG_GROUP_A_ID 1
|
||||
#define CFG_GROUP_B_ID 2
|
||||
#define CV_GROUP_A_ID 3
|
||||
#define CV_GROUP_B_ID 4
|
||||
#define CV_GROUP_C_ID 5
|
||||
#define CV_GROUP_D_ID 6
|
||||
#define CV_GROUP_E_ID 7
|
||||
#define CV_GROUP_F_ID 8
|
||||
|
||||
#define AUX_GROUP_A_ID 9
|
||||
#define AUX_GROUP_B_ID 10
|
||||
#define AUX_GROUP_C_ID 11
|
||||
#define AUX_GROUP_D_ID 12
|
||||
|
||||
#define STATUS_GROUP_A_ID 13
|
||||
#define STATUS_GROUP_B_ID 14
|
||||
#define COMM_GROUP_ID 15
|
||||
#define S_CONTROL_GROUP_ID 16
|
||||
#define PWM_GROUP_ID 17
|
||||
#define PWM_S_CONTROL_GROUP_B_ID 18
|
||||
|
||||
#endif /* INC_ADBMS_CMD_MAKROS_H_ */
|
||||
44
Software/Core/Inc/ADBMS_LL_Driver.h
Executable file
44
Software/Core/Inc/ADBMS_LL_Driver.h
Executable file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* ADBMS_LL_Driver.h
|
||||
*
|
||||
* Created on: 05.06.2022
|
||||
* Author: max
|
||||
*/
|
||||
|
||||
#ifndef ADBMS_LL_DRIVER_H_
|
||||
#define ADBMS_LL_DRIVER_H_
|
||||
|
||||
#define TARGET_STM32
|
||||
|
||||
#include "main.h"
|
||||
|
||||
#ifdef TARGET_STM32
|
||||
typedef uint8_t uint8;
|
||||
typedef uint16_t uint16;
|
||||
typedef uint32_t uint32;
|
||||
#endif
|
||||
|
||||
uint8 adbmsDriverInit(SPI_HandleTypeDef* hspi);
|
||||
uint8 calculateCommandPEC(uint8* data, uint8 datalen);
|
||||
uint16 updateCommandPEC(uint16 currentPEC, uint8 din);
|
||||
uint8 checkCommandPEC(uint8* data, uint8 datalen);
|
||||
|
||||
uint8 calculateDataPEC(uint8* data, uint8 datalen);
|
||||
uint16 updateDataPEC(uint16 currentPEC, uint8 din);
|
||||
uint8 checkDataPEC(uint8* data, uint8 datalen);
|
||||
|
||||
[[gnu::access(read_only, 2, 3)]] uint8 writeCMD(uint16 command, const uint8* args, uint8 arglen);
|
||||
[[gnu::access(write_only, 2, 3)]] uint8 readCMD(uint16 command, uint8* buffer, uint8 buflen);
|
||||
uint8 pollCMD(uint16 command);
|
||||
|
||||
void mcuAdbmsCSLow();
|
||||
void mcuAdbmsCSHigh();
|
||||
|
||||
uint8 mcuSPITransmit(uint8* buffer, uint8 buffersize);
|
||||
uint8 mcuSPIReceive(uint8* buffer, uint8 buffersize);
|
||||
uint8 mcuSPITransmitReceive(uint8* rxbuffer, uint8* txbuffer, uint8 buffersize);
|
||||
|
||||
uint8 wakeUpCmd();
|
||||
void mcuDelay(uint16 delay);
|
||||
|
||||
#endif /* ADBMS_LL_DRIVER_H_ */
|
||||
47
Software/Core/Inc/AMS_HighLevel.h
Executable file
47
Software/Core/Inc/AMS_HighLevel.h
Executable file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* AMS_HighLevel.h
|
||||
*
|
||||
* Created on: 20.07.2022
|
||||
* Author: max
|
||||
*/
|
||||
|
||||
#ifndef INC_AMS_HIGHLEVEL_H_
|
||||
#define INC_AMS_HIGHLEVEL_H_
|
||||
|
||||
#include "ADBMS_Abstraction.h"
|
||||
#include "ADBMS_CMD_MAKROS.h"
|
||||
#include "ADBMS_LL_Driver.h"
|
||||
#include "can-halal.h"
|
||||
#include "errors.h"
|
||||
#include "stm32f3xx_hal.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef enum {
|
||||
AMSDEACTIVE,
|
||||
AMSIDLE,
|
||||
AMSCHARGING,
|
||||
AMSIDLEBALANCING,
|
||||
AMSDISCHARGING,
|
||||
AMSWARNING,
|
||||
AMSERROR
|
||||
} amsState;
|
||||
|
||||
extern amsState currentAMSState;
|
||||
extern Cell_Module module;
|
||||
extern uint32_t balancedCells;
|
||||
extern bool BalancingActive;
|
||||
|
||||
extern uint8_t numberofCells;
|
||||
extern uint8_t numberofAux;
|
||||
|
||||
void AMS_Init(SPI_HandleTypeDef* hspi);
|
||||
void AMS_Loop();
|
||||
|
||||
uint8_t AMS_Balancing_Loop();
|
||||
uint8_t AMS_Idle_Loop();
|
||||
uint8_t AMS_Warning_Loop();
|
||||
uint8_t AMS_Error_Loop();
|
||||
uint8_t AMS_Charging_Loop();
|
||||
uint8_t AMS_Discharging_Loop();
|
||||
|
||||
#endif /* INC_AMS_HIGHLEVEL_H_ */
|
||||
45
Software/Core/Inc/PWM_control.h
Normal file
45
Software/Core/Inc/PWM_control.h
Normal file
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* PWM_control.h
|
||||
*
|
||||
* Created on: 07.07.2024
|
||||
* Author: Hamza
|
||||
*/
|
||||
|
||||
#ifndef INC_PWM_CONTROL_H
|
||||
#define INC_PWM_CONTROL_H
|
||||
|
||||
#include "stm32f3xx_hal.h"
|
||||
#include "state_machine.h"
|
||||
|
||||
/* The PWM period (1/FPWM) is defined by the following parameters:
|
||||
ARR value, the Prescaler value, and the internal clock itself which drives the timer module FCLK.
|
||||
F_PWM = (F_CLK)/((ARR + 1) * (PSC + 1))
|
||||
(ARR + 1) * (PSC + 1) = (F_CLK)/(F_PWM)
|
||||
(PSC + 1) = (F_CLK)/(F_PWM * (ARR + 1))
|
||||
|
||||
F_CLK = 16 MHz
|
||||
|
||||
POWERGROUND ESC Signal: pulse every 20 ms, 1 ms = 0%, 2 ms = 100%
|
||||
FREQ = 50 Hz -> 16 MHz/50 Hz = 320000 = ((39999 + 1) * (7 + 1))
|
||||
DUTY CYCLE = 1/20 -> 0%, DUTY CYCLE = 2/20 -> 100%
|
||||
CCR * DUTY_CYCLE
|
||||
CCR: 1/20 -> 500, 2/20 -> 1000
|
||||
*/
|
||||
// UNUSED
|
||||
#define POWERGROUND_FREQ 50
|
||||
#define POWERGROUND_PRESCALER 7
|
||||
#define POWERGROUND_ARR 39999
|
||||
#define POWERGROUND_MIN_DUTY_CYCLE 0.05
|
||||
#define POWERGROUND_MAX_DUTY_CYCLE 0.1
|
||||
|
||||
//#define BATTERY_COOLING_FREQ 20000
|
||||
|
||||
extern uint8_t current_powerground_status;
|
||||
extern uint8_t target_powerground_status;
|
||||
|
||||
void PWM_control_init(TIM_HandleTypeDef* pg, TIM_HandleTypeDef* bat_cool, TIM_HandleTypeDef* esc_cool);
|
||||
void PWM_powerground_softcontrol();
|
||||
void PWM_powerground_control(uint8_t percent);
|
||||
void PWM_battery_cooling_control(uint8_t percent);
|
||||
|
||||
#endif /* INC_CHANNEL_CONTROL_H */
|
||||
20
Software/Core/Inc/TMP1075.h
Normal file
20
Software/Core/Inc/TMP1075.h
Normal file
@ -0,0 +1,20 @@
|
||||
#ifndef INC_TMP1075_H_
|
||||
#define INC_TMP1075_H_
|
||||
|
||||
#include "stm32f3xx_hal.h"
|
||||
#include "can-halal.h"
|
||||
#include "errors.h"
|
||||
#include <stdint.h>
|
||||
|
||||
#define N_CELLS 13
|
||||
#define N_TEMP_SENSORS 13
|
||||
|
||||
extern uint32_t tmp1075_failed_sensors;
|
||||
extern int16_t tmp1075_temps[N_TEMP_SENSORS];
|
||||
|
||||
HAL_StatusTypeDef tmp1075_init(I2C_HandleTypeDef* hi2c);
|
||||
HAL_StatusTypeDef tmp1075_measure();
|
||||
HAL_StatusTypeDef tmp1075_sensor_init(int n);
|
||||
HAL_StatusTypeDef tmp1075_sensor_read(int n, int16_t* res);
|
||||
|
||||
#endif // INC_TMP1075_H_
|
||||
29
Software/Core/Inc/can.h
Normal file
29
Software/Core/Inc/can.h
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* can.h
|
||||
*
|
||||
* Created on: 07.07.2024
|
||||
* Author: Hamza
|
||||
*/
|
||||
|
||||
#ifndef INC_CAN_H
|
||||
#define INC_CAN_H
|
||||
|
||||
#include "stm32f3xx_hal.h"
|
||||
#include "main.h"
|
||||
#include "can-halal.h"
|
||||
#include "state_machine.h"
|
||||
|
||||
extern uint32_t can_status_timer, can_log_timer, can_timeout_timer;
|
||||
|
||||
void can_init(CAN_HandleTypeDef* hcan);
|
||||
|
||||
void can_handle_send_status();
|
||||
void can_handle_send_log();
|
||||
|
||||
void can_handle_dump();
|
||||
|
||||
void can_handle_recieve_command(const uint8_t *data);
|
||||
|
||||
void ftcan_msg_received_cb(uint16_t id, size_t datalen, const uint8_t *data);
|
||||
|
||||
#endif /* "INC_CAN_H" */
|
||||
33
Software/Core/Inc/eeprom.h
Executable file
33
Software/Core/Inc/eeprom.h
Executable file
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* PWM_control.h
|
||||
*
|
||||
* Created on: 10.07.2024
|
||||
* Author: Hamza
|
||||
*/
|
||||
|
||||
#ifndef INC_EEPROM_H_
|
||||
#define INC_EEPROM_H_
|
||||
|
||||
#include <stm32f3xx_hal.h>
|
||||
#include "ADBMS_LL_Driver.h"
|
||||
#include "soc_estimation.h"
|
||||
#include <state_machine.h>
|
||||
#include "stm32f3xx_hal_def.h"
|
||||
#include "stm32f3xx_hal_i2c.h"
|
||||
#include "TMP1075.h"
|
||||
|
||||
// see Datasheet for these values
|
||||
#define EEPROM_I2C_ADDR 0xA4 // 0xA4 for the the first 2⁸ addresses and 0xA6 for the the last 2⁸ addresses
|
||||
#define EERROM_MEMORY_ADDR_SIZE 2 // it is controlled by A17 in the address Byte, see datasheet
|
||||
#define EEPROM_MEMORY_SIZE 131072 // in bytes
|
||||
#define EEPROM_PAGE_SIZE 32 // in bytes
|
||||
|
||||
extern uint32_t write_address, read_address;
|
||||
|
||||
void eeprom_init(I2C_HandleTypeDef* hi2c);
|
||||
void eeprom_write_status();
|
||||
|
||||
HAL_StatusTypeDef eeprom_read(uint8_t* data, uint16_t data_length);
|
||||
HAL_StatusTypeDef eeprom_write(uint8_t* data, uint16_t data_length);
|
||||
|
||||
#endif // INC_EEPROM_H_
|
||||
41
Software/Core/Inc/errors.h
Normal file
41
Software/Core/Inc/errors.h
Normal file
@ -0,0 +1,41 @@
|
||||
#ifndef INC_ERRORS_H
|
||||
#define INC_ERRORS_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define ERROR_SOURCE_VOLTAGES (1 << 0)
|
||||
#define ERROR_SOURCE_TEMPERATURES (1 << 1)
|
||||
#define ERROR_SOURCE_TOO_FEW_WORKING_TEMP_SENSORS (1 << 2)
|
||||
#define ERROR_SOURCE_OPEN_CELL_CONNECTION (1 << 3)
|
||||
#define ERROR_SOURCE_EEPROM (1 << 4)
|
||||
#define ERROR_SOURCE_INTERNAL (1 << 5)
|
||||
|
||||
#define ERROR_TIME_THRESH 150 // ms
|
||||
|
||||
typedef enum : uint16_t {
|
||||
SEK_OVERTEMP = 0x0,
|
||||
SEK_UNDERTEMP = 0x1,
|
||||
SEK_OVERVOLT = 0x2,
|
||||
SEK_UNDERVOLT = 0x3,
|
||||
SEK_TOO_FEW_TEMPS = 0x4,
|
||||
SEK_OPENWIRE = 0x5,
|
||||
SEK_EEPROM_ERR = 0x6,
|
||||
SEK_INTERNAL_BMS_TIMEOUT = 0x7,
|
||||
SEK_INTERNAL_BMS_CHECKSUM_FAIL = 0x8,
|
||||
SEK_INTERNAL_BMS_OVERTEMP = 0x9,
|
||||
SEK_INTERNAL_BMS_FAULT = 0xA,
|
||||
} SlaveErrorKind;
|
||||
|
||||
typedef struct {
|
||||
uint16_t error_sources;
|
||||
SlaveErrorKind data_kind;
|
||||
uint8_t data[4];
|
||||
uint32_t errors_since;
|
||||
} SlaveErrorData;
|
||||
|
||||
extern SlaveErrorData error_data;
|
||||
|
||||
void set_error_source(SlaveErrorKind source);
|
||||
void clear_error_source(SlaveErrorKind source);
|
||||
|
||||
#endif // INC_ERRORS_H
|
||||
105
Software/Core/Inc/main.h
Normal file
105
Software/Core/Inc/main.h
Normal file
@ -0,0 +1,105 @@
|
||||
/* USER CODE BEGIN Header */
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file : main.h
|
||||
* @brief : Header for main.c file.
|
||||
* This file contains the common defines of the application.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2024 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
/* USER CODE END Header */
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef __MAIN_H
|
||||
#define __MAIN_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f3xx_hal.h"
|
||||
|
||||
/* Private includes ----------------------------------------------------------*/
|
||||
/* USER CODE BEGIN Includes */
|
||||
|
||||
/* USER CODE END Includes */
|
||||
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
/* USER CODE BEGIN ET */
|
||||
|
||||
/* USER CODE END ET */
|
||||
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
/* USER CODE BEGIN EC */
|
||||
|
||||
/* USER CODE END EC */
|
||||
|
||||
/* Exported macro ------------------------------------------------------------*/
|
||||
/* USER CODE BEGIN EM */
|
||||
|
||||
/* USER CODE END EM */
|
||||
|
||||
void HAL_TIM_MspPostInit(TIM_HandleTypeDef *htim);
|
||||
|
||||
/* Exported functions prototypes ---------------------------------------------*/
|
||||
void Error_Handler(void);
|
||||
|
||||
/* USER CODE BEGIN EFP */
|
||||
|
||||
/* USER CODE END EFP */
|
||||
|
||||
/* Private defines -----------------------------------------------------------*/
|
||||
#define CSB_Pin GPIO_PIN_4
|
||||
#define CSB_GPIO_Port GPIOA
|
||||
#define ESC_L_PWM_Pin GPIO_PIN_0
|
||||
#define ESC_L_PWM_GPIO_Port GPIOB
|
||||
#define ESC_R_PWM_Pin GPIO_PIN_1
|
||||
#define ESC_R_PWM_GPIO_Port GPIOB
|
||||
#define BAT_COOLING_PWM_Pin GPIO_PIN_10
|
||||
#define BAT_COOLING_PWM_GPIO_Port GPIOB
|
||||
#define BAT_COOLING_ENABLE_Pin GPIO_PIN_11
|
||||
#define BAT_COOLING_ENABLE_GPIO_Port GPIOB
|
||||
#define ESC_COOLING_ENABLE_Pin GPIO_PIN_14
|
||||
#define ESC_COOLING_ENABLE_GPIO_Port GPIOB
|
||||
#define ESC_COOLING_PWM_Pin GPIO_PIN_15
|
||||
#define ESC_COOLING_PWM_GPIO_Port GPIOB
|
||||
#define EEPROM___WC__Pin GPIO_PIN_8
|
||||
#define EEPROM___WC__GPIO_Port GPIOA
|
||||
#define EEPROM_SCL_Pin GPIO_PIN_9
|
||||
#define EEPROM_SCL_GPIO_Port GPIOA
|
||||
#define EEPROM_SDA_Pin GPIO_PIN_10
|
||||
#define EEPROM_SDA_GPIO_Port GPIOA
|
||||
#define TMP_SCL_Pin GPIO_PIN_15
|
||||
#define TMP_SCL_GPIO_Port GPIOA
|
||||
#define RELAY_ENABLE_Pin GPIO_PIN_4
|
||||
#define RELAY_ENABLE_GPIO_Port GPIOB
|
||||
#define PRECHARGE_ENABLE_Pin GPIO_PIN_5
|
||||
#define PRECHARGE_ENABLE_GPIO_Port GPIOB
|
||||
#define STATUS_LED_R_Pin GPIO_PIN_6
|
||||
#define STATUS_LED_R_GPIO_Port GPIOB
|
||||
#define STATUS_LED_G_Pin GPIO_PIN_7
|
||||
#define STATUS_LED_G_GPIO_Port GPIOB
|
||||
#define STATUS_LED_B_Pin GPIO_PIN_8
|
||||
#define STATUS_LED_B_GPIO_Port GPIOB
|
||||
#define TMP_SDA_Pin GPIO_PIN_9
|
||||
#define TMP_SDA_GPIO_Port GPIOB
|
||||
|
||||
/* USER CODE BEGIN Private defines */
|
||||
|
||||
/* USER CODE END Private defines */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __MAIN_H */
|
||||
21
Software/Core/Inc/soc_estimation.h
Normal file
21
Software/Core/Inc/soc_estimation.h
Normal file
@ -0,0 +1,21 @@
|
||||
#ifndef INC_SOC_ESTIMATION_H
|
||||
#define INC_SOC_ESTIMATION_H
|
||||
|
||||
#include "state_machine.h"
|
||||
#include "stm32f3xx_hal.h"
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
extern float current_soc;
|
||||
|
||||
void soc_init();
|
||||
void soc_update();
|
||||
|
||||
typedef struct {
|
||||
uint16_t ocv;
|
||||
float soc;
|
||||
} ocv_soc_pair_t;
|
||||
extern ocv_soc_pair_t OCV_SOC_PAIRS[];
|
||||
float soc_for_ocv(uint16_t ocv);
|
||||
|
||||
#endif // INC_SOC_ESTIMATION_H
|
||||
98
Software/Core/Inc/state_machine.h
Normal file
98
Software/Core/Inc/state_machine.h
Normal file
@ -0,0 +1,98 @@
|
||||
/*
|
||||
* state_machine.h
|
||||
*
|
||||
* Created on: 07.07.2024
|
||||
* Author: Hamza
|
||||
*/
|
||||
|
||||
#ifndef INC_STATE_MACHINE_H
|
||||
#define INC_STATE_MACHINE_H
|
||||
|
||||
#include "ADBMS_LL_Driver.h"
|
||||
#include <AMS_HighLevel.h>
|
||||
#include <can.h>
|
||||
#include <eeprom.h>
|
||||
#include <errors.h>
|
||||
#include <PWM_control.h>
|
||||
#include <status_LED.h>
|
||||
#include <TMP1075.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <math.h>
|
||||
|
||||
typedef enum { // states -> 3 bit. valid transitions: (all could transition to error)
|
||||
STATE_INACTIVE, // INACTIVE -> PRECHARGE, CHARGING, ERROR
|
||||
STATE_PRECHARGE, // PRECHARGE -> INACTIVE, READY, DISCHARGE, ERROR
|
||||
STATE_READY, // READY -> ACTIVE, DISCHARGE, ERROR
|
||||
STATE_ACTIVE, // ACTIVE -> READY, DISCHARGE, ERROR
|
||||
STATE_DISCHARGE, // DISCHARGE -> INACTIVE, PRECHARGE, ERROR
|
||||
STATE_CHARGING_PRECHARGE,
|
||||
STATE_CHARGING, // CHARGING -> INACTIVE, DISCHARGE, ERROR
|
||||
STATE_ERROR, // ERROR -> INACTIVE, DISCHARGE, ERROR
|
||||
} State;
|
||||
|
||||
typedef struct {
|
||||
uint16_t bms_timeout : 1;
|
||||
uint16_t bms_fault : 1;
|
||||
uint16_t temperature_error : 1;
|
||||
uint16_t current_error : 1;
|
||||
uint16_t current_sensor_missing : 1;
|
||||
uint16_t voltage_error : 1;
|
||||
uint16_t voltage_missing : 1;
|
||||
uint16_t state_transition_fail : 1;
|
||||
uint16_t eeprom_error : 1;
|
||||
uint16_t : 7; // padding
|
||||
} ErrorKind;
|
||||
|
||||
//typedef enum {} WarningKind;
|
||||
|
||||
typedef struct {
|
||||
State current_state;
|
||||
State target_state;
|
||||
uint16_t error_source; // TSErrorSource (bitmask)
|
||||
ErrorKind error_type; // TSErrorKind
|
||||
} StateHandle;
|
||||
|
||||
typedef enum { RELAY_MAIN, RELAY_PRECHARGE } Relay;
|
||||
|
||||
extern StateHandle state;
|
||||
extern bool programming_mode;
|
||||
|
||||
extern int32_t RELAY_BAT_SIDE_VOLTAGE;
|
||||
extern int32_t RELAY_ESC_SIDE_VOLTAGE;
|
||||
extern int32_t CURRENT_MEASUREMENT;
|
||||
|
||||
void sm_init();
|
||||
void sm_update();
|
||||
void sm_handle_ams_in(const uint8 *data);
|
||||
void sm_precharge_discharge_manager();
|
||||
void sm_powerground_manager();
|
||||
void sm_calibrate_powerground();
|
||||
void sm_balancing();
|
||||
void sm_eeprom_write_status();
|
||||
void sm_program_powerground();
|
||||
|
||||
void sm_check_errors();
|
||||
void sm_set_error_source();
|
||||
|
||||
State sm_update_inactive();
|
||||
State sm_update_precharge();
|
||||
State sm_update_ready();
|
||||
State sm_update_active();
|
||||
State sm_update_discharge();
|
||||
State sm_update_charging_precharge();
|
||||
State sm_update_charging();
|
||||
State sm_update_error();
|
||||
|
||||
void sm_set_relay_positions(State state);
|
||||
void sm_set_relay(Relay relay, bool closed);
|
||||
|
||||
void sm_check_battery_temperature(uint8_t* id, uint16_t* temp);
|
||||
void sm_check_battery_voltage(uint8_t* id, uint16_t* voltage);
|
||||
int16_t sm_return_cell_temperature(int id);
|
||||
int16_t sm_return_cell_voltage(int id);
|
||||
|
||||
void sm_test_cycle_states();
|
||||
|
||||
#endif /* "INC_STATE_MACHINE_H" */
|
||||
31
Software/Core/Inc/status_LED.h
Normal file
31
Software/Core/Inc/status_LED.h
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* status_LED.h
|
||||
*
|
||||
* Created on: 07.07.2024
|
||||
* Author: Hamza
|
||||
*/
|
||||
|
||||
#ifndef INC_STATUS_LED_H
|
||||
#define INC_STATUS_LED_H
|
||||
|
||||
#include "stm32f3xx_hal.h"
|
||||
#include <state_machine.h>
|
||||
|
||||
typedef enum {
|
||||
OFF,
|
||||
RED,
|
||||
GREEN,
|
||||
BLUE,
|
||||
YELLOW,
|
||||
PINK,
|
||||
CYAN,
|
||||
WHITE
|
||||
} color;
|
||||
|
||||
void status_led_init(TIM_HandleTypeDef* r, TIM_HandleTypeDef* g, TIM_HandleTypeDef* b);
|
||||
void status_led_update();
|
||||
|
||||
void status_led_set_color(color color);
|
||||
void status_led_set(uint8_t r, uint8_t g, uint8_t b);
|
||||
|
||||
#endif /* "INC_STATUS_LED_H" */
|
||||
359
Software/Core/Inc/stm32f3xx_hal_conf.h
Normal file
359
Software/Core/Inc/stm32f3xx_hal_conf.h
Normal file
@ -0,0 +1,359 @@
|
||||
/* USER CODE BEGIN Header */
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f3xx_hal_conf.h
|
||||
* @brief HAL configuration file.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2016 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
/* USER CODE END Header */
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef __STM32F3xx_HAL_CONF_H
|
||||
#define __STM32F3xx_HAL_CONF_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
|
||||
/* ########################## Module Selection ############################## */
|
||||
/**
|
||||
* @brief This is the list of modules to be used in the HAL driver
|
||||
*/
|
||||
|
||||
#define HAL_MODULE_ENABLED
|
||||
/*#define HAL_ADC_MODULE_ENABLED */
|
||||
/*#define HAL_CRYP_MODULE_ENABLED */
|
||||
#define HAL_CAN_MODULE_ENABLED
|
||||
/*#define HAL_CEC_MODULE_ENABLED */
|
||||
/*#define HAL_NAND_MODULE_ENABLED */
|
||||
/*#define HAL_NOR_MODULE_ENABLED */
|
||||
/*#define HAL_PCCARD_MODULE_ENABLED */
|
||||
/*#define HAL_SRAM_MODULE_ENABLED */
|
||||
/*#define HAL_HRTIM_MODULE_ENABLED */
|
||||
/*#define HAL_OPAMP_MODULE_ENABLED */
|
||||
/*#define HAL_SDADC_MODULE_ENABLED */
|
||||
/*#define HAL_TSC_MODULE_ENABLED */
|
||||
/*#define HAL_COMP_MODULE_ENABLED */
|
||||
/*#define HAL_CRC_MODULE_ENABLED */
|
||||
/*#define HAL_CRYP_MODULE_ENABLED */
|
||||
/*#define HAL_DAC_MODULE_ENABLED */
|
||||
/*#define HAL_I2S_MODULE_ENABLED */
|
||||
/*#define HAL_IWDG_MODULE_ENABLED */
|
||||
/*#define HAL_LCD_MODULE_ENABLED */
|
||||
/*#define HAL_LPTIM_MODULE_ENABLED */
|
||||
/*#define HAL_RNG_MODULE_ENABLED */
|
||||
/*#define HAL_RTC_MODULE_ENABLED */
|
||||
#define HAL_SPI_MODULE_ENABLED
|
||||
#define HAL_TIM_MODULE_ENABLED
|
||||
/*#define HAL_UART_MODULE_ENABLED */
|
||||
/*#define HAL_USART_MODULE_ENABLED */
|
||||
/*#define HAL_IRDA_MODULE_ENABLED */
|
||||
/*#define HAL_SMARTCARD_MODULE_ENABLED */
|
||||
/*#define HAL_SMBUS_MODULE_ENABLED */
|
||||
/*#define HAL_WWDG_MODULE_ENABLED */
|
||||
/*#define HAL_PCD_MODULE_ENABLED */
|
||||
#define HAL_GPIO_MODULE_ENABLED
|
||||
#define HAL_EXTI_MODULE_ENABLED
|
||||
/* #define HAL_CAN_LEGACY_MODULE_ENABLED */
|
||||
#define HAL_DMA_MODULE_ENABLED
|
||||
#define HAL_RCC_MODULE_ENABLED
|
||||
#define HAL_FLASH_MODULE_ENABLED
|
||||
#define HAL_PWR_MODULE_ENABLED
|
||||
#define HAL_CORTEX_MODULE_ENABLED
|
||||
#define HAL_I2C_MODULE_ENABLED
|
||||
/* ########################## HSE/HSI Values adaptation ##################### */
|
||||
/**
|
||||
* @brief Adjust the value of External High Speed oscillator (HSE) used in your application.
|
||||
* This value is used by the RCC HAL module to compute the system frequency
|
||||
* (when HSE is used as system clock source, directly or through the PLL).
|
||||
*/
|
||||
#if !defined (HSE_VALUE)
|
||||
#define HSE_VALUE ((uint32_t)16000000) /*!< Value of the External oscillator in Hz */
|
||||
#endif /* HSE_VALUE */
|
||||
|
||||
/**
|
||||
* @brief In the following line adjust the External High Speed oscillator (HSE) Startup
|
||||
* Timeout value
|
||||
*/
|
||||
#if !defined (HSE_STARTUP_TIMEOUT)
|
||||
#define HSE_STARTUP_TIMEOUT ((uint32_t)100) /*!< Time out for HSE start up, in ms */
|
||||
#endif /* HSE_STARTUP_TIMEOUT */
|
||||
|
||||
/**
|
||||
* @brief Internal High Speed oscillator (HSI) value.
|
||||
* This value is used by the RCC HAL module to compute the system frequency
|
||||
* (when HSI is used as system clock source, directly or through the PLL).
|
||||
*/
|
||||
#if !defined (HSI_VALUE)
|
||||
#define HSI_VALUE ((uint32_t)8000000) /*!< Value of the Internal oscillator in Hz*/
|
||||
#endif /* HSI_VALUE */
|
||||
|
||||
/**
|
||||
* @brief In the following line adjust the Internal High Speed oscillator (HSI) Startup
|
||||
* Timeout value
|
||||
*/
|
||||
#if !defined (HSI_STARTUP_TIMEOUT)
|
||||
#define HSI_STARTUP_TIMEOUT ((uint32_t)5000) /*!< Time out for HSI start up */
|
||||
#endif /* HSI_STARTUP_TIMEOUT */
|
||||
|
||||
/**
|
||||
* @brief Internal Low Speed oscillator (LSI) value.
|
||||
*/
|
||||
#if !defined (LSI_VALUE)
|
||||
#define LSI_VALUE ((uint32_t)40000)
|
||||
#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz
|
||||
The real value may vary depending on the variations
|
||||
in voltage and temperature. */
|
||||
/**
|
||||
* @brief External Low Speed oscillator (LSE) value.
|
||||
*/
|
||||
#if !defined (LSE_VALUE)
|
||||
#define LSE_VALUE ((uint32_t)32768) /*!< Value of the External Low Speed oscillator in Hz */
|
||||
#endif /* LSE_VALUE */
|
||||
|
||||
/**
|
||||
* @brief Time out for LSE start up value in ms.
|
||||
*/
|
||||
#if !defined (LSE_STARTUP_TIMEOUT)
|
||||
#define LSE_STARTUP_TIMEOUT ((uint32_t)5000) /*!< Time out for LSE start up, in ms */
|
||||
#endif /* LSE_STARTUP_TIMEOUT */
|
||||
|
||||
/**
|
||||
* @brief External clock source for I2S peripheral
|
||||
* This value is used by the I2S HAL module to compute the I2S clock source
|
||||
* frequency, this source is inserted directly through I2S_CKIN pad.
|
||||
* - External clock generated through external PLL component on EVAL 303 (based on MCO or crystal)
|
||||
* - External clock not generated on EVAL 373
|
||||
*/
|
||||
#if !defined (EXTERNAL_CLOCK_VALUE)
|
||||
#define EXTERNAL_CLOCK_VALUE ((uint32_t)8000000) /*!< Value of the External oscillator in Hz*/
|
||||
#endif /* EXTERNAL_CLOCK_VALUE */
|
||||
|
||||
/* Tip: To avoid modifying this file each time you need to use different HSE,
|
||||
=== you can define the HSE value in your toolchain compiler preprocessor. */
|
||||
|
||||
/* ########################### System Configuration ######################### */
|
||||
/**
|
||||
* @brief This is the HAL system configuration section
|
||||
*/
|
||||
|
||||
#define VDD_VALUE ((uint32_t)3300) /*!< Value of VDD in mv */
|
||||
#define TICK_INT_PRIORITY ((uint32_t)15) /*!< tick interrupt priority (lowest by default) */
|
||||
#define USE_RTOS 0
|
||||
#define PREFETCH_ENABLE 1
|
||||
#define INSTRUCTION_CACHE_ENABLE 0
|
||||
#define DATA_CACHE_ENABLE 0
|
||||
#define USE_SPI_CRC 0U
|
||||
|
||||
#define USE_HAL_ADC_REGISTER_CALLBACKS 0U /* ADC register callback disabled */
|
||||
#define USE_HAL_CAN_REGISTER_CALLBACKS 0U /* CAN register callback disabled */
|
||||
#define USE_HAL_COMP_REGISTER_CALLBACKS 0U /* COMP register callback disabled */
|
||||
#define USE_HAL_CEC_REGISTER_CALLBACKS 0U /* CEC register callback disabled */
|
||||
#define USE_HAL_DAC_REGISTER_CALLBACKS 0U /* DAC register callback disabled */
|
||||
#define USE_HAL_SRAM_REGISTER_CALLBACKS 0U /* SRAM register callback disabled */
|
||||
#define USE_HAL_SMBUS_REGISTER_CALLBACKS 0U /* SMBUS register callback disabled */
|
||||
#define USE_HAL_NAND_REGISTER_CALLBACKS 0U /* NAND register callback disabled */
|
||||
#define USE_HAL_NOR_REGISTER_CALLBACKS 0U /* NOR register callback disabled */
|
||||
#define USE_HAL_PCCARD_REGISTER_CALLBACKS 0U /* PCCARD register callback disabled */
|
||||
#define USE_HAL_HRTIM_REGISTER_CALLBACKS 0U /* HRTIM register callback disabled */
|
||||
#define USE_HAL_I2C_REGISTER_CALLBACKS 0U /* I2C register callback disabled */
|
||||
#define USE_HAL_UART_REGISTER_CALLBACKS 0U /* UART register callback disabled */
|
||||
#define USE_HAL_USART_REGISTER_CALLBACKS 0U /* USART register callback disabled */
|
||||
#define USE_HAL_IRDA_REGISTER_CALLBACKS 0U /* IRDA register callback disabled */
|
||||
#define USE_HAL_SMARTCARD_REGISTER_CALLBACKS 0U /* SMARTCARD register callback disabled */
|
||||
#define USE_HAL_WWDG_REGISTER_CALLBACKS 0U /* WWDG register callback disabled */
|
||||
#define USE_HAL_OPAMP_REGISTER_CALLBACKS 0U /* OPAMP register callback disabled */
|
||||
#define USE_HAL_RTC_REGISTER_CALLBACKS 0U /* RTC register callback disabled */
|
||||
#define USE_HAL_SPI_REGISTER_CALLBACKS 0U /* SPI register callback disabled */
|
||||
#define USE_HAL_I2S_REGISTER_CALLBACKS 0U /* I2S register callback disabled */
|
||||
#define USE_HAL_TIM_REGISTER_CALLBACKS 0U /* TIM register callback disabled */
|
||||
#define USE_HAL_TSC_REGISTER_CALLBACKS 0U /* TSC register callback disabled */
|
||||
#define USE_HAL_PCD_REGISTER_CALLBACKS 0U /* PCD register callback disabled */
|
||||
|
||||
/* ########################## Assert Selection ############################## */
|
||||
/**
|
||||
* @brief Uncomment the line below to expanse the "assert_param" macro in the
|
||||
* HAL drivers code
|
||||
*/
|
||||
/* #define USE_FULL_ASSERT 1U */
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
/**
|
||||
* @brief Include module's header file
|
||||
*/
|
||||
|
||||
#ifdef HAL_RCC_MODULE_ENABLED
|
||||
#include "stm32f3xx_hal_rcc.h"
|
||||
#endif /* HAL_RCC_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_GPIO_MODULE_ENABLED
|
||||
#include "stm32f3xx_hal_gpio.h"
|
||||
#endif /* HAL_GPIO_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_EXTI_MODULE_ENABLED
|
||||
#include "stm32f3xx_hal_exti.h"
|
||||
#endif /* HAL_EXTI_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_DMA_MODULE_ENABLED
|
||||
#include "stm32f3xx_hal_dma.h"
|
||||
#endif /* HAL_DMA_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_CORTEX_MODULE_ENABLED
|
||||
#include "stm32f3xx_hal_cortex.h"
|
||||
#endif /* HAL_CORTEX_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_ADC_MODULE_ENABLED
|
||||
#include "stm32f3xx_hal_adc.h"
|
||||
#endif /* HAL_ADC_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_CAN_MODULE_ENABLED
|
||||
#include "stm32f3xx_hal_can.h"
|
||||
#endif /* HAL_CAN_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_CAN_LEGACY_MODULE_ENABLED
|
||||
#include "stm32f3xx_hal_can_legacy.h"
|
||||
#endif /* HAL_CAN_LEGACY_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_CEC_MODULE_ENABLED
|
||||
#include "stm32f3xx_hal_cec.h"
|
||||
#endif /* HAL_CEC_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_COMP_MODULE_ENABLED
|
||||
#include "stm32f3xx_hal_comp.h"
|
||||
#endif /* HAL_COMP_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_CRC_MODULE_ENABLED
|
||||
#include "stm32f3xx_hal_crc.h"
|
||||
#endif /* HAL_CRC_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_DAC_MODULE_ENABLED
|
||||
#include "stm32f3xx_hal_dac.h"
|
||||
#endif /* HAL_DAC_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_FLASH_MODULE_ENABLED
|
||||
#include "stm32f3xx_hal_flash.h"
|
||||
#endif /* HAL_FLASH_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_SRAM_MODULE_ENABLED
|
||||
#include "stm32f3xx_hal_sram.h"
|
||||
#endif /* HAL_SRAM_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_NOR_MODULE_ENABLED
|
||||
#include "stm32f3xx_hal_nor.h"
|
||||
#endif /* HAL_NOR_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_NAND_MODULE_ENABLED
|
||||
#include "stm32f3xx_hal_nand.h"
|
||||
#endif /* HAL_NAND_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_PCCARD_MODULE_ENABLED
|
||||
#include "stm32f3xx_hal_pccard.h"
|
||||
#endif /* HAL_PCCARD_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_HRTIM_MODULE_ENABLED
|
||||
#include "stm32f3xx_hal_hrtim.h"
|
||||
#endif /* HAL_HRTIM_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_I2C_MODULE_ENABLED
|
||||
#include "stm32f3xx_hal_i2c.h"
|
||||
#endif /* HAL_I2C_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_I2S_MODULE_ENABLED
|
||||
#include "stm32f3xx_hal_i2s.h"
|
||||
#endif /* HAL_I2S_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_IRDA_MODULE_ENABLED
|
||||
#include "stm32f3xx_hal_irda.h"
|
||||
#endif /* HAL_IRDA_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_IWDG_MODULE_ENABLED
|
||||
#include "stm32f3xx_hal_iwdg.h"
|
||||
#endif /* HAL_IWDG_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_OPAMP_MODULE_ENABLED
|
||||
#include "stm32f3xx_hal_opamp.h"
|
||||
#endif /* HAL_OPAMP_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_PCD_MODULE_ENABLED
|
||||
#include "stm32f3xx_hal_pcd.h"
|
||||
#endif /* HAL_PCD_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_PWR_MODULE_ENABLED
|
||||
#include "stm32f3xx_hal_pwr.h"
|
||||
#endif /* HAL_PWR_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_RTC_MODULE_ENABLED
|
||||
#include "stm32f3xx_hal_rtc.h"
|
||||
#endif /* HAL_RTC_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_SDADC_MODULE_ENABLED
|
||||
#include "stm32f3xx_hal_sdadc.h"
|
||||
#endif /* HAL_SDADC_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_SMARTCARD_MODULE_ENABLED
|
||||
#include "stm32f3xx_hal_smartcard.h"
|
||||
#endif /* HAL_SMARTCARD_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_SMBUS_MODULE_ENABLED
|
||||
#include "stm32f3xx_hal_smbus.h"
|
||||
#endif /* HAL_SMBUS_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_SPI_MODULE_ENABLED
|
||||
#include "stm32f3xx_hal_spi.h"
|
||||
#endif /* HAL_SPI_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_TIM_MODULE_ENABLED
|
||||
#include "stm32f3xx_hal_tim.h"
|
||||
#endif /* HAL_TIM_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_TSC_MODULE_ENABLED
|
||||
#include "stm32f3xx_hal_tsc.h"
|
||||
#endif /* HAL_TSC_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_UART_MODULE_ENABLED
|
||||
#include "stm32f3xx_hal_uart.h"
|
||||
#endif /* HAL_UART_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_USART_MODULE_ENABLED
|
||||
#include "stm32f3xx_hal_usart.h"
|
||||
#endif /* HAL_USART_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_WWDG_MODULE_ENABLED
|
||||
#include "stm32f3xx_hal_wwdg.h"
|
||||
#endif /* HAL_WWDG_MODULE_ENABLED */
|
||||
|
||||
/* Exported macro ------------------------------------------------------------*/
|
||||
#ifdef USE_FULL_ASSERT
|
||||
/**
|
||||
* @brief The assert_param macro is used for function's parameters check.
|
||||
* @param expr If expr is false, it calls assert_failed function
|
||||
* which reports the name of the source file and the source
|
||||
* line number of the call that failed.
|
||||
* If expr is true, it returns no value.
|
||||
* @retval None
|
||||
*/
|
||||
#define assert_param(expr) ((expr) ? (void)0U : assert_failed((uint8_t *)__FILE__, __LINE__))
|
||||
/* Exported functions ------------------------------------------------------- */
|
||||
void assert_failed(uint8_t* file, uint32_t line);
|
||||
#else
|
||||
#define assert_param(expr) ((void)0U)
|
||||
#endif /* USE_FULL_ASSERT */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __STM32F3xx_HAL_CONF_H */
|
||||
68
Software/Core/Inc/stm32f3xx_it.h
Normal file
68
Software/Core/Inc/stm32f3xx_it.h
Normal file
@ -0,0 +1,68 @@
|
||||
/* USER CODE BEGIN Header */
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f3xx_it.h
|
||||
* @brief This file contains the headers of the interrupt handlers.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2024 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
/* USER CODE END Header */
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef __STM32F3xx_IT_H
|
||||
#define __STM32F3xx_IT_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Private includes ----------------------------------------------------------*/
|
||||
/* USER CODE BEGIN Includes */
|
||||
|
||||
/* USER CODE END Includes */
|
||||
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
/* USER CODE BEGIN ET */
|
||||
|
||||
/* USER CODE END ET */
|
||||
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
/* USER CODE BEGIN EC */
|
||||
|
||||
/* USER CODE END EC */
|
||||
|
||||
/* Exported macro ------------------------------------------------------------*/
|
||||
/* USER CODE BEGIN EM */
|
||||
|
||||
/* USER CODE END EM */
|
||||
|
||||
/* Exported functions prototypes ---------------------------------------------*/
|
||||
void NMI_Handler(void);
|
||||
void HardFault_Handler(void);
|
||||
void MemManage_Handler(void);
|
||||
void BusFault_Handler(void);
|
||||
void UsageFault_Handler(void);
|
||||
void SVC_Handler(void);
|
||||
void DebugMon_Handler(void);
|
||||
void PendSV_Handler(void);
|
||||
void SysTick_Handler(void);
|
||||
void USB_LP_CAN_RX0_IRQHandler(void);
|
||||
void CAN_RX1_IRQHandler(void);
|
||||
/* USER CODE BEGIN EFP */
|
||||
|
||||
/* USER CODE END EFP */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __STM32F3xx_IT_H */
|
||||
33
Software/Core/Lib/can-halal/README.md
Normal file
33
Software/Core/Lib/can-halal/README.md
Normal file
@ -0,0 +1,33 @@
|
||||
# FaSTTUBe CAN HAL Abstraction Layer
|
||||
|
||||
This repository contains an abstraction layer to provide a simplified & unified
|
||||
interface to the STM32 bxCAN and FDCAN peripherals.
|
||||
|
||||
## Installation
|
||||
|
||||
Simply add the repository to your `Core/Lib` directory. You can also add it as a
|
||||
git submodule:
|
||||
|
||||
mkdir -p Core/Lib
|
||||
cd Core/Lib
|
||||
git submodule add ssh://git@git.fasttube.de:313/FaSTTUBe/can-halal.git
|
||||
|
||||
The library needs to be told what STM family you're using, so make sure one of
|
||||
the following symbols is defined when `can-halal.c` is compiled or `can-halal.h`
|
||||
is included:
|
||||
|
||||
- `STM32F3`
|
||||
- `STM32H7`
|
||||
|
||||
When using the FDCAN peripheral (H7 series), you also need to define
|
||||
`FTCAN_NUM_FILTERS` (and set it to the value of "Std Filters Nbr" you configured
|
||||
in your `.ioc`).
|
||||
|
||||
## Usage
|
||||
|
||||
1. Include `can-halal.h`
|
||||
2. Call `ftcan_init()` with the appropriate handle
|
||||
3. Call `ftcan_add_filter()` with all your filters
|
||||
4. To transmit messages, call `ftcan_transmit()`
|
||||
5. When a message is received, `ftcan_msg_received_cb()` is called. It has a
|
||||
default empty implementation, which you can simply override.
|
||||
273
Software/Core/Lib/can-halal/can-halal.c
Normal file
273
Software/Core/Lib/can-halal/can-halal.c
Normal file
@ -0,0 +1,273 @@
|
||||
#include "can-halal.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#if defined(FTCAN_IS_BXCAN)
|
||||
static CAN_HandleTypeDef *hcan;
|
||||
|
||||
HAL_StatusTypeDef ftcan_init(CAN_HandleTypeDef *handle) {
|
||||
hcan = handle;
|
||||
|
||||
HAL_StatusTypeDef status =
|
||||
HAL_CAN_ActivateNotification(hcan, CAN_IT_RX_FIFO0_MSG_PENDING);
|
||||
if (status != HAL_OK) {
|
||||
return status;
|
||||
}
|
||||
|
||||
return HAL_CAN_Start(hcan);
|
||||
}
|
||||
|
||||
HAL_StatusTypeDef ftcan_transmit(uint16_t id, const uint8_t *data,
|
||||
size_t datalen) {
|
||||
static CAN_TxHeaderTypeDef header;
|
||||
header.StdId = id;
|
||||
header.IDE = CAN_ID_STD;
|
||||
header.RTR = CAN_RTR_DATA;
|
||||
header.DLC = datalen;
|
||||
uint32_t mailbox;
|
||||
return HAL_CAN_AddTxMessage(hcan, &header, data, &mailbox);
|
||||
}
|
||||
|
||||
HAL_StatusTypeDef ftcan_add_filter(uint16_t id, uint16_t mask) {
|
||||
static uint32_t next_filter_no = 0;
|
||||
static CAN_FilterTypeDef filter;
|
||||
if (next_filter_no % 2 == 0) {
|
||||
filter.FilterIdHigh = id << 5;
|
||||
filter.FilterMaskIdHigh = mask << 5;
|
||||
filter.FilterIdLow = id << 5;
|
||||
filter.FilterMaskIdLow = mask << 5;
|
||||
} else {
|
||||
// Leave high filter untouched from the last configuration
|
||||
filter.FilterIdLow = id << 5;
|
||||
filter.FilterMaskIdLow = mask << 5;
|
||||
}
|
||||
filter.FilterFIFOAssignment = CAN_FILTER_FIFO0;
|
||||
filter.FilterBank = next_filter_no / 2;
|
||||
if (filter.FilterBank > FTCAN_NUM_FILTERS + 1) {
|
||||
return HAL_ERROR;
|
||||
}
|
||||
filter.FilterMode = CAN_FILTERMODE_IDMASK;
|
||||
filter.FilterScale = CAN_FILTERSCALE_16BIT;
|
||||
filter.FilterActivation = CAN_FILTER_ENABLE;
|
||||
|
||||
// Disable slave filters
|
||||
// TODO: Some STM32 have multiple CAN peripherals, and one uses the slave
|
||||
// filter bank
|
||||
filter.SlaveStartFilterBank = FTCAN_NUM_FILTERS;
|
||||
|
||||
HAL_StatusTypeDef status = HAL_CAN_ConfigFilter(hcan, &filter);
|
||||
if (status == HAL_OK) {
|
||||
next_filter_no++;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *handle) {
|
||||
if (handle != hcan) {
|
||||
return;
|
||||
}
|
||||
CAN_RxHeaderTypeDef header;
|
||||
uint8_t data[8];
|
||||
if (HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &header, data) != HAL_OK) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (header.IDE != CAN_ID_STD) {
|
||||
return;
|
||||
}
|
||||
|
||||
ftcan_msg_received_cb(header.StdId, header.DLC, data);
|
||||
}
|
||||
#elif defined(FTCAN_IS_FDCAN)
|
||||
static FDCAN_HandleTypeDef *hcan;
|
||||
|
||||
HAL_StatusTypeDef ftcan_init(FDCAN_HandleTypeDef *handle) {
|
||||
hcan = handle;
|
||||
|
||||
HAL_StatusTypeDef status =
|
||||
HAL_FDCAN_ActivateNotification(hcan, FDCAN_IT_RX_FIFO0_NEW_MESSAGE, 0);
|
||||
if (status != HAL_OK) {
|
||||
return status;
|
||||
}
|
||||
// Reject non-matching messages
|
||||
status =
|
||||
HAL_FDCAN_ConfigGlobalFilter(hcan, FDCAN_REJECT, FDCAN_REJECT,
|
||||
FDCAN_REJECT_REMOTE, FDCAN_REJECT_REMOTE);
|
||||
if (status != HAL_OK) {
|
||||
return status;
|
||||
}
|
||||
|
||||
return HAL_FDCAN_Start(hcan);
|
||||
}
|
||||
|
||||
HAL_StatusTypeDef ftcan_transmit(uint16_t id, const uint8_t *data,
|
||||
size_t datalen) {
|
||||
static FDCAN_TxHeaderTypeDef header;
|
||||
header.Identifier = id;
|
||||
header.IdType = FDCAN_STANDARD_ID;
|
||||
header.TxFrameType = FDCAN_DATA_FRAME;
|
||||
switch (datalen) {
|
||||
case 0:
|
||||
header.DataLength = FDCAN_DLC_BYTES_0;
|
||||
break;
|
||||
case 1:
|
||||
header.DataLength = FDCAN_DLC_BYTES_1;
|
||||
break;
|
||||
case 2:
|
||||
header.DataLength = FDCAN_DLC_BYTES_2;
|
||||
break;
|
||||
case 3:
|
||||
header.DataLength = FDCAN_DLC_BYTES_3;
|
||||
break;
|
||||
case 4:
|
||||
header.DataLength = FDCAN_DLC_BYTES_4;
|
||||
break;
|
||||
case 5:
|
||||
header.DataLength = FDCAN_DLC_BYTES_5;
|
||||
break;
|
||||
case 6:
|
||||
header.DataLength = FDCAN_DLC_BYTES_6;
|
||||
break;
|
||||
case 7:
|
||||
header.DataLength = FDCAN_DLC_BYTES_7;
|
||||
break;
|
||||
case 8:
|
||||
default:
|
||||
header.DataLength = FDCAN_DLC_BYTES_8;
|
||||
break;
|
||||
}
|
||||
header.ErrorStateIndicator = FDCAN_ESI_PASSIVE;
|
||||
header.BitRateSwitch = FDCAN_BRS_OFF;
|
||||
header.FDFormat = FDCAN_CLASSIC_CAN;
|
||||
header.TxEventFifoControl = FDCAN_NO_TX_EVENTS;
|
||||
|
||||
// HAL_FDCAN_AddMessageToTxFifoQ doesn't modify the data, but it's not marked
|
||||
// as const for some reason.
|
||||
uint8_t *data_nonconst = (uint8_t *)data;
|
||||
return HAL_FDCAN_AddMessageToTxFifoQ(hcan, &header, data_nonconst);
|
||||
}
|
||||
|
||||
HAL_StatusTypeDef ftcan_add_filter(uint16_t id, uint16_t mask) {
|
||||
static uint32_t next_filter_no = 0;
|
||||
static FDCAN_FilterTypeDef filter;
|
||||
filter.IdType = FDCAN_STANDARD_ID;
|
||||
filter.FilterIndex = next_filter_no;
|
||||
if (filter.FilterIndex > FTCAN_NUM_FILTERS + 1) {
|
||||
return HAL_ERROR;
|
||||
}
|
||||
filter.FilterType = FDCAN_FILTER_MASK;
|
||||
filter.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
|
||||
filter.FilterID1 = id;
|
||||
filter.FilterID2 = mask;
|
||||
|
||||
HAL_StatusTypeDef status = HAL_FDCAN_ConfigFilter(hcan, &filter);
|
||||
if (status == HAL_OK) {
|
||||
next_filter_no++;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
void HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef *handle,
|
||||
uint32_t RxFifo0ITs) {
|
||||
if (handle != hcan || (RxFifo0ITs & FDCAN_IT_RX_FIFO0_NEW_MESSAGE) == RESET) {
|
||||
return;
|
||||
}
|
||||
|
||||
static FDCAN_RxHeaderTypeDef header;
|
||||
static uint8_t data[8];
|
||||
if (HAL_FDCAN_GetRxMessage(hcan, FDCAN_RX_FIFO0, &header, data) != HAL_OK) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (header.FDFormat != FDCAN_CLASSIC_CAN ||
|
||||
header.RxFrameType != FDCAN_DATA_FRAME ||
|
||||
header.IdType != FDCAN_STANDARD_ID) {
|
||||
return;
|
||||
}
|
||||
|
||||
size_t datalen;
|
||||
switch (header.DataLength) {
|
||||
case FDCAN_DLC_BYTES_0:
|
||||
datalen = 0;
|
||||
break;
|
||||
case FDCAN_DLC_BYTES_1:
|
||||
datalen = 1;
|
||||
break;
|
||||
case FDCAN_DLC_BYTES_2:
|
||||
datalen = 2;
|
||||
break;
|
||||
case FDCAN_DLC_BYTES_3:
|
||||
datalen = 3;
|
||||
break;
|
||||
case FDCAN_DLC_BYTES_4:
|
||||
datalen = 4;
|
||||
break;
|
||||
case FDCAN_DLC_BYTES_5:
|
||||
datalen = 5;
|
||||
break;
|
||||
case FDCAN_DLC_BYTES_6:
|
||||
datalen = 6;
|
||||
break;
|
||||
case FDCAN_DLC_BYTES_7:
|
||||
datalen = 7;
|
||||
break;
|
||||
case FDCAN_DLC_BYTES_8:
|
||||
datalen = 8;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
ftcan_msg_received_cb(header.Identifier, datalen, data);
|
||||
}
|
||||
#endif
|
||||
|
||||
__weak void ftcan_msg_received_cb(uint16_t id, size_t datalen,
|
||||
const uint8_t *data) {}
|
||||
|
||||
uint64_t ftcan_unmarshal_unsigned(const uint8_t **data_ptr, size_t num_bytes) {
|
||||
if (num_bytes > 8) {
|
||||
num_bytes = 8;
|
||||
}
|
||||
|
||||
const uint8_t *data = *data_ptr;
|
||||
uint64_t result = 0;
|
||||
for (size_t i = 0; i < num_bytes; i++) {
|
||||
result <<= 8;
|
||||
result |= data[i];
|
||||
}
|
||||
*data_ptr += num_bytes;
|
||||
return result;
|
||||
}
|
||||
|
||||
int64_t ftcan_unmarshal_signed(const uint8_t **data_ptr, size_t num_bytes) {
|
||||
if (num_bytes > 8) {
|
||||
num_bytes = 8;
|
||||
}
|
||||
|
||||
uint64_t result_unsigned = ftcan_unmarshal_unsigned(data_ptr, num_bytes);
|
||||
// Sign extend by shifting left, then copying to a signed int and shifting
|
||||
// back to the right
|
||||
size_t diff_to_64 = 64 - num_bytes * 8;
|
||||
result_unsigned <<= diff_to_64;
|
||||
int64_t result;
|
||||
memcpy(&result, &result_unsigned, 8);
|
||||
return result >> diff_to_64;
|
||||
}
|
||||
|
||||
uint8_t *ftcan_marshal_unsigned(uint8_t *data, uint64_t val, size_t num_bytes) {
|
||||
if (num_bytes > 8) {
|
||||
num_bytes = 8;
|
||||
}
|
||||
|
||||
for (int i = num_bytes - 1; i >= 0; i--) {
|
||||
data[i] = val & 0xFF;
|
||||
val >>= 8;
|
||||
}
|
||||
|
||||
return data + num_bytes;
|
||||
}
|
||||
|
||||
uint8_t *ftcan_marshal_signed(uint8_t *data, int64_t val, size_t num_bytes) {
|
||||
return ftcan_marshal_unsigned(data, val, num_bytes);
|
||||
}
|
||||
64
Software/Core/Lib/can-halal/can-halal.h
Normal file
64
Software/Core/Lib/can-halal/can-halal.h
Normal file
@ -0,0 +1,64 @@
|
||||
#ifndef CAN_HALAL_H
|
||||
#define CAN_HALAL_H
|
||||
|
||||
// Define family macros if none are defined and we recognize a chip macro
|
||||
#if !defined(STM32F3) && !defined(STM32H7)
|
||||
#if defined(STM32F302x6) || defined(STM32F302x8) || defined(STM32F302xB) || \
|
||||
defined(STM32F302xC)
|
||||
#define STM32F3
|
||||
#endif
|
||||
#if defined(STM32H7A3xx)
|
||||
#define STM32H7
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(STM32F3)
|
||||
#include "stm32f3xx_hal.h"
|
||||
#define FTCAN_IS_BXCAN
|
||||
#define FTCAN_NUM_FILTERS 13
|
||||
#elif defined(STM32H7)
|
||||
#include "stm32h7xx_hal.h"
|
||||
#define FTCAN_IS_FDCAN
|
||||
#ifndef FTCAN_NUM_FILTERS
|
||||
#error "Please configure the number of filters in CubeMX, and then add a compiler define for FTCAN_NUM_FILTERS"
|
||||
#endif
|
||||
#else
|
||||
#error "Couldn't detect STM family"
|
||||
#endif
|
||||
|
||||
#if defined(FTCAN_IS_BXCAN)
|
||||
HAL_StatusTypeDef ftcan_init(CAN_HandleTypeDef *handle);
|
||||
#elif defined(FTCAN_IS_FDCAN)
|
||||
HAL_StatusTypeDef ftcan_init(FDCAN_HandleTypeDef *handle);
|
||||
#else
|
||||
#error "Unknown CAN peripheral"
|
||||
#endif
|
||||
|
||||
HAL_StatusTypeDef ftcan_transmit(uint16_t id, const uint8_t *data,
|
||||
size_t datalen);
|
||||
|
||||
HAL_StatusTypeDef ftcan_add_filter(uint16_t id, uint16_t mask);
|
||||
|
||||
/**
|
||||
* Define this function to be notified of incoming CAN messages
|
||||
*/
|
||||
void ftcan_msg_received_cb(uint16_t id, size_t datalen, const uint8_t *data);
|
||||
|
||||
/**
|
||||
* Read num_bytes bytes from a message (unmarshalled network byte order). The
|
||||
* msg pointer is advanced by the corresponding number of bytes.
|
||||
*
|
||||
* Both methods return a 64-bit integer, but you can safely cast it to a smaller
|
||||
* integer type.
|
||||
*/
|
||||
uint64_t ftcan_unmarshal_unsigned(const uint8_t **data, size_t num_bytes);
|
||||
int64_t ftcan_unmarshal_signed(const uint8_t **data, size_t num_bytes);
|
||||
|
||||
/**
|
||||
* Write num_bytes to a message (marshalled in network byte order). The pointer
|
||||
* is advanced by the corresponding number of bytes and returned.
|
||||
*/
|
||||
uint8_t *ftcan_marshal_unsigned(uint8_t *data, uint64_t val, size_t num_bytes);
|
||||
uint8_t *ftcan_marshal_signed(uint8_t *data, int64_t val, size_t num_bytes);
|
||||
|
||||
#endif // CAN_HALAL_H
|
||||
243
Software/Core/Src/ADBMS_Abstraction.c
Executable file
243
Software/Core/Src/ADBMS_Abstraction.c
Executable file
@ -0,0 +1,243 @@
|
||||
/*
|
||||
* ADBMS_Abstraction.c
|
||||
*
|
||||
* Created on: 14.07.2022
|
||||
* Author: max
|
||||
*/
|
||||
|
||||
#include "ADBMS_Abstraction.h"
|
||||
#include "ADBMS_CMD_MAKROS.h"
|
||||
#include "ADBMS_LL_Driver.h"
|
||||
#include <stddef.h>
|
||||
|
||||
uint8 numberofcells;
|
||||
uint8 numberofauxchannels;
|
||||
|
||||
#define CHECK_RETURN(x) \
|
||||
{ \
|
||||
uint8 status = x; \
|
||||
if (status != 0) \
|
||||
return status; \
|
||||
}
|
||||
|
||||
uint8 amsReset() {
|
||||
amsWakeUp();
|
||||
readCMD(SRST, NULL, 0);
|
||||
mcuDelay(10);
|
||||
amsWakeUp();
|
||||
amsStopBalancing();
|
||||
amsConfigOverUnderVoltage(DEFAULT_OV, DEFAULT_UV);
|
||||
|
||||
const uint8 buffer[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
|
||||
|
||||
CHECK_RETURN(writeCMD(CLRFLAG, buffer, 6)); //clear flags,
|
||||
CHECK_RETURN(writeCMD(CLOVUV, buffer, 6)); //OVUV flags
|
||||
CHECK_RETURN(writeCMD(ADCV | ADCV_CONT | ADCV_RD, NULL, 0)); //start continuous cell voltage measurement with redundancy
|
||||
CHECK_RETURN(writeCMD(ADAX | ADAX_CONV_ALL, NULL, 0)); //start aux measurement
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8 initAMS(SPI_HandleTypeDef* hspi, uint8 numofcells, uint8 numofaux) {
|
||||
adbmsDriverInit(hspi);
|
||||
numberofcells = numofcells;
|
||||
numberofauxchannels = numofaux;
|
||||
|
||||
return amsReset();
|
||||
}
|
||||
|
||||
uint8 amsWakeUp() {
|
||||
uint8 buf[6];
|
||||
return readCMD(RDCFGA, buf, 6);
|
||||
}
|
||||
|
||||
uint8 amsCellMeasurement(Cell_Module* module) {
|
||||
#warning check conversion counter to ensure that continous conversion has not been stopped
|
||||
#warning check for OW conditions: ADSV | ADSV_OW_0 / ADSV_OW_1
|
||||
return amsReadCellVoltages(module);
|
||||
}
|
||||
|
||||
uint8 amsConfigCellMeasurement(uint8 numberofChannels) {
|
||||
numberofcells = numberofChannels;
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8 amsAuxAndStatusMeasurement(Cell_Module* module) {
|
||||
uint8 rxbuf[AUX_GROUP_A_SIZE] = {};
|
||||
|
||||
CHECK_RETURN(readCMD(RDSTATC, rxbuf, STATUS_GROUP_C_SIZE));
|
||||
|
||||
module->status.CS_FLT = rxbuf[0] | (rxbuf[1] << 8);
|
||||
module->status.CCTS = rxbuf[2] | (rxbuf[3] << 8);
|
||||
module->status.VA_OV = (rxbuf[4] >> 7) & 0x01;
|
||||
module->status.VA_UV = (rxbuf[4] >> 6) & 0x01;
|
||||
module->status.VD_OV = (rxbuf[4] >> 5) & 0x01;
|
||||
module->status.VD_UV = (rxbuf[4] >> 4) & 0x01;
|
||||
module->status.CED = (rxbuf[4] >> 3) & 0x01;
|
||||
module->status.CMED = (rxbuf[4] >> 2) & 0x01;
|
||||
module->status.SED = (rxbuf[4] >> 1) & 0x01;
|
||||
module->status.SMED = (rxbuf[4] >> 0) & 0x01;
|
||||
module->status.VDEL = (rxbuf[5] >> 7) & 0x01;
|
||||
module->status.VDE = (rxbuf[5] >> 6) & 0x01;
|
||||
module->status.COMPARE= (rxbuf[5] >> 5) & 0x01;
|
||||
module->status.SPIFLT = (rxbuf[5] >> 4) & 0x01;
|
||||
module->status.SLEEP = (rxbuf[5] >> 3) & 0x01;
|
||||
module->status.THSD = (rxbuf[5] >> 2) & 0x01;
|
||||
module->status.TMODCHK= (rxbuf[5] >> 1) & 0x01;
|
||||
module->status.OSCCHK = (rxbuf[5] >> 0) & 0x01;
|
||||
|
||||
if (pollCMD(PLAUX) == 0x0) { //TODO: check for SPI fault
|
||||
return 0; // aux ADC data not ready
|
||||
}
|
||||
|
||||
CHECK_RETURN(readCMD(RDAUXA, rxbuf, AUX_GROUP_A_SIZE));
|
||||
|
||||
module->auxVoltages[0] = mV_from_ADBMS6830(rxbuf[0] | (rxbuf[1] << 8));
|
||||
module->auxVoltages[1] = mV_from_ADBMS6830(rxbuf[2] | (rxbuf[3] << 8));
|
||||
module->auxVoltages[2] = mV_from_ADBMS6830(rxbuf[4] | (rxbuf[5] << 8));
|
||||
|
||||
CHECK_RETURN(readCMD(RDAUXB, rxbuf, AUX_GROUP_A_SIZE));
|
||||
|
||||
module->auxVoltages[3] = mV_from_ADBMS6830(rxbuf[0] | (rxbuf[1] << 8));
|
||||
module->auxVoltages[4] = mV_from_ADBMS6830(rxbuf[2] | (rxbuf[3] << 8));
|
||||
module->auxVoltages[5] = mV_from_ADBMS6830(rxbuf[4] | (rxbuf[5] << 8));
|
||||
|
||||
CHECK_RETURN(readCMD(RDAUXC, rxbuf, AUX_GROUP_A_SIZE));
|
||||
|
||||
module->auxVoltages[6] = mV_from_ADBMS6830(rxbuf[0] | (rxbuf[1] << 8));
|
||||
module->auxVoltages[7] = mV_from_ADBMS6830(rxbuf[2] | (rxbuf[3] << 8));
|
||||
module->auxVoltages[8] = mV_from_ADBMS6830(rxbuf[4] | (rxbuf[5] << 8));
|
||||
|
||||
CHECK_RETURN(readCMD(RDAUXD, rxbuf, AUX_GROUP_A_SIZE));
|
||||
|
||||
module->auxVoltages[9] = mV_from_ADBMS6830(rxbuf[0] | (rxbuf[1] << 8));
|
||||
|
||||
uint8 rxbuffer[STATUS_GROUP_A_SIZE];
|
||||
|
||||
CHECK_RETURN(readCMD(RDSTATA, rxbuffer, STATUS_GROUP_A_SIZE));
|
||||
|
||||
module->internalDieTemp = rxbuffer[2] | (rxbuffer[3] << 8);
|
||||
|
||||
CHECK_RETURN(readCMD(RDSTATB, rxbuffer, STATUS_GROUP_B_SIZE));
|
||||
module->digitalSupplyVoltage = mV_from_ADBMS6830(rxbuffer[0] | (rxbuffer[1] << 8));
|
||||
module->analogSupplyVoltage = mV_from_ADBMS6830(rxbuffer[2] | (rxbuffer[3] << 8));
|
||||
module->refVoltage = mV_from_ADBMS6830(rxbuffer[4] | (rxbuffer[5] << 8));
|
||||
|
||||
CHECK_RETURN(writeCMD(ADAX | ADAX_CONV_ALL, NULL, 0)); //start aux measurement for next cycle
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8 amsConfigBalancing(uint32 channels, uint8 dutyCycle) {
|
||||
uint8 buffer_a[PWM_GROUP_A_SIZE] = {};
|
||||
uint8 buffer_b[PWM_GROUP_B_SIZE] = {};
|
||||
CHECK_RETURN(writeCMD(ADCV | ADCV_CONT, NULL, 0)); //start continuous cell voltage measurement with redundancy
|
||||
CHECK_RETURN(readCMD(RDPWMA, buffer_a, PWM_GROUP_A_SIZE));
|
||||
CHECK_RETURN(readCMD(RDPWMB, buffer_b, PWM_GROUP_B_SIZE));
|
||||
|
||||
if (dutyCycle > 0x0F) { // there are only 4 bits for duty cycle
|
||||
return 1;
|
||||
}
|
||||
|
||||
buffer_a[0] = ((channels & (1 << 0)) ? dutyCycle : 0) | ((channels & (1 << 1)) ? (dutyCycle << 4) : 0);
|
||||
buffer_a[1] = ((channels & (1 << 2)) ? dutyCycle : 0) | ((channels & (1 << 3)) ? (dutyCycle << 4) : 0);
|
||||
buffer_a[2] = ((channels & (1 << 4)) ? dutyCycle : 0) | ((channels & (1 << 5)) ? (dutyCycle << 4) : 0);
|
||||
buffer_a[3] = ((channels & (1 << 6)) ? dutyCycle : 0) | ((channels & (1 << 7)) ? (dutyCycle << 4) : 0);
|
||||
buffer_a[4] = ((channels & (1 << 8)) ? dutyCycle : 0) | ((channels & (1 << 9)) ? (dutyCycle << 4) : 0);
|
||||
buffer_a[5] = ((channels & (1 << 10)) ? dutyCycle : 0) | ((channels & (1 << 11)) ? (dutyCycle << 4) : 0);
|
||||
|
||||
buffer_b[0] = ((channels & (1 << 12)) ? dutyCycle : 0) | ((channels & (1 << 13)) ? (dutyCycle << 4) : 0);
|
||||
buffer_b[1] = ((channels & (1 << 14)) ? dutyCycle : 0) | ((channels & (1 << 15)) ? (dutyCycle << 4) : 0);
|
||||
|
||||
CHECK_RETURN(writeCMD(WRPWMA, buffer_a, PWM_GROUP_A_SIZE));
|
||||
CHECK_RETURN(writeCMD(WRPWMB, buffer_b, PWM_GROUP_B_SIZE));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8 amsStartBalancing(uint8 dutyCycle) { return writeCMD(UNMUTE, NULL, 0); }
|
||||
|
||||
uint8 amsStopBalancing() { return writeCMD(MUTE, NULL, 0); }
|
||||
|
||||
uint8 amsSelfTest() { return 0; }
|
||||
|
||||
uint8 amsConfigOverUnderVoltage(uint16 overVoltage, uint16 underVoltage) {
|
||||
uint8 buffer[CFG_GROUP_A_SIZE];
|
||||
|
||||
if (underVoltage & 0xF000 || overVoltage & 0xF000) { // only 12 bits allowed
|
||||
return 1;
|
||||
}
|
||||
|
||||
CHECK_RETURN(readCMD(RDCFGB, buffer, CFG_GROUP_A_SIZE));
|
||||
|
||||
//UV
|
||||
buffer[0] = (uint8) (underVoltage & 0xFF);
|
||||
buffer[1] &= 0xF0;
|
||||
buffer[1] |= (uint8) ((underVoltage >> 8) & 0x0F);
|
||||
|
||||
//OV
|
||||
buffer[1] &= 0x0F;
|
||||
buffer[1] |= (uint8) (overVoltage << 4);
|
||||
buffer[2] = (uint8) (overVoltage >> 4);
|
||||
|
||||
return writeCMD(WRCFGB, buffer, CFG_GROUP_A_SIZE);
|
||||
}
|
||||
|
||||
uint8 amsCheckUnderOverVoltage(Cell_Module* module) {
|
||||
uint8 regbuffer[STATUS_GROUP_D_SIZE];
|
||||
uint32 ov_uv_data = 0;
|
||||
CHECK_RETURN(readCMD(RDSTATD, regbuffer, STATUS_GROUP_D_SIZE));
|
||||
ov_uv_data = (regbuffer[0] << 0) | (regbuffer[1] << 8) |
|
||||
(regbuffer[2] << 16) | (regbuffer[3] << 24);
|
||||
|
||||
module->overVoltage = 0;
|
||||
module->underVoltage = 0;
|
||||
|
||||
for (size_t i = 0; i < numberofcells; i++) { // ov/uv flags are 1-bit flags for each cell C0UV, C0OV, C1UV, C1OV, ...
|
||||
module->underVoltage |= (ov_uv_data >> (i * 2)) & 0x01;
|
||||
module->overVoltage |= (ov_uv_data >> (i * 2 + 1)) & 0x01;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8 amsClearAux() {
|
||||
return writeCMD(CLRAUX, NULL, 0);
|
||||
}
|
||||
|
||||
uint8 amsClearCells() {
|
||||
return writeCMD(CLRCELL, NULL, 0);
|
||||
}
|
||||
|
||||
uint8 amsReadCellVoltages(Cell_Module* module) {
|
||||
uint8 rxbuffer[CV_GROUP_A_SIZE];
|
||||
CHECK_RETURN(readCMD(RDCVA, rxbuffer, CV_GROUP_A_SIZE));
|
||||
module->cellVoltages[0] = mV_from_ADBMS6830(rxbuffer[0] | (rxbuffer[1] << 8));
|
||||
module->cellVoltages[1] = mV_from_ADBMS6830(rxbuffer[2] | (rxbuffer[3] << 8));
|
||||
module->cellVoltages[2] = mV_from_ADBMS6830(rxbuffer[4] | (rxbuffer[5] << 8));
|
||||
|
||||
CHECK_RETURN(readCMD(RDCVB, rxbuffer, CV_GROUP_A_SIZE));
|
||||
module->cellVoltages[3] = mV_from_ADBMS6830(rxbuffer[0] | (rxbuffer[1] << 8));
|
||||
module->cellVoltages[4] = mV_from_ADBMS6830(rxbuffer[2] | (rxbuffer[3] << 8));
|
||||
module->cellVoltages[5] = mV_from_ADBMS6830(rxbuffer[4] | (rxbuffer[5] << 8));
|
||||
|
||||
CHECK_RETURN(readCMD(RDCVC, rxbuffer, CV_GROUP_A_SIZE));
|
||||
module->cellVoltages[6] = mV_from_ADBMS6830(rxbuffer[0] | (rxbuffer[1] << 8));
|
||||
module->cellVoltages[7] = mV_from_ADBMS6830(rxbuffer[2] | (rxbuffer[3] << 8));
|
||||
module->cellVoltages[8] = mV_from_ADBMS6830(rxbuffer[4] | (rxbuffer[5] << 8));
|
||||
|
||||
CHECK_RETURN(readCMD(RDCVD, rxbuffer, CV_GROUP_A_SIZE));
|
||||
module->cellVoltages[9] = mV_from_ADBMS6830(rxbuffer[0] | (rxbuffer[1] << 8));
|
||||
module->cellVoltages[10] = mV_from_ADBMS6830(rxbuffer[2] | (rxbuffer[3] << 8));
|
||||
module->cellVoltages[11] = mV_from_ADBMS6830(rxbuffer[4] | (rxbuffer[5] << 8));
|
||||
|
||||
CHECK_RETURN(readCMD(RDCVE, rxbuffer, CV_GROUP_A_SIZE));
|
||||
module->cellVoltages[12] = mV_from_ADBMS6830(rxbuffer[0] | (rxbuffer[1] << 8));
|
||||
module->cellVoltages[13] = mV_from_ADBMS6830(rxbuffer[2] | (rxbuffer[3] << 8));
|
||||
module->cellVoltages[14] = mV_from_ADBMS6830(rxbuffer[4] | (rxbuffer[5] << 8));
|
||||
|
||||
CHECK_RETURN(readCMD(RDCVF, rxbuffer, CV_GROUP_A_SIZE));
|
||||
module->cellVoltages[15] = mV_from_ADBMS6830(rxbuffer[0] | (rxbuffer[1] << 8));
|
||||
|
||||
return 0;
|
||||
}
|
||||
340
Software/Core/Src/ADBMS_LL_Driver.c
Executable file
340
Software/Core/Src/ADBMS_LL_Driver.c
Executable file
@ -0,0 +1,340 @@
|
||||
/*
|
||||
* ADBMS_LL_Driver.c
|
||||
*
|
||||
* Created on: 05.06.2022
|
||||
* Author: max
|
||||
*/
|
||||
|
||||
#include "ADBMS_LL_Driver.h"
|
||||
|
||||
#define INITIAL_COMMAND_PEC 0x0010
|
||||
#define INITIAL_DATA_PEC 0x0010
|
||||
#define ADBMS_SPI_TIMEOUT 100 // Timeout in ms
|
||||
#warning ask about the timeout value
|
||||
|
||||
SPI_HandleTypeDef* adbmsspi;
|
||||
|
||||
uint8 adbmsDriverInit(SPI_HandleTypeDef* hspi) {
|
||||
mcuAdbmsCSLow();
|
||||
HAL_Delay(1);
|
||||
mcuAdbmsCSHigh();
|
||||
adbmsspi = hspi;
|
||||
return 0;
|
||||
}
|
||||
|
||||
//command PEC calculation
|
||||
//CRC-15
|
||||
//x^15 + x^14 + x^10 + x^8 + x^7 + x^4 + x^3 + 1
|
||||
|
||||
uint8 calculateCommandPEC(uint8_t* data, uint8_t datalen) {
|
||||
uint16 currentpec = INITIAL_COMMAND_PEC;
|
||||
if (datalen >= 3) {
|
||||
for (int i = 0; i < (datalen - 2); i++) {
|
||||
for (int n = 0; n < 8; n++) {
|
||||
const uint8 din = data[i] << (n);
|
||||
currentpec = updateCommandPEC(currentpec, din);
|
||||
}
|
||||
}
|
||||
|
||||
data[datalen - 2] = (currentpec >> 7) & 0xFF;
|
||||
data[datalen - 1] = (currentpec << 1) & 0xFF;
|
||||
return 0;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
uint8 checkCommandPEC(uint8* data, uint8 datalen) {
|
||||
if (datalen <= 3) {
|
||||
return 255;
|
||||
}
|
||||
|
||||
uint16 currentpec = INITIAL_COMMAND_PEC;
|
||||
|
||||
for (int i = 0; i < (datalen - 2); i++) {
|
||||
for (int n = 0; n < 8; n++) {
|
||||
const uint8 din = data[i] << (n);
|
||||
currentpec = updateCommandPEC(currentpec, din);
|
||||
}
|
||||
}
|
||||
|
||||
const uint8 pechigh = (currentpec >> 7) & 0xFF;
|
||||
const uint8 peclow = (currentpec << 1) & 0xFF;
|
||||
|
||||
if ((pechigh == data[datalen - 2]) && (peclow == data[datalen - 1])) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint16 updateCommandPEC(uint16 currentPEC, uint8 din) {
|
||||
din = (din >> 7) & 0x01;
|
||||
const uint8 in0 = din ^ ((currentPEC >> 14) & 0x01);
|
||||
const uint8 in3 = in0 ^ ((currentPEC >> 2) & 0x01);
|
||||
const uint8 in4 = in0 ^ ((currentPEC >> 3) & 0x01);
|
||||
const uint8 in7 = in0 ^ ((currentPEC >> 6) & 0x01);
|
||||
const uint8 in8 = in0 ^ ((currentPEC >> 7) & 0x01);
|
||||
const uint8 in10 = in0 ^ ((currentPEC >> 9) & 0x01);
|
||||
const uint8 in14 = in0 ^ ((currentPEC >> 13) & 0x01);
|
||||
|
||||
uint16 newPEC = 0;
|
||||
|
||||
newPEC |= in14 << 14;
|
||||
newPEC |= (currentPEC & (0x01 << 12)) << 1;
|
||||
newPEC |= (currentPEC & (0x01 << 11)) << 1;
|
||||
newPEC |= (currentPEC & (0x01 << 10)) << 1;
|
||||
newPEC |= in10 << 10;
|
||||
newPEC |= (currentPEC & (0x01 << 8)) << 1;
|
||||
newPEC |= in8 << 8;
|
||||
newPEC |= in7 << 7;
|
||||
newPEC |= (currentPEC & (0x01 << 5)) << 1;
|
||||
newPEC |= (currentPEC & (0x01 << 4)) << 1;
|
||||
newPEC |= in4 << 4;
|
||||
newPEC |= in3 << 3;
|
||||
newPEC |= (currentPEC & (0x01 << 1)) << 1;
|
||||
newPEC |= (currentPEC & (0x01)) << 1;
|
||||
newPEC |= in0;
|
||||
|
||||
return newPEC;
|
||||
}
|
||||
|
||||
//data PEC calculation
|
||||
//CRC-10
|
||||
//x^10 + x^7 + x^3 + x^2 + x + 1
|
||||
|
||||
uint16_t pec10_calc(bool rx_cmd, int len, const uint8_t* data) {
|
||||
uint16_t remainder = 16; /* PEC_SEED; 0000010000 */
|
||||
const uint16_t polynom = 0x8F; /* x10 + x7 + x3 + x2 + x + 1 <- the CRC15 polynomial
|
||||
100 1000 1111 48F */
|
||||
|
||||
/* Perform modulo-2 division, a byte at a time. */
|
||||
for (uint8_t pbyte = 0; pbyte < len; ++pbyte) {
|
||||
/* Bring the next byte into the remainder. */
|
||||
remainder ^= (uint16_t)(data[pbyte] << 2);
|
||||
/* Perform modulo-2 division, a bit at a time.*/
|
||||
for (uint8_t bit_ = 8; bit_ > 0; --bit_) {
|
||||
/* Try to divide the current data bit. */
|
||||
if ((remainder & 0x200) >
|
||||
0) // equivalent to remainder & 2^14 simply check for MSB
|
||||
{
|
||||
remainder = (uint16_t)((remainder << 1));
|
||||
remainder = (uint16_t)(remainder ^ polynom);
|
||||
} else {
|
||||
remainder = (uint16_t)(remainder << 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (rx_cmd == true) {
|
||||
remainder ^= (uint16_t)((data[len] & 0xFC) << 2);
|
||||
/* Perform modulo-2 division, a bit at a time */
|
||||
for (uint8_t bit_ = 6; bit_ > 0; --bit_) {
|
||||
/* Try to divide the current data bit */
|
||||
if ((remainder & 0x200) >
|
||||
0) // equivalent to remainder & 2^14 simply check for MSB
|
||||
{
|
||||
remainder = (uint16_t)((remainder << 1));
|
||||
remainder = (uint16_t)(remainder ^ polynom);
|
||||
} else {
|
||||
remainder = (uint16_t)((remainder << 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
return ((uint16_t)(remainder & 0x3FF));
|
||||
}
|
||||
|
||||
typedef uint16_t crc;
|
||||
crc F_CRC_CalculaCheckSum(uint8_t const AF_Datos[], uint16_t VF_nBytes);
|
||||
|
||||
uint8 calculateDataPEC(uint8_t* data, uint8_t datalen) {
|
||||
|
||||
if (datalen >= 3) {
|
||||
|
||||
const crc currentpec = pec10_calc(true, datalen - 2, data) & 0x3FF; // mask to 10 bits
|
||||
|
||||
// memory layout is [[zeroes], PEC[9:8]], [PEC[7:0]]
|
||||
data[datalen - 2] = (currentpec >> 8) & 0xFF;
|
||||
data[datalen - 1] = currentpec & 0xFF;
|
||||
|
||||
return 0;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
uint8 checkDataPEC(uint8* data, uint8 len) {
|
||||
if (len <= 2) {
|
||||
return 255;
|
||||
}
|
||||
|
||||
const crc currentpec = F_CRC_CalculaCheckSum(data, len);
|
||||
|
||||
return (currentpec == 0) ? 0 : 1;
|
||||
}
|
||||
|
||||
|
||||
static crc F_CRC_ObtenValorDeTabla(uint8_t VP_Pos_Tabla) {
|
||||
crc VP_CRCTableValue = 0;
|
||||
uint8_t VP_Pos_bit = 0;
|
||||
|
||||
VP_CRCTableValue = ((crc)(VP_Pos_Tabla)) << (10 - 8);
|
||||
|
||||
for (VP_Pos_bit = 0; VP_Pos_bit < 8; VP_Pos_bit++) {
|
||||
if (VP_CRCTableValue & (((crc)1) << (10 - 1))) {
|
||||
VP_CRCTableValue = (VP_CRCTableValue << 1) ^ 0x8F;
|
||||
} else {
|
||||
VP_CRCTableValue = (VP_CRCTableValue << 1);
|
||||
}
|
||||
}
|
||||
return ((VP_CRCTableValue));
|
||||
}
|
||||
crc F_CRC_CalculaCheckSum(uint8_t const AF_Datos[], uint16_t VF_nBytes) {
|
||||
crc VP_CRCTableValue = 16;
|
||||
int16_t VP_bytes = 0;
|
||||
|
||||
for (VP_bytes = 0; VP_bytes < VF_nBytes; VP_bytes++) {
|
||||
|
||||
VP_CRCTableValue = (VP_CRCTableValue << 8) ^
|
||||
F_CRC_ObtenValorDeTabla(
|
||||
((uint8_t)((VP_CRCTableValue >> (10 - 8)) & 0xFF)) ^
|
||||
AF_Datos[VP_bytes]);
|
||||
}
|
||||
|
||||
if ((8 * sizeof(crc)) > 10) {
|
||||
VP_CRCTableValue = VP_CRCTableValue & ((((crc)(1)) << 10) - 1);
|
||||
}
|
||||
|
||||
return (VP_CRCTableValue ^ 0x0000);
|
||||
}
|
||||
|
||||
uint16 updateDataPEC(uint16 currentPEC, uint8 din) {
|
||||
din = (din >> 7) & 0x01;
|
||||
const uint8 in0 = din ^ ((currentPEC >> 9) & 0x01);
|
||||
const uint8 in2 = in0 ^ ((currentPEC >> 1) & 0x01);
|
||||
const uint8 in3 = in0 ^ ((currentPEC >> 2) & 0x01);
|
||||
const uint8 in7 = in0 ^ ((currentPEC >> 6) & 0x01);
|
||||
|
||||
uint16 newPEC = 0;
|
||||
|
||||
newPEC |= (currentPEC & (0x01 << 8)) << 1;
|
||||
newPEC |= (currentPEC & (0x01 << 7)) << 1;
|
||||
newPEC |= in7 << 7;
|
||||
newPEC |= (currentPEC & (0x01 << 5)) << 1;
|
||||
newPEC |= (currentPEC & (0x01 << 4)) << 1;
|
||||
newPEC |= in3 << 3;
|
||||
newPEC |= in2 << 2;
|
||||
newPEC |= (currentPEC & (0x01)) << 1;
|
||||
newPEC |= in0;
|
||||
|
||||
return newPEC;
|
||||
}
|
||||
|
||||
uint8 writeCMD(uint16 command, const uint8 * args, uint8 arglen) {
|
||||
uint8 ret;
|
||||
if (arglen > 0) {
|
||||
uint8 buffer[6 + arglen]; //command + PEC (2 bytes) + data + DPEC (2 bytes)
|
||||
buffer[0] = (command >> 8) & 0xFF;
|
||||
buffer[1] = (command) & 0xFF;
|
||||
|
||||
calculateCommandPEC(buffer, 4);
|
||||
|
||||
for (uint8 i = 0; i < arglen; i++) {
|
||||
buffer[4 + i] = args[i];
|
||||
}
|
||||
|
||||
calculateDataPEC(&buffer[4], arglen + 2); //DPEC is calculated over the data, not the command, and placed at the end of the data
|
||||
|
||||
mcuAdbmsCSLow();
|
||||
ret = mcuSPITransmit(buffer, 6 + arglen);
|
||||
mcuAdbmsCSHigh();
|
||||
} else {
|
||||
uint8 buffer[4];
|
||||
buffer[0] = (command >> 8) & 0xFF;
|
||||
buffer[1] = (command) & 0xFF;
|
||||
calculateCommandPEC(buffer, 4);
|
||||
|
||||
mcuAdbmsCSLow();
|
||||
|
||||
ret = mcuSPITransmit(buffer, 4);
|
||||
|
||||
mcuAdbmsCSHigh();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint8 readCMD(uint16 command, uint8 * buffer, uint8 buflen) {
|
||||
uint8 txbuffer[6 + buflen];
|
||||
uint8 rxbuffer[6 + buflen];
|
||||
|
||||
txbuffer[0] = (command >> 8) & 0xFF;
|
||||
txbuffer[1] = (command)&0xFF;
|
||||
calculateCommandPEC(txbuffer, 4);
|
||||
|
||||
mcuAdbmsCSLow();
|
||||
uint8 status = mcuSPITransmitReceive(rxbuffer, txbuffer, 6 + buflen);
|
||||
mcuAdbmsCSHigh();
|
||||
|
||||
if (status != 0) {
|
||||
return status;
|
||||
}
|
||||
|
||||
for (uint8 i = 0; i < buflen; i++) {
|
||||
buffer[i] = rxbuffer[i + 4];
|
||||
}
|
||||
|
||||
[[maybe_unused]] uint8 commandCounter = rxbuffer[sizeof(rxbuffer) - 2] & 0xFC; //command counter is bits 7-2
|
||||
//TODO: check command counter?
|
||||
|
||||
return checkDataPEC(&rxbuffer[4], buflen + 2);
|
||||
}
|
||||
|
||||
//check poll command - no data PEC sent back
|
||||
uint8 pollCMD(uint16 command) {
|
||||
uint8 txbuffer[5] = {};
|
||||
uint8 rxbuffer[5] = {};
|
||||
|
||||
txbuffer[0] = (command >> 8) & 0xFF;
|
||||
txbuffer[1] = (command)&0xFF;
|
||||
calculateCommandPEC(txbuffer, 4);
|
||||
|
||||
mcuAdbmsCSLow();
|
||||
uint8 status = mcuSPITransmitReceive(rxbuffer, txbuffer, 5);
|
||||
mcuAdbmsCSHigh();
|
||||
|
||||
if (status != 0) {
|
||||
return status;
|
||||
}
|
||||
|
||||
return rxbuffer[4]; //last byte will be poll response
|
||||
}
|
||||
|
||||
void mcuAdbmsCSLow() {
|
||||
HAL_GPIO_WritePin(CSB_GPIO_Port, CSB_Pin, GPIO_PIN_RESET);
|
||||
}
|
||||
|
||||
void mcuAdbmsCSHigh() {
|
||||
HAL_GPIO_WritePin(CSB_GPIO_Port, CSB_Pin, GPIO_PIN_SET);
|
||||
}
|
||||
|
||||
uint8 mcuSPITransmit(uint8* buffer, uint8 buffersize) {
|
||||
uint8 rxbuf[buffersize];
|
||||
const HAL_StatusTypeDef status = HAL_SPI_TransmitReceive(adbmsspi, buffer, rxbuf, buffersize,
|
||||
ADBMS_SPI_TIMEOUT);
|
||||
__HAL_SPI_CLEAR_OVRFLAG(adbmsspi);
|
||||
return status;
|
||||
}
|
||||
|
||||
uint8 mcuSPIReceive(uint8* buffer, uint8 buffersize) {
|
||||
const HAL_StatusTypeDef status = HAL_SPI_Receive(adbmsspi, buffer, buffersize, ADBMS_SPI_TIMEOUT);
|
||||
return status;
|
||||
}
|
||||
|
||||
uint8 mcuSPITransmitReceive(uint8* rxbuffer, uint8* txbuffer,
|
||||
uint8 buffersize) {
|
||||
const HAL_StatusTypeDef status = HAL_SPI_TransmitReceive(adbmsspi, txbuffer, rxbuffer, buffersize,
|
||||
ADBMS_SPI_TIMEOUT);
|
||||
return status;
|
||||
}
|
||||
|
||||
inline void mcuDelay(uint16 delay) { HAL_Delay(delay); }
|
||||
209
Software/Core/Src/AMS_HighLevel.c
Executable file
209
Software/Core/Src/AMS_HighLevel.c
Executable file
@ -0,0 +1,209 @@
|
||||
/*
|
||||
* AMS_HighLevel.c
|
||||
*
|
||||
* Created on: 20.07.2022
|
||||
* Author: max
|
||||
*/
|
||||
|
||||
#include "AMS_HighLevel.h"
|
||||
#include "ADBMS_Abstraction.h"
|
||||
#include "ADBMS_LL_Driver.h"
|
||||
#include <stdint.h>
|
||||
|
||||
Cell_Module module = {};
|
||||
uint32_t balancedCells = 0;
|
||||
bool balancingActive = false;
|
||||
|
||||
uint16_t amsuv = 0;
|
||||
uint16_t amsov = 0;
|
||||
|
||||
uint8_t numberofCells = 13;
|
||||
uint8_t numberofAux = 0;
|
||||
|
||||
uint8_t packetChecksumFails = 0;
|
||||
#define MAX_PACKET_CHECKSUM_FAILS 5
|
||||
|
||||
uint8_t deviceSleeps = 0;
|
||||
#define MAX_DEVICE_SLEEP 3 //TODO: change to correct value
|
||||
#define MAX_CELL_VOLTAGE 4200 //change to 4200
|
||||
#define MIN_CELL_VOLTAGE 3200 //change to 3000
|
||||
#define CELL_VOLTAGE_DIFF_BALANCING 20 //max difference between lowest cell and any other cell
|
||||
|
||||
amsState currentAMSState = AMSDEACTIVE;
|
||||
amsState lastAMSState = AMSDEACTIVE;
|
||||
|
||||
struct pollingTimes {
|
||||
uint32_t S_ADC_OW_CHECK;
|
||||
uint32_t TMP1075;
|
||||
};
|
||||
|
||||
struct pollingTimes pollingTimes = {0, 0};
|
||||
|
||||
void AMS_Init(SPI_HandleTypeDef* hspi) {
|
||||
initAMS(hspi, numberofCells, numberofAux);
|
||||
amsov = DEFAULT_OV;
|
||||
amsuv = DEFAULT_UV;
|
||||
|
||||
pollingTimes = (struct pollingTimes) {HAL_GetTick(), HAL_GetTick()};
|
||||
|
||||
currentAMSState = AMSIDLE;
|
||||
}
|
||||
|
||||
void AMS_Loop() {
|
||||
|
||||
// On Transition Functions called ones if the State Changed
|
||||
|
||||
if (currentAMSState != lastAMSState) {
|
||||
switch (currentAMSState) {
|
||||
case AMSIDLE:
|
||||
break;
|
||||
case AMSDEACTIVE:
|
||||
break;
|
||||
case AMSCHARGING:
|
||||
break;
|
||||
case AMSIDLEBALANCING:
|
||||
break;
|
||||
case AMSDISCHARGING:
|
||||
break;
|
||||
case AMSWARNING:
|
||||
break;
|
||||
case AMSERROR:
|
||||
break;
|
||||
}
|
||||
lastAMSState = currentAMSState;
|
||||
}
|
||||
|
||||
// Main Loops for different AMS States
|
||||
|
||||
switch (currentAMSState) {
|
||||
case AMSIDLE:
|
||||
AMS_Idle_Loop();
|
||||
break;
|
||||
case AMSDEACTIVE:
|
||||
break;
|
||||
case AMSCHARGING:
|
||||
AMS_Idle_Loop();
|
||||
break;
|
||||
case AMSIDLEBALANCING:
|
||||
AMS_Idle_Loop();
|
||||
break;
|
||||
case AMSDISCHARGING:
|
||||
break;
|
||||
case AMSWARNING:
|
||||
AMS_Warning_Loop();
|
||||
break;
|
||||
case AMSERROR:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t AMS_Idle_Loop() {
|
||||
if (!amsWakeUp()) {
|
||||
error_data.data_kind = SEK_INTERNAL_BMS_TIMEOUT; //we don't receive data for the wakeup command
|
||||
set_error_source(ERROR_SOURCE_INTERNAL); //so we can't tell if we timed out
|
||||
}
|
||||
|
||||
packetChecksumFails += amsAuxAndStatusMeasurement(&module);
|
||||
|
||||
if (module.status.SLEEP) {
|
||||
deviceSleeps++;
|
||||
if (deviceSleeps > MAX_DEVICE_SLEEP) {
|
||||
error_data.data_kind = SEK_INTERNAL_BMS_TIMEOUT;
|
||||
set_error_source(ERROR_SOURCE_INTERNAL);
|
||||
} else {
|
||||
amsReset();
|
||||
}
|
||||
}
|
||||
|
||||
if (module.status.CS_FLT || module.status.SPIFLT || module.status.CMED ||
|
||||
module.status.SMED || module.status.VDE || module.status.VDEL ||
|
||||
module.status.OSCCHK || module.status.TMODCHK) {
|
||||
error_data.data_kind = SEK_INTERNAL_BMS_FAULT;
|
||||
set_error_source(ERROR_SOURCE_INTERNAL);
|
||||
}
|
||||
|
||||
if (module.status.THSD) {
|
||||
error_data.data_kind = SEK_INTERNAL_BMS_OVERTEMP;
|
||||
set_error_source(ERROR_SOURCE_INTERNAL);
|
||||
}
|
||||
|
||||
packetChecksumFails += amsCellMeasurement(&module);
|
||||
packetChecksumFails += amsCheckUnderOverVoltage(&module);
|
||||
|
||||
if (packetChecksumFails > MAX_PACKET_CHECKSUM_FAILS) {
|
||||
error_data.data_kind = SEK_INTERNAL_BMS_CHECKSUM_FAIL;
|
||||
set_error_source(ERROR_SOURCE_INTERNAL);
|
||||
}
|
||||
|
||||
int any_voltage_error = 0;
|
||||
for (size_t i = 0; i < numberofCells; i++) {
|
||||
if (module.cellVoltages[i] < MIN_CELL_VOLTAGE) {
|
||||
any_voltage_error = 1;
|
||||
error_data.data_kind = SEK_UNDERVOLT;
|
||||
error_data.data[0] = i;
|
||||
uint8_t* ptr = &error_data.data[1];
|
||||
ptr = ftcan_marshal_unsigned(ptr, module.cellVoltages[i], 2);
|
||||
} else if (module.cellVoltages[i] > MAX_CELL_VOLTAGE) {
|
||||
any_voltage_error = 1;
|
||||
error_data.data_kind = SEK_OVERVOLT;
|
||||
error_data.data[0] = i;
|
||||
uint8_t* ptr = &error_data.data[1];
|
||||
ptr = ftcan_marshal_unsigned(ptr, module.cellVoltages[i], 2);
|
||||
}
|
||||
}
|
||||
|
||||
if (module.internalDieTemp > 28000) { //TODO: change to correct value
|
||||
error_data.data_kind = SEK_INTERNAL_BMS_OVERTEMP;
|
||||
uint8_t* ptr = &error_data.data[0];
|
||||
ptr = ftcan_marshal_unsigned(ptr, module.internalDieTemp, 2);
|
||||
|
||||
set_error_source(ERROR_SOURCE_INTERNAL);
|
||||
} else {
|
||||
clear_error_source(ERROR_SOURCE_INTERNAL);
|
||||
}
|
||||
|
||||
if (any_voltage_error) {
|
||||
set_error_source(ERROR_SOURCE_VOLTAGES);
|
||||
} else {
|
||||
clear_error_source(ERROR_SOURCE_VOLTAGES);
|
||||
}
|
||||
|
||||
mcuDelay(10);
|
||||
|
||||
AMS_Balancing_Loop();
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t AMS_Warning_Loop() { return 0; }
|
||||
|
||||
uint8_t AMS_Error_Loop() { return 0; }
|
||||
|
||||
uint8_t AMS_Charging_Loop() { return 0; }
|
||||
|
||||
uint8_t AMS_Discharging_Loop() { return 0; }
|
||||
|
||||
uint8_t AMS_Balancing_Loop() {
|
||||
uint8_t id_cell_lowest_voltage = 0;
|
||||
uint8_t num_of_cells_to_balance = 0;
|
||||
uint32_t channels = 0;
|
||||
for (int i = 0; i < 13; i++) {
|
||||
if (module.cellVoltages[i] < module.cellVoltages[id_cell_lowest_voltage])
|
||||
id_cell_lowest_voltage = i;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 13; i++) {
|
||||
if (module.cellVoltages[i] - CELL_VOLTAGE_DIFF_BALANCING < module.cellVoltages[id_cell_lowest_voltage]){
|
||||
channels |= 1 << i;
|
||||
num_of_cells_to_balance++;
|
||||
}
|
||||
}
|
||||
|
||||
if (num_of_cells_to_balance == 0){
|
||||
balancingActive = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
amsConfigBalancing(channels, 0xF);
|
||||
balancingActive = 1;
|
||||
return 0;
|
||||
}
|
||||
71
Software/Core/Src/PWM_control.c
Normal file
71
Software/Core/Src/PWM_control.c
Normal file
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* PWM_control.h
|
||||
*
|
||||
* Created on: 07.07.2024
|
||||
* Author: Hamza
|
||||
*/
|
||||
|
||||
#include "PWM_control.h"
|
||||
|
||||
//uint32_t powerground1_CCR, powerground2_CCR, battery_cooling_CCR;
|
||||
|
||||
TIM_HandleTypeDef *powerground, *battery_cooling, *esc_cooling;
|
||||
|
||||
/*
|
||||
Pulse width modulation mode allows for generating a signal with a frequency determined by
|
||||
the value of the TIMx_ARR register and a duty cycle determined by the value of the TIMx_CCRx register.
|
||||
*/
|
||||
|
||||
void PWM_control_init(TIM_HandleTypeDef* pg, TIM_HandleTypeDef* bat_cool, TIM_HandleTypeDef* esc_cool){
|
||||
current_powerground_status = 0;
|
||||
target_powerground_status = 0;
|
||||
|
||||
//battery_cooling_status = 0;
|
||||
|
||||
powerground = pg;
|
||||
battery_cooling = bat_cool;
|
||||
esc_cooling = esc_cool;
|
||||
|
||||
// htim2 CH3,4 BAT_COOLING_PWM,ENABLE
|
||||
// htim3 CH3,4 ESC_L_PWM,R_PWM
|
||||
// htim4 CH1,2,3 LED R,G,B
|
||||
// htim15 CH1,2 ESC_COOLING_ENABLE,PWM
|
||||
|
||||
HAL_TIM_PWM_Start(powerground, TIM_CHANNEL_3); //TIM3CH3
|
||||
HAL_TIM_PWM_Start(powerground, TIM_CHANNEL_4); //TIM3CH4
|
||||
//HAL_TIM_PWM_Start(bat_cool, TIM_CHANNEL_3); //TIM1CH3
|
||||
|
||||
__HAL_TIM_SET_COMPARE(powerground, TIM_CHANNEL_1, 0);
|
||||
__HAL_TIM_SET_COMPARE(powerground, TIM_CHANNEL_2, 0);
|
||||
|
||||
//PWM_powerground_control(0);
|
||||
//__HAL_TIM_SET_COMPARE(battery_cooling, TIM_CHANNEL_3, 2000);
|
||||
}
|
||||
|
||||
/*
|
||||
controls the duty cycle of the fans by setting the CCR of the channel
|
||||
6+percent/100 = x/ARR
|
||||
DUTYCYCLE = 40000 * X/100
|
||||
*/
|
||||
void PWM_powerground_control(uint8_t percent){
|
||||
if (percent > 100){ //something went wrong
|
||||
__HAL_TIM_SET_COMPARE(powerground, TIM_CHANNEL_3, 0);
|
||||
__HAL_TIM_SET_COMPARE(powerground, TIM_CHANNEL_4, 0);
|
||||
current_powerground_status = target_powerground_status = 0;
|
||||
return;
|
||||
}
|
||||
current_powerground_status = target_powerground_status = percent;
|
||||
|
||||
int ccr = 2000 + (20 * percent);
|
||||
__HAL_TIM_SET_COMPARE(powerground, TIM_CHANNEL_3, ccr);
|
||||
__HAL_TIM_SET_COMPARE(powerground, TIM_CHANNEL_4, ccr);
|
||||
}
|
||||
|
||||
void PWM_powerground_softcontrol(){
|
||||
int ccr = 2000 + (20 * current_powerground_status);
|
||||
__HAL_TIM_SET_COMPARE(powerground, TIM_CHANNEL_3, ccr);
|
||||
__HAL_TIM_SET_COMPARE(powerground, TIM_CHANNEL_4, ccr);
|
||||
}
|
||||
|
||||
void PWM_battery_cooling_control(uint8_t percent){}
|
||||
void PWM_esc_cooling(uint8_t percent){}
|
||||
99
Software/Core/Src/TMP1075.c
Normal file
99
Software/Core/Src/TMP1075.c
Normal file
@ -0,0 +1,99 @@
|
||||
#include "TMP1075.h"
|
||||
#include "state_machine.h"
|
||||
|
||||
#define MAX_TEMP_DISCHARGING ((int16_t)(59 / 0.0625f))
|
||||
#define MIN_TEMP_DISCHARGING ((int16_t)(-20 / 0.0625f))
|
||||
#define MAX_TEMP_CHARGING ((int16_t)(45 / 0.0625f))
|
||||
#define MIN_TEMP_CHARGING ((int16_t)(0 / 0.0625f))
|
||||
|
||||
#define MAX_FAILED_TEMP 2 //TODO: change value for compliance with the actual number of sensors
|
||||
// TODO: "change value for compliance with the actual number of sensors", change temps to float
|
||||
|
||||
int16_t tmp1075_temps[N_TEMP_SENSORS] = {0};
|
||||
uint32_t tmp1075_failed_sensors = 0;
|
||||
uint8_t nfailed_temp_sensors = 0;
|
||||
|
||||
I2C_HandleTypeDef* hi2c;
|
||||
|
||||
HAL_StatusTypeDef tmp1075_init(I2C_HandleTypeDef* handle) {
|
||||
hi2c = handle;
|
||||
for (int i = 0; i < N_TEMP_SENSORS; i++) {
|
||||
HAL_StatusTypeDef status = tmp1075_sensor_init(i);
|
||||
if (status != HAL_OK) {
|
||||
return status;
|
||||
}
|
||||
}
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
void handle_over_maxtemp(uint8_t index, uint16_t value) {
|
||||
set_error_source(ERROR_SOURCE_TEMPERATURES);
|
||||
error_data.data_kind = SEK_OVERTEMP;
|
||||
error_data.data[0] = index;
|
||||
uint8_t* ptr = &error_data.data[1];
|
||||
ptr = ftcan_marshal_unsigned(ptr, value, 2);
|
||||
}
|
||||
|
||||
HAL_StatusTypeDef tmp1075_measure() {
|
||||
int err = 0;
|
||||
int temp_error = 0;
|
||||
for (int i = 0; i < N_TEMP_SENSORS; i++) {
|
||||
if (tmp1075_sensor_read(i, &tmp1075_temps[i]) != HAL_OK || (tmp1075_temps[i] & 0x000F) != 0) {
|
||||
tmp1075_failed_sensors |= 1 << i;
|
||||
nfailed_temp_sensors++;
|
||||
err = 1;
|
||||
} else {
|
||||
tmp1075_temps[i] >>= 4;
|
||||
tmp1075_failed_sensors &= ~(1 << i);
|
||||
if (state.current_state == STATE_CHARGING || state.current_state == STATE_CHARGING_PRECHARGE){
|
||||
if (tmp1075_temps[i] >= MAX_TEMP_CHARGING) {
|
||||
temp_error = 1;
|
||||
handle_over_maxtemp(i, tmp1075_temps[i]);
|
||||
}
|
||||
} else {
|
||||
if (tmp1075_temps[i] >= MAX_TEMP_DISCHARGING) {
|
||||
temp_error = 1;
|
||||
handle_over_maxtemp(i, tmp1075_temps[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (state.current_state == STATE_CHARGING || state.current_state == STATE_CHARGING_PRECHARGE){
|
||||
if (tmp1075_temps[i] <= MIN_TEMP_CHARGING) {
|
||||
temp_error = 1;
|
||||
handle_over_maxtemp(i, tmp1075_temps[i]);
|
||||
}
|
||||
} else {
|
||||
if (tmp1075_temps[i] <= MIN_TEMP_DISCHARGING) {
|
||||
temp_error = 1;
|
||||
handle_over_maxtemp(i, tmp1075_temps[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (nfailed_temp_sensors > MAX_FAILED_TEMP) {
|
||||
error_data.data_kind = SEK_TOO_FEW_TEMPS;
|
||||
set_error_source(ERROR_SOURCE_TEMPERATURES);
|
||||
} else if (!temp_error) {
|
||||
clear_error_source(ERROR_SOURCE_TEMPERATURES);
|
||||
}
|
||||
nfailed_temp_sensors = 0;
|
||||
return err ? HAL_ERROR : HAL_OK;
|
||||
}
|
||||
|
||||
HAL_StatusTypeDef tmp1075_sensor_init(int n) {
|
||||
uint16_t addr = (0b1000000 | n) << 1;
|
||||
uint8_t data[] = {0};
|
||||
return HAL_I2C_Master_Transmit(hi2c, addr, data, sizeof(data), 100);
|
||||
}
|
||||
|
||||
HAL_StatusTypeDef tmp1075_sensor_read(int n, int16_t* res) {
|
||||
uint16_t addr = (0b1000000 | n) << 1;
|
||||
addr |= 1; // Read
|
||||
uint8_t result[2];
|
||||
HAL_StatusTypeDef status =
|
||||
HAL_I2C_Master_Receive(hi2c, addr, result, sizeof(result), 5); //5ms timeout for failure (cascading faliure max = 30 * 5 = 150ms)
|
||||
if (status == HAL_OK) {
|
||||
*res = (result[0] << 8) | result[1];
|
||||
}
|
||||
return status;
|
||||
}
|
||||
207
Software/Core/Src/can.c
Normal file
207
Software/Core/Src/can.c
Normal file
@ -0,0 +1,207 @@
|
||||
/*
|
||||
* can.h
|
||||
*
|
||||
* Created on: 07.07.2024
|
||||
* Author: Hamza
|
||||
*/
|
||||
|
||||
#include "can.h"
|
||||
#include "AMS_HighLevel.h"
|
||||
#include "PWM_control.h"
|
||||
#include "TMP1075.h"
|
||||
#include "can-halal.h"
|
||||
#include "eeprom.h"
|
||||
#include "soc_estimation.h"
|
||||
#include "state_machine.h"
|
||||
#include "stm32f3xx_hal.h"
|
||||
#include "stm32f3xx_hal_def.h"
|
||||
#include <stdint.h>
|
||||
|
||||
#define CAN_ID_IN 0x501
|
||||
#define CAN_ID_OUT 0x502
|
||||
#define CAN_ID_LOG 0x503
|
||||
|
||||
// Every X ms, send message
|
||||
#define CAN_STATUS_FREQ 1000
|
||||
#define CAN_LOGGING_FREQ 200
|
||||
#define CAN_DUMP_FREQ 10
|
||||
// Delay between the resets of last_message
|
||||
#define CAN_RESET_DELAY 5000
|
||||
// Max time to wait for CAN messages. If we reach it then we target state is set to STATE_ERROR.
|
||||
#define CAN_TIMEOUT 10000
|
||||
|
||||
uint8_t id_to_log;
|
||||
uint8_t last_message[8];
|
||||
uint32_t can_status_timer, can_log_timer, can_timeout_timer, can_reset_timer;
|
||||
|
||||
void can_init(CAN_HandleTypeDef* hcan) {
|
||||
ftcan_init(hcan);
|
||||
ftcan_add_filter(CAN_ID_IN, 0xFFF);
|
||||
last_message[0] = -1;
|
||||
last_message[1] = -1;
|
||||
can_status_timer = HAL_GetTick() + CAN_STATUS_FREQ;
|
||||
can_log_timer = HAL_GetTick() + CAN_LOGGING_FREQ;
|
||||
can_timeout_timer = HAL_GetTick() + CAN_TIMEOUT;
|
||||
can_reset_timer = HAL_GetTick() + CAN_RESET_DELAY;
|
||||
id_to_log = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
This function sends the status of the mvbms, the battery and of powerground.
|
||||
once every 1s in states: INACTIVE, PRECHARGE, DISCHARGE, CHARGING, ERROR.
|
||||
once every 0.5s in states: READY, ACTIVE.
|
||||
with format of:
|
||||
CAN Messages:
|
||||
Error bit
|
||||
MVBMS state
|
||||
Powerground Status 0-100%
|
||||
Errors
|
||||
Battery state of charge
|
||||
Pack Voltage
|
||||
Current
|
||||
Battery temperature (12 bit)
|
||||
|
||||
Min/Max. Cell Temp (ID, Min Temp, ID, Max Temp)(3B),
|
||||
Min/Max Cell Voltage (ID, Min Voltage, ID, Max Voltage)(3B)
|
||||
|
||||
bit 0 (1b): empty
|
||||
bit 1-3 (3b): state
|
||||
bit 4-11 (8b): powerground status
|
||||
bit 12-19 (8b): error
|
||||
bit 20-27 (8b): state of charge from 0-100%
|
||||
bit 28-39 (12b): battery voltage
|
||||
bit 40-51 (12b): current measurement
|
||||
bit 52-63 (12b): temperature of the cell with highest temperature
|
||||
|
||||
|
||||
bit 0-3 (4b): ID of the sensor with highest temperature
|
||||
bit 4-7 (4b): ID of the sensor with lowest temperataure
|
||||
bit 8-19 (12b): temperature of the coldest cell
|
||||
bit 20-23 (4b): ID of the cell with the lowest voltage
|
||||
bit 24-35 (12b): lowest cell voltage
|
||||
bit 36-39 (4b): ID of the cell the the highest voltage
|
||||
bit 40-51 (12b): highest cell voltage
|
||||
bit 52-63 (12b): empty
|
||||
*/
|
||||
|
||||
void can_handle_send_status() {
|
||||
if (can_status_timer > HAL_GetTick())
|
||||
return;
|
||||
else {
|
||||
uint8_t data[8] = {};
|
||||
can_status_timer = HAL_GetTick() + CAN_STATUS_FREQ;
|
||||
|
||||
uint8_t id_highest_temp = 0;
|
||||
uint16_t highest_temp = 0;
|
||||
sm_check_battery_temperature(&id_highest_temp, &highest_temp);
|
||||
|
||||
data[0] = (state.current_state); // 8 bit state (only 3 are use)
|
||||
data[1] = (current_powerground_status); // 8 bit powerground
|
||||
data[2] = (state.error_source); // 8 bit error
|
||||
data[3] = ((int) current_soc); // 8 bit state of charge
|
||||
data[4] = (roundf(RELAY_BAT_SIDE_VOLTAGE / 1000.0)); // 8 bit battery voltage
|
||||
data[5] = (roundf(RELAY_ESC_SIDE_VOLTAGE / 1000.0)); // 8 bit Inverter voltage
|
||||
data[6] = (roundf(CURRENT_MEASUREMENT / 1000.0)); // 8 bit Current
|
||||
data[7] = ((highest_temp) >> 4); // 8 bit highest cell temperature
|
||||
//data[7] = state.error_source;
|
||||
ftcan_transmit(CAN_ID_OUT, data, sizeof(data));
|
||||
}
|
||||
}
|
||||
|
||||
void can_handle_send_log(){
|
||||
if (can_log_timer > HAL_GetTick())
|
||||
return;
|
||||
else {
|
||||
uint8_t data[4] = {};
|
||||
can_log_timer = HAL_GetTick() + CAN_LOGGING_FREQ;
|
||||
data[0] = id_to_log;
|
||||
data[1] = module.cellVoltages[id_to_log] >> 8;
|
||||
data[2] = module.cellVoltages[id_to_log];
|
||||
data[3] = tmp1075_temps[id_to_log] >> 4;
|
||||
ftcan_transmit(CAN_ID_LOG, data, 4);
|
||||
id_to_log++;
|
||||
if (id_to_log == 13)
|
||||
id_to_log = 0;
|
||||
}
|
||||
/*
|
||||
021E 30
|
||||
0232 50
|
||||
0238 60
|
||||
0246 70
|
||||
0250 80
|
||||
025A 90
|
||||
0264 100
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
can_handle_recieve_command() should only check if the message is valid and then hand it
|
||||
to the sm_handle_ams_in() which handles the state machine transition.
|
||||
|
||||
This function recieves a command from the Autobox with the CAN ID of 0x501.
|
||||
with format of:
|
||||
data[0] = target state
|
||||
0x00 STATE_INACTIVE | disconnect power to the ESC of powerground. Send it to return the mvbms to idle/monitoring mode. If data[1] != 0 -> assume bad CAN message.
|
||||
0x01 STATE_READY | connect power to the ESC of powerground and but with no PWM signal. If data[1] != 0 -> assume bad CAN message.
|
||||
0x02 STATE_ACTIVE | activate powerground at (data[1]) percent. If data[1] > 100 -> assume bad CAN message.
|
||||
|
||||
allowed transitions:
|
||||
STATE_INACTIVE -> STATE_READY
|
||||
STATE_READY -> STATE_INACTIVE, STATE_ACTIVE
|
||||
STATE_ACTIVE -> STATE_INACTIVE, STATE_READY
|
||||
*/
|
||||
void can_handle_recieve_command(const uint8_t *data){
|
||||
if (data[0] == 0x00){
|
||||
sm_handle_ams_in(data);
|
||||
} else if (data[0] == 0x01 && data[1] == 0x00){
|
||||
sm_handle_ams_in(data);
|
||||
} else if (data[0] == 0x02 && data[1] <= 100) {
|
||||
sm_handle_ams_in(data);
|
||||
} else if (data[0] == 0xF0 && data[1] == 0x00) {
|
||||
sm_handle_ams_in(data);
|
||||
} else if (data[0] == 0xF1 && data[1] == 0x00) {
|
||||
//sm_handle_ams_in(data);
|
||||
} else if (data[0] == 0xFF && data[1] == 0x00) {
|
||||
//sm_handle_ams_in(data);
|
||||
}
|
||||
}
|
||||
|
||||
void can_handle_dump() {
|
||||
uint8_t* data = {};
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
while (status == HAL_OK){
|
||||
HAL_Delay(2);
|
||||
eeprom_read(data, 62);
|
||||
for (int i = 0; i < (EEPROM_MEMORY_SIZE-8)/8; i += 8) {
|
||||
ftcan_transmit(CAN_ID_OUT, &data[i], 8);
|
||||
}
|
||||
ftcan_transmit(CAN_ID_OUT, &data[56], 6);
|
||||
}
|
||||
read_address = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
implements the _weak method ftcan_msg_recieved_cb() which throws an interrupt when a CAN message is recieved.
|
||||
it only checks if the id is and datalen is correct thans hands data over to can_handle_recieve_command().
|
||||
|
||||
in MXCUBE under CAN NVIC settings "USB low priority or CAN_RX0 interrupts" has to be on
|
||||
*/
|
||||
void ftcan_msg_received_cb(uint16_t id, size_t datalen, const uint8_t *data){
|
||||
if (programming_mode == 1){
|
||||
can_handle_recieve_command(data);
|
||||
return;
|
||||
}
|
||||
|
||||
if (id == 0x501 && datalen == 2){
|
||||
can_timeout_timer = HAL_GetTick() + CAN_TIMEOUT;
|
||||
if (state.current_state == STATE_ERROR){
|
||||
last_message[0] = 0;
|
||||
last_message[1] = 0;
|
||||
}
|
||||
if (last_message[0] != data[0] || last_message[1] != data[1]){
|
||||
last_message[0] = data[0];
|
||||
last_message[1] = data[1];
|
||||
can_handle_recieve_command(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
96
Software/Core/Src/eeprom.c
Executable file
96
Software/Core/Src/eeprom.c
Executable file
@ -0,0 +1,96 @@
|
||||
/*
|
||||
* PWM_control.h
|
||||
*
|
||||
* Created on: 10.07.2024
|
||||
* Author: Hamza
|
||||
*/
|
||||
|
||||
#include <eeprom.h>
|
||||
|
||||
// TODO: test this
|
||||
static I2C_HandleTypeDef* hi2c;
|
||||
uint32_t write_address, read_address;
|
||||
|
||||
void eeprom_init(I2C_HandleTypeDef* handle) {
|
||||
hi2c = handle;
|
||||
write_address = 0;
|
||||
read_address = 0;
|
||||
}
|
||||
|
||||
void eeprom_write_status(){
|
||||
uint8_t data_length = 62;
|
||||
uint8_t data[data_length] = {};
|
||||
|
||||
// data 0-9
|
||||
data[0] = ((state.current_state << 4) | (current_powerground_status >> 4));
|
||||
data[1] = ((current_powerground_status << 4) | (state.error_source >> 4)); // 4 bit powerground | 4 bit error
|
||||
data[2] = ((state.error_source << 4) | (0)); // 4 bit error | 4 bit state of charge
|
||||
data[3] = ((int) current_soc); // 8 bit state of charge
|
||||
data[4] = (RELAY_BAT_SIDE_VOLTAGE >> 8); // 16 bit battery voltage
|
||||
data[5] = (RELAY_BAT_SIDE_VOLTAGE);
|
||||
data[6] = (RELAY_ESC_SIDE_VOLTAGE >> 8); // 16 bit Inverter voltage
|
||||
data[7] = (RELAY_ESC_SIDE_VOLTAGE);
|
||||
data[8] = (CURRENT_MEASUREMENT >> 8); // 16 bit Inverter voltage
|
||||
data[9] = (CURRENT_MEASUREMENT);
|
||||
|
||||
// data 10-35
|
||||
for (int i = 0; i < 13; i++) {
|
||||
data[(i*2)] = ((int) module.auxVoltages[i]) >> 8;
|
||||
data[(i*2)+1] = ((int) module.auxVoltages[i]);
|
||||
}
|
||||
|
||||
// data 36-61
|
||||
for (int i = 0; i < 13; i++) {
|
||||
data[(i*2)] = (tmp1075_temps[i]) >> 8;
|
||||
data[(i*2)+1] = (tmp1075_temps[i]);
|
||||
}
|
||||
eeprom_write(data, 62);
|
||||
write_address++;
|
||||
}
|
||||
|
||||
HAL_StatusTypeDef eeprom_read(uint8_t* data, uint16_t data_length){
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
for (size_t i = 0; i < data_length; i++) {
|
||||
if (read_address > EEPROM_MEMORY_SIZE){
|
||||
read_address = 0;
|
||||
return HAL_BUSY;
|
||||
} else if (read_address <= 65535){
|
||||
status = HAL_I2C_Mem_Read(
|
||||
hi2c, EEPROM_I2C_ADDR,
|
||||
read_address, EERROM_MEMORY_ADDR_SIZE,
|
||||
&data[i], 1, 10);
|
||||
} else if (read_address > 65535) {
|
||||
status = HAL_I2C_Mem_Read(
|
||||
hi2c, EEPROM_I2C_ADDR + 2,
|
||||
read_address - 65535, EERROM_MEMORY_ADDR_SIZE,
|
||||
&data[i], 1, 10);
|
||||
}
|
||||
read_address++;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
HAL_StatusTypeDef eeprom_write(uint8_t* data, uint16_t data_length){
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
HAL_GPIO_WritePin(EEPROM___WC__GPIO_Port, EEPROM___WC__Pin, GPIO_PIN_RESET);
|
||||
for (size_t i = 0; i < data_length; i++) {
|
||||
if (write_address > EEPROM_MEMORY_SIZE){
|
||||
write_address = 0;
|
||||
return HAL_BUSY;
|
||||
} else if (write_address <= 65535){
|
||||
status = HAL_I2C_Mem_Write(
|
||||
hi2c, EEPROM_I2C_ADDR,
|
||||
write_address, EERROM_MEMORY_ADDR_SIZE,
|
||||
&data[i], 1, 10);
|
||||
|
||||
} else if (write_address > 65535) {
|
||||
status = HAL_I2C_Mem_Write(
|
||||
hi2c, EEPROM_I2C_ADDR + 2,
|
||||
write_address - 65535, EERROM_MEMORY_ADDR_SIZE,
|
||||
&data[i], 1, 10);
|
||||
}
|
||||
write_address++;
|
||||
}
|
||||
HAL_GPIO_WritePin(EEPROM___WC__GPIO_Port, EEPROM___WC__Pin, GPIO_PIN_SET);
|
||||
return status;
|
||||
}
|
||||
16
Software/Core/Src/errors.c
Normal file
16
Software/Core/Src/errors.c
Normal file
@ -0,0 +1,16 @@
|
||||
#include "errors.h"
|
||||
#include "stm32f3xx_hal.h"
|
||||
|
||||
|
||||
#warning move all errors here
|
||||
|
||||
SlaveErrorData error_data;
|
||||
|
||||
void set_error_source(SlaveErrorKind source) {
|
||||
if (!error_data.error_sources) {
|
||||
error_data.errors_since = HAL_GetTick();
|
||||
}
|
||||
error_data.error_sources |= (1 << source);
|
||||
}
|
||||
|
||||
void clear_error_source(SlaveErrorKind source) { error_data.error_sources &= ~(1 << source); }
|
||||
706
Software/Core/Src/main.c
Normal file
706
Software/Core/Src/main.c
Normal file
@ -0,0 +1,706 @@
|
||||
/* USER CODE BEGIN Header */
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file : main.c
|
||||
* @brief : Main program body
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2024 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
/* USER CODE END Header */
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "main.h"
|
||||
|
||||
/* Private includes ----------------------------------------------------------*/
|
||||
/* USER CODE BEGIN Includes */
|
||||
#include "ADBMS_Abstraction.h"
|
||||
#include "ADBMS_CMD_MAKROS.h"
|
||||
#include "PWM_control.h"
|
||||
#include "can.h"
|
||||
#include "AMS_HighLevel.h"
|
||||
#include "soc_estimation.h"
|
||||
#include "state_machine.h"
|
||||
#include <status_LED.h>
|
||||
#include <stdint.h>
|
||||
#include "TMP1075.h"
|
||||
#include "errors.h"
|
||||
#include "stm32f302xc.h"
|
||||
#include "stm32f3xx_hal.h"
|
||||
#include "stm32f3xx_hal_tim.h"
|
||||
/* USER CODE END Includes */
|
||||
|
||||
/* 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 */
|
||||
|
||||
// htim2 CH3,4 BAT_COOLING_PWM,ENABLE
|
||||
// htim3 CH3,4 ESC_L_PWM,R_PWM
|
||||
// htim4 CH1,2,3 LED R,G,B
|
||||
// htim15 CH1,2 ESC_COOLING_ENABLE,PWM
|
||||
|
||||
/* USER CODE END PM */
|
||||
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
CAN_HandleTypeDef hcan;
|
||||
|
||||
I2C_HandleTypeDef hi2c1;
|
||||
I2C_HandleTypeDef hi2c2;
|
||||
|
||||
SPI_HandleTypeDef hspi1;
|
||||
|
||||
TIM_HandleTypeDef htim2;
|
||||
TIM_HandleTypeDef htim3;
|
||||
TIM_HandleTypeDef htim4;
|
||||
TIM_HandleTypeDef htim15;
|
||||
|
||||
/* USER CODE BEGIN PV */
|
||||
|
||||
/* USER CODE END PV */
|
||||
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
void SystemClock_Config(void);
|
||||
static void MX_GPIO_Init(void);
|
||||
static void MX_CAN_Init(void);
|
||||
static void MX_I2C1_Init(void);
|
||||
static void MX_SPI1_Init(void);
|
||||
static void MX_TIM15_Init(void);
|
||||
static void MX_I2C2_Init(void);
|
||||
static void MX_TIM2_Init(void);
|
||||
static void MX_TIM3_Init(void);
|
||||
static void MX_TIM4_Init(void);
|
||||
/* USER CODE BEGIN PFP */
|
||||
|
||||
/* USER CODE END PFP */
|
||||
|
||||
/* Private user code ---------------------------------------------------------*/
|
||||
/* USER CODE BEGIN 0 */
|
||||
|
||||
/* USER CODE END 0 */
|
||||
|
||||
/**
|
||||
* @brief The application entry point.
|
||||
* @retval int
|
||||
*/
|
||||
int main(void)
|
||||
{
|
||||
|
||||
/* USER CODE BEGIN 1 */
|
||||
|
||||
/* USER CODE END 1 */
|
||||
|
||||
/* MCU Configuration--------------------------------------------------------*/
|
||||
|
||||
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
|
||||
HAL_Init();
|
||||
|
||||
/* USER CODE BEGIN Init */
|
||||
|
||||
/* USER CODE END Init */
|
||||
|
||||
/* Configure the system clock */
|
||||
SystemClock_Config();
|
||||
|
||||
/* USER CODE BEGIN SysInit */
|
||||
|
||||
/* USER CODE END SysInit */
|
||||
|
||||
/* Initialize all configured peripherals */
|
||||
MX_GPIO_Init();
|
||||
MX_CAN_Init();
|
||||
MX_I2C1_Init();
|
||||
MX_SPI1_Init();
|
||||
MX_TIM15_Init();
|
||||
MX_I2C2_Init();
|
||||
MX_TIM2_Init();
|
||||
MX_TIM3_Init();
|
||||
MX_TIM4_Init();
|
||||
/* USER CODE BEGIN 2 */
|
||||
sm_init();
|
||||
tmp1075_init(&hi2c1);
|
||||
AMS_Init(&hspi1);
|
||||
can_init(&hcan);
|
||||
PWM_control_init(&htim3, &htim2, &htim15);
|
||||
soc_init();
|
||||
status_led_init(&htim4, &htim4, &htim4);
|
||||
sm_program_powerground();
|
||||
eeprom_init(&hi2c2);
|
||||
AMS_Loop();
|
||||
uint32_t startup_timer = 500 + HAL_GetTick();
|
||||
while (startup_timer > HAL_GetTick());
|
||||
/* USER CODE END 2 */
|
||||
|
||||
/* Infinite loop */
|
||||
/* USER CODE BEGIN WHILE */
|
||||
while (1)
|
||||
{
|
||||
/* USER CODE END WHILE */
|
||||
|
||||
/* USER CODE BEGIN 3 */
|
||||
AMS_Loop();
|
||||
sm_update();
|
||||
//sm_test_cycle_states();
|
||||
}
|
||||
/* USER CODE END 3 */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief System Clock Configuration
|
||||
* @retval None
|
||||
*/
|
||||
void SystemClock_Config(void)
|
||||
{
|
||||
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
|
||||
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
|
||||
RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
|
||||
|
||||
/** Initializes the RCC Oscillators according to the specified parameters
|
||||
* in the RCC_OscInitTypeDef structure.
|
||||
*/
|
||||
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
|
||||
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
|
||||
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
|
||||
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
|
||||
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
|
||||
/** Initializes the CPU, AHB and APB buses clocks
|
||||
*/
|
||||
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|
||||
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
|
||||
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSE;
|
||||
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
|
||||
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
|
||||
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
|
||||
|
||||
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_I2C1|RCC_PERIPHCLK_I2C2;
|
||||
PeriphClkInit.I2c1ClockSelection = RCC_I2C1CLKSOURCE_SYSCLK;
|
||||
PeriphClkInit.I2c2ClockSelection = RCC_I2C2CLKSOURCE_SYSCLK;
|
||||
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief CAN Initialization Function
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
static void MX_CAN_Init(void)
|
||||
{
|
||||
|
||||
/* USER CODE BEGIN CAN_Init 0 */
|
||||
|
||||
/* USER CODE END CAN_Init 0 */
|
||||
|
||||
/* USER CODE BEGIN CAN_Init 1 */
|
||||
|
||||
/* USER CODE END CAN_Init 1 */
|
||||
hcan.Instance = CAN;
|
||||
hcan.Init.Prescaler = 2;
|
||||
hcan.Init.Mode = CAN_MODE_NORMAL;
|
||||
hcan.Init.SyncJumpWidth = CAN_SJW_1TQ;
|
||||
hcan.Init.TimeSeg1 = CAN_BS1_13TQ;
|
||||
hcan.Init.TimeSeg2 = CAN_BS2_2TQ;
|
||||
hcan.Init.TimeTriggeredMode = DISABLE;
|
||||
hcan.Init.AutoBusOff = ENABLE;
|
||||
hcan.Init.AutoWakeUp = DISABLE;
|
||||
hcan.Init.AutoRetransmission = ENABLE;
|
||||
hcan.Init.ReceiveFifoLocked = DISABLE;
|
||||
hcan.Init.TransmitFifoPriority = DISABLE;
|
||||
if (HAL_CAN_Init(&hcan) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
/* USER CODE BEGIN CAN_Init 2 */
|
||||
|
||||
/* USER CODE END CAN_Init 2 */
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief I2C1 Initialization Function
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
static void MX_I2C1_Init(void)
|
||||
{
|
||||
|
||||
/* USER CODE BEGIN I2C1_Init 0 */
|
||||
|
||||
/* USER CODE END I2C1_Init 0 */
|
||||
|
||||
/* USER CODE BEGIN I2C1_Init 1 */
|
||||
|
||||
/* USER CODE END I2C1_Init 1 */
|
||||
hi2c1.Instance = I2C1;
|
||||
hi2c1.Init.Timing = 0x00303D5B;
|
||||
hi2c1.Init.OwnAddress1 = 0;
|
||||
hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
|
||||
hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
|
||||
hi2c1.Init.OwnAddress2 = 0;
|
||||
hi2c1.Init.OwnAddress2Masks = I2C_OA2_NOMASK;
|
||||
hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
|
||||
hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
|
||||
if (HAL_I2C_Init(&hi2c1) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
|
||||
/** Configure Analogue filter
|
||||
*/
|
||||
if (HAL_I2CEx_ConfigAnalogFilter(&hi2c1, I2C_ANALOGFILTER_ENABLE) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
|
||||
/** Configure Digital filter
|
||||
*/
|
||||
if (HAL_I2CEx_ConfigDigitalFilter(&hi2c1, 0) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
/* USER CODE BEGIN I2C1_Init 2 */
|
||||
|
||||
/* USER CODE END I2C1_Init 2 */
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief I2C2 Initialization Function
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
static void MX_I2C2_Init(void)
|
||||
{
|
||||
|
||||
/* USER CODE BEGIN I2C2_Init 0 */
|
||||
|
||||
/* USER CODE END I2C2_Init 0 */
|
||||
|
||||
/* USER CODE BEGIN I2C2_Init 1 */
|
||||
|
||||
/* USER CODE END I2C2_Init 1 */
|
||||
hi2c2.Instance = I2C2;
|
||||
hi2c2.Init.Timing = 0x00303D5B;
|
||||
hi2c2.Init.OwnAddress1 = 0;
|
||||
hi2c2.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
|
||||
hi2c2.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
|
||||
hi2c2.Init.OwnAddress2 = 0;
|
||||
hi2c2.Init.OwnAddress2Masks = I2C_OA2_NOMASK;
|
||||
hi2c2.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
|
||||
hi2c2.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
|
||||
if (HAL_I2C_Init(&hi2c2) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
|
||||
/** Configure Analogue filter
|
||||
*/
|
||||
if (HAL_I2CEx_ConfigAnalogFilter(&hi2c2, I2C_ANALOGFILTER_ENABLE) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
|
||||
/** Configure Digital filter
|
||||
*/
|
||||
if (HAL_I2CEx_ConfigDigitalFilter(&hi2c2, 0) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
/* USER CODE BEGIN I2C2_Init 2 */
|
||||
|
||||
/* USER CODE END I2C2_Init 2 */
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief SPI1 Initialization Function
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
static void MX_SPI1_Init(void)
|
||||
{
|
||||
|
||||
/* USER CODE BEGIN SPI1_Init 0 */
|
||||
|
||||
/* USER CODE END SPI1_Init 0 */
|
||||
|
||||
/* USER CODE BEGIN SPI1_Init 1 */
|
||||
|
||||
/* USER CODE END SPI1_Init 1 */
|
||||
/* SPI1 parameter configuration*/
|
||||
hspi1.Instance = SPI1;
|
||||
hspi1.Init.Mode = SPI_MODE_MASTER;
|
||||
hspi1.Init.Direction = SPI_DIRECTION_2LINES;
|
||||
hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
|
||||
hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
|
||||
hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
|
||||
hspi1.Init.NSS = SPI_NSS_SOFT;
|
||||
hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_32;
|
||||
hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
|
||||
hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
|
||||
hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
|
||||
hspi1.Init.CRCPolynomial = 7;
|
||||
hspi1.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;
|
||||
hspi1.Init.NSSPMode = SPI_NSS_PULSE_ENABLE;
|
||||
if (HAL_SPI_Init(&hspi1) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
/* USER CODE BEGIN SPI1_Init 2 */
|
||||
|
||||
/* USER CODE END SPI1_Init 2 */
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief TIM2 Initialization Function
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
static void MX_TIM2_Init(void)
|
||||
{
|
||||
|
||||
/* USER CODE BEGIN TIM2_Init 0 */
|
||||
|
||||
/* USER CODE END TIM2_Init 0 */
|
||||
|
||||
TIM_MasterConfigTypeDef sMasterConfig = {0};
|
||||
TIM_OC_InitTypeDef sConfigOC = {0};
|
||||
|
||||
/* USER CODE BEGIN TIM2_Init 1 */
|
||||
|
||||
/* USER CODE END TIM2_Init 1 */
|
||||
htim2.Instance = TIM2;
|
||||
htim2.Init.Prescaler = 0;
|
||||
htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
|
||||
htim2.Init.Period = 4294967295;
|
||||
htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
|
||||
htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
|
||||
if (HAL_TIM_PWM_Init(&htim2) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
|
||||
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
|
||||
if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
sConfigOC.OCMode = TIM_OCMODE_PWM1;
|
||||
sConfigOC.Pulse = 0;
|
||||
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
|
||||
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
|
||||
if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_3) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_4) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
/* USER CODE BEGIN TIM2_Init 2 */
|
||||
|
||||
/* USER CODE END TIM2_Init 2 */
|
||||
HAL_TIM_MspPostInit(&htim2);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief TIM3 Initialization Function
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
static void MX_TIM3_Init(void)
|
||||
{
|
||||
|
||||
/* USER CODE BEGIN TIM3_Init 0 */
|
||||
|
||||
/* USER CODE END TIM3_Init 0 */
|
||||
|
||||
TIM_MasterConfigTypeDef sMasterConfig = {0};
|
||||
TIM_OC_InitTypeDef sConfigOC = {0};
|
||||
|
||||
/* USER CODE BEGIN TIM3_Init 1 */
|
||||
|
||||
/* USER CODE END TIM3_Init 1 */
|
||||
htim3.Instance = TIM3;
|
||||
htim3.Init.Prescaler = 7;
|
||||
htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
|
||||
htim3.Init.Period = 39999;
|
||||
htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
|
||||
htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
|
||||
if (HAL_TIM_PWM_Init(&htim3) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
|
||||
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
|
||||
if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
sConfigOC.OCMode = TIM_OCMODE_PWM1;
|
||||
sConfigOC.Pulse = 0;
|
||||
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
|
||||
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
|
||||
if (HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_3) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
if (HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_4) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
/* USER CODE BEGIN TIM3_Init 2 */
|
||||
|
||||
/* USER CODE END TIM3_Init 2 */
|
||||
HAL_TIM_MspPostInit(&htim3);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief TIM4 Initialization Function
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
static void MX_TIM4_Init(void)
|
||||
{
|
||||
|
||||
/* USER CODE BEGIN TIM4_Init 0 */
|
||||
|
||||
/* USER CODE END TIM4_Init 0 */
|
||||
|
||||
TIM_MasterConfigTypeDef sMasterConfig = {0};
|
||||
TIM_OC_InitTypeDef sConfigOC = {0};
|
||||
|
||||
/* USER CODE BEGIN TIM4_Init 1 */
|
||||
|
||||
/* USER CODE END TIM4_Init 1 */
|
||||
htim4.Instance = TIM4;
|
||||
htim4.Init.Prescaler = 624;
|
||||
htim4.Init.CounterMode = TIM_COUNTERMODE_UP;
|
||||
htim4.Init.Period = 255;
|
||||
htim4.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
|
||||
htim4.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
|
||||
if (HAL_TIM_PWM_Init(&htim4) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
|
||||
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
|
||||
if (HAL_TIMEx_MasterConfigSynchronization(&htim4, &sMasterConfig) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
sConfigOC.OCMode = TIM_OCMODE_PWM1;
|
||||
sConfigOC.Pulse = 0;
|
||||
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
|
||||
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
|
||||
if (HAL_TIM_PWM_ConfigChannel(&htim4, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
if (HAL_TIM_PWM_ConfigChannel(&htim4, &sConfigOC, TIM_CHANNEL_2) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
if (HAL_TIM_PWM_ConfigChannel(&htim4, &sConfigOC, TIM_CHANNEL_3) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
/* USER CODE BEGIN TIM4_Init 2 */
|
||||
|
||||
/* USER CODE END TIM4_Init 2 */
|
||||
HAL_TIM_MspPostInit(&htim4);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief TIM15 Initialization Function
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
static void MX_TIM15_Init(void)
|
||||
{
|
||||
|
||||
/* USER CODE BEGIN TIM15_Init 0 */
|
||||
|
||||
/* USER CODE END TIM15_Init 0 */
|
||||
|
||||
TIM_MasterConfigTypeDef sMasterConfig = {0};
|
||||
TIM_OC_InitTypeDef sConfigOC = {0};
|
||||
TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = {0};
|
||||
|
||||
/* USER CODE BEGIN TIM15_Init 1 */
|
||||
|
||||
/* USER CODE END TIM15_Init 1 */
|
||||
htim15.Instance = TIM15;
|
||||
htim15.Init.Prescaler = 0;
|
||||
htim15.Init.CounterMode = TIM_COUNTERMODE_UP;
|
||||
htim15.Init.Period = 65535;
|
||||
htim15.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
|
||||
htim15.Init.RepetitionCounter = 0;
|
||||
htim15.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
|
||||
if (HAL_TIM_PWM_Init(&htim15) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
|
||||
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
|
||||
if (HAL_TIMEx_MasterConfigSynchronization(&htim15, &sMasterConfig) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
sConfigOC.OCMode = TIM_OCMODE_PWM1;
|
||||
sConfigOC.Pulse = 0;
|
||||
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
|
||||
sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;
|
||||
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
|
||||
sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;
|
||||
sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;
|
||||
if (HAL_TIM_PWM_ConfigChannel(&htim15, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
if (HAL_TIM_PWM_ConfigChannel(&htim15, &sConfigOC, TIM_CHANNEL_2) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE;
|
||||
sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE;
|
||||
sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF;
|
||||
sBreakDeadTimeConfig.DeadTime = 0;
|
||||
sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE;
|
||||
sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH;
|
||||
sBreakDeadTimeConfig.BreakFilter = 0;
|
||||
sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE;
|
||||
if (HAL_TIMEx_ConfigBreakDeadTime(&htim15, &sBreakDeadTimeConfig) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
/* USER CODE BEGIN TIM15_Init 2 */
|
||||
|
||||
/* USER CODE END TIM15_Init 2 */
|
||||
HAL_TIM_MspPostInit(&htim15);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief GPIO Initialization Function
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
static void MX_GPIO_Init(void)
|
||||
{
|
||||
GPIO_InitTypeDef GPIO_InitStruct = {0};
|
||||
/* USER CODE BEGIN MX_GPIO_Init_1 */
|
||||
/* USER CODE END MX_GPIO_Init_1 */
|
||||
|
||||
/* GPIO Ports Clock Enable */
|
||||
__HAL_RCC_GPIOC_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOF_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOA_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOB_CLK_ENABLE();
|
||||
|
||||
/*Configure GPIO pin Output Level */
|
||||
HAL_GPIO_WritePin(GPIOA, CSB_Pin|EEPROM___WC__Pin, GPIO_PIN_RESET);
|
||||
|
||||
/*Configure GPIO pin Output Level */
|
||||
HAL_GPIO_WritePin(GPIOB, RELAY_ENABLE_Pin|PRECHARGE_ENABLE_Pin, GPIO_PIN_RESET);
|
||||
|
||||
/*Configure GPIO pins : PC13 PC14 PC15 */
|
||||
GPIO_InitStruct.Pin = GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
|
||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
|
||||
|
||||
/*Configure GPIO pins : PA0 PA1 PA2 PA3 */
|
||||
GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
|
||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
|
||||
|
||||
/*Configure GPIO pins : CSB_Pin EEPROM___WC__Pin */
|
||||
GPIO_InitStruct.Pin = CSB_Pin|EEPROM___WC__Pin;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
|
||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
|
||||
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
|
||||
|
||||
/*Configure GPIO pins : PB2 PB12 PB13 */
|
||||
GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_12|GPIO_PIN_13;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
|
||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
|
||||
|
||||
/*Configure GPIO pins : RELAY_ENABLE_Pin PRECHARGE_ENABLE_Pin */
|
||||
GPIO_InitStruct.Pin = RELAY_ENABLE_Pin|PRECHARGE_ENABLE_Pin;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
|
||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
|
||||
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
|
||||
|
||||
/* USER CODE BEGIN MX_GPIO_Init_2 */
|
||||
/* USER CODE END MX_GPIO_Init_2 */
|
||||
}
|
||||
|
||||
/* USER CODE BEGIN 4 */
|
||||
|
||||
/* USER CODE END 4 */
|
||||
|
||||
/**
|
||||
* @brief This function is executed in case of error occurrence.
|
||||
* @retval None
|
||||
*/
|
||||
void Error_Handler(void)
|
||||
{
|
||||
/* USER CODE BEGIN Error_Handler_Debug */
|
||||
/* User can add his own implementation to report the HAL error return state */
|
||||
__disable_irq();
|
||||
while (1)
|
||||
{
|
||||
}
|
||||
/* USER CODE END Error_Handler_Debug */
|
||||
}
|
||||
|
||||
#ifdef USE_FULL_ASSERT
|
||||
/**
|
||||
* @brief Reports the name of the source file and the source line number
|
||||
* where the assert_param error has occurred.
|
||||
* @param file: pointer to the source file name
|
||||
* @param line: assert_param error line source number
|
||||
* @retval None
|
||||
*/
|
||||
void assert_failed(uint8_t *file, uint32_t line)
|
||||
{
|
||||
/* USER CODE BEGIN 6 */
|
||||
/* User can add his own implementation to report the file name and line number,
|
||||
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
|
||||
/* USER CODE END 6 */
|
||||
}
|
||||
#endif /* USE_FULL_ASSERT */
|
||||
92
Software/Core/Src/soc_estimation.c
Normal file
92
Software/Core/Src/soc_estimation.c
Normal file
@ -0,0 +1,92 @@
|
||||
#include "soc_estimation.h"
|
||||
#include <stdint.h>
|
||||
|
||||
#define SOC_ESTIMATION_NO_CURRENT_THRESH 1000 // mA
|
||||
#define SOC_ESTIMATION_NO_CURRENT_TIME 100000 // ms
|
||||
#define SOC_ESTIMATION_BATTERY_CAPACITY 28800 // mAs
|
||||
|
||||
#define MIN_CELL_VOLTAGE 3000
|
||||
#define MAX_CELL_VOLTAGE 4130
|
||||
|
||||
|
||||
// https://www.desmos.com/calculator/mm22vmxl2x
|
||||
ocv_soc_pair_t OCV_SOC_PAIRS[] = {
|
||||
{3000, 0.00f}, {3350, 10.00f}, {3450, 20.00f},
|
||||
{3500, 30.00f}, {3530, 40.00f}, {3570, 50.00f},
|
||||
{3600, 60.00f}, {3630, 70.00f}, {3700, 80.00f},
|
||||
{3800, 90.00f}, {4130, 100.00f}
|
||||
};
|
||||
|
||||
float current_soc;
|
||||
|
||||
int current_was_flowing;
|
||||
uint32_t last_current_time;
|
||||
float soc_before_current;
|
||||
float mAs_before_current;
|
||||
|
||||
void soc_init() {
|
||||
current_soc = 0;
|
||||
last_current_time = 0;
|
||||
current_was_flowing = 1;
|
||||
}
|
||||
|
||||
void soc_update() {
|
||||
uint32_t now = HAL_GetTick();
|
||||
if (CURRENT_MEASUREMENT >= SOC_ESTIMATION_NO_CURRENT_THRESH) {
|
||||
last_current_time = now;
|
||||
if (!current_was_flowing) {
|
||||
soc_before_current = current_soc;
|
||||
mAs_before_current = CURRENT_MEASUREMENT;
|
||||
}
|
||||
current_was_flowing = 1;
|
||||
} else {
|
||||
current_was_flowing = 0;
|
||||
}
|
||||
|
||||
if (now - last_current_time >= SOC_ESTIMATION_NO_CURRENT_TIME ||
|
||||
last_current_time == 0) {
|
||||
// Assume we're measuring OCV if there's been no current for a while (or
|
||||
// we've just turned on the battery).
|
||||
uint8_t id = 0;
|
||||
uint16_t min_voltage = 0;
|
||||
sm_check_battery_temperature(&id, &min_voltage);
|
||||
current_soc = soc_for_ocv(min_voltage);
|
||||
} else {
|
||||
// Otherwise, use the current counter to update SoC
|
||||
float as_delta = CURRENT_MEASUREMENT - mAs_before_current;
|
||||
float soc_delta = as_delta / SOC_ESTIMATION_BATTERY_CAPACITY * 100;
|
||||
current_soc = soc_before_current + soc_delta;
|
||||
}
|
||||
}
|
||||
|
||||
float soc_for_ocv(uint16_t ocv) {
|
||||
size_t i = 0;
|
||||
size_t array_length = sizeof(OCV_SOC_PAIRS) / sizeof(*OCV_SOC_PAIRS);
|
||||
// Find the index of the first element with OCV greater than the target OCV
|
||||
while (i < array_length && OCV_SOC_PAIRS[i].ocv <= ocv) {
|
||||
i++;
|
||||
}
|
||||
|
||||
// If the target OCV is lower than the smallest OCV in the array, return the
|
||||
// first SOC value
|
||||
if (i == 0) {
|
||||
return OCV_SOC_PAIRS[0].soc;
|
||||
}
|
||||
|
||||
// If the target OCV is higher than the largest OCV in the array, return the
|
||||
// last SOC value
|
||||
if (i == array_length) {
|
||||
return OCV_SOC_PAIRS[array_length - 1].soc;
|
||||
}
|
||||
|
||||
// Perform linear interpolation
|
||||
uint16_t ocv1 = OCV_SOC_PAIRS[i - 1].ocv;
|
||||
uint16_t ocv2 = OCV_SOC_PAIRS[i].ocv;
|
||||
float soc1 = OCV_SOC_PAIRS[i - 1].soc;
|
||||
float soc2 = OCV_SOC_PAIRS[i].soc;
|
||||
|
||||
float slope = (soc2 - soc1) / (ocv2 - ocv1);
|
||||
float interpolated_soc = soc1 + slope * (ocv - ocv1);
|
||||
|
||||
return interpolated_soc;
|
||||
}
|
||||
540
Software/Core/Src/state_machine.c
Normal file
540
Software/Core/Src/state_machine.c
Normal file
@ -0,0 +1,540 @@
|
||||
/*
|
||||
* state_machine.h
|
||||
*
|
||||
* Created on: 07.07.2024
|
||||
* Author: Hamza
|
||||
*/
|
||||
|
||||
#include <state_machine.h>
|
||||
#include <stdint.h>
|
||||
#include "ADBMS_Abstraction.h"
|
||||
#include "AMS_HighLevel.h"
|
||||
#include "PWM_control.h"
|
||||
#include "can.h"
|
||||
#include "eeprom.h"
|
||||
#include "stm32f3xx_hal.h"
|
||||
|
||||
// Time to wait after reaching 95% of battery voltage before exiting precharge
|
||||
// Set this to 1000 in scruti to demonstrate the voltage on the multimeter
|
||||
#define PRECHARGE_DURATION 8000 // ms
|
||||
// Time to wait for discharge
|
||||
#define DISCHARGE_DURATION 8000 // ms
|
||||
// waiting time between to eeprom writes
|
||||
#define EEPROM_WRITE_FREQ 1000
|
||||
// how delay between steps of 5 -> 15ms * (100/5) = 300ms
|
||||
#define POWERGROUND_SOFTSTART_INCREMENT_DELAY 15
|
||||
// after errors are cleared wait for ERROR_LATCH_TIME ms before returning to inactive mode
|
||||
#define ERROR_LATCH_TIME 10000 //ms
|
||||
|
||||
/*
|
||||
10
|
||||
20
|
||||
30
|
||||
40
|
||||
50
|
||||
60
|
||||
70
|
||||
80
|
||||
90
|
||||
100
|
||||
*/
|
||||
|
||||
bool programming_mode;
|
||||
bool debugging_mode;
|
||||
|
||||
StateHandle state;
|
||||
int32_t RELAY_BAT_SIDE_VOLTAGE;
|
||||
int32_t RELAY_ESC_SIDE_VOLTAGE;
|
||||
int32_t CURRENT_MEASUREMENT;
|
||||
bool CURRENT_MEASUREMENT_ON;
|
||||
bool balancing_state;
|
||||
float base_offset = 0;
|
||||
|
||||
uint32_t error_timer;
|
||||
uint32_t precharge_timer;
|
||||
uint32_t discharge_timer;
|
||||
uint32_t balancing_timer;
|
||||
uint32_t eeprom_timer;
|
||||
|
||||
uint32_t powerground_softstart_timer;
|
||||
uint32_t powerground_calibration_timer;
|
||||
uint8_t powerground_calibration_stage;
|
||||
|
||||
uint8_t current_powerground_status;
|
||||
uint8_t target_powerground_status;
|
||||
|
||||
static uint32_t timestamp;
|
||||
|
||||
void sm_init(){
|
||||
state.current_state = STATE_INACTIVE;
|
||||
state.target_state = STATE_INACTIVE;
|
||||
state.error_source = 0;
|
||||
precharge_timer = discharge_timer = powerground_calibration_timer = error_timer = eeprom_timer = balancing_timer = 0;
|
||||
programming_mode = 0;
|
||||
debugging_mode = 0;
|
||||
balancing_state = 0;
|
||||
}
|
||||
|
||||
void sm_update(){
|
||||
|
||||
CURRENT_MEASUREMENT = (module.auxVoltages[0] > 2495) ? (module.auxVoltages[0] - (2495.0)) * (300.0) : 0;
|
||||
CURRENT_MEASUREMENT_ON = (module.auxVoltages[1] > 2400);
|
||||
RELAY_ESC_SIDE_VOLTAGE = module.auxVoltages[2] * 15.19;
|
||||
RELAY_BAT_SIDE_VOLTAGE = module.auxVoltages[3] * 15.19; // the calculation says the factor is 11. 11.711 yields the better result
|
||||
|
||||
if (can_timeout_timer < HAL_GetTick())
|
||||
state.current_state = state.target_state = STATE_INACTIVE;
|
||||
/*
|
||||
if (eeprom_timer < HAL_GetTick()){
|
||||
eeprom_write_status();
|
||||
eeprom_timer = HAL_GetTick() + EEPROM_WRITE_FREQ;
|
||||
}
|
||||
*/
|
||||
can_handle_send_status();
|
||||
can_handle_send_log();
|
||||
sm_check_errors();
|
||||
sm_precharge_discharge_manager();
|
||||
//sm_calibrate_powerground();
|
||||
sm_balancing();
|
||||
sm_powerground_manager();
|
||||
tmp1075_measure();
|
||||
status_led_update();
|
||||
soc_update();
|
||||
|
||||
switch (state.current_state) {
|
||||
case STATE_INACTIVE:
|
||||
state.current_state = sm_update_inactive(); // monitor only
|
||||
break;
|
||||
case STATE_PRECHARGE:
|
||||
state.current_state = sm_update_precharge(); // set PRECHARGE
|
||||
break;
|
||||
case STATE_READY:
|
||||
state.current_state = sm_update_ready();
|
||||
break;
|
||||
case STATE_ACTIVE:
|
||||
state.current_state = sm_update_active();
|
||||
break;
|
||||
case STATE_DISCHARGE:
|
||||
state.current_state = sm_update_discharge();
|
||||
break;
|
||||
case STATE_CHARGING_PRECHARGE:
|
||||
state.current_state = sm_update_charging_precharge();
|
||||
break;
|
||||
case STATE_CHARGING:
|
||||
state.current_state = sm_update_charging();
|
||||
break;
|
||||
case STATE_ERROR:
|
||||
state.current_state = sm_update_error(); // enter the correct ERROR state
|
||||
break;
|
||||
}
|
||||
|
||||
sm_set_relay_positions(state.current_state);
|
||||
state.target_state = state.current_state;
|
||||
}
|
||||
|
||||
void sm_handle_ams_in(const uint8_t *data){
|
||||
if (programming_mode == 1 && (state.current_state == STATE_READY || state.current_state == STATE_ACTIVE)){ PWM_powerground_control(data[1]); }
|
||||
|
||||
switch (data[0]) {
|
||||
case 0x00:
|
||||
if (state.current_state != STATE_INACTIVE){
|
||||
state.target_state = STATE_DISCHARGE;
|
||||
PWM_powerground_control(255);
|
||||
}
|
||||
break;
|
||||
case 0x01:
|
||||
if (state.target_state == STATE_INACTIVE || state.target_state == STATE_DISCHARGE){
|
||||
state.target_state = STATE_PRECHARGE;
|
||||
PWM_powerground_control(0);
|
||||
} else if (state.target_state == STATE_ACTIVE){
|
||||
state.target_state = STATE_READY;
|
||||
PWM_powerground_control(0);
|
||||
}
|
||||
break;
|
||||
case 0x02:
|
||||
if (state.current_state == STATE_READY || state.current_state == STATE_ACTIVE){
|
||||
target_powerground_status = data[1];
|
||||
state.target_state = STATE_ACTIVE; // READY -> ACTIVE
|
||||
}
|
||||
break;
|
||||
case 0xF0:
|
||||
if (state.current_state == STATE_INACTIVE){
|
||||
state.target_state = STATE_CHARGING_PRECHARGE;
|
||||
}
|
||||
break;
|
||||
case 0xF1: // EEPROM
|
||||
if (state.current_state == STATE_INACTIVE)
|
||||
can_handle_dump();
|
||||
break;
|
||||
case 0xFF: // EMERGENCY SHUTDOWN
|
||||
state.current_state = STATE_DISCHARGE;
|
||||
state.target_state = STATE_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void sm_precharge_discharge_manager(){
|
||||
|
||||
if (state.current_state != STATE_PRECHARGE && state.target_state == STATE_PRECHARGE){
|
||||
precharge_timer = HAL_GetTick() + PRECHARGE_DURATION;
|
||||
} else if (state.current_state == STATE_PRECHARGE && precharge_timer < HAL_GetTick()) {
|
||||
state.target_state = STATE_READY;
|
||||
precharge_timer = 0;
|
||||
}
|
||||
|
||||
if (state.current_state != STATE_CHARGING_PRECHARGE && state.target_state == STATE_CHARGING_PRECHARGE){
|
||||
precharge_timer = HAL_GetTick() + PRECHARGE_DURATION;
|
||||
} else if (state.current_state == STATE_CHARGING_PRECHARGE && precharge_timer < HAL_GetTick()) {
|
||||
state.target_state = STATE_CHARGING;
|
||||
precharge_timer = 0;
|
||||
}
|
||||
|
||||
if (state.current_state != STATE_DISCHARGE && state.target_state == STATE_DISCHARGE){
|
||||
discharge_timer = HAL_GetTick() + DISCHARGE_DURATION;
|
||||
} else if (state.current_state == STATE_DISCHARGE && discharge_timer < HAL_GetTick()) {
|
||||
state.target_state = STATE_INACTIVE;
|
||||
discharge_timer = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void sm_powerground_manager(){
|
||||
if (current_powerground_status == target_powerground_status)
|
||||
return;
|
||||
if ( current_powerground_status > 100 || target_powerground_status > 100){ //something went wrong
|
||||
PWM_powerground_control(255);
|
||||
current_powerground_status = target_powerground_status= 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (powerground_softstart_timer < HAL_GetTick()){
|
||||
if (current_powerground_status < target_powerground_status){
|
||||
current_powerground_status += 5;
|
||||
PWM_powerground_softcontrol();
|
||||
powerground_softstart_timer = HAL_GetTick() + POWERGROUND_SOFTSTART_INCREMENT_DELAY;
|
||||
} else if (current_powerground_status > target_powerground_status) {
|
||||
current_powerground_status -= 5;
|
||||
PWM_powerground_softcontrol();
|
||||
powerground_softstart_timer = HAL_GetTick() + POWERGROUND_SOFTSTART_INCREMENT_DELAY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void sm_calibrate_powerground(){
|
||||
if (powerground_calibration_stage != 4 && state.current_state == STATE_PRECHARGE){
|
||||
switch (powerground_calibration_stage) {
|
||||
case 0:
|
||||
powerground_calibration_timer = HAL_GetTick() + 0;
|
||||
powerground_calibration_stage = 1;
|
||||
return;
|
||||
case 1:
|
||||
if (powerground_calibration_timer < HAL_GetTick()){
|
||||
powerground_calibration_timer = HAL_GetTick() + 2000;
|
||||
powerground_calibration_stage = 2;
|
||||
PWM_powerground_control(100);
|
||||
}
|
||||
return;
|
||||
case 2:
|
||||
if (powerground_calibration_timer < HAL_GetTick()){
|
||||
powerground_calibration_timer = HAL_GetTick() + 1000;
|
||||
powerground_calibration_stage = 3;
|
||||
PWM_powerground_control(0);
|
||||
}
|
||||
return;
|
||||
case 3:
|
||||
if (powerground_calibration_timer < HAL_GetTick()){
|
||||
powerground_calibration_stage = 4;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void sm_balancing(){
|
||||
uint32_t channels = 0b11111111111111111111111111111100;
|
||||
if (balancing_timer < HAL_GetTick()){
|
||||
if (balancing_state){
|
||||
balancing_timer = HAL_GetTick() + 30000;
|
||||
|
||||
uint8_t id_cell_lowest_voltage = 0;
|
||||
uint8_t num_of_cells_to_balance = 0;
|
||||
uint32_t channels = 0;
|
||||
|
||||
for (int i = 0; i < 13; i++) {
|
||||
if (module.cellVoltages[i] < module.cellVoltages[id_cell_lowest_voltage])
|
||||
id_cell_lowest_voltage = i;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 13; i++) {
|
||||
if (module.cellVoltages[i] - 20 > module.cellVoltages[id_cell_lowest_voltage]){
|
||||
channels |= 1 << i;
|
||||
num_of_cells_to_balance++;
|
||||
}
|
||||
}
|
||||
|
||||
if (num_of_cells_to_balance == 0){
|
||||
amsStopBalancing();
|
||||
balancing_state = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
amsConfigBalancing(channels, 0xF);
|
||||
amsStartBalancing(0xF);
|
||||
balancing_state = 1;
|
||||
} else {
|
||||
balancing_timer = HAL_GetTick() + 1000;
|
||||
balancing_state = 0;
|
||||
amsStopBalancing();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void sm_program_powerground(){
|
||||
if (programming_mode == 0)
|
||||
return;
|
||||
PWM_powerground_control(100);
|
||||
state.current_state = state.target_state = STATE_ACTIVE;
|
||||
while (1) {
|
||||
can_handle_send_status();
|
||||
}
|
||||
}
|
||||
|
||||
void sm_eeprom_write_status(){
|
||||
if (eeprom_timer < HAL_GetTick()){
|
||||
eeprom_write_status();
|
||||
eeprom_timer = HAL_GetTick() + EEPROM_WRITE_FREQ;
|
||||
}
|
||||
}
|
||||
|
||||
void sm_check_errors(){
|
||||
if (programming_mode == 1 || debugging_mode == 1) {return;} // to disable error checking
|
||||
state.error_type.temperature_error = (error_data.error_sources & (1 << 0) || error_data.error_sources & (1 << 1) || error_data.error_sources & (1 << 4)) ? 1 : 0;
|
||||
state.error_type.voltage_error = (error_data.error_sources & (1 << 2)|| error_data.error_sources & (1 << 3)|| error_data.error_sources & (1 << 5) || RELAY_BAT_SIDE_VOLTAGE < 30000) ? 1 : 0;
|
||||
state.error_type.bms_timeout = (error_data.error_sources & (1 << 7)) ? 1 : 0;
|
||||
state.error_type.bms_fault = (error_data.error_sources & (1 << 8) || error_data.error_sources & (1 << 10) || error_data.error_sources & (1 << 9)) ? 1 : 0;
|
||||
//SEK_EEPROM_ERR: state.error_type.eeprom_error = 1;
|
||||
//state.error_type.current_error = (powerground_status > 10 && CURRENT_MEASUREMENT < 500) ? 1 : 0;
|
||||
state.error_type.current_sensor_missing = (!CURRENT_MEASUREMENT_ON) ? 1 : 0;
|
||||
state.error_type.voltage_missing = (RELAY_BAT_SIDE_VOLTAGE < 1000) ? 1 : 0;
|
||||
|
||||
|
||||
if (state.error_type.current_error == 1 || state.error_type.current_sensor_missing == 1 || //state.error_type.eeprom_error == 1 ||
|
||||
state.error_type.state_transition_fail == 1 || state.error_type.temperature_error == 1 || state.error_type.voltage_error == 1 ||
|
||||
state.error_type.voltage_missing == 1 || state.error_type.bms_fault == 1 || state.error_type.bms_timeout == 1)
|
||||
{
|
||||
if (state.current_state != STATE_INACTIVE && state.current_state != STATE_ERROR)
|
||||
state.current_state = STATE_DISCHARGE;
|
||||
state.target_state = STATE_ERROR;
|
||||
PWM_powerground_control(255);
|
||||
error_timer = HAL_GetTick() + ERROR_LATCH_TIME;
|
||||
} else if (state.current_state == STATE_ERROR && error_timer < HAL_GetTick()){
|
||||
state.target_state = STATE_INACTIVE;
|
||||
}
|
||||
sm_set_error_source();
|
||||
}
|
||||
|
||||
void sm_set_error_source(){
|
||||
state.error_source = 0;
|
||||
state.error_source |= (state.error_type.bms_timeout << 0);
|
||||
state.error_source |= (state.error_type.bms_fault << 1);
|
||||
state.error_source |= (state.error_type.temperature_error << 2);
|
||||
state.error_source |= (state.error_type.current_error << 3);
|
||||
|
||||
state.error_source |= (state.error_type.current_sensor_missing << 4);
|
||||
state.error_source |= (state.error_type.voltage_error << 5);
|
||||
state.error_source |= (state.error_type.voltage_missing << 6);
|
||||
state.error_source |= (state.error_type.state_transition_fail << 7);
|
||||
}
|
||||
|
||||
State sm_update_inactive(){
|
||||
switch (state.target_state) {
|
||||
case STATE_PRECHARGE:
|
||||
return STATE_PRECHARGE;
|
||||
case STATE_CHARGING_PRECHARGE:
|
||||
return STATE_CHARGING_PRECHARGE;
|
||||
case STATE_ERROR:
|
||||
return STATE_ERROR;
|
||||
default:
|
||||
return STATE_INACTIVE;
|
||||
}
|
||||
}
|
||||
|
||||
State sm_update_precharge(){
|
||||
switch (state.target_state) {
|
||||
case STATE_INACTIVE: // if CAN Signal 0000 0000 then immidiete shutdown
|
||||
return STATE_DISCHARGE;
|
||||
case STATE_READY:
|
||||
return STATE_READY;
|
||||
default:
|
||||
return STATE_PRECHARGE;
|
||||
}
|
||||
}
|
||||
|
||||
State sm_update_ready(){
|
||||
switch (state.target_state) {
|
||||
case STATE_ACTIVE: // if CAN Signal 1100 0000 then turn on powerground
|
||||
return STATE_ACTIVE;
|
||||
case STATE_DISCHARGE: // if CAN Signal 0000 0000 then shutdown
|
||||
return STATE_DISCHARGE;
|
||||
default:
|
||||
return STATE_READY;
|
||||
}
|
||||
}
|
||||
|
||||
State sm_update_active(){
|
||||
switch (state.target_state) {
|
||||
case STATE_READY: // if CAN Signal 1000 0000 then turn oof powerground but stay ready
|
||||
return STATE_READY;
|
||||
case STATE_DISCHARGE: // if CAN Signal 0000 0000 then shutdown
|
||||
return STATE_DISCHARGE;
|
||||
default:
|
||||
return STATE_ACTIVE;
|
||||
}
|
||||
}
|
||||
|
||||
State sm_update_discharge(){
|
||||
switch (state.target_state) {
|
||||
case STATE_INACTIVE:
|
||||
return STATE_INACTIVE;
|
||||
case STATE_ERROR:
|
||||
return STATE_ERROR;
|
||||
default:
|
||||
return STATE_DISCHARGE;
|
||||
}
|
||||
}
|
||||
|
||||
State sm_update_charging_precharge(){
|
||||
switch (state.target_state) {
|
||||
case STATE_CHARGING:
|
||||
return STATE_CHARGING;
|
||||
case STATE_DISCHARGE:
|
||||
return STATE_DISCHARGE;
|
||||
default:
|
||||
return STATE_CHARGING_PRECHARGE;
|
||||
}
|
||||
}
|
||||
|
||||
State sm_update_charging(){
|
||||
switch (state.target_state) {
|
||||
case STATE_DISCHARGE:
|
||||
currentAMSState = AMSIDLE;
|
||||
return STATE_DISCHARGE;
|
||||
default:
|
||||
currentAMSState = AMSCHARGING;
|
||||
return STATE_CHARGING;
|
||||
}
|
||||
}
|
||||
|
||||
State sm_update_error(){
|
||||
switch (state.target_state) {
|
||||
case STATE_DISCHARGE:
|
||||
return STATE_DISCHARGE;
|
||||
case STATE_INACTIVE:
|
||||
return STATE_INACTIVE;
|
||||
default:
|
||||
return STATE_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
void sm_set_relay_positions(State current_state){
|
||||
switch (state.current_state) {
|
||||
case STATE_INACTIVE:
|
||||
sm_set_relay(RELAY_MAIN, 0);
|
||||
sm_set_relay(RELAY_PRECHARGE, 0);
|
||||
break;
|
||||
case STATE_PRECHARGE:
|
||||
sm_set_relay(RELAY_MAIN, 0);
|
||||
sm_set_relay(RELAY_PRECHARGE, 1);
|
||||
break;
|
||||
case STATE_READY:
|
||||
sm_set_relay(RELAY_MAIN, 1);
|
||||
sm_set_relay(RELAY_PRECHARGE, 0);
|
||||
break;
|
||||
case STATE_ACTIVE:
|
||||
sm_set_relay(RELAY_MAIN, 1);
|
||||
sm_set_relay(RELAY_PRECHARGE, 0);
|
||||
break;
|
||||
case STATE_DISCHARGE:
|
||||
sm_set_relay(RELAY_MAIN, 0);
|
||||
sm_set_relay(RELAY_PRECHARGE, 1);
|
||||
break;
|
||||
case STATE_CHARGING_PRECHARGE:
|
||||
sm_set_relay(RELAY_MAIN, 0);
|
||||
sm_set_relay(RELAY_PRECHARGE, 1);
|
||||
break;
|
||||
case STATE_CHARGING:
|
||||
sm_set_relay(RELAY_MAIN, 1);
|
||||
sm_set_relay(RELAY_PRECHARGE, 0);
|
||||
break;
|
||||
case STATE_ERROR:
|
||||
sm_set_relay(RELAY_MAIN, 0);
|
||||
sm_set_relay(RELAY_PRECHARGE, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void sm_set_relay(Relay relay, bool closed){
|
||||
GPIO_PinState state = closed ? GPIO_PIN_SET : GPIO_PIN_RESET;
|
||||
switch (relay) {
|
||||
case RELAY_MAIN:
|
||||
HAL_GPIO_WritePin(RELAY_ENABLE_GPIO_Port, RELAY_ENABLE_Pin, state);
|
||||
break;
|
||||
case RELAY_PRECHARGE:
|
||||
HAL_GPIO_WritePin(PRECHARGE_ENABLE_GPIO_Port, PRECHARGE_ENABLE_Pin, state);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* returns the ID and temperature of the hottest cell */
|
||||
void sm_check_battery_temperature(uint8_t *id, uint16_t *temp){
|
||||
for (int i = 0; i < N_TEMP_SENSORS; i++) {
|
||||
if (tmp1075_temps[i] > *temp){
|
||||
*id = i;
|
||||
*temp = tmp1075_temps[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int16_t sm_return_cell_temperature(int id){ return tmp1075_temps[id]; }
|
||||
|
||||
int16_t sm_return_cell_voltage(int id){ return module.cellVoltages[id]; }
|
||||
|
||||
void sm_test_cycle_states(){
|
||||
RELAY_BAT_SIDE_VOLTAGE = module.auxVoltages[0];
|
||||
RELAY_ESC_SIDE_VOLTAGE = module.auxVoltages[1];
|
||||
CURRENT_MEASUREMENT = module.auxVoltages[2];
|
||||
sm_set_relay_positions(state.current_state);
|
||||
|
||||
if (timestamp > HAL_GetTick())
|
||||
return;
|
||||
switch (state.current_state) {
|
||||
case STATE_INACTIVE:
|
||||
state.current_state = STATE_PRECHARGE;
|
||||
timestamp = HAL_GetTick() + 30000;
|
||||
PWM_powerground_control(0);
|
||||
break;
|
||||
case STATE_PRECHARGE:
|
||||
state.current_state = STATE_READY;
|
||||
timestamp = HAL_GetTick() + 10000;
|
||||
break;
|
||||
case STATE_READY:
|
||||
state.current_state = STATE_ACTIVE;
|
||||
timestamp = HAL_GetTick() + 10000;
|
||||
break;
|
||||
case STATE_ACTIVE:
|
||||
state.current_state = STATE_DISCHARGE;
|
||||
timestamp = HAL_GetTick() + 10000;
|
||||
PWM_powerground_control(10);
|
||||
break;
|
||||
case STATE_DISCHARGE:
|
||||
state.current_state = STATE_INACTIVE;
|
||||
timestamp = HAL_GetTick() + 10000;
|
||||
break;
|
||||
case STATE_CHARGING_PRECHARGE:
|
||||
case STATE_CHARGING:
|
||||
case STATE_ERROR:
|
||||
break;
|
||||
}
|
||||
|
||||
state.target_state = state.current_state;
|
||||
}
|
||||
132
Software/Core/Src/status_LED.c
Normal file
132
Software/Core/Src/status_LED.c
Normal file
@ -0,0 +1,132 @@
|
||||
/*
|
||||
* status_LED.h
|
||||
*
|
||||
* Created on: 07.07.2024
|
||||
* Author: Hamza
|
||||
*/
|
||||
|
||||
#include "ADBMS_LL_Driver.h"
|
||||
#include "state_machine.h"
|
||||
#include "stm32f3xx_hal.h"
|
||||
#include <status_LED.h>
|
||||
#include <stdint.h>
|
||||
|
||||
// TODO test out pulldown and pushpull settings
|
||||
|
||||
/* The PWM period (1/FPWM) is defined by the following parameters:
|
||||
ARR value, the Prescaler value, and the internal clock itself which drives the timer module FCLK.
|
||||
F_PWM = (F_CLK)/((ARR + 1) * (PSC + 1))
|
||||
|
||||
Prescaler:
|
||||
(ARR + 1) * (PSC + 1) = (F_CLK)/(F_PWM)
|
||||
(PSC + 1) = (F_CLK)/(F_PWM * (ARR + 1))
|
||||
625 = (16MHz)/(100Hz * (255 + 1))
|
||||
|
||||
F_CLK = 16 MHz
|
||||
*/
|
||||
|
||||
#define STATUS_LED_ARR 255
|
||||
#define TIME_BLINK_SLOW 2000
|
||||
#define TIME_BLINK_FAST 500
|
||||
|
||||
TIM_HandleTypeDef* red;
|
||||
TIM_HandleTypeDef* green;
|
||||
TIM_HandleTypeDef* blue;
|
||||
|
||||
uint32_t blink_timer;
|
||||
bool blink_state;
|
||||
|
||||
void status_led_init(TIM_HandleTypeDef* r, TIM_HandleTypeDef* g, TIM_HandleTypeDef* b){
|
||||
red = r;
|
||||
green = g;
|
||||
blue = b;
|
||||
|
||||
blink_timer = 0;
|
||||
blink_state = 0;
|
||||
|
||||
HAL_TIM_PWM_Start(red, TIM_CHANNEL_1); //TIM4CH1
|
||||
HAL_TIM_PWM_Start(green, TIM_CHANNEL_2); //TIM4CH2
|
||||
HAL_TIM_PWM_Start(blue, TIM_CHANNEL_3); //TIM4CH3
|
||||
|
||||
status_led_set(255, 255, 255);
|
||||
}
|
||||
|
||||
void status_led_update(){
|
||||
if (state.current_state == STATE_ERROR){
|
||||
status_led_set_color(RED);
|
||||
return;
|
||||
}
|
||||
if(blink_timer > HAL_GetTick()){
|
||||
return;
|
||||
}
|
||||
|
||||
if (blink_state == 1){
|
||||
if (state.current_state == STATE_INACTIVE)
|
||||
blink_timer = HAL_GetTick() + TIME_BLINK_SLOW/10;
|
||||
else
|
||||
blink_timer = HAL_GetTick() + TIME_BLINK_FAST/10;
|
||||
blink_state = 0;
|
||||
status_led_set_color(OFF);
|
||||
return;
|
||||
} else {
|
||||
if (state.current_state == STATE_INACTIVE)
|
||||
blink_timer = HAL_GetTick() + TIME_BLINK_SLOW;
|
||||
else
|
||||
blink_timer = HAL_GetTick() + TIME_BLINK_FAST;
|
||||
blink_state = 1;
|
||||
}
|
||||
|
||||
switch (state.current_state) {
|
||||
case STATE_INACTIVE:
|
||||
status_led_set_color(GREEN);
|
||||
break;
|
||||
case STATE_CHARGING_PRECHARGE:
|
||||
case STATE_PRECHARGE:
|
||||
case STATE_DISCHARGE:
|
||||
status_led_set_color( YELLOW);
|
||||
break;
|
||||
case STATE_CHARGING:
|
||||
case STATE_READY:
|
||||
case STATE_ACTIVE:
|
||||
status_led_set_color(PINK);
|
||||
break;
|
||||
case STATE_ERROR:
|
||||
status_led_set_color(RED);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void status_led_set_color(color color){
|
||||
switch (color) {
|
||||
case RED:
|
||||
status_led_set(0, 255, 255);
|
||||
break;
|
||||
case GREEN:
|
||||
status_led_set(255, 0, 255);
|
||||
break;
|
||||
case BLUE:
|
||||
status_led_set(255, 255, 0);
|
||||
break;
|
||||
case YELLOW:
|
||||
status_led_set(0, 0, 255);
|
||||
break;
|
||||
case PINK:
|
||||
status_led_set(0, 255, 0);
|
||||
break;
|
||||
case CYAN:
|
||||
status_led_set(255, 0, 0);
|
||||
break;
|
||||
case WHITE:
|
||||
status_led_set(0, 0, 0);
|
||||
break;
|
||||
case OFF:
|
||||
status_led_set(255,255,255);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void status_led_set(uint8_t r, uint8_t g, uint8_t b){
|
||||
__HAL_TIM_SET_COMPARE(red, TIM_CHANNEL_1, r);
|
||||
__HAL_TIM_SET_COMPARE(green, TIM_CHANNEL_2, g);
|
||||
__HAL_TIM_SET_COMPARE(blue, TIM_CHANNEL_3, b);
|
||||
}
|
||||
546
Software/Core/Src/stm32f3xx_hal_msp.c
Normal file
546
Software/Core/Src/stm32f3xx_hal_msp.c
Normal file
@ -0,0 +1,546 @@
|
||||
/* USER CODE BEGIN Header */
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f3xx_hal_msp.c
|
||||
* @brief This file provides code for the MSP Initialization
|
||||
* and de-Initialization codes.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2024 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
/* USER CODE END Header */
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "main.h"
|
||||
/* USER CODE BEGIN Includes */
|
||||
|
||||
/* USER CODE END Includes */
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* USER CODE BEGIN TD */
|
||||
|
||||
/* USER CODE END TD */
|
||||
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/* USER CODE BEGIN Define */
|
||||
|
||||
/* USER CODE END Define */
|
||||
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* USER CODE BEGIN Macro */
|
||||
|
||||
/* USER CODE END Macro */
|
||||
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* USER CODE BEGIN PV */
|
||||
|
||||
/* USER CODE END PV */
|
||||
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/* USER CODE BEGIN PFP */
|
||||
|
||||
/* USER CODE END PFP */
|
||||
|
||||
/* External functions --------------------------------------------------------*/
|
||||
/* USER CODE BEGIN ExternalFunctions */
|
||||
|
||||
/* USER CODE END ExternalFunctions */
|
||||
|
||||
/* USER CODE BEGIN 0 */
|
||||
|
||||
/* USER CODE END 0 */
|
||||
|
||||
void HAL_TIM_MspPostInit(TIM_HandleTypeDef *htim);
|
||||
/**
|
||||
* Initializes the Global MSP.
|
||||
*/
|
||||
void HAL_MspInit(void)
|
||||
{
|
||||
|
||||
/* USER CODE BEGIN MspInit 0 */
|
||||
|
||||
/* USER CODE END MspInit 0 */
|
||||
|
||||
__HAL_RCC_SYSCFG_CLK_ENABLE();
|
||||
__HAL_RCC_PWR_CLK_ENABLE();
|
||||
|
||||
/* System interrupt init*/
|
||||
|
||||
/* USER CODE BEGIN MspInit 1 */
|
||||
|
||||
/* USER CODE END MspInit 1 */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief CAN MSP Initialization
|
||||
* This function configures the hardware resources used in this example
|
||||
* @param hcan: CAN handle pointer
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_CAN_MspInit(CAN_HandleTypeDef* hcan)
|
||||
{
|
||||
GPIO_InitTypeDef GPIO_InitStruct = {0};
|
||||
if(hcan->Instance==CAN)
|
||||
{
|
||||
/* USER CODE BEGIN CAN_MspInit 0 */
|
||||
|
||||
/* USER CODE END CAN_MspInit 0 */
|
||||
/* Peripheral clock enable */
|
||||
__HAL_RCC_CAN1_CLK_ENABLE();
|
||||
|
||||
__HAL_RCC_GPIOA_CLK_ENABLE();
|
||||
/**CAN GPIO Configuration
|
||||
PA11 ------> CAN_RX
|
||||
PA12 ------> CAN_TX
|
||||
*/
|
||||
GPIO_InitStruct.Pin = GPIO_PIN_11|GPIO_PIN_12;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
|
||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
|
||||
GPIO_InitStruct.Alternate = GPIO_AF9_CAN;
|
||||
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
|
||||
|
||||
/* CAN interrupt Init */
|
||||
HAL_NVIC_SetPriority(USB_LP_CAN_RX0_IRQn, 0, 0);
|
||||
HAL_NVIC_EnableIRQ(USB_LP_CAN_RX0_IRQn);
|
||||
HAL_NVIC_SetPriority(CAN_RX1_IRQn, 0, 0);
|
||||
HAL_NVIC_EnableIRQ(CAN_RX1_IRQn);
|
||||
/* USER CODE BEGIN CAN_MspInit 1 */
|
||||
|
||||
/* USER CODE END CAN_MspInit 1 */
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief CAN MSP De-Initialization
|
||||
* This function freeze the hardware resources used in this example
|
||||
* @param hcan: CAN handle pointer
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_CAN_MspDeInit(CAN_HandleTypeDef* hcan)
|
||||
{
|
||||
if(hcan->Instance==CAN)
|
||||
{
|
||||
/* USER CODE BEGIN CAN_MspDeInit 0 */
|
||||
|
||||
/* USER CODE END CAN_MspDeInit 0 */
|
||||
/* Peripheral clock disable */
|
||||
__HAL_RCC_CAN1_CLK_DISABLE();
|
||||
|
||||
/**CAN GPIO Configuration
|
||||
PA11 ------> CAN_RX
|
||||
PA12 ------> CAN_TX
|
||||
*/
|
||||
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_11|GPIO_PIN_12);
|
||||
|
||||
/* CAN interrupt DeInit */
|
||||
HAL_NVIC_DisableIRQ(USB_LP_CAN_RX0_IRQn);
|
||||
HAL_NVIC_DisableIRQ(CAN_RX1_IRQn);
|
||||
/* USER CODE BEGIN CAN_MspDeInit 1 */
|
||||
|
||||
/* USER CODE END CAN_MspDeInit 1 */
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief I2C MSP Initialization
|
||||
* This function configures the hardware resources used in this example
|
||||
* @param hi2c: I2C handle pointer
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_I2C_MspInit(I2C_HandleTypeDef* hi2c)
|
||||
{
|
||||
GPIO_InitTypeDef GPIO_InitStruct = {0};
|
||||
if(hi2c->Instance==I2C1)
|
||||
{
|
||||
/* USER CODE BEGIN I2C1_MspInit 0 */
|
||||
|
||||
/* USER CODE END I2C1_MspInit 0 */
|
||||
|
||||
__HAL_RCC_GPIOA_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOB_CLK_ENABLE();
|
||||
/**I2C1 GPIO Configuration
|
||||
PA15 ------> I2C1_SCL
|
||||
PB9 ------> I2C1_SDA
|
||||
*/
|
||||
GPIO_InitStruct.Pin = TMP_SCL_Pin;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
|
||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
|
||||
GPIO_InitStruct.Alternate = GPIO_AF4_I2C1;
|
||||
HAL_GPIO_Init(TMP_SCL_GPIO_Port, &GPIO_InitStruct);
|
||||
|
||||
GPIO_InitStruct.Pin = TMP_SDA_Pin;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
|
||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
|
||||
GPIO_InitStruct.Alternate = GPIO_AF4_I2C1;
|
||||
HAL_GPIO_Init(TMP_SDA_GPIO_Port, &GPIO_InitStruct);
|
||||
|
||||
/* Peripheral clock enable */
|
||||
__HAL_RCC_I2C1_CLK_ENABLE();
|
||||
/* USER CODE BEGIN I2C1_MspInit 1 */
|
||||
|
||||
/* USER CODE END I2C1_MspInit 1 */
|
||||
}
|
||||
else if(hi2c->Instance==I2C2)
|
||||
{
|
||||
/* USER CODE BEGIN I2C2_MspInit 0 */
|
||||
|
||||
/* USER CODE END I2C2_MspInit 0 */
|
||||
|
||||
__HAL_RCC_GPIOA_CLK_ENABLE();
|
||||
/**I2C2 GPIO Configuration
|
||||
PA9 ------> I2C2_SCL
|
||||
PA10 ------> I2C2_SDA
|
||||
*/
|
||||
GPIO_InitStruct.Pin = EEPROM_SCL_Pin|EEPROM_SDA_Pin;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
|
||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
|
||||
GPIO_InitStruct.Alternate = GPIO_AF4_I2C2;
|
||||
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
|
||||
|
||||
/* Peripheral clock enable */
|
||||
__HAL_RCC_I2C2_CLK_ENABLE();
|
||||
/* USER CODE BEGIN I2C2_MspInit 1 */
|
||||
|
||||
/* USER CODE END I2C2_MspInit 1 */
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief I2C MSP De-Initialization
|
||||
* This function freeze the hardware resources used in this example
|
||||
* @param hi2c: I2C handle pointer
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_I2C_MspDeInit(I2C_HandleTypeDef* hi2c)
|
||||
{
|
||||
if(hi2c->Instance==I2C1)
|
||||
{
|
||||
/* USER CODE BEGIN I2C1_MspDeInit 0 */
|
||||
|
||||
/* USER CODE END I2C1_MspDeInit 0 */
|
||||
/* Peripheral clock disable */
|
||||
__HAL_RCC_I2C1_CLK_DISABLE();
|
||||
|
||||
/**I2C1 GPIO Configuration
|
||||
PA15 ------> I2C1_SCL
|
||||
PB9 ------> I2C1_SDA
|
||||
*/
|
||||
HAL_GPIO_DeInit(TMP_SCL_GPIO_Port, TMP_SCL_Pin);
|
||||
|
||||
HAL_GPIO_DeInit(TMP_SDA_GPIO_Port, TMP_SDA_Pin);
|
||||
|
||||
/* USER CODE BEGIN I2C1_MspDeInit 1 */
|
||||
|
||||
/* USER CODE END I2C1_MspDeInit 1 */
|
||||
}
|
||||
else if(hi2c->Instance==I2C2)
|
||||
{
|
||||
/* USER CODE BEGIN I2C2_MspDeInit 0 */
|
||||
|
||||
/* USER CODE END I2C2_MspDeInit 0 */
|
||||
/* Peripheral clock disable */
|
||||
__HAL_RCC_I2C2_CLK_DISABLE();
|
||||
|
||||
/**I2C2 GPIO Configuration
|
||||
PA9 ------> I2C2_SCL
|
||||
PA10 ------> I2C2_SDA
|
||||
*/
|
||||
HAL_GPIO_DeInit(EEPROM_SCL_GPIO_Port, EEPROM_SCL_Pin);
|
||||
|
||||
HAL_GPIO_DeInit(EEPROM_SDA_GPIO_Port, EEPROM_SDA_Pin);
|
||||
|
||||
/* USER CODE BEGIN I2C2_MspDeInit 1 */
|
||||
|
||||
/* USER CODE END I2C2_MspDeInit 1 */
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief SPI MSP Initialization
|
||||
* This function configures the hardware resources used in this example
|
||||
* @param hspi: SPI handle pointer
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi)
|
||||
{
|
||||
GPIO_InitTypeDef GPIO_InitStruct = {0};
|
||||
if(hspi->Instance==SPI1)
|
||||
{
|
||||
/* USER CODE BEGIN SPI1_MspInit 0 */
|
||||
|
||||
/* USER CODE END SPI1_MspInit 0 */
|
||||
/* Peripheral clock enable */
|
||||
__HAL_RCC_SPI1_CLK_ENABLE();
|
||||
|
||||
__HAL_RCC_GPIOA_CLK_ENABLE();
|
||||
/**SPI1 GPIO Configuration
|
||||
PA5 ------> SPI1_SCK
|
||||
PA6 ------> SPI1_MISO
|
||||
PA7 ------> SPI1_MOSI
|
||||
*/
|
||||
GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
|
||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
|
||||
GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
|
||||
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
|
||||
|
||||
/* USER CODE BEGIN SPI1_MspInit 1 */
|
||||
|
||||
/* USER CODE END SPI1_MspInit 1 */
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief SPI MSP De-Initialization
|
||||
* This function freeze the hardware resources used in this example
|
||||
* @param hspi: SPI handle pointer
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_SPI_MspDeInit(SPI_HandleTypeDef* hspi)
|
||||
{
|
||||
if(hspi->Instance==SPI1)
|
||||
{
|
||||
/* USER CODE BEGIN SPI1_MspDeInit 0 */
|
||||
|
||||
/* USER CODE END SPI1_MspDeInit 0 */
|
||||
/* Peripheral clock disable */
|
||||
__HAL_RCC_SPI1_CLK_DISABLE();
|
||||
|
||||
/**SPI1 GPIO Configuration
|
||||
PA5 ------> SPI1_SCK
|
||||
PA6 ------> SPI1_MISO
|
||||
PA7 ------> SPI1_MOSI
|
||||
*/
|
||||
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7);
|
||||
|
||||
/* USER CODE BEGIN SPI1_MspDeInit 1 */
|
||||
|
||||
/* USER CODE END SPI1_MspDeInit 1 */
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief TIM_PWM MSP Initialization
|
||||
* This function configures the hardware resources used in this example
|
||||
* @param htim_pwm: TIM_PWM handle pointer
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef* htim_pwm)
|
||||
{
|
||||
if(htim_pwm->Instance==TIM2)
|
||||
{
|
||||
/* USER CODE BEGIN TIM2_MspInit 0 */
|
||||
|
||||
/* USER CODE END TIM2_MspInit 0 */
|
||||
/* Peripheral clock enable */
|
||||
__HAL_RCC_TIM2_CLK_ENABLE();
|
||||
/* USER CODE BEGIN TIM2_MspInit 1 */
|
||||
|
||||
/* USER CODE END TIM2_MspInit 1 */
|
||||
}
|
||||
else if(htim_pwm->Instance==TIM3)
|
||||
{
|
||||
/* USER CODE BEGIN TIM3_MspInit 0 */
|
||||
|
||||
/* USER CODE END TIM3_MspInit 0 */
|
||||
/* Peripheral clock enable */
|
||||
__HAL_RCC_TIM3_CLK_ENABLE();
|
||||
/* USER CODE BEGIN TIM3_MspInit 1 */
|
||||
|
||||
/* USER CODE END TIM3_MspInit 1 */
|
||||
}
|
||||
else if(htim_pwm->Instance==TIM4)
|
||||
{
|
||||
/* USER CODE BEGIN TIM4_MspInit 0 */
|
||||
|
||||
/* USER CODE END TIM4_MspInit 0 */
|
||||
/* Peripheral clock enable */
|
||||
__HAL_RCC_TIM4_CLK_ENABLE();
|
||||
/* USER CODE BEGIN TIM4_MspInit 1 */
|
||||
|
||||
/* USER CODE END TIM4_MspInit 1 */
|
||||
}
|
||||
else if(htim_pwm->Instance==TIM15)
|
||||
{
|
||||
/* USER CODE BEGIN TIM15_MspInit 0 */
|
||||
|
||||
/* USER CODE END TIM15_MspInit 0 */
|
||||
/* Peripheral clock enable */
|
||||
__HAL_RCC_TIM15_CLK_ENABLE();
|
||||
/* USER CODE BEGIN TIM15_MspInit 1 */
|
||||
|
||||
/* USER CODE END TIM15_MspInit 1 */
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void HAL_TIM_MspPostInit(TIM_HandleTypeDef* htim)
|
||||
{
|
||||
GPIO_InitTypeDef GPIO_InitStruct = {0};
|
||||
if(htim->Instance==TIM2)
|
||||
{
|
||||
/* USER CODE BEGIN TIM2_MspPostInit 0 */
|
||||
|
||||
/* USER CODE END TIM2_MspPostInit 0 */
|
||||
__HAL_RCC_GPIOB_CLK_ENABLE();
|
||||
/**TIM2 GPIO Configuration
|
||||
PB10 ------> TIM2_CH3
|
||||
PB11 ------> TIM2_CH4
|
||||
*/
|
||||
GPIO_InitStruct.Pin = BAT_COOLING_PWM_Pin|BAT_COOLING_ENABLE_Pin;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
|
||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
|
||||
GPIO_InitStruct.Alternate = GPIO_AF1_TIM2;
|
||||
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
|
||||
|
||||
/* USER CODE BEGIN TIM2_MspPostInit 1 */
|
||||
|
||||
/* USER CODE END TIM2_MspPostInit 1 */
|
||||
}
|
||||
else if(htim->Instance==TIM3)
|
||||
{
|
||||
/* USER CODE BEGIN TIM3_MspPostInit 0 */
|
||||
|
||||
/* USER CODE END TIM3_MspPostInit 0 */
|
||||
|
||||
__HAL_RCC_GPIOB_CLK_ENABLE();
|
||||
/**TIM3 GPIO Configuration
|
||||
PB0 ------> TIM3_CH3
|
||||
PB1 ------> TIM3_CH4
|
||||
*/
|
||||
GPIO_InitStruct.Pin = ESC_L_PWM_Pin|ESC_R_PWM_Pin;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
|
||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
|
||||
GPIO_InitStruct.Alternate = GPIO_AF2_TIM3;
|
||||
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
|
||||
|
||||
/* USER CODE BEGIN TIM3_MspPostInit 1 */
|
||||
|
||||
/* USER CODE END TIM3_MspPostInit 1 */
|
||||
}
|
||||
else if(htim->Instance==TIM4)
|
||||
{
|
||||
/* USER CODE BEGIN TIM4_MspPostInit 0 */
|
||||
|
||||
/* USER CODE END TIM4_MspPostInit 0 */
|
||||
|
||||
__HAL_RCC_GPIOB_CLK_ENABLE();
|
||||
/**TIM4 GPIO Configuration
|
||||
PB6 ------> TIM4_CH1
|
||||
PB7 ------> TIM4_CH2
|
||||
PB8 ------> TIM4_CH3
|
||||
*/
|
||||
GPIO_InitStruct.Pin = STATUS_LED_R_Pin|STATUS_LED_G_Pin|STATUS_LED_B_Pin;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
|
||||
GPIO_InitStruct.Pull = GPIO_PULLDOWN;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
|
||||
GPIO_InitStruct.Alternate = GPIO_AF2_TIM4;
|
||||
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
|
||||
|
||||
/* USER CODE BEGIN TIM4_MspPostInit 1 */
|
||||
|
||||
/* USER CODE END TIM4_MspPostInit 1 */
|
||||
}
|
||||
else if(htim->Instance==TIM15)
|
||||
{
|
||||
/* USER CODE BEGIN TIM15_MspPostInit 0 */
|
||||
|
||||
/* USER CODE END TIM15_MspPostInit 0 */
|
||||
|
||||
__HAL_RCC_GPIOB_CLK_ENABLE();
|
||||
/**TIM15 GPIO Configuration
|
||||
PB14 ------> TIM15_CH1
|
||||
PB15 ------> TIM15_CH2
|
||||
*/
|
||||
GPIO_InitStruct.Pin = ESC_COOLING_ENABLE_Pin|ESC_COOLING_PWM_Pin;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
|
||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
|
||||
GPIO_InitStruct.Alternate = GPIO_AF1_TIM15;
|
||||
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
|
||||
|
||||
/* USER CODE BEGIN TIM15_MspPostInit 1 */
|
||||
|
||||
/* USER CODE END TIM15_MspPostInit 1 */
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* @brief TIM_PWM MSP De-Initialization
|
||||
* This function freeze the hardware resources used in this example
|
||||
* @param htim_pwm: TIM_PWM handle pointer
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_TIM_PWM_MspDeInit(TIM_HandleTypeDef* htim_pwm)
|
||||
{
|
||||
if(htim_pwm->Instance==TIM2)
|
||||
{
|
||||
/* USER CODE BEGIN TIM2_MspDeInit 0 */
|
||||
|
||||
/* USER CODE END TIM2_MspDeInit 0 */
|
||||
/* Peripheral clock disable */
|
||||
__HAL_RCC_TIM2_CLK_DISABLE();
|
||||
/* USER CODE BEGIN TIM2_MspDeInit 1 */
|
||||
|
||||
/* USER CODE END TIM2_MspDeInit 1 */
|
||||
}
|
||||
else if(htim_pwm->Instance==TIM3)
|
||||
{
|
||||
/* USER CODE BEGIN TIM3_MspDeInit 0 */
|
||||
|
||||
/* USER CODE END TIM3_MspDeInit 0 */
|
||||
/* Peripheral clock disable */
|
||||
__HAL_RCC_TIM3_CLK_DISABLE();
|
||||
/* USER CODE BEGIN TIM3_MspDeInit 1 */
|
||||
|
||||
/* USER CODE END TIM3_MspDeInit 1 */
|
||||
}
|
||||
else if(htim_pwm->Instance==TIM4)
|
||||
{
|
||||
/* USER CODE BEGIN TIM4_MspDeInit 0 */
|
||||
|
||||
/* USER CODE END TIM4_MspDeInit 0 */
|
||||
/* Peripheral clock disable */
|
||||
__HAL_RCC_TIM4_CLK_DISABLE();
|
||||
/* USER CODE BEGIN TIM4_MspDeInit 1 */
|
||||
|
||||
/* USER CODE END TIM4_MspDeInit 1 */
|
||||
}
|
||||
else if(htim_pwm->Instance==TIM15)
|
||||
{
|
||||
/* USER CODE BEGIN TIM15_MspDeInit 0 */
|
||||
|
||||
/* USER CODE END TIM15_MspDeInit 0 */
|
||||
/* Peripheral clock disable */
|
||||
__HAL_RCC_TIM15_CLK_DISABLE();
|
||||
/* USER CODE BEGIN TIM15_MspDeInit 1 */
|
||||
|
||||
/* USER CODE END TIM15_MspDeInit 1 */
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* USER CODE BEGIN 1 */
|
||||
|
||||
/* USER CODE END 1 */
|
||||
231
Software/Core/Src/stm32f3xx_it.c
Normal file
231
Software/Core/Src/stm32f3xx_it.c
Normal file
@ -0,0 +1,231 @@
|
||||
/* USER CODE BEGIN Header */
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f3xx_it.c
|
||||
* @brief Interrupt Service Routines.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2024 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
/* USER CODE END Header */
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "main.h"
|
||||
#include "stm32f3xx_it.h"
|
||||
/* Private includes ----------------------------------------------------------*/
|
||||
/* USER CODE BEGIN Includes */
|
||||
/* USER CODE END Includes */
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* USER CODE BEGIN TD */
|
||||
|
||||
/* USER CODE END TD */
|
||||
|
||||
/* 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 PV */
|
||||
|
||||
/* USER CODE END PV */
|
||||
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/* USER CODE BEGIN PFP */
|
||||
|
||||
/* USER CODE END PFP */
|
||||
|
||||
/* Private user code ---------------------------------------------------------*/
|
||||
/* USER CODE BEGIN 0 */
|
||||
|
||||
/* USER CODE END 0 */
|
||||
|
||||
/* External variables --------------------------------------------------------*/
|
||||
extern CAN_HandleTypeDef hcan;
|
||||
/* USER CODE BEGIN EV */
|
||||
|
||||
/* USER CODE END EV */
|
||||
|
||||
/******************************************************************************/
|
||||
/* Cortex-M4 Processor Interruption and Exception Handlers */
|
||||
/******************************************************************************/
|
||||
/**
|
||||
* @brief This function handles Non maskable interrupt.
|
||||
*/
|
||||
void NMI_Handler(void)
|
||||
{
|
||||
/* USER CODE BEGIN NonMaskableInt_IRQn 0 */
|
||||
|
||||
/* USER CODE END NonMaskableInt_IRQn 0 */
|
||||
/* USER CODE BEGIN NonMaskableInt_IRQn 1 */
|
||||
while (1)
|
||||
{
|
||||
}
|
||||
/* USER CODE END NonMaskableInt_IRQn 1 */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles Hard fault interrupt.
|
||||
*/
|
||||
void HardFault_Handler(void)
|
||||
{
|
||||
/* USER CODE BEGIN HardFault_IRQn 0 */
|
||||
|
||||
/* USER CODE END HardFault_IRQn 0 */
|
||||
while (1)
|
||||
{
|
||||
/* USER CODE BEGIN W1_HardFault_IRQn 0 */
|
||||
/* USER CODE END W1_HardFault_IRQn 0 */
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles Memory management fault.
|
||||
*/
|
||||
void MemManage_Handler(void)
|
||||
{
|
||||
/* USER CODE BEGIN MemoryManagement_IRQn 0 */
|
||||
|
||||
/* USER CODE END MemoryManagement_IRQn 0 */
|
||||
while (1)
|
||||
{
|
||||
/* USER CODE BEGIN W1_MemoryManagement_IRQn 0 */
|
||||
/* USER CODE END W1_MemoryManagement_IRQn 0 */
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles Pre-fetch fault, memory access fault.
|
||||
*/
|
||||
void BusFault_Handler(void)
|
||||
{
|
||||
/* USER CODE BEGIN BusFault_IRQn 0 */
|
||||
|
||||
/* USER CODE END BusFault_IRQn 0 */
|
||||
while (1)
|
||||
{
|
||||
/* USER CODE BEGIN W1_BusFault_IRQn 0 */
|
||||
/* USER CODE END W1_BusFault_IRQn 0 */
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles Undefined instruction or illegal state.
|
||||
*/
|
||||
void UsageFault_Handler(void)
|
||||
{
|
||||
/* USER CODE BEGIN UsageFault_IRQn 0 */
|
||||
|
||||
/* USER CODE END UsageFault_IRQn 0 */
|
||||
while (1)
|
||||
{
|
||||
/* USER CODE BEGIN W1_UsageFault_IRQn 0 */
|
||||
/* USER CODE END W1_UsageFault_IRQn 0 */
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles System service call via SWI instruction.
|
||||
*/
|
||||
void SVC_Handler(void)
|
||||
{
|
||||
/* USER CODE BEGIN SVCall_IRQn 0 */
|
||||
|
||||
/* USER CODE END SVCall_IRQn 0 */
|
||||
/* USER CODE BEGIN SVCall_IRQn 1 */
|
||||
|
||||
/* USER CODE END SVCall_IRQn 1 */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles Debug monitor.
|
||||
*/
|
||||
void DebugMon_Handler(void)
|
||||
{
|
||||
/* USER CODE BEGIN DebugMonitor_IRQn 0 */
|
||||
|
||||
/* USER CODE END DebugMonitor_IRQn 0 */
|
||||
/* USER CODE BEGIN DebugMonitor_IRQn 1 */
|
||||
|
||||
/* USER CODE END DebugMonitor_IRQn 1 */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles Pendable request for system service.
|
||||
*/
|
||||
void PendSV_Handler(void)
|
||||
{
|
||||
/* USER CODE BEGIN PendSV_IRQn 0 */
|
||||
|
||||
/* USER CODE END PendSV_IRQn 0 */
|
||||
/* USER CODE BEGIN PendSV_IRQn 1 */
|
||||
|
||||
/* USER CODE END PendSV_IRQn 1 */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles System tick timer.
|
||||
*/
|
||||
void SysTick_Handler(void)
|
||||
{
|
||||
/* USER CODE BEGIN SysTick_IRQn 0 */
|
||||
|
||||
/* USER CODE END SysTick_IRQn 0 */
|
||||
HAL_IncTick();
|
||||
/* USER CODE BEGIN SysTick_IRQn 1 */
|
||||
|
||||
/* USER CODE END SysTick_IRQn 1 */
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/* STM32F3xx Peripheral Interrupt Handlers */
|
||||
/* Add here the Interrupt Handlers for the used peripherals. */
|
||||
/* For the available peripheral interrupt handler names, */
|
||||
/* please refer to the startup file (startup_stm32f3xx.s). */
|
||||
/******************************************************************************/
|
||||
|
||||
/**
|
||||
* @brief This function handles USB low priority or CAN_RX0 interrupts.
|
||||
*/
|
||||
void USB_LP_CAN_RX0_IRQHandler(void)
|
||||
{
|
||||
/* USER CODE BEGIN USB_LP_CAN_RX0_IRQn 0 */
|
||||
|
||||
/* USER CODE END USB_LP_CAN_RX0_IRQn 0 */
|
||||
HAL_CAN_IRQHandler(&hcan);
|
||||
/* USER CODE BEGIN USB_LP_CAN_RX0_IRQn 1 */
|
||||
|
||||
/* USER CODE END USB_LP_CAN_RX0_IRQn 1 */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles CAN RX1 interrupt.
|
||||
*/
|
||||
void CAN_RX1_IRQHandler(void)
|
||||
{
|
||||
/* USER CODE BEGIN CAN_RX1_IRQn 0 */
|
||||
|
||||
/* USER CODE END CAN_RX1_IRQn 0 */
|
||||
HAL_CAN_IRQHandler(&hcan);
|
||||
/* USER CODE BEGIN CAN_RX1_IRQn 1 */
|
||||
|
||||
/* USER CODE END CAN_RX1_IRQn 1 */
|
||||
}
|
||||
|
||||
/* USER CODE BEGIN 1 */
|
||||
|
||||
/* USER CODE END 1 */
|
||||
176
Software/Core/Src/syscalls.c
Normal file
176
Software/Core/Src/syscalls.c
Normal file
@ -0,0 +1,176 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file syscalls.c
|
||||
* @author Auto-generated by STM32CubeMX
|
||||
* @brief Minimal System calls file
|
||||
*
|
||||
* For more information about which c-functions
|
||||
* need which of these lowlevel functions
|
||||
* please consult the Newlib libc-manual
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2020-2024 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes */
|
||||
#include <sys/stat.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <signal.h>
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/times.h>
|
||||
|
||||
|
||||
/* Variables */
|
||||
extern int __io_putchar(int ch) __attribute__((weak));
|
||||
extern int __io_getchar(void) __attribute__((weak));
|
||||
|
||||
|
||||
char *__env[1] = { 0 };
|
||||
char **environ = __env;
|
||||
|
||||
|
||||
/* Functions */
|
||||
void initialise_monitor_handles()
|
||||
{
|
||||
}
|
||||
|
||||
int _getpid(void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
int _kill(int pid, int sig)
|
||||
{
|
||||
(void)pid;
|
||||
(void)sig;
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
void _exit (int status)
|
||||
{
|
||||
_kill(status, -1);
|
||||
while (1) {} /* Make sure we hang here */
|
||||
}
|
||||
|
||||
__attribute__((weak)) int _read(int file, char *ptr, int len)
|
||||
{
|
||||
(void)file;
|
||||
int DataIdx;
|
||||
|
||||
for (DataIdx = 0; DataIdx < len; DataIdx++)
|
||||
{
|
||||
*ptr++ = __io_getchar();
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
__attribute__((weak)) int _write(int file, char *ptr, int len)
|
||||
{
|
||||
(void)file;
|
||||
int DataIdx;
|
||||
|
||||
for (DataIdx = 0; DataIdx < len; DataIdx++)
|
||||
{
|
||||
__io_putchar(*ptr++);
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
int _close(int file)
|
||||
{
|
||||
(void)file;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int _fstat(int file, struct stat *st)
|
||||
{
|
||||
(void)file;
|
||||
st->st_mode = S_IFCHR;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _isatty(int file)
|
||||
{
|
||||
(void)file;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int _lseek(int file, int ptr, int dir)
|
||||
{
|
||||
(void)file;
|
||||
(void)ptr;
|
||||
(void)dir;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _open(char *path, int flags, ...)
|
||||
{
|
||||
(void)path;
|
||||
(void)flags;
|
||||
/* Pretend like we always fail */
|
||||
return -1;
|
||||
}
|
||||
|
||||
int _wait(int *status)
|
||||
{
|
||||
(void)status;
|
||||
errno = ECHILD;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int _unlink(char *name)
|
||||
{
|
||||
(void)name;
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int _times(struct tms *buf)
|
||||
{
|
||||
(void)buf;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int _stat(char *file, struct stat *st)
|
||||
{
|
||||
(void)file;
|
||||
st->st_mode = S_IFCHR;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _link(char *old, char *new)
|
||||
{
|
||||
(void)old;
|
||||
(void)new;
|
||||
errno = EMLINK;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int _fork(void)
|
||||
{
|
||||
errno = EAGAIN;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int _execve(char *name, char **argv, char **env)
|
||||
{
|
||||
(void)name;
|
||||
(void)argv;
|
||||
(void)env;
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
79
Software/Core/Src/sysmem.c
Normal file
79
Software/Core/Src/sysmem.c
Normal file
@ -0,0 +1,79 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file sysmem.c
|
||||
* @author Generated by STM32CubeMX
|
||||
* @brief System Memory calls file
|
||||
*
|
||||
* For more information about which C functions
|
||||
* need which of these lowlevel functions
|
||||
* please consult the newlib libc manual
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2024 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes */
|
||||
#include <errno.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* Pointer to the current high watermark of the heap usage
|
||||
*/
|
||||
static uint8_t *__sbrk_heap_end = NULL;
|
||||
|
||||
/**
|
||||
* @brief _sbrk() allocates memory to the newlib heap and is used by malloc
|
||||
* and others from the C library
|
||||
*
|
||||
* @verbatim
|
||||
* ############################################################################
|
||||
* # .data # .bss # newlib heap # MSP stack #
|
||||
* # # # # Reserved by _Min_Stack_Size #
|
||||
* ############################################################################
|
||||
* ^-- RAM start ^-- _end _estack, RAM end --^
|
||||
* @endverbatim
|
||||
*
|
||||
* This implementation starts allocating at the '_end' linker symbol
|
||||
* The '_Min_Stack_Size' linker symbol reserves a memory for the MSP stack
|
||||
* The implementation considers '_estack' linker symbol to be RAM end
|
||||
* NOTE: If the MSP stack, at any point during execution, grows larger than the
|
||||
* reserved size, please increase the '_Min_Stack_Size'.
|
||||
*
|
||||
* @param incr Memory size
|
||||
* @return Pointer to allocated memory
|
||||
*/
|
||||
void *_sbrk(ptrdiff_t incr)
|
||||
{
|
||||
extern uint8_t _end; /* Symbol defined in the linker script */
|
||||
extern uint8_t _estack; /* Symbol defined in the linker script */
|
||||
extern uint32_t _Min_Stack_Size; /* Symbol defined in the linker script */
|
||||
const uint32_t stack_limit = (uint32_t)&_estack - (uint32_t)&_Min_Stack_Size;
|
||||
const uint8_t *max_heap = (uint8_t *)stack_limit;
|
||||
uint8_t *prev_heap_end;
|
||||
|
||||
/* Initialize heap end at first call */
|
||||
if (NULL == __sbrk_heap_end)
|
||||
{
|
||||
__sbrk_heap_end = &_end;
|
||||
}
|
||||
|
||||
/* Protect heap from growing into the reserved MSP stack */
|
||||
if (__sbrk_heap_end + incr > max_heap)
|
||||
{
|
||||
errno = ENOMEM;
|
||||
return (void *)-1;
|
||||
}
|
||||
|
||||
prev_heap_end = __sbrk_heap_end;
|
||||
__sbrk_heap_end += incr;
|
||||
|
||||
return (void *)prev_heap_end;
|
||||
}
|
||||
287
Software/Core/Src/system_stm32f3xx.c
Normal file
287
Software/Core/Src/system_stm32f3xx.c
Normal file
@ -0,0 +1,287 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file system_stm32f3xx.c
|
||||
* @author MCD Application Team
|
||||
* @brief CMSIS Cortex-M4 Device Peripheral Access Layer System Source File.
|
||||
*
|
||||
* 1. This file provides two functions and one global variable to be called from
|
||||
* user application:
|
||||
* - SystemInit(): This function is called at startup just after reset and
|
||||
* before branch to main program. This call is made inside
|
||||
* the "startup_stm32f3xx.s" file.
|
||||
*
|
||||
* - SystemCoreClock variable: Contains the core clock (HCLK), it can be used
|
||||
* by the user application to setup the SysTick
|
||||
* timer or configure other parameters.
|
||||
*
|
||||
* - SystemCoreClockUpdate(): Updates the variable SystemCoreClock and must
|
||||
* be called whenever the core clock is changed
|
||||
* during program execution.
|
||||
*
|
||||
* 2. After each device reset the HSI (8 MHz) is used as system clock source.
|
||||
* Then SystemInit() function is called, in "startup_stm32f3xx.s" file, to
|
||||
* configure the system clock before to branch to main program.
|
||||
*
|
||||
* 3. This file configures the system clock as follows:
|
||||
*=============================================================================
|
||||
* Supported STM32F3xx device
|
||||
*-----------------------------------------------------------------------------
|
||||
* System Clock source | HSI
|
||||
*-----------------------------------------------------------------------------
|
||||
* SYSCLK(Hz) | 8000000
|
||||
*-----------------------------------------------------------------------------
|
||||
* HCLK(Hz) | 8000000
|
||||
*-----------------------------------------------------------------------------
|
||||
* AHB Prescaler | 1
|
||||
*-----------------------------------------------------------------------------
|
||||
* APB2 Prescaler | 1
|
||||
*-----------------------------------------------------------------------------
|
||||
* APB1 Prescaler | 1
|
||||
*-----------------------------------------------------------------------------
|
||||
* USB Clock | DISABLE
|
||||
*-----------------------------------------------------------------------------
|
||||
*=============================================================================
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2016 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/** @addtogroup CMSIS
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup stm32f3xx_system
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup STM32F3xx_System_Private_Includes
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "stm32f3xx.h"
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup STM32F3xx_System_Private_TypesDefinitions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup STM32F3xx_System_Private_Defines
|
||||
* @{
|
||||
*/
|
||||
#if !defined (HSE_VALUE)
|
||||
#define HSE_VALUE ((uint32_t)8000000) /*!< Default value of the External oscillator in Hz.
|
||||
This value can be provided and adapted by the user application. */
|
||||
#endif /* HSE_VALUE */
|
||||
|
||||
#if !defined (HSI_VALUE)
|
||||
#define HSI_VALUE ((uint32_t)8000000) /*!< Default value of the Internal oscillator in Hz.
|
||||
This value can be provided and adapted by the user application. */
|
||||
#endif /* HSI_VALUE */
|
||||
|
||||
/* Note: Following vector table addresses must be defined in line with linker
|
||||
configuration. */
|
||||
/*!< Uncomment the following line if you need to relocate the vector table
|
||||
anywhere in Flash or Sram, else the vector table is kept at the automatic
|
||||
remap of boot address selected */
|
||||
/* #define USER_VECT_TAB_ADDRESS */
|
||||
|
||||
#if defined(USER_VECT_TAB_ADDRESS)
|
||||
/*!< Uncomment the following line if you need to relocate your vector Table
|
||||
in Sram else user remap will be done in Flash. */
|
||||
/* #define VECT_TAB_SRAM */
|
||||
#if defined(VECT_TAB_SRAM)
|
||||
#define VECT_TAB_BASE_ADDRESS SRAM_BASE /*!< Vector Table base address field.
|
||||
This value must be a multiple of 0x200. */
|
||||
#define VECT_TAB_OFFSET 0x00000000U /*!< Vector Table base offset field.
|
||||
This value must be a multiple of 0x200. */
|
||||
#else
|
||||
#define VECT_TAB_BASE_ADDRESS FLASH_BASE /*!< Vector Table base address field.
|
||||
This value must be a multiple of 0x200. */
|
||||
#define VECT_TAB_OFFSET 0x00000000U /*!< Vector Table base offset field.
|
||||
This value must be a multiple of 0x200. */
|
||||
#endif /* VECT_TAB_SRAM */
|
||||
#endif /* USER_VECT_TAB_ADDRESS */
|
||||
|
||||
/******************************************************************************/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup STM32F3xx_System_Private_Macros
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup STM32F3xx_System_Private_Variables
|
||||
* @{
|
||||
*/
|
||||
/* This variable is updated in three ways:
|
||||
1) by calling CMSIS function SystemCoreClockUpdate()
|
||||
2) by calling HAL API function HAL_RCC_GetHCLKFreq()
|
||||
3) each time HAL_RCC_ClockConfig() is called to configure the system clock frequency
|
||||
Note: If you use this function to configure the system clock there is no need to
|
||||
call the 2 first functions listed above, since SystemCoreClock variable is
|
||||
updated automatically.
|
||||
*/
|
||||
uint32_t SystemCoreClock = 8000000;
|
||||
|
||||
const uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9};
|
||||
const uint8_t APBPrescTable[8] = {0, 0, 0, 0, 1, 2, 3, 4};
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup STM32F3xx_System_Private_FunctionPrototypes
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup STM32F3xx_System_Private_Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Setup the microcontroller system
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
void SystemInit(void)
|
||||
{
|
||||
/* FPU settings --------------------------------------------------------------*/
|
||||
#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
|
||||
SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2)); /* set CP10 and CP11 Full Access */
|
||||
#endif
|
||||
|
||||
/* Configure the Vector Table location -------------------------------------*/
|
||||
#if defined(USER_VECT_TAB_ADDRESS)
|
||||
SCB->VTOR = VECT_TAB_BASE_ADDRESS | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */
|
||||
#endif /* USER_VECT_TAB_ADDRESS */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Update SystemCoreClock variable according to Clock Register Values.
|
||||
* The SystemCoreClock variable contains the core clock (HCLK), it can
|
||||
* be used by the user application to setup the SysTick timer or configure
|
||||
* other parameters.
|
||||
*
|
||||
* @note Each time the core clock (HCLK) changes, this function must be called
|
||||
* to update SystemCoreClock variable value. Otherwise, any configuration
|
||||
* based on this variable will be incorrect.
|
||||
*
|
||||
* @note - The system frequency computed by this function is not the real
|
||||
* frequency in the chip. It is calculated based on the predefined
|
||||
* constant and the selected clock source:
|
||||
*
|
||||
* - If SYSCLK source is HSI, SystemCoreClock will contain the HSI_VALUE(*)
|
||||
*
|
||||
* - If SYSCLK source is HSE, SystemCoreClock will contain the HSE_VALUE(**)
|
||||
*
|
||||
* - If SYSCLK source is PLL, SystemCoreClock will contain the HSE_VALUE(**)
|
||||
* or HSI_VALUE(*) multiplied/divided by the PLL factors.
|
||||
*
|
||||
* (*) HSI_VALUE is a constant defined in stm32f3xx_hal.h file (default value
|
||||
* 8 MHz) but the real value may vary depending on the variations
|
||||
* in voltage and temperature.
|
||||
*
|
||||
* (**) HSE_VALUE is a constant defined in stm32f3xx_hal.h file (default value
|
||||
* 8 MHz), user has to ensure that HSE_VALUE is same as the real
|
||||
* frequency of the crystal used. Otherwise, this function may
|
||||
* have wrong result.
|
||||
*
|
||||
* - The result of this function could be not correct when using fractional
|
||||
* value for HSE crystal.
|
||||
*
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
void SystemCoreClockUpdate (void)
|
||||
{
|
||||
uint32_t tmp = 0, pllmull = 0, pllsource = 0, predivfactor = 0;
|
||||
|
||||
/* Get SYSCLK source -------------------------------------------------------*/
|
||||
tmp = RCC->CFGR & RCC_CFGR_SWS;
|
||||
|
||||
switch (tmp)
|
||||
{
|
||||
case RCC_CFGR_SWS_HSI: /* HSI used as system clock */
|
||||
SystemCoreClock = HSI_VALUE;
|
||||
break;
|
||||
case RCC_CFGR_SWS_HSE: /* HSE used as system clock */
|
||||
SystemCoreClock = HSE_VALUE;
|
||||
break;
|
||||
case RCC_CFGR_SWS_PLL: /* PLL used as system clock */
|
||||
/* Get PLL clock source and multiplication factor ----------------------*/
|
||||
pllmull = RCC->CFGR & RCC_CFGR_PLLMUL;
|
||||
pllsource = RCC->CFGR & RCC_CFGR_PLLSRC;
|
||||
pllmull = ( pllmull >> 18) + 2;
|
||||
|
||||
#if defined (STM32F302xE) || defined (STM32F303xE) || defined (STM32F398xx)
|
||||
predivfactor = (RCC->CFGR2 & RCC_CFGR2_PREDIV) + 1;
|
||||
if (pllsource == RCC_CFGR_PLLSRC_HSE_PREDIV)
|
||||
{
|
||||
/* HSE oscillator clock selected as PREDIV1 clock entry */
|
||||
SystemCoreClock = (HSE_VALUE / predivfactor) * pllmull;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* HSI oscillator clock selected as PREDIV1 clock entry */
|
||||
SystemCoreClock = (HSI_VALUE / predivfactor) * pllmull;
|
||||
}
|
||||
#else
|
||||
if (pllsource == RCC_CFGR_PLLSRC_HSI_DIV2)
|
||||
{
|
||||
/* HSI oscillator clock divided by 2 selected as PLL clock entry */
|
||||
SystemCoreClock = (HSI_VALUE >> 1) * pllmull;
|
||||
}
|
||||
else
|
||||
{
|
||||
predivfactor = (RCC->CFGR2 & RCC_CFGR2_PREDIV) + 1;
|
||||
/* HSE oscillator clock selected as PREDIV1 clock entry */
|
||||
SystemCoreClock = (HSE_VALUE / predivfactor) * pllmull;
|
||||
}
|
||||
#endif /* STM32F302xE || STM32F303xE || STM32F398xx */
|
||||
break;
|
||||
default: /* HSI used as system clock */
|
||||
SystemCoreClock = HSI_VALUE;
|
||||
break;
|
||||
}
|
||||
/* Compute HCLK clock frequency ----------------*/
|
||||
/* Get HCLK prescaler */
|
||||
tmp = AHBPrescTable[((RCC->CFGR & RCC_CFGR_HPRE) >> 4)];
|
||||
/* HCLK clock frequency */
|
||||
SystemCoreClock >>= tmp;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
BIN
Software/Documentation/AT 115A 14S.jpg
Normal file
BIN
Software/Documentation/AT 115A 14S.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.3 MiB |
3220
Software/Documentation/AT 195A 14S.pdf
Normal file
3220
Software/Documentation/AT 195A 14S.pdf
Normal file
File diff suppressed because one or more lines are too long
192
Software/Documentation/State machine diagram.drawio
Normal file
192
Software/Documentation/State machine diagram.drawio
Normal file
@ -0,0 +1,192 @@
|
||||
<mxfile host="app.diagrams.net" modified="2024-05-26T20:29:49.256Z" agent="Mozilla/5.0 (X11; Linux x86_64; rv:126.0) Gecko/20100101 Firefox/126.0" etag="129cpu7azo9v42CLPjC2" version="24.4.8" type="device">
|
||||
<diagram name="Page-1" id="1QHtqUjNJOinxrO5YjKP">
|
||||
<mxGraphModel dx="1500" dy="866" grid="1" gridSize="10" guides="0" tooltips="1" connect="0" arrows="0" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
|
||||
<root>
|
||||
<mxCell id="0" />
|
||||
<mxCell id="1" parent="0" />
|
||||
<mxCell id="Uq7C48yd8U4UPNIid9w1-36" value="" style="whiteSpace=wrap;html=1;movable=1;resizable=1;rotatable=1;deletable=1;editable=1;locked=0;connectable=1;glass=0;rounded=0;fillColor=default;" vertex="1" parent="1">
|
||||
<mxGeometry x="80" y="5.684341886080802e-14" width="680" height="720" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="Uq7C48yd8U4UPNIid9w1-2" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="Uq7C48yd8U4UPNIid9w1-1" target="Uq7C48yd8U4UPNIid9w1-3">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="420" y="420.00000000000006" as="targetPoint" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="Uq7C48yd8U4UPNIid9w1-20" value="CAN Signal: 1000 0000" style="edgeLabel;align=center;verticalAlign=middle;resizable=0;points=[];rounded=1;" vertex="1" connectable="0" parent="Uq7C48yd8U4UPNIid9w1-2">
|
||||
<mxGeometry y="3" relative="1" as="geometry">
|
||||
<mxPoint x="-63" as="offset" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="Uq7C48yd8U4UPNIid9w1-13" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="Uq7C48yd8U4UPNIid9w1-1" target="Uq7C48yd8U4UPNIid9w1-12">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<Array as="points">
|
||||
<mxPoint x="620" y="100.00000000000001" />
|
||||
</Array>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="Uq7C48yd8U4UPNIid9w1-22" value="RELAY_BAT_SIDE > RELAY_ESC_SIDE
for longer than 5 seconds
" style="edgeLabel;align=center;verticalAlign=middle;resizable=0;points=[];rounded=1;" vertex="1" connectable="0" parent="Uq7C48yd8U4UPNIid9w1-13">
|
||||
<mxGeometry x="-0.513" y="-2" relative="1" as="geometry">
|
||||
<mxPoint x="-22" y="-54" as="offset" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="Uq7C48yd8U4UPNIid9w1-1" value="INACTIVE" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="560" y="189.99999999999997" width="120" height="60" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="Uq7C48yd8U4UPNIid9w1-4" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="Uq7C48yd8U4UPNIid9w1-3" target="Uq7C48yd8U4UPNIid9w1-5">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="240" y="380.00000000000006" as="targetPoint" />
|
||||
<Array as="points">
|
||||
<mxPoint x="430" y="400.00000000000006" />
|
||||
<mxPoint x="430" y="400.00000000000006" />
|
||||
</Array>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="Uq7C48yd8U4UPNIid9w1-35" value="Allows quick shutdown. Could be done with ERROR" style="edgeLabel;align=center;verticalAlign=middle;resizable=0;points=[];rounded=1;" vertex="1" connectable="0" parent="Uq7C48yd8U4UPNIid9w1-4">
|
||||
<mxGeometry x="0.0063" relative="1" as="geometry">
|
||||
<mxPoint x="1" y="10" as="offset" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="Uq7C48yd8U4UPNIid9w1-7" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="Uq7C48yd8U4UPNIid9w1-3" target="Uq7C48yd8U4UPNIid9w1-6">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<Array as="points">
|
||||
<mxPoint x="620" y="520" />
|
||||
</Array>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="Uq7C48yd8U4UPNIid9w1-26" value="RELAY_BAT_SIDE = RELAY_ESC_SIDE
if it is around 90% done" style="edgeLabel;align=left;verticalAlign=middle;resizable=0;points=[];rounded=1;" vertex="1" connectable="0" parent="Uq7C48yd8U4UPNIid9w1-7">
|
||||
<mxGeometry x="-0.128" y="1" relative="1" as="geometry">
|
||||
<mxPoint x="-131" y="21" as="offset" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="Uq7C48yd8U4UPNIid9w1-3" value="PRECHARGE" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="560" y="350.00000000000006" width="120" height="60" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="Uq7C48yd8U4UPNIid9w1-17" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="Uq7C48yd8U4UPNIid9w1-5" target="Uq7C48yd8U4UPNIid9w1-3">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<Array as="points">
|
||||
<mxPoint x="420" y="380.00000000000006" />
|
||||
<mxPoint x="420" y="380.00000000000006" />
|
||||
</Array>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="Uq7C48yd8U4UPNIid9w1-34" value="Allows quick reactivation instead of shutdown" style="edgeLabel;align=center;verticalAlign=middle;resizable=0;points=[];rounded=1;" vertex="1" connectable="0" parent="Uq7C48yd8U4UPNIid9w1-17">
|
||||
<mxGeometry x="-0.0651" relative="1" as="geometry">
|
||||
<mxPoint x="9" y="-10" as="offset" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="Uq7C48yd8U4UPNIid9w1-31" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" target="Uq7C48yd8U4UPNIid9w1-1">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="280" y="360.00000000000006" as="sourcePoint" />
|
||||
<Array as="points">
|
||||
<mxPoint x="400" y="360.00000000000006" />
|
||||
<mxPoint x="400" y="219.99999999999997" />
|
||||
</Array>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="Uq7C48yd8U4UPNIid9w1-32" value="RELAY_ESC_SIDE == 0
" style="edgeLabel;align=center;verticalAlign=middle;resizable=0;points=[];rounded=1;" vertex="1" connectable="0" parent="Uq7C48yd8U4UPNIid9w1-31">
|
||||
<mxGeometry x="-0.0317" y="3" relative="1" as="geometry">
|
||||
<mxPoint x="83" y="-37" as="offset" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="Uq7C48yd8U4UPNIid9w1-5" value="DISCHARGE" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="160" y="350.00000000000006" width="120" height="60" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="Uq7C48yd8U4UPNIid9w1-8" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="1" source="Uq7C48yd8U4UPNIid9w1-6" target="Uq7C48yd8U4UPNIid9w1-5">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="Uq7C48yd8U4UPNIid9w1-10" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="Uq7C48yd8U4UPNIid9w1-6" target="Uq7C48yd8U4UPNIid9w1-9">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<Array as="points">
|
||||
<mxPoint x="440" y="600" />
|
||||
<mxPoint x="440" y="600" />
|
||||
</Array>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="Uq7C48yd8U4UPNIid9w1-27" value="CAN Signal = 1100 0000" style="edgeLabel;align=center;verticalAlign=middle;resizable=0;points=[];rounded=1;" vertex="1" connectable="0" parent="Uq7C48yd8U4UPNIid9w1-10">
|
||||
<mxGeometry x="-0.1" y="1" relative="1" as="geometry">
|
||||
<mxPoint x="69" as="offset" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="Uq7C48yd8U4UPNIid9w1-6" value="READY" style="whiteSpace=wrap;html=1;rounded=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="360" y="490.00000000000006" width="120" height="60" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="Uq7C48yd8U4UPNIid9w1-11" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="Uq7C48yd8U4UPNIid9w1-9" target="Uq7C48yd8U4UPNIid9w1-5">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="340" y="660" as="sourcePoint" />
|
||||
<mxPoint x="160" y="390" as="targetPoint" />
|
||||
<Array as="points">
|
||||
<mxPoint x="140" y="660" />
|
||||
<mxPoint x="140" y="390" />
|
||||
</Array>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="Uq7C48yd8U4UPNIid9w1-28" value="CAN Signal: 0000 0000 OR
Battery out of charge
" style="edgeLabel;align=center;verticalAlign=middle;resizable=0;points=[];rounded=1;" vertex="1" connectable="0" parent="Uq7C48yd8U4UPNIid9w1-11">
|
||||
<mxGeometry x="-0.6115" relative="1" as="geometry">
|
||||
<mxPoint y="30" as="offset" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="Uq7C48yd8U4UPNIid9w1-18" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="Uq7C48yd8U4UPNIid9w1-9" target="Uq7C48yd8U4UPNIid9w1-6">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<Array as="points">
|
||||
<mxPoint x="400" y="600" />
|
||||
<mxPoint x="400" y="600" />
|
||||
</Array>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="Uq7C48yd8U4UPNIid9w1-19" value="CAN_Signal: 1000 0000 " style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];rounded=1;" vertex="1" connectable="0" parent="Uq7C48yd8U4UPNIid9w1-18">
|
||||
<mxGeometry x="0.075" y="-3" relative="1" as="geometry">
|
||||
<mxPoint x="-73" as="offset" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="Uq7C48yd8U4UPNIid9w1-9" value="ACTIVE" style="whiteSpace=wrap;html=1;rounded=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="360" y="630" width="120" height="60" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="Uq7C48yd8U4UPNIid9w1-15" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="Uq7C48yd8U4UPNIid9w1-12" target="Uq7C48yd8U4UPNIid9w1-14">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="Uq7C48yd8U4UPNIid9w1-23" value="PRECHARGE is done 
" style="edgeLabel;align=center;verticalAlign=middle;resizable=0;points=[];rounded=1;" vertex="1" connectable="0" parent="Uq7C48yd8U4UPNIid9w1-15">
|
||||
<mxGeometry x="0.3217" y="1" relative="1" as="geometry">
|
||||
<mxPoint x="69" y="-22" as="offset" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="Uq7C48yd8U4UPNIid9w1-12" value="CHARGING
PRECHAGE" style="rounded=1;whiteSpace=wrap;" vertex="1" parent="1">
|
||||
<mxGeometry x="360" y="70" width="120" height="60" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="Uq7C48yd8U4UPNIid9w1-16" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="Uq7C48yd8U4UPNIid9w1-14" target="Uq7C48yd8U4UPNIid9w1-5">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="40" y="380.00000000000006" as="targetPoint" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="Uq7C48yd8U4UPNIid9w1-24" value="CHARGING is done" style="edgeLabel;align=center;verticalAlign=middle;resizable=0;points=[];rounded=1;" vertex="1" connectable="0" parent="Uq7C48yd8U4UPNIid9w1-16">
|
||||
<mxGeometry x="-0.1" y="1" relative="1" as="geometry">
|
||||
<mxPoint x="59" y="5" as="offset" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="Uq7C48yd8U4UPNIid9w1-14" value="CHARGING" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="160" y="189.99999999999997" width="120" height="60" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="Uq7C48yd8U4UPNIid9w1-30" value="CAN_Signal: 0000 0000 " style="edgeLabel;align=center;verticalAlign=middle;resizable=0;points=[];rounded=1;" vertex="1" connectable="0" parent="1">
|
||||
<mxGeometry x="280" y="520" as="geometry">
|
||||
<mxPoint x="12" y="11" as="offset" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="Uq7C48yd8U4UPNIid9w1-46" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.503;exitY=-0.006;exitDx=0;exitDy=0;exitPerimeter=0;" edge="1" parent="1" source="Uq7C48yd8U4UPNIid9w1-12" target="Uq7C48yd8U4UPNIid9w1-5">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="420" y="59.99" as="sourcePoint" />
|
||||
<mxPoint x="200" y="350.00000000000006" as="targetPoint" />
|
||||
<Array as="points">
|
||||
<mxPoint x="420" y="40" />
|
||||
<mxPoint x="120" y="40" />
|
||||
<mxPoint x="120" y="370" />
|
||||
</Array>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="Uq7C48yd8U4UPNIid9w1-48" value="PRECHARGE failure" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="Uq7C48yd8U4UPNIid9w1-46">
|
||||
<mxGeometry x="0.2339" y="-1" relative="1" as="geometry">
|
||||
<mxPoint x="61" y="-91" as="offset" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
</root>
|
||||
</mxGraphModel>
|
||||
</diagram>
|
||||
</mxfile>
|
||||
4
Software/Documentation/State machine diagram.svg
Normal file
4
Software/Documentation/State machine diagram.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 36 KiB |
865
Software/Drivers/CMSIS/Core/Include/cmsis_armcc.h
Normal file
865
Software/Drivers/CMSIS/Core/Include/cmsis_armcc.h
Normal file
@ -0,0 +1,865 @@
|
||||
/**************************************************************************//**
|
||||
* @file cmsis_armcc.h
|
||||
* @brief CMSIS compiler ARMCC (Arm Compiler 5) header file
|
||||
* @version V5.0.4
|
||||
* @date 10. January 2018
|
||||
******************************************************************************/
|
||||
/*
|
||||
* Copyright (c) 2009-2018 Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef __CMSIS_ARMCC_H
|
||||
#define __CMSIS_ARMCC_H
|
||||
|
||||
|
||||
#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 400677)
|
||||
#error "Please use Arm Compiler Toolchain V4.0.677 or later!"
|
||||
#endif
|
||||
|
||||
/* CMSIS compiler control architecture macros */
|
||||
#if ((defined (__TARGET_ARCH_6_M ) && (__TARGET_ARCH_6_M == 1)) || \
|
||||
(defined (__TARGET_ARCH_6S_M ) && (__TARGET_ARCH_6S_M == 1)) )
|
||||
#define __ARM_ARCH_6M__ 1
|
||||
#endif
|
||||
|
||||
#if (defined (__TARGET_ARCH_7_M ) && (__TARGET_ARCH_7_M == 1))
|
||||
#define __ARM_ARCH_7M__ 1
|
||||
#endif
|
||||
|
||||
#if (defined (__TARGET_ARCH_7E_M) && (__TARGET_ARCH_7E_M == 1))
|
||||
#define __ARM_ARCH_7EM__ 1
|
||||
#endif
|
||||
|
||||
/* __ARM_ARCH_8M_BASE__ not applicable */
|
||||
/* __ARM_ARCH_8M_MAIN__ not applicable */
|
||||
|
||||
|
||||
/* CMSIS compiler specific defines */
|
||||
#ifndef __ASM
|
||||
#define __ASM __asm
|
||||
#endif
|
||||
#ifndef __INLINE
|
||||
#define __INLINE __inline
|
||||
#endif
|
||||
#ifndef __STATIC_INLINE
|
||||
#define __STATIC_INLINE static __inline
|
||||
#endif
|
||||
#ifndef __STATIC_FORCEINLINE
|
||||
#define __STATIC_FORCEINLINE static __forceinline
|
||||
#endif
|
||||
#ifndef __NO_RETURN
|
||||
#define __NO_RETURN __declspec(noreturn)
|
||||
#endif
|
||||
#ifndef __USED
|
||||
#define __USED __attribute__((used))
|
||||
#endif
|
||||
#ifndef __WEAK
|
||||
#define __WEAK __attribute__((weak))
|
||||
#endif
|
||||
#ifndef __PACKED
|
||||
#define __PACKED __attribute__((packed))
|
||||
#endif
|
||||
#ifndef __PACKED_STRUCT
|
||||
#define __PACKED_STRUCT __packed struct
|
||||
#endif
|
||||
#ifndef __PACKED_UNION
|
||||
#define __PACKED_UNION __packed union
|
||||
#endif
|
||||
#ifndef __UNALIGNED_UINT32 /* deprecated */
|
||||
#define __UNALIGNED_UINT32(x) (*((__packed uint32_t *)(x)))
|
||||
#endif
|
||||
#ifndef __UNALIGNED_UINT16_WRITE
|
||||
#define __UNALIGNED_UINT16_WRITE(addr, val) ((*((__packed uint16_t *)(addr))) = (val))
|
||||
#endif
|
||||
#ifndef __UNALIGNED_UINT16_READ
|
||||
#define __UNALIGNED_UINT16_READ(addr) (*((const __packed uint16_t *)(addr)))
|
||||
#endif
|
||||
#ifndef __UNALIGNED_UINT32_WRITE
|
||||
#define __UNALIGNED_UINT32_WRITE(addr, val) ((*((__packed uint32_t *)(addr))) = (val))
|
||||
#endif
|
||||
#ifndef __UNALIGNED_UINT32_READ
|
||||
#define __UNALIGNED_UINT32_READ(addr) (*((const __packed uint32_t *)(addr)))
|
||||
#endif
|
||||
#ifndef __ALIGNED
|
||||
#define __ALIGNED(x) __attribute__((aligned(x)))
|
||||
#endif
|
||||
#ifndef __RESTRICT
|
||||
#define __RESTRICT __restrict
|
||||
#endif
|
||||
|
||||
/* ########################### Core Function Access ########################### */
|
||||
/** \ingroup CMSIS_Core_FunctionInterface
|
||||
\defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions
|
||||
@{
|
||||
*/
|
||||
|
||||
/**
|
||||
\brief Enable IRQ Interrupts
|
||||
\details Enables IRQ interrupts by clearing the I-bit in the CPSR.
|
||||
Can only be executed in Privileged modes.
|
||||
*/
|
||||
/* intrinsic void __enable_irq(); */
|
||||
|
||||
|
||||
/**
|
||||
\brief Disable IRQ Interrupts
|
||||
\details Disables IRQ interrupts by setting the I-bit in the CPSR.
|
||||
Can only be executed in Privileged modes.
|
||||
*/
|
||||
/* intrinsic void __disable_irq(); */
|
||||
|
||||
/**
|
||||
\brief Get Control Register
|
||||
\details Returns the content of the Control Register.
|
||||
\return Control Register value
|
||||
*/
|
||||
__STATIC_INLINE uint32_t __get_CONTROL(void)
|
||||
{
|
||||
register uint32_t __regControl __ASM("control");
|
||||
return(__regControl);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\brief Set Control Register
|
||||
\details Writes the given value to the Control Register.
|
||||
\param [in] control Control Register value to set
|
||||
*/
|
||||
__STATIC_INLINE void __set_CONTROL(uint32_t control)
|
||||
{
|
||||
register uint32_t __regControl __ASM("control");
|
||||
__regControl = control;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\brief Get IPSR Register
|
||||
\details Returns the content of the IPSR Register.
|
||||
\return IPSR Register value
|
||||
*/
|
||||
__STATIC_INLINE uint32_t __get_IPSR(void)
|
||||
{
|
||||
register uint32_t __regIPSR __ASM("ipsr");
|
||||
return(__regIPSR);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\brief Get APSR Register
|
||||
\details Returns the content of the APSR Register.
|
||||
\return APSR Register value
|
||||
*/
|
||||
__STATIC_INLINE uint32_t __get_APSR(void)
|
||||
{
|
||||
register uint32_t __regAPSR __ASM("apsr");
|
||||
return(__regAPSR);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\brief Get xPSR Register
|
||||
\details Returns the content of the xPSR Register.
|
||||
\return xPSR Register value
|
||||
*/
|
||||
__STATIC_INLINE uint32_t __get_xPSR(void)
|
||||
{
|
||||
register uint32_t __regXPSR __ASM("xpsr");
|
||||
return(__regXPSR);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\brief Get Process Stack Pointer
|
||||
\details Returns the current value of the Process Stack Pointer (PSP).
|
||||
\return PSP Register value
|
||||
*/
|
||||
__STATIC_INLINE uint32_t __get_PSP(void)
|
||||
{
|
||||
register uint32_t __regProcessStackPointer __ASM("psp");
|
||||
return(__regProcessStackPointer);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\brief Set Process Stack Pointer
|
||||
\details Assigns the given value to the Process Stack Pointer (PSP).
|
||||
\param [in] topOfProcStack Process Stack Pointer value to set
|
||||
*/
|
||||
__STATIC_INLINE void __set_PSP(uint32_t topOfProcStack)
|
||||
{
|
||||
register uint32_t __regProcessStackPointer __ASM("psp");
|
||||
__regProcessStackPointer = topOfProcStack;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\brief Get Main Stack Pointer
|
||||
\details Returns the current value of the Main Stack Pointer (MSP).
|
||||
\return MSP Register value
|
||||
*/
|
||||
__STATIC_INLINE uint32_t __get_MSP(void)
|
||||
{
|
||||
register uint32_t __regMainStackPointer __ASM("msp");
|
||||
return(__regMainStackPointer);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\brief Set Main Stack Pointer
|
||||
\details Assigns the given value to the Main Stack Pointer (MSP).
|
||||
\param [in] topOfMainStack Main Stack Pointer value to set
|
||||
*/
|
||||
__STATIC_INLINE void __set_MSP(uint32_t topOfMainStack)
|
||||
{
|
||||
register uint32_t __regMainStackPointer __ASM("msp");
|
||||
__regMainStackPointer = topOfMainStack;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\brief Get Priority Mask
|
||||
\details Returns the current state of the priority mask bit from the Priority Mask Register.
|
||||
\return Priority Mask value
|
||||
*/
|
||||
__STATIC_INLINE uint32_t __get_PRIMASK(void)
|
||||
{
|
||||
register uint32_t __regPriMask __ASM("primask");
|
||||
return(__regPriMask);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\brief Set Priority Mask
|
||||
\details Assigns the given value to the Priority Mask Register.
|
||||
\param [in] priMask Priority Mask
|
||||
*/
|
||||
__STATIC_INLINE void __set_PRIMASK(uint32_t priMask)
|
||||
{
|
||||
register uint32_t __regPriMask __ASM("primask");
|
||||
__regPriMask = (priMask);
|
||||
}
|
||||
|
||||
|
||||
#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \
|
||||
(defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) )
|
||||
|
||||
/**
|
||||
\brief Enable FIQ
|
||||
\details Enables FIQ interrupts by clearing the F-bit in the CPSR.
|
||||
Can only be executed in Privileged modes.
|
||||
*/
|
||||
#define __enable_fault_irq __enable_fiq
|
||||
|
||||
|
||||
/**
|
||||
\brief Disable FIQ
|
||||
\details Disables FIQ interrupts by setting the F-bit in the CPSR.
|
||||
Can only be executed in Privileged modes.
|
||||
*/
|
||||
#define __disable_fault_irq __disable_fiq
|
||||
|
||||
|
||||
/**
|
||||
\brief Get Base Priority
|
||||
\details Returns the current value of the Base Priority register.
|
||||
\return Base Priority register value
|
||||
*/
|
||||
__STATIC_INLINE uint32_t __get_BASEPRI(void)
|
||||
{
|
||||
register uint32_t __regBasePri __ASM("basepri");
|
||||
return(__regBasePri);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\brief Set Base Priority
|
||||
\details Assigns the given value to the Base Priority register.
|
||||
\param [in] basePri Base Priority value to set
|
||||
*/
|
||||
__STATIC_INLINE void __set_BASEPRI(uint32_t basePri)
|
||||
{
|
||||
register uint32_t __regBasePri __ASM("basepri");
|
||||
__regBasePri = (basePri & 0xFFU);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\brief Set Base Priority with condition
|
||||
\details Assigns the given value to the Base Priority register only if BASEPRI masking is disabled,
|
||||
or the new value increases the BASEPRI priority level.
|
||||
\param [in] basePri Base Priority value to set
|
||||
*/
|
||||
__STATIC_INLINE void __set_BASEPRI_MAX(uint32_t basePri)
|
||||
{
|
||||
register uint32_t __regBasePriMax __ASM("basepri_max");
|
||||
__regBasePriMax = (basePri & 0xFFU);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\brief Get Fault Mask
|
||||
\details Returns the current value of the Fault Mask register.
|
||||
\return Fault Mask register value
|
||||
*/
|
||||
__STATIC_INLINE uint32_t __get_FAULTMASK(void)
|
||||
{
|
||||
register uint32_t __regFaultMask __ASM("faultmask");
|
||||
return(__regFaultMask);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\brief Set Fault Mask
|
||||
\details Assigns the given value to the Fault Mask register.
|
||||
\param [in] faultMask Fault Mask value to set
|
||||
*/
|
||||
__STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask)
|
||||
{
|
||||
register uint32_t __regFaultMask __ASM("faultmask");
|
||||
__regFaultMask = (faultMask & (uint32_t)1U);
|
||||
}
|
||||
|
||||
#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \
|
||||
(defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) */
|
||||
|
||||
|
||||
/**
|
||||
\brief Get FPSCR
|
||||
\details Returns the current value of the Floating Point Status/Control register.
|
||||
\return Floating Point Status/Control register value
|
||||
*/
|
||||
__STATIC_INLINE uint32_t __get_FPSCR(void)
|
||||
{
|
||||
#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \
|
||||
(defined (__FPU_USED ) && (__FPU_USED == 1U)) )
|
||||
register uint32_t __regfpscr __ASM("fpscr");
|
||||
return(__regfpscr);
|
||||
#else
|
||||
return(0U);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\brief Set FPSCR
|
||||
\details Assigns the given value to the Floating Point Status/Control register.
|
||||
\param [in] fpscr Floating Point Status/Control value to set
|
||||
*/
|
||||
__STATIC_INLINE void __set_FPSCR(uint32_t fpscr)
|
||||
{
|
||||
#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \
|
||||
(defined (__FPU_USED ) && (__FPU_USED == 1U)) )
|
||||
register uint32_t __regfpscr __ASM("fpscr");
|
||||
__regfpscr = (fpscr);
|
||||
#else
|
||||
(void)fpscr;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*@} end of CMSIS_Core_RegAccFunctions */
|
||||
|
||||
|
||||
/* ########################## Core Instruction Access ######################### */
|
||||
/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface
|
||||
Access to dedicated instructions
|
||||
@{
|
||||
*/
|
||||
|
||||
/**
|
||||
\brief No Operation
|
||||
\details No Operation does nothing. This instruction can be used for code alignment purposes.
|
||||
*/
|
||||
#define __NOP __nop
|
||||
|
||||
|
||||
/**
|
||||
\brief Wait For Interrupt
|
||||
\details Wait For Interrupt is a hint instruction that suspends execution until one of a number of events occurs.
|
||||
*/
|
||||
#define __WFI __wfi
|
||||
|
||||
|
||||
/**
|
||||
\brief Wait For Event
|
||||
\details Wait For Event is a hint instruction that permits the processor to enter
|
||||
a low-power state until one of a number of events occurs.
|
||||
*/
|
||||
#define __WFE __wfe
|
||||
|
||||
|
||||
/**
|
||||
\brief Send Event
|
||||
\details Send Event is a hint instruction. It causes an event to be signaled to the CPU.
|
||||
*/
|
||||
#define __SEV __sev
|
||||
|
||||
|
||||
/**
|
||||
\brief Instruction Synchronization Barrier
|
||||
\details Instruction Synchronization Barrier flushes the pipeline in the processor,
|
||||
so that all instructions following the ISB are fetched from cache or memory,
|
||||
after the instruction has been completed.
|
||||
*/
|
||||
#define __ISB() do {\
|
||||
__schedule_barrier();\
|
||||
__isb(0xF);\
|
||||
__schedule_barrier();\
|
||||
} while (0U)
|
||||
|
||||
/**
|
||||
\brief Data Synchronization Barrier
|
||||
\details Acts as a special kind of Data Memory Barrier.
|
||||
It completes when all explicit memory accesses before this instruction complete.
|
||||
*/
|
||||
#define __DSB() do {\
|
||||
__schedule_barrier();\
|
||||
__dsb(0xF);\
|
||||
__schedule_barrier();\
|
||||
} while (0U)
|
||||
|
||||
/**
|
||||
\brief Data Memory Barrier
|
||||
\details Ensures the apparent order of the explicit memory operations before
|
||||
and after the instruction, without ensuring their completion.
|
||||
*/
|
||||
#define __DMB() do {\
|
||||
__schedule_barrier();\
|
||||
__dmb(0xF);\
|
||||
__schedule_barrier();\
|
||||
} while (0U)
|
||||
|
||||
|
||||
/**
|
||||
\brief Reverse byte order (32 bit)
|
||||
\details Reverses the byte order in unsigned integer value. For example, 0x12345678 becomes 0x78563412.
|
||||
\param [in] value Value to reverse
|
||||
\return Reversed value
|
||||
*/
|
||||
#define __REV __rev
|
||||
|
||||
|
||||
/**
|
||||
\brief Reverse byte order (16 bit)
|
||||
\details Reverses the byte order within each halfword of a word. For example, 0x12345678 becomes 0x34127856.
|
||||
\param [in] value Value to reverse
|
||||
\return Reversed value
|
||||
*/
|
||||
#ifndef __NO_EMBEDDED_ASM
|
||||
__attribute__((section(".rev16_text"))) __STATIC_INLINE __ASM uint32_t __REV16(uint32_t value)
|
||||
{
|
||||
rev16 r0, r0
|
||||
bx lr
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
\brief Reverse byte order (16 bit)
|
||||
\details Reverses the byte order in a 16-bit value and returns the signed 16-bit result. For example, 0x0080 becomes 0x8000.
|
||||
\param [in] value Value to reverse
|
||||
\return Reversed value
|
||||
*/
|
||||
#ifndef __NO_EMBEDDED_ASM
|
||||
__attribute__((section(".revsh_text"))) __STATIC_INLINE __ASM int16_t __REVSH(int16_t value)
|
||||
{
|
||||
revsh r0, r0
|
||||
bx lr
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
\brief Rotate Right in unsigned value (32 bit)
|
||||
\details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits.
|
||||
\param [in] op1 Value to rotate
|
||||
\param [in] op2 Number of Bits to rotate
|
||||
\return Rotated value
|
||||
*/
|
||||
#define __ROR __ror
|
||||
|
||||
|
||||
/**
|
||||
\brief Breakpoint
|
||||
\details Causes the processor to enter Debug state.
|
||||
Debug tools can use this to investigate system state when the instruction at a particular address is reached.
|
||||
\param [in] value is ignored by the processor.
|
||||
If required, a debugger can use it to store additional information about the breakpoint.
|
||||
*/
|
||||
#define __BKPT(value) __breakpoint(value)
|
||||
|
||||
|
||||
/**
|
||||
\brief Reverse bit order of value
|
||||
\details Reverses the bit order of the given value.
|
||||
\param [in] value Value to reverse
|
||||
\return Reversed value
|
||||
*/
|
||||
#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \
|
||||
(defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) )
|
||||
#define __RBIT __rbit
|
||||
#else
|
||||
__attribute__((always_inline)) __STATIC_INLINE uint32_t __RBIT(uint32_t value)
|
||||
{
|
||||
uint32_t result;
|
||||
uint32_t s = (4U /*sizeof(v)*/ * 8U) - 1U; /* extra shift needed at end */
|
||||
|
||||
result = value; /* r will be reversed bits of v; first get LSB of v */
|
||||
for (value >>= 1U; value != 0U; value >>= 1U)
|
||||
{
|
||||
result <<= 1U;
|
||||
result |= value & 1U;
|
||||
s--;
|
||||
}
|
||||
result <<= s; /* shift when v's highest bits are zero */
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
\brief Count leading zeros
|
||||
\details Counts the number of leading zeros of a data value.
|
||||
\param [in] value Value to count the leading zeros
|
||||
\return number of leading zeros in value
|
||||
*/
|
||||
#define __CLZ __clz
|
||||
|
||||
|
||||
#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \
|
||||
(defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) )
|
||||
|
||||
/**
|
||||
\brief LDR Exclusive (8 bit)
|
||||
\details Executes a exclusive LDR instruction for 8 bit value.
|
||||
\param [in] ptr Pointer to data
|
||||
\return value of type uint8_t at (*ptr)
|
||||
*/
|
||||
#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020)
|
||||
#define __LDREXB(ptr) ((uint8_t ) __ldrex(ptr))
|
||||
#else
|
||||
#define __LDREXB(ptr) _Pragma("push") _Pragma("diag_suppress 3731") ((uint8_t ) __ldrex(ptr)) _Pragma("pop")
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
\brief LDR Exclusive (16 bit)
|
||||
\details Executes a exclusive LDR instruction for 16 bit values.
|
||||
\param [in] ptr Pointer to data
|
||||
\return value of type uint16_t at (*ptr)
|
||||
*/
|
||||
#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020)
|
||||
#define __LDREXH(ptr) ((uint16_t) __ldrex(ptr))
|
||||
#else
|
||||
#define __LDREXH(ptr) _Pragma("push") _Pragma("diag_suppress 3731") ((uint16_t) __ldrex(ptr)) _Pragma("pop")
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
\brief LDR Exclusive (32 bit)
|
||||
\details Executes a exclusive LDR instruction for 32 bit values.
|
||||
\param [in] ptr Pointer to data
|
||||
\return value of type uint32_t at (*ptr)
|
||||
*/
|
||||
#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020)
|
||||
#define __LDREXW(ptr) ((uint32_t ) __ldrex(ptr))
|
||||
#else
|
||||
#define __LDREXW(ptr) _Pragma("push") _Pragma("diag_suppress 3731") ((uint32_t ) __ldrex(ptr)) _Pragma("pop")
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
\brief STR Exclusive (8 bit)
|
||||
\details Executes a exclusive STR instruction for 8 bit values.
|
||||
\param [in] value Value to store
|
||||
\param [in] ptr Pointer to location
|
||||
\return 0 Function succeeded
|
||||
\return 1 Function failed
|
||||
*/
|
||||
#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020)
|
||||
#define __STREXB(value, ptr) __strex(value, ptr)
|
||||
#else
|
||||
#define __STREXB(value, ptr) _Pragma("push") _Pragma("diag_suppress 3731") __strex(value, ptr) _Pragma("pop")
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
\brief STR Exclusive (16 bit)
|
||||
\details Executes a exclusive STR instruction for 16 bit values.
|
||||
\param [in] value Value to store
|
||||
\param [in] ptr Pointer to location
|
||||
\return 0 Function succeeded
|
||||
\return 1 Function failed
|
||||
*/
|
||||
#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020)
|
||||
#define __STREXH(value, ptr) __strex(value, ptr)
|
||||
#else
|
||||
#define __STREXH(value, ptr) _Pragma("push") _Pragma("diag_suppress 3731") __strex(value, ptr) _Pragma("pop")
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
\brief STR Exclusive (32 bit)
|
||||
\details Executes a exclusive STR instruction for 32 bit values.
|
||||
\param [in] value Value to store
|
||||
\param [in] ptr Pointer to location
|
||||
\return 0 Function succeeded
|
||||
\return 1 Function failed
|
||||
*/
|
||||
#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020)
|
||||
#define __STREXW(value, ptr) __strex(value, ptr)
|
||||
#else
|
||||
#define __STREXW(value, ptr) _Pragma("push") _Pragma("diag_suppress 3731") __strex(value, ptr) _Pragma("pop")
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
\brief Remove the exclusive lock
|
||||
\details Removes the exclusive lock which is created by LDREX.
|
||||
*/
|
||||
#define __CLREX __clrex
|
||||
|
||||
|
||||
/**
|
||||
\brief Signed Saturate
|
||||
\details Saturates a signed value.
|
||||
\param [in] value Value to be saturated
|
||||
\param [in] sat Bit position to saturate to (1..32)
|
||||
\return Saturated value
|
||||
*/
|
||||
#define __SSAT __ssat
|
||||
|
||||
|
||||
/**
|
||||
\brief Unsigned Saturate
|
||||
\details Saturates an unsigned value.
|
||||
\param [in] value Value to be saturated
|
||||
\param [in] sat Bit position to saturate to (0..31)
|
||||
\return Saturated value
|
||||
*/
|
||||
#define __USAT __usat
|
||||
|
||||
|
||||
/**
|
||||
\brief Rotate Right with Extend (32 bit)
|
||||
\details Moves each bit of a bitstring right by one bit.
|
||||
The carry input is shifted in at the left end of the bitstring.
|
||||
\param [in] value Value to rotate
|
||||
\return Rotated value
|
||||
*/
|
||||
#ifndef __NO_EMBEDDED_ASM
|
||||
__attribute__((section(".rrx_text"))) __STATIC_INLINE __ASM uint32_t __RRX(uint32_t value)
|
||||
{
|
||||
rrx r0, r0
|
||||
bx lr
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
\brief LDRT Unprivileged (8 bit)
|
||||
\details Executes a Unprivileged LDRT instruction for 8 bit value.
|
||||
\param [in] ptr Pointer to data
|
||||
\return value of type uint8_t at (*ptr)
|
||||
*/
|
||||
#define __LDRBT(ptr) ((uint8_t ) __ldrt(ptr))
|
||||
|
||||
|
||||
/**
|
||||
\brief LDRT Unprivileged (16 bit)
|
||||
\details Executes a Unprivileged LDRT instruction for 16 bit values.
|
||||
\param [in] ptr Pointer to data
|
||||
\return value of type uint16_t at (*ptr)
|
||||
*/
|
||||
#define __LDRHT(ptr) ((uint16_t) __ldrt(ptr))
|
||||
|
||||
|
||||
/**
|
||||
\brief LDRT Unprivileged (32 bit)
|
||||
\details Executes a Unprivileged LDRT instruction for 32 bit values.
|
||||
\param [in] ptr Pointer to data
|
||||
\return value of type uint32_t at (*ptr)
|
||||
*/
|
||||
#define __LDRT(ptr) ((uint32_t ) __ldrt(ptr))
|
||||
|
||||
|
||||
/**
|
||||
\brief STRT Unprivileged (8 bit)
|
||||
\details Executes a Unprivileged STRT instruction for 8 bit values.
|
||||
\param [in] value Value to store
|
||||
\param [in] ptr Pointer to location
|
||||
*/
|
||||
#define __STRBT(value, ptr) __strt(value, ptr)
|
||||
|
||||
|
||||
/**
|
||||
\brief STRT Unprivileged (16 bit)
|
||||
\details Executes a Unprivileged STRT instruction for 16 bit values.
|
||||
\param [in] value Value to store
|
||||
\param [in] ptr Pointer to location
|
||||
*/
|
||||
#define __STRHT(value, ptr) __strt(value, ptr)
|
||||
|
||||
|
||||
/**
|
||||
\brief STRT Unprivileged (32 bit)
|
||||
\details Executes a Unprivileged STRT instruction for 32 bit values.
|
||||
\param [in] value Value to store
|
||||
\param [in] ptr Pointer to location
|
||||
*/
|
||||
#define __STRT(value, ptr) __strt(value, ptr)
|
||||
|
||||
#else /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \
|
||||
(defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) */
|
||||
|
||||
/**
|
||||
\brief Signed Saturate
|
||||
\details Saturates a signed value.
|
||||
\param [in] value Value to be saturated
|
||||
\param [in] sat Bit position to saturate to (1..32)
|
||||
\return Saturated value
|
||||
*/
|
||||
__attribute__((always_inline)) __STATIC_INLINE int32_t __SSAT(int32_t val, uint32_t sat)
|
||||
{
|
||||
if ((sat >= 1U) && (sat <= 32U))
|
||||
{
|
||||
const int32_t max = (int32_t)((1U << (sat - 1U)) - 1U);
|
||||
const int32_t min = -1 - max ;
|
||||
if (val > max)
|
||||
{
|
||||
return max;
|
||||
}
|
||||
else if (val < min)
|
||||
{
|
||||
return min;
|
||||
}
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Unsigned Saturate
|
||||
\details Saturates an unsigned value.
|
||||
\param [in] value Value to be saturated
|
||||
\param [in] sat Bit position to saturate to (0..31)
|
||||
\return Saturated value
|
||||
*/
|
||||
__attribute__((always_inline)) __STATIC_INLINE uint32_t __USAT(int32_t val, uint32_t sat)
|
||||
{
|
||||
if (sat <= 31U)
|
||||
{
|
||||
const uint32_t max = ((1U << sat) - 1U);
|
||||
if (val > (int32_t)max)
|
||||
{
|
||||
return max;
|
||||
}
|
||||
else if (val < 0)
|
||||
{
|
||||
return 0U;
|
||||
}
|
||||
}
|
||||
return (uint32_t)val;
|
||||
}
|
||||
|
||||
#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \
|
||||
(defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) */
|
||||
|
||||
/*@}*/ /* end of group CMSIS_Core_InstructionInterface */
|
||||
|
||||
|
||||
/* ################### Compiler specific Intrinsics ########################### */
|
||||
/** \defgroup CMSIS_SIMD_intrinsics CMSIS SIMD Intrinsics
|
||||
Access to dedicated SIMD instructions
|
||||
@{
|
||||
*/
|
||||
|
||||
#if ((defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) )
|
||||
|
||||
#define __SADD8 __sadd8
|
||||
#define __QADD8 __qadd8
|
||||
#define __SHADD8 __shadd8
|
||||
#define __UADD8 __uadd8
|
||||
#define __UQADD8 __uqadd8
|
||||
#define __UHADD8 __uhadd8
|
||||
#define __SSUB8 __ssub8
|
||||
#define __QSUB8 __qsub8
|
||||
#define __SHSUB8 __shsub8
|
||||
#define __USUB8 __usub8
|
||||
#define __UQSUB8 __uqsub8
|
||||
#define __UHSUB8 __uhsub8
|
||||
#define __SADD16 __sadd16
|
||||
#define __QADD16 __qadd16
|
||||
#define __SHADD16 __shadd16
|
||||
#define __UADD16 __uadd16
|
||||
#define __UQADD16 __uqadd16
|
||||
#define __UHADD16 __uhadd16
|
||||
#define __SSUB16 __ssub16
|
||||
#define __QSUB16 __qsub16
|
||||
#define __SHSUB16 __shsub16
|
||||
#define __USUB16 __usub16
|
||||
#define __UQSUB16 __uqsub16
|
||||
#define __UHSUB16 __uhsub16
|
||||
#define __SASX __sasx
|
||||
#define __QASX __qasx
|
||||
#define __SHASX __shasx
|
||||
#define __UASX __uasx
|
||||
#define __UQASX __uqasx
|
||||
#define __UHASX __uhasx
|
||||
#define __SSAX __ssax
|
||||
#define __QSAX __qsax
|
||||
#define __SHSAX __shsax
|
||||
#define __USAX __usax
|
||||
#define __UQSAX __uqsax
|
||||
#define __UHSAX __uhsax
|
||||
#define __USAD8 __usad8
|
||||
#define __USADA8 __usada8
|
||||
#define __SSAT16 __ssat16
|
||||
#define __USAT16 __usat16
|
||||
#define __UXTB16 __uxtb16
|
||||
#define __UXTAB16 __uxtab16
|
||||
#define __SXTB16 __sxtb16
|
||||
#define __SXTAB16 __sxtab16
|
||||
#define __SMUAD __smuad
|
||||
#define __SMUADX __smuadx
|
||||
#define __SMLAD __smlad
|
||||
#define __SMLADX __smladx
|
||||
#define __SMLALD __smlald
|
||||
#define __SMLALDX __smlaldx
|
||||
#define __SMUSD __smusd
|
||||
#define __SMUSDX __smusdx
|
||||
#define __SMLSD __smlsd
|
||||
#define __SMLSDX __smlsdx
|
||||
#define __SMLSLD __smlsld
|
||||
#define __SMLSLDX __smlsldx
|
||||
#define __SEL __sel
|
||||
#define __QADD __qadd
|
||||
#define __QSUB __qsub
|
||||
|
||||
#define __PKHBT(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0x0000FFFFUL) | \
|
||||
((((uint32_t)(ARG2)) << (ARG3)) & 0xFFFF0000UL) )
|
||||
|
||||
#define __PKHTB(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0xFFFF0000UL) | \
|
||||
((((uint32_t)(ARG2)) >> (ARG3)) & 0x0000FFFFUL) )
|
||||
|
||||
#define __SMMLA(ARG1,ARG2,ARG3) ( (int32_t)((((int64_t)(ARG1) * (ARG2)) + \
|
||||
((int64_t)(ARG3) << 32U) ) >> 32U))
|
||||
|
||||
#endif /* ((defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) */
|
||||
/*@} end of group CMSIS_SIMD_intrinsics */
|
||||
|
||||
|
||||
#endif /* __CMSIS_ARMCC_H */
|
||||
1869
Software/Drivers/CMSIS/Core/Include/cmsis_armclang.h
Normal file
1869
Software/Drivers/CMSIS/Core/Include/cmsis_armclang.h
Normal file
File diff suppressed because it is too large
Load Diff
266
Software/Drivers/CMSIS/Core/Include/cmsis_compiler.h
Normal file
266
Software/Drivers/CMSIS/Core/Include/cmsis_compiler.h
Normal file
@ -0,0 +1,266 @@
|
||||
/**************************************************************************//**
|
||||
* @file cmsis_compiler.h
|
||||
* @brief CMSIS compiler generic header file
|
||||
* @version V5.0.4
|
||||
* @date 10. January 2018
|
||||
******************************************************************************/
|
||||
/*
|
||||
* Copyright (c) 2009-2018 Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef __CMSIS_COMPILER_H
|
||||
#define __CMSIS_COMPILER_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/*
|
||||
* Arm Compiler 4/5
|
||||
*/
|
||||
#if defined ( __CC_ARM )
|
||||
#include "cmsis_armcc.h"
|
||||
|
||||
|
||||
/*
|
||||
* Arm Compiler 6 (armclang)
|
||||
*/
|
||||
#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
|
||||
#include "cmsis_armclang.h"
|
||||
|
||||
|
||||
/*
|
||||
* GNU Compiler
|
||||
*/
|
||||
#elif defined ( __GNUC__ )
|
||||
#include "cmsis_gcc.h"
|
||||
|
||||
|
||||
/*
|
||||
* IAR Compiler
|
||||
*/
|
||||
#elif defined ( __ICCARM__ )
|
||||
#include <cmsis_iccarm.h>
|
||||
|
||||
|
||||
/*
|
||||
* TI Arm Compiler
|
||||
*/
|
||||
#elif defined ( __TI_ARM__ )
|
||||
#include <cmsis_ccs.h>
|
||||
|
||||
#ifndef __ASM
|
||||
#define __ASM __asm
|
||||
#endif
|
||||
#ifndef __INLINE
|
||||
#define __INLINE inline
|
||||
#endif
|
||||
#ifndef __STATIC_INLINE
|
||||
#define __STATIC_INLINE static inline
|
||||
#endif
|
||||
#ifndef __STATIC_FORCEINLINE
|
||||
#define __STATIC_FORCEINLINE __STATIC_INLINE
|
||||
#endif
|
||||
#ifndef __NO_RETURN
|
||||
#define __NO_RETURN __attribute__((noreturn))
|
||||
#endif
|
||||
#ifndef __USED
|
||||
#define __USED __attribute__((used))
|
||||
#endif
|
||||
#ifndef __WEAK
|
||||
#define __WEAK __attribute__((weak))
|
||||
#endif
|
||||
#ifndef __PACKED
|
||||
#define __PACKED __attribute__((packed))
|
||||
#endif
|
||||
#ifndef __PACKED_STRUCT
|
||||
#define __PACKED_STRUCT struct __attribute__((packed))
|
||||
#endif
|
||||
#ifndef __PACKED_UNION
|
||||
#define __PACKED_UNION union __attribute__((packed))
|
||||
#endif
|
||||
#ifndef __UNALIGNED_UINT32 /* deprecated */
|
||||
struct __attribute__((packed)) T_UINT32 { uint32_t v; };
|
||||
#define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v)
|
||||
#endif
|
||||
#ifndef __UNALIGNED_UINT16_WRITE
|
||||
__PACKED_STRUCT T_UINT16_WRITE { uint16_t v; };
|
||||
#define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void*)(addr))->v) = (val))
|
||||
#endif
|
||||
#ifndef __UNALIGNED_UINT16_READ
|
||||
__PACKED_STRUCT T_UINT16_READ { uint16_t v; };
|
||||
#define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v)
|
||||
#endif
|
||||
#ifndef __UNALIGNED_UINT32_WRITE
|
||||
__PACKED_STRUCT T_UINT32_WRITE { uint32_t v; };
|
||||
#define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val))
|
||||
#endif
|
||||
#ifndef __UNALIGNED_UINT32_READ
|
||||
__PACKED_STRUCT T_UINT32_READ { uint32_t v; };
|
||||
#define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v)
|
||||
#endif
|
||||
#ifndef __ALIGNED
|
||||
#define __ALIGNED(x) __attribute__((aligned(x)))
|
||||
#endif
|
||||
#ifndef __RESTRICT
|
||||
#warning No compiler specific solution for __RESTRICT. __RESTRICT is ignored.
|
||||
#define __RESTRICT
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* TASKING Compiler
|
||||
*/
|
||||
#elif defined ( __TASKING__ )
|
||||
/*
|
||||
* The CMSIS functions have been implemented as intrinsics in the compiler.
|
||||
* Please use "carm -?i" to get an up to date list of all intrinsics,
|
||||
* Including the CMSIS ones.
|
||||
*/
|
||||
|
||||
#ifndef __ASM
|
||||
#define __ASM __asm
|
||||
#endif
|
||||
#ifndef __INLINE
|
||||
#define __INLINE inline
|
||||
#endif
|
||||
#ifndef __STATIC_INLINE
|
||||
#define __STATIC_INLINE static inline
|
||||
#endif
|
||||
#ifndef __STATIC_FORCEINLINE
|
||||
#define __STATIC_FORCEINLINE __STATIC_INLINE
|
||||
#endif
|
||||
#ifndef __NO_RETURN
|
||||
#define __NO_RETURN __attribute__((noreturn))
|
||||
#endif
|
||||
#ifndef __USED
|
||||
#define __USED __attribute__((used))
|
||||
#endif
|
||||
#ifndef __WEAK
|
||||
#define __WEAK __attribute__((weak))
|
||||
#endif
|
||||
#ifndef __PACKED
|
||||
#define __PACKED __packed__
|
||||
#endif
|
||||
#ifndef __PACKED_STRUCT
|
||||
#define __PACKED_STRUCT struct __packed__
|
||||
#endif
|
||||
#ifndef __PACKED_UNION
|
||||
#define __PACKED_UNION union __packed__
|
||||
#endif
|
||||
#ifndef __UNALIGNED_UINT32 /* deprecated */
|
||||
struct __packed__ T_UINT32 { uint32_t v; };
|
||||
#define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v)
|
||||
#endif
|
||||
#ifndef __UNALIGNED_UINT16_WRITE
|
||||
__PACKED_STRUCT T_UINT16_WRITE { uint16_t v; };
|
||||
#define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val))
|
||||
#endif
|
||||
#ifndef __UNALIGNED_UINT16_READ
|
||||
__PACKED_STRUCT T_UINT16_READ { uint16_t v; };
|
||||
#define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v)
|
||||
#endif
|
||||
#ifndef __UNALIGNED_UINT32_WRITE
|
||||
__PACKED_STRUCT T_UINT32_WRITE { uint32_t v; };
|
||||
#define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val))
|
||||
#endif
|
||||
#ifndef __UNALIGNED_UINT32_READ
|
||||
__PACKED_STRUCT T_UINT32_READ { uint32_t v; };
|
||||
#define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v)
|
||||
#endif
|
||||
#ifndef __ALIGNED
|
||||
#define __ALIGNED(x) __align(x)
|
||||
#endif
|
||||
#ifndef __RESTRICT
|
||||
#warning No compiler specific solution for __RESTRICT. __RESTRICT is ignored.
|
||||
#define __RESTRICT
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* COSMIC Compiler
|
||||
*/
|
||||
#elif defined ( __CSMC__ )
|
||||
#include <cmsis_csm.h>
|
||||
|
||||
#ifndef __ASM
|
||||
#define __ASM _asm
|
||||
#endif
|
||||
#ifndef __INLINE
|
||||
#define __INLINE inline
|
||||
#endif
|
||||
#ifndef __STATIC_INLINE
|
||||
#define __STATIC_INLINE static inline
|
||||
#endif
|
||||
#ifndef __STATIC_FORCEINLINE
|
||||
#define __STATIC_FORCEINLINE __STATIC_INLINE
|
||||
#endif
|
||||
#ifndef __NO_RETURN
|
||||
// NO RETURN is automatically detected hence no warning here
|
||||
#define __NO_RETURN
|
||||
#endif
|
||||
#ifndef __USED
|
||||
#warning No compiler specific solution for __USED. __USED is ignored.
|
||||
#define __USED
|
||||
#endif
|
||||
#ifndef __WEAK
|
||||
#define __WEAK __weak
|
||||
#endif
|
||||
#ifndef __PACKED
|
||||
#define __PACKED @packed
|
||||
#endif
|
||||
#ifndef __PACKED_STRUCT
|
||||
#define __PACKED_STRUCT @packed struct
|
||||
#endif
|
||||
#ifndef __PACKED_UNION
|
||||
#define __PACKED_UNION @packed union
|
||||
#endif
|
||||
#ifndef __UNALIGNED_UINT32 /* deprecated */
|
||||
@packed struct T_UINT32 { uint32_t v; };
|
||||
#define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v)
|
||||
#endif
|
||||
#ifndef __UNALIGNED_UINT16_WRITE
|
||||
__PACKED_STRUCT T_UINT16_WRITE { uint16_t v; };
|
||||
#define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val))
|
||||
#endif
|
||||
#ifndef __UNALIGNED_UINT16_READ
|
||||
__PACKED_STRUCT T_UINT16_READ { uint16_t v; };
|
||||
#define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v)
|
||||
#endif
|
||||
#ifndef __UNALIGNED_UINT32_WRITE
|
||||
__PACKED_STRUCT T_UINT32_WRITE { uint32_t v; };
|
||||
#define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val))
|
||||
#endif
|
||||
#ifndef __UNALIGNED_UINT32_READ
|
||||
__PACKED_STRUCT T_UINT32_READ { uint32_t v; };
|
||||
#define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v)
|
||||
#endif
|
||||
#ifndef __ALIGNED
|
||||
#warning No compiler specific solution for __ALIGNED. __ALIGNED is ignored.
|
||||
#define __ALIGNED(x)
|
||||
#endif
|
||||
#ifndef __RESTRICT
|
||||
#warning No compiler specific solution for __RESTRICT. __RESTRICT is ignored.
|
||||
#define __RESTRICT
|
||||
#endif
|
||||
|
||||
|
||||
#else
|
||||
#error Unknown compiler.
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* __CMSIS_COMPILER_H */
|
||||
|
||||
2085
Software/Drivers/CMSIS/Core/Include/cmsis_gcc.h
Normal file
2085
Software/Drivers/CMSIS/Core/Include/cmsis_gcc.h
Normal file
File diff suppressed because it is too large
Load Diff
935
Software/Drivers/CMSIS/Core/Include/cmsis_iccarm.h
Normal file
935
Software/Drivers/CMSIS/Core/Include/cmsis_iccarm.h
Normal file
@ -0,0 +1,935 @@
|
||||
/**************************************************************************//**
|
||||
* @file cmsis_iccarm.h
|
||||
* @brief CMSIS compiler ICCARM (IAR Compiler for Arm) header file
|
||||
* @version V5.0.7
|
||||
* @date 19. June 2018
|
||||
******************************************************************************/
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright (c) 2017-2018 IAR Systems
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License")
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
#ifndef __CMSIS_ICCARM_H__
|
||||
#define __CMSIS_ICCARM_H__
|
||||
|
||||
#ifndef __ICCARM__
|
||||
#error This file should only be compiled by ICCARM
|
||||
#endif
|
||||
|
||||
#pragma system_include
|
||||
|
||||
#define __IAR_FT _Pragma("inline=forced") __intrinsic
|
||||
|
||||
#if (__VER__ >= 8000000)
|
||||
#define __ICCARM_V8 1
|
||||
#else
|
||||
#define __ICCARM_V8 0
|
||||
#endif
|
||||
|
||||
#ifndef __ALIGNED
|
||||
#if __ICCARM_V8
|
||||
#define __ALIGNED(x) __attribute__((aligned(x)))
|
||||
#elif (__VER__ >= 7080000)
|
||||
/* Needs IAR language extensions */
|
||||
#define __ALIGNED(x) __attribute__((aligned(x)))
|
||||
#else
|
||||
#warning No compiler specific solution for __ALIGNED.__ALIGNED is ignored.
|
||||
#define __ALIGNED(x)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/* Define compiler macros for CPU architecture, used in CMSIS 5.
|
||||
*/
|
||||
#if __ARM_ARCH_6M__ || __ARM_ARCH_7M__ || __ARM_ARCH_7EM__ || __ARM_ARCH_8M_BASE__ || __ARM_ARCH_8M_MAIN__
|
||||
/* Macros already defined */
|
||||
#else
|
||||
#if defined(__ARM8M_MAINLINE__) || defined(__ARM8EM_MAINLINE__)
|
||||
#define __ARM_ARCH_8M_MAIN__ 1
|
||||
#elif defined(__ARM8M_BASELINE__)
|
||||
#define __ARM_ARCH_8M_BASE__ 1
|
||||
#elif defined(__ARM_ARCH_PROFILE) && __ARM_ARCH_PROFILE == 'M'
|
||||
#if __ARM_ARCH == 6
|
||||
#define __ARM_ARCH_6M__ 1
|
||||
#elif __ARM_ARCH == 7
|
||||
#if __ARM_FEATURE_DSP
|
||||
#define __ARM_ARCH_7EM__ 1
|
||||
#else
|
||||
#define __ARM_ARCH_7M__ 1
|
||||
#endif
|
||||
#endif /* __ARM_ARCH */
|
||||
#endif /* __ARM_ARCH_PROFILE == 'M' */
|
||||
#endif
|
||||
|
||||
/* Alternativ core deduction for older ICCARM's */
|
||||
#if !defined(__ARM_ARCH_6M__) && !defined(__ARM_ARCH_7M__) && !defined(__ARM_ARCH_7EM__) && \
|
||||
!defined(__ARM_ARCH_8M_BASE__) && !defined(__ARM_ARCH_8M_MAIN__)
|
||||
#if defined(__ARM6M__) && (__CORE__ == __ARM6M__)
|
||||
#define __ARM_ARCH_6M__ 1
|
||||
#elif defined(__ARM7M__) && (__CORE__ == __ARM7M__)
|
||||
#define __ARM_ARCH_7M__ 1
|
||||
#elif defined(__ARM7EM__) && (__CORE__ == __ARM7EM__)
|
||||
#define __ARM_ARCH_7EM__ 1
|
||||
#elif defined(__ARM8M_BASELINE__) && (__CORE == __ARM8M_BASELINE__)
|
||||
#define __ARM_ARCH_8M_BASE__ 1
|
||||
#elif defined(__ARM8M_MAINLINE__) && (__CORE == __ARM8M_MAINLINE__)
|
||||
#define __ARM_ARCH_8M_MAIN__ 1
|
||||
#elif defined(__ARM8EM_MAINLINE__) && (__CORE == __ARM8EM_MAINLINE__)
|
||||
#define __ARM_ARCH_8M_MAIN__ 1
|
||||
#else
|
||||
#error "Unknown target."
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#if defined(__ARM_ARCH_6M__) && __ARM_ARCH_6M__==1
|
||||
#define __IAR_M0_FAMILY 1
|
||||
#elif defined(__ARM_ARCH_8M_BASE__) && __ARM_ARCH_8M_BASE__==1
|
||||
#define __IAR_M0_FAMILY 1
|
||||
#else
|
||||
#define __IAR_M0_FAMILY 0
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef __ASM
|
||||
#define __ASM __asm
|
||||
#endif
|
||||
|
||||
#ifndef __INLINE
|
||||
#define __INLINE inline
|
||||
#endif
|
||||
|
||||
#ifndef __NO_RETURN
|
||||
#if __ICCARM_V8
|
||||
#define __NO_RETURN __attribute__((__noreturn__))
|
||||
#else
|
||||
#define __NO_RETURN _Pragma("object_attribute=__noreturn")
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef __PACKED
|
||||
#if __ICCARM_V8
|
||||
#define __PACKED __attribute__((packed, aligned(1)))
|
||||
#else
|
||||
/* Needs IAR language extensions */
|
||||
#define __PACKED __packed
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef __PACKED_STRUCT
|
||||
#if __ICCARM_V8
|
||||
#define __PACKED_STRUCT struct __attribute__((packed, aligned(1)))
|
||||
#else
|
||||
/* Needs IAR language extensions */
|
||||
#define __PACKED_STRUCT __packed struct
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef __PACKED_UNION
|
||||
#if __ICCARM_V8
|
||||
#define __PACKED_UNION union __attribute__((packed, aligned(1)))
|
||||
#else
|
||||
/* Needs IAR language extensions */
|
||||
#define __PACKED_UNION __packed union
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef __RESTRICT
|
||||
#define __RESTRICT __restrict
|
||||
#endif
|
||||
|
||||
#ifndef __STATIC_INLINE
|
||||
#define __STATIC_INLINE static inline
|
||||
#endif
|
||||
|
||||
#ifndef __FORCEINLINE
|
||||
#define __FORCEINLINE _Pragma("inline=forced")
|
||||
#endif
|
||||
|
||||
#ifndef __STATIC_FORCEINLINE
|
||||
#define __STATIC_FORCEINLINE __FORCEINLINE __STATIC_INLINE
|
||||
#endif
|
||||
|
||||
#ifndef __UNALIGNED_UINT16_READ
|
||||
#pragma language=save
|
||||
#pragma language=extended
|
||||
__IAR_FT uint16_t __iar_uint16_read(void const *ptr)
|
||||
{
|
||||
return *(__packed uint16_t*)(ptr);
|
||||
}
|
||||
#pragma language=restore
|
||||
#define __UNALIGNED_UINT16_READ(PTR) __iar_uint16_read(PTR)
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef __UNALIGNED_UINT16_WRITE
|
||||
#pragma language=save
|
||||
#pragma language=extended
|
||||
__IAR_FT void __iar_uint16_write(void const *ptr, uint16_t val)
|
||||
{
|
||||
*(__packed uint16_t*)(ptr) = val;;
|
||||
}
|
||||
#pragma language=restore
|
||||
#define __UNALIGNED_UINT16_WRITE(PTR,VAL) __iar_uint16_write(PTR,VAL)
|
||||
#endif
|
||||
|
||||
#ifndef __UNALIGNED_UINT32_READ
|
||||
#pragma language=save
|
||||
#pragma language=extended
|
||||
__IAR_FT uint32_t __iar_uint32_read(void const *ptr)
|
||||
{
|
||||
return *(__packed uint32_t*)(ptr);
|
||||
}
|
||||
#pragma language=restore
|
||||
#define __UNALIGNED_UINT32_READ(PTR) __iar_uint32_read(PTR)
|
||||
#endif
|
||||
|
||||
#ifndef __UNALIGNED_UINT32_WRITE
|
||||
#pragma language=save
|
||||
#pragma language=extended
|
||||
__IAR_FT void __iar_uint32_write(void const *ptr, uint32_t val)
|
||||
{
|
||||
*(__packed uint32_t*)(ptr) = val;;
|
||||
}
|
||||
#pragma language=restore
|
||||
#define __UNALIGNED_UINT32_WRITE(PTR,VAL) __iar_uint32_write(PTR,VAL)
|
||||
#endif
|
||||
|
||||
#ifndef __UNALIGNED_UINT32 /* deprecated */
|
||||
#pragma language=save
|
||||
#pragma language=extended
|
||||
__packed struct __iar_u32 { uint32_t v; };
|
||||
#pragma language=restore
|
||||
#define __UNALIGNED_UINT32(PTR) (((struct __iar_u32 *)(PTR))->v)
|
||||
#endif
|
||||
|
||||
#ifndef __USED
|
||||
#if __ICCARM_V8
|
||||
#define __USED __attribute__((used))
|
||||
#else
|
||||
#define __USED _Pragma("__root")
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef __WEAK
|
||||
#if __ICCARM_V8
|
||||
#define __WEAK __attribute__((weak))
|
||||
#else
|
||||
#define __WEAK _Pragma("__weak")
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef __ICCARM_INTRINSICS_VERSION__
|
||||
#define __ICCARM_INTRINSICS_VERSION__ 0
|
||||
#endif
|
||||
|
||||
#if __ICCARM_INTRINSICS_VERSION__ == 2
|
||||
|
||||
#if defined(__CLZ)
|
||||
#undef __CLZ
|
||||
#endif
|
||||
#if defined(__REVSH)
|
||||
#undef __REVSH
|
||||
#endif
|
||||
#if defined(__RBIT)
|
||||
#undef __RBIT
|
||||
#endif
|
||||
#if defined(__SSAT)
|
||||
#undef __SSAT
|
||||
#endif
|
||||
#if defined(__USAT)
|
||||
#undef __USAT
|
||||
#endif
|
||||
|
||||
#include "iccarm_builtin.h"
|
||||
|
||||
#define __disable_fault_irq __iar_builtin_disable_fiq
|
||||
#define __disable_irq __iar_builtin_disable_interrupt
|
||||
#define __enable_fault_irq __iar_builtin_enable_fiq
|
||||
#define __enable_irq __iar_builtin_enable_interrupt
|
||||
#define __arm_rsr __iar_builtin_rsr
|
||||
#define __arm_wsr __iar_builtin_wsr
|
||||
|
||||
|
||||
#define __get_APSR() (__arm_rsr("APSR"))
|
||||
#define __get_BASEPRI() (__arm_rsr("BASEPRI"))
|
||||
#define __get_CONTROL() (__arm_rsr("CONTROL"))
|
||||
#define __get_FAULTMASK() (__arm_rsr("FAULTMASK"))
|
||||
|
||||
#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \
|
||||
(defined (__FPU_USED ) && (__FPU_USED == 1U)) )
|
||||
#define __get_FPSCR() (__arm_rsr("FPSCR"))
|
||||
#define __set_FPSCR(VALUE) (__arm_wsr("FPSCR", (VALUE)))
|
||||
#else
|
||||
#define __get_FPSCR() ( 0 )
|
||||
#define __set_FPSCR(VALUE) ((void)VALUE)
|
||||
#endif
|
||||
|
||||
#define __get_IPSR() (__arm_rsr("IPSR"))
|
||||
#define __get_MSP() (__arm_rsr("MSP"))
|
||||
#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \
|
||||
(!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3)))
|
||||
// without main extensions, the non-secure MSPLIM is RAZ/WI
|
||||
#define __get_MSPLIM() (0U)
|
||||
#else
|
||||
#define __get_MSPLIM() (__arm_rsr("MSPLIM"))
|
||||
#endif
|
||||
#define __get_PRIMASK() (__arm_rsr("PRIMASK"))
|
||||
#define __get_PSP() (__arm_rsr("PSP"))
|
||||
|
||||
#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \
|
||||
(!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3)))
|
||||
// without main extensions, the non-secure PSPLIM is RAZ/WI
|
||||
#define __get_PSPLIM() (0U)
|
||||
#else
|
||||
#define __get_PSPLIM() (__arm_rsr("PSPLIM"))
|
||||
#endif
|
||||
|
||||
#define __get_xPSR() (__arm_rsr("xPSR"))
|
||||
|
||||
#define __set_BASEPRI(VALUE) (__arm_wsr("BASEPRI", (VALUE)))
|
||||
#define __set_BASEPRI_MAX(VALUE) (__arm_wsr("BASEPRI_MAX", (VALUE)))
|
||||
#define __set_CONTROL(VALUE) (__arm_wsr("CONTROL", (VALUE)))
|
||||
#define __set_FAULTMASK(VALUE) (__arm_wsr("FAULTMASK", (VALUE)))
|
||||
#define __set_MSP(VALUE) (__arm_wsr("MSP", (VALUE)))
|
||||
|
||||
#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \
|
||||
(!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3)))
|
||||
// without main extensions, the non-secure MSPLIM is RAZ/WI
|
||||
#define __set_MSPLIM(VALUE) ((void)(VALUE))
|
||||
#else
|
||||
#define __set_MSPLIM(VALUE) (__arm_wsr("MSPLIM", (VALUE)))
|
||||
#endif
|
||||
#define __set_PRIMASK(VALUE) (__arm_wsr("PRIMASK", (VALUE)))
|
||||
#define __set_PSP(VALUE) (__arm_wsr("PSP", (VALUE)))
|
||||
#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \
|
||||
(!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3)))
|
||||
// without main extensions, the non-secure PSPLIM is RAZ/WI
|
||||
#define __set_PSPLIM(VALUE) ((void)(VALUE))
|
||||
#else
|
||||
#define __set_PSPLIM(VALUE) (__arm_wsr("PSPLIM", (VALUE)))
|
||||
#endif
|
||||
|
||||
#define __TZ_get_CONTROL_NS() (__arm_rsr("CONTROL_NS"))
|
||||
#define __TZ_set_CONTROL_NS(VALUE) (__arm_wsr("CONTROL_NS", (VALUE)))
|
||||
#define __TZ_get_PSP_NS() (__arm_rsr("PSP_NS"))
|
||||
#define __TZ_set_PSP_NS(VALUE) (__arm_wsr("PSP_NS", (VALUE)))
|
||||
#define __TZ_get_MSP_NS() (__arm_rsr("MSP_NS"))
|
||||
#define __TZ_set_MSP_NS(VALUE) (__arm_wsr("MSP_NS", (VALUE)))
|
||||
#define __TZ_get_SP_NS() (__arm_rsr("SP_NS"))
|
||||
#define __TZ_set_SP_NS(VALUE) (__arm_wsr("SP_NS", (VALUE)))
|
||||
#define __TZ_get_PRIMASK_NS() (__arm_rsr("PRIMASK_NS"))
|
||||
#define __TZ_set_PRIMASK_NS(VALUE) (__arm_wsr("PRIMASK_NS", (VALUE)))
|
||||
#define __TZ_get_BASEPRI_NS() (__arm_rsr("BASEPRI_NS"))
|
||||
#define __TZ_set_BASEPRI_NS(VALUE) (__arm_wsr("BASEPRI_NS", (VALUE)))
|
||||
#define __TZ_get_FAULTMASK_NS() (__arm_rsr("FAULTMASK_NS"))
|
||||
#define __TZ_set_FAULTMASK_NS(VALUE)(__arm_wsr("FAULTMASK_NS", (VALUE)))
|
||||
|
||||
#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \
|
||||
(!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3)))
|
||||
// without main extensions, the non-secure PSPLIM is RAZ/WI
|
||||
#define __TZ_get_PSPLIM_NS() (0U)
|
||||
#define __TZ_set_PSPLIM_NS(VALUE) ((void)(VALUE))
|
||||
#else
|
||||
#define __TZ_get_PSPLIM_NS() (__arm_rsr("PSPLIM_NS"))
|
||||
#define __TZ_set_PSPLIM_NS(VALUE) (__arm_wsr("PSPLIM_NS", (VALUE)))
|
||||
#endif
|
||||
|
||||
#define __TZ_get_MSPLIM_NS() (__arm_rsr("MSPLIM_NS"))
|
||||
#define __TZ_set_MSPLIM_NS(VALUE) (__arm_wsr("MSPLIM_NS", (VALUE)))
|
||||
|
||||
#define __NOP __iar_builtin_no_operation
|
||||
|
||||
#define __CLZ __iar_builtin_CLZ
|
||||
#define __CLREX __iar_builtin_CLREX
|
||||
|
||||
#define __DMB __iar_builtin_DMB
|
||||
#define __DSB __iar_builtin_DSB
|
||||
#define __ISB __iar_builtin_ISB
|
||||
|
||||
#define __LDREXB __iar_builtin_LDREXB
|
||||
#define __LDREXH __iar_builtin_LDREXH
|
||||
#define __LDREXW __iar_builtin_LDREX
|
||||
|
||||
#define __RBIT __iar_builtin_RBIT
|
||||
#define __REV __iar_builtin_REV
|
||||
#define __REV16 __iar_builtin_REV16
|
||||
|
||||
__IAR_FT int16_t __REVSH(int16_t val)
|
||||
{
|
||||
return (int16_t) __iar_builtin_REVSH(val);
|
||||
}
|
||||
|
||||
#define __ROR __iar_builtin_ROR
|
||||
#define __RRX __iar_builtin_RRX
|
||||
|
||||
#define __SEV __iar_builtin_SEV
|
||||
|
||||
#if !__IAR_M0_FAMILY
|
||||
#define __SSAT __iar_builtin_SSAT
|
||||
#endif
|
||||
|
||||
#define __STREXB __iar_builtin_STREXB
|
||||
#define __STREXH __iar_builtin_STREXH
|
||||
#define __STREXW __iar_builtin_STREX
|
||||
|
||||
#if !__IAR_M0_FAMILY
|
||||
#define __USAT __iar_builtin_USAT
|
||||
#endif
|
||||
|
||||
#define __WFE __iar_builtin_WFE
|
||||
#define __WFI __iar_builtin_WFI
|
||||
|
||||
#if __ARM_MEDIA__
|
||||
#define __SADD8 __iar_builtin_SADD8
|
||||
#define __QADD8 __iar_builtin_QADD8
|
||||
#define __SHADD8 __iar_builtin_SHADD8
|
||||
#define __UADD8 __iar_builtin_UADD8
|
||||
#define __UQADD8 __iar_builtin_UQADD8
|
||||
#define __UHADD8 __iar_builtin_UHADD8
|
||||
#define __SSUB8 __iar_builtin_SSUB8
|
||||
#define __QSUB8 __iar_builtin_QSUB8
|
||||
#define __SHSUB8 __iar_builtin_SHSUB8
|
||||
#define __USUB8 __iar_builtin_USUB8
|
||||
#define __UQSUB8 __iar_builtin_UQSUB8
|
||||
#define __UHSUB8 __iar_builtin_UHSUB8
|
||||
#define __SADD16 __iar_builtin_SADD16
|
||||
#define __QADD16 __iar_builtin_QADD16
|
||||
#define __SHADD16 __iar_builtin_SHADD16
|
||||
#define __UADD16 __iar_builtin_UADD16
|
||||
#define __UQADD16 __iar_builtin_UQADD16
|
||||
#define __UHADD16 __iar_builtin_UHADD16
|
||||
#define __SSUB16 __iar_builtin_SSUB16
|
||||
#define __QSUB16 __iar_builtin_QSUB16
|
||||
#define __SHSUB16 __iar_builtin_SHSUB16
|
||||
#define __USUB16 __iar_builtin_USUB16
|
||||
#define __UQSUB16 __iar_builtin_UQSUB16
|
||||
#define __UHSUB16 __iar_builtin_UHSUB16
|
||||
#define __SASX __iar_builtin_SASX
|
||||
#define __QASX __iar_builtin_QASX
|
||||
#define __SHASX __iar_builtin_SHASX
|
||||
#define __UASX __iar_builtin_UASX
|
||||
#define __UQASX __iar_builtin_UQASX
|
||||
#define __UHASX __iar_builtin_UHASX
|
||||
#define __SSAX __iar_builtin_SSAX
|
||||
#define __QSAX __iar_builtin_QSAX
|
||||
#define __SHSAX __iar_builtin_SHSAX
|
||||
#define __USAX __iar_builtin_USAX
|
||||
#define __UQSAX __iar_builtin_UQSAX
|
||||
#define __UHSAX __iar_builtin_UHSAX
|
||||
#define __USAD8 __iar_builtin_USAD8
|
||||
#define __USADA8 __iar_builtin_USADA8
|
||||
#define __SSAT16 __iar_builtin_SSAT16
|
||||
#define __USAT16 __iar_builtin_USAT16
|
||||
#define __UXTB16 __iar_builtin_UXTB16
|
||||
#define __UXTAB16 __iar_builtin_UXTAB16
|
||||
#define __SXTB16 __iar_builtin_SXTB16
|
||||
#define __SXTAB16 __iar_builtin_SXTAB16
|
||||
#define __SMUAD __iar_builtin_SMUAD
|
||||
#define __SMUADX __iar_builtin_SMUADX
|
||||
#define __SMMLA __iar_builtin_SMMLA
|
||||
#define __SMLAD __iar_builtin_SMLAD
|
||||
#define __SMLADX __iar_builtin_SMLADX
|
||||
#define __SMLALD __iar_builtin_SMLALD
|
||||
#define __SMLALDX __iar_builtin_SMLALDX
|
||||
#define __SMUSD __iar_builtin_SMUSD
|
||||
#define __SMUSDX __iar_builtin_SMUSDX
|
||||
#define __SMLSD __iar_builtin_SMLSD
|
||||
#define __SMLSDX __iar_builtin_SMLSDX
|
||||
#define __SMLSLD __iar_builtin_SMLSLD
|
||||
#define __SMLSLDX __iar_builtin_SMLSLDX
|
||||
#define __SEL __iar_builtin_SEL
|
||||
#define __QADD __iar_builtin_QADD
|
||||
#define __QSUB __iar_builtin_QSUB
|
||||
#define __PKHBT __iar_builtin_PKHBT
|
||||
#define __PKHTB __iar_builtin_PKHTB
|
||||
#endif
|
||||
|
||||
#else /* __ICCARM_INTRINSICS_VERSION__ == 2 */
|
||||
|
||||
#if __IAR_M0_FAMILY
|
||||
/* Avoid clash between intrinsics.h and arm_math.h when compiling for Cortex-M0. */
|
||||
#define __CLZ __cmsis_iar_clz_not_active
|
||||
#define __SSAT __cmsis_iar_ssat_not_active
|
||||
#define __USAT __cmsis_iar_usat_not_active
|
||||
#define __RBIT __cmsis_iar_rbit_not_active
|
||||
#define __get_APSR __cmsis_iar_get_APSR_not_active
|
||||
#endif
|
||||
|
||||
|
||||
#if (!((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \
|
||||
(defined (__FPU_USED ) && (__FPU_USED == 1U)) ))
|
||||
#define __get_FPSCR __cmsis_iar_get_FPSR_not_active
|
||||
#define __set_FPSCR __cmsis_iar_set_FPSR_not_active
|
||||
#endif
|
||||
|
||||
#ifdef __INTRINSICS_INCLUDED
|
||||
#error intrinsics.h is already included previously!
|
||||
#endif
|
||||
|
||||
#include <intrinsics.h>
|
||||
|
||||
#if __IAR_M0_FAMILY
|
||||
/* Avoid clash between intrinsics.h and arm_math.h when compiling for Cortex-M0. */
|
||||
#undef __CLZ
|
||||
#undef __SSAT
|
||||
#undef __USAT
|
||||
#undef __RBIT
|
||||
#undef __get_APSR
|
||||
|
||||
__STATIC_INLINE uint8_t __CLZ(uint32_t data)
|
||||
{
|
||||
if (data == 0U) { return 32U; }
|
||||
|
||||
uint32_t count = 0U;
|
||||
uint32_t mask = 0x80000000U;
|
||||
|
||||
while ((data & mask) == 0U)
|
||||
{
|
||||
count += 1U;
|
||||
mask = mask >> 1U;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
__STATIC_INLINE uint32_t __RBIT(uint32_t v)
|
||||
{
|
||||
uint8_t sc = 31U;
|
||||
uint32_t r = v;
|
||||
for (v >>= 1U; v; v >>= 1U)
|
||||
{
|
||||
r <<= 1U;
|
||||
r |= v & 1U;
|
||||
sc--;
|
||||
}
|
||||
return (r << sc);
|
||||
}
|
||||
|
||||
__STATIC_INLINE uint32_t __get_APSR(void)
|
||||
{
|
||||
uint32_t res;
|
||||
__asm("MRS %0,APSR" : "=r" (res));
|
||||
return res;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if (!((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \
|
||||
(defined (__FPU_USED ) && (__FPU_USED == 1U)) ))
|
||||
#undef __get_FPSCR
|
||||
#undef __set_FPSCR
|
||||
#define __get_FPSCR() (0)
|
||||
#define __set_FPSCR(VALUE) ((void)VALUE)
|
||||
#endif
|
||||
|
||||
#pragma diag_suppress=Pe940
|
||||
#pragma diag_suppress=Pe177
|
||||
|
||||
#define __enable_irq __enable_interrupt
|
||||
#define __disable_irq __disable_interrupt
|
||||
#define __NOP __no_operation
|
||||
|
||||
#define __get_xPSR __get_PSR
|
||||
|
||||
#if (!defined(__ARM_ARCH_6M__) || __ARM_ARCH_6M__==0)
|
||||
|
||||
__IAR_FT uint32_t __LDREXW(uint32_t volatile *ptr)
|
||||
{
|
||||
return __LDREX((unsigned long *)ptr);
|
||||
}
|
||||
|
||||
__IAR_FT uint32_t __STREXW(uint32_t value, uint32_t volatile *ptr)
|
||||
{
|
||||
return __STREX(value, (unsigned long *)ptr);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* __CORTEX_M is defined in core_cm0.h, core_cm3.h and core_cm4.h. */
|
||||
#if (__CORTEX_M >= 0x03)
|
||||
|
||||
__IAR_FT uint32_t __RRX(uint32_t value)
|
||||
{
|
||||
uint32_t result;
|
||||
__ASM("RRX %0, %1" : "=r"(result) : "r" (value) : "cc");
|
||||
return(result);
|
||||
}
|
||||
|
||||
__IAR_FT void __set_BASEPRI_MAX(uint32_t value)
|
||||
{
|
||||
__asm volatile("MSR BASEPRI_MAX,%0"::"r" (value));
|
||||
}
|
||||
|
||||
|
||||
#define __enable_fault_irq __enable_fiq
|
||||
#define __disable_fault_irq __disable_fiq
|
||||
|
||||
|
||||
#endif /* (__CORTEX_M >= 0x03) */
|
||||
|
||||
__IAR_FT uint32_t __ROR(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
return (op1 >> op2) | (op1 << ((sizeof(op1)*8)-op2));
|
||||
}
|
||||
|
||||
#if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \
|
||||
(defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) )
|
||||
|
||||
__IAR_FT uint32_t __get_MSPLIM(void)
|
||||
{
|
||||
uint32_t res;
|
||||
#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \
|
||||
(!defined (__ARM_FEATURE_CMSE ) || (__ARM_FEATURE_CMSE < 3)))
|
||||
// without main extensions, the non-secure MSPLIM is RAZ/WI
|
||||
res = 0U;
|
||||
#else
|
||||
__asm volatile("MRS %0,MSPLIM" : "=r" (res));
|
||||
#endif
|
||||
return res;
|
||||
}
|
||||
|
||||
__IAR_FT void __set_MSPLIM(uint32_t value)
|
||||
{
|
||||
#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \
|
||||
(!defined (__ARM_FEATURE_CMSE ) || (__ARM_FEATURE_CMSE < 3)))
|
||||
// without main extensions, the non-secure MSPLIM is RAZ/WI
|
||||
(void)value;
|
||||
#else
|
||||
__asm volatile("MSR MSPLIM,%0" :: "r" (value));
|
||||
#endif
|
||||
}
|
||||
|
||||
__IAR_FT uint32_t __get_PSPLIM(void)
|
||||
{
|
||||
uint32_t res;
|
||||
#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \
|
||||
(!defined (__ARM_FEATURE_CMSE ) || (__ARM_FEATURE_CMSE < 3)))
|
||||
// without main extensions, the non-secure PSPLIM is RAZ/WI
|
||||
res = 0U;
|
||||
#else
|
||||
__asm volatile("MRS %0,PSPLIM" : "=r" (res));
|
||||
#endif
|
||||
return res;
|
||||
}
|
||||
|
||||
__IAR_FT void __set_PSPLIM(uint32_t value)
|
||||
{
|
||||
#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \
|
||||
(!defined (__ARM_FEATURE_CMSE ) || (__ARM_FEATURE_CMSE < 3)))
|
||||
// without main extensions, the non-secure PSPLIM is RAZ/WI
|
||||
(void)value;
|
||||
#else
|
||||
__asm volatile("MSR PSPLIM,%0" :: "r" (value));
|
||||
#endif
|
||||
}
|
||||
|
||||
__IAR_FT uint32_t __TZ_get_CONTROL_NS(void)
|
||||
{
|
||||
uint32_t res;
|
||||
__asm volatile("MRS %0,CONTROL_NS" : "=r" (res));
|
||||
return res;
|
||||
}
|
||||
|
||||
__IAR_FT void __TZ_set_CONTROL_NS(uint32_t value)
|
||||
{
|
||||
__asm volatile("MSR CONTROL_NS,%0" :: "r" (value));
|
||||
}
|
||||
|
||||
__IAR_FT uint32_t __TZ_get_PSP_NS(void)
|
||||
{
|
||||
uint32_t res;
|
||||
__asm volatile("MRS %0,PSP_NS" : "=r" (res));
|
||||
return res;
|
||||
}
|
||||
|
||||
__IAR_FT void __TZ_set_PSP_NS(uint32_t value)
|
||||
{
|
||||
__asm volatile("MSR PSP_NS,%0" :: "r" (value));
|
||||
}
|
||||
|
||||
__IAR_FT uint32_t __TZ_get_MSP_NS(void)
|
||||
{
|
||||
uint32_t res;
|
||||
__asm volatile("MRS %0,MSP_NS" : "=r" (res));
|
||||
return res;
|
||||
}
|
||||
|
||||
__IAR_FT void __TZ_set_MSP_NS(uint32_t value)
|
||||
{
|
||||
__asm volatile("MSR MSP_NS,%0" :: "r" (value));
|
||||
}
|
||||
|
||||
__IAR_FT uint32_t __TZ_get_SP_NS(void)
|
||||
{
|
||||
uint32_t res;
|
||||
__asm volatile("MRS %0,SP_NS" : "=r" (res));
|
||||
return res;
|
||||
}
|
||||
__IAR_FT void __TZ_set_SP_NS(uint32_t value)
|
||||
{
|
||||
__asm volatile("MSR SP_NS,%0" :: "r" (value));
|
||||
}
|
||||
|
||||
__IAR_FT uint32_t __TZ_get_PRIMASK_NS(void)
|
||||
{
|
||||
uint32_t res;
|
||||
__asm volatile("MRS %0,PRIMASK_NS" : "=r" (res));
|
||||
return res;
|
||||
}
|
||||
|
||||
__IAR_FT void __TZ_set_PRIMASK_NS(uint32_t value)
|
||||
{
|
||||
__asm volatile("MSR PRIMASK_NS,%0" :: "r" (value));
|
||||
}
|
||||
|
||||
__IAR_FT uint32_t __TZ_get_BASEPRI_NS(void)
|
||||
{
|
||||
uint32_t res;
|
||||
__asm volatile("MRS %0,BASEPRI_NS" : "=r" (res));
|
||||
return res;
|
||||
}
|
||||
|
||||
__IAR_FT void __TZ_set_BASEPRI_NS(uint32_t value)
|
||||
{
|
||||
__asm volatile("MSR BASEPRI_NS,%0" :: "r" (value));
|
||||
}
|
||||
|
||||
__IAR_FT uint32_t __TZ_get_FAULTMASK_NS(void)
|
||||
{
|
||||
uint32_t res;
|
||||
__asm volatile("MRS %0,FAULTMASK_NS" : "=r" (res));
|
||||
return res;
|
||||
}
|
||||
|
||||
__IAR_FT void __TZ_set_FAULTMASK_NS(uint32_t value)
|
||||
{
|
||||
__asm volatile("MSR FAULTMASK_NS,%0" :: "r" (value));
|
||||
}
|
||||
|
||||
__IAR_FT uint32_t __TZ_get_PSPLIM_NS(void)
|
||||
{
|
||||
uint32_t res;
|
||||
#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \
|
||||
(!defined (__ARM_FEATURE_CMSE ) || (__ARM_FEATURE_CMSE < 3)))
|
||||
// without main extensions, the non-secure PSPLIM is RAZ/WI
|
||||
res = 0U;
|
||||
#else
|
||||
__asm volatile("MRS %0,PSPLIM_NS" : "=r" (res));
|
||||
#endif
|
||||
return res;
|
||||
}
|
||||
|
||||
__IAR_FT void __TZ_set_PSPLIM_NS(uint32_t value)
|
||||
{
|
||||
#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \
|
||||
(!defined (__ARM_FEATURE_CMSE ) || (__ARM_FEATURE_CMSE < 3)))
|
||||
// without main extensions, the non-secure PSPLIM is RAZ/WI
|
||||
(void)value;
|
||||
#else
|
||||
__asm volatile("MSR PSPLIM_NS,%0" :: "r" (value));
|
||||
#endif
|
||||
}
|
||||
|
||||
__IAR_FT uint32_t __TZ_get_MSPLIM_NS(void)
|
||||
{
|
||||
uint32_t res;
|
||||
__asm volatile("MRS %0,MSPLIM_NS" : "=r" (res));
|
||||
return res;
|
||||
}
|
||||
|
||||
__IAR_FT void __TZ_set_MSPLIM_NS(uint32_t value)
|
||||
{
|
||||
__asm volatile("MSR MSPLIM_NS,%0" :: "r" (value));
|
||||
}
|
||||
|
||||
#endif /* __ARM_ARCH_8M_MAIN__ or __ARM_ARCH_8M_BASE__ */
|
||||
|
||||
#endif /* __ICCARM_INTRINSICS_VERSION__ == 2 */
|
||||
|
||||
#define __BKPT(value) __asm volatile ("BKPT %0" : : "i"(value))
|
||||
|
||||
#if __IAR_M0_FAMILY
|
||||
__STATIC_INLINE int32_t __SSAT(int32_t val, uint32_t sat)
|
||||
{
|
||||
if ((sat >= 1U) && (sat <= 32U))
|
||||
{
|
||||
const int32_t max = (int32_t)((1U << (sat - 1U)) - 1U);
|
||||
const int32_t min = -1 - max ;
|
||||
if (val > max)
|
||||
{
|
||||
return max;
|
||||
}
|
||||
else if (val < min)
|
||||
{
|
||||
return min;
|
||||
}
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
__STATIC_INLINE uint32_t __USAT(int32_t val, uint32_t sat)
|
||||
{
|
||||
if (sat <= 31U)
|
||||
{
|
||||
const uint32_t max = ((1U << sat) - 1U);
|
||||
if (val > (int32_t)max)
|
||||
{
|
||||
return max;
|
||||
}
|
||||
else if (val < 0)
|
||||
{
|
||||
return 0U;
|
||||
}
|
||||
}
|
||||
return (uint32_t)val;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (__CORTEX_M >= 0x03) /* __CORTEX_M is defined in core_cm0.h, core_cm3.h and core_cm4.h. */
|
||||
|
||||
__IAR_FT uint8_t __LDRBT(volatile uint8_t *addr)
|
||||
{
|
||||
uint32_t res;
|
||||
__ASM("LDRBT %0, [%1]" : "=r" (res) : "r" (addr) : "memory");
|
||||
return ((uint8_t)res);
|
||||
}
|
||||
|
||||
__IAR_FT uint16_t __LDRHT(volatile uint16_t *addr)
|
||||
{
|
||||
uint32_t res;
|
||||
__ASM("LDRHT %0, [%1]" : "=r" (res) : "r" (addr) : "memory");
|
||||
return ((uint16_t)res);
|
||||
}
|
||||
|
||||
__IAR_FT uint32_t __LDRT(volatile uint32_t *addr)
|
||||
{
|
||||
uint32_t res;
|
||||
__ASM("LDRT %0, [%1]" : "=r" (res) : "r" (addr) : "memory");
|
||||
return res;
|
||||
}
|
||||
|
||||
__IAR_FT void __STRBT(uint8_t value, volatile uint8_t *addr)
|
||||
{
|
||||
__ASM("STRBT %1, [%0]" : : "r" (addr), "r" ((uint32_t)value) : "memory");
|
||||
}
|
||||
|
||||
__IAR_FT void __STRHT(uint16_t value, volatile uint16_t *addr)
|
||||
{
|
||||
__ASM("STRHT %1, [%0]" : : "r" (addr), "r" ((uint32_t)value) : "memory");
|
||||
}
|
||||
|
||||
__IAR_FT void __STRT(uint32_t value, volatile uint32_t *addr)
|
||||
{
|
||||
__ASM("STRT %1, [%0]" : : "r" (addr), "r" (value) : "memory");
|
||||
}
|
||||
|
||||
#endif /* (__CORTEX_M >= 0x03) */
|
||||
|
||||
#if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \
|
||||
(defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) )
|
||||
|
||||
|
||||
__IAR_FT uint8_t __LDAB(volatile uint8_t *ptr)
|
||||
{
|
||||
uint32_t res;
|
||||
__ASM volatile ("LDAB %0, [%1]" : "=r" (res) : "r" (ptr) : "memory");
|
||||
return ((uint8_t)res);
|
||||
}
|
||||
|
||||
__IAR_FT uint16_t __LDAH(volatile uint16_t *ptr)
|
||||
{
|
||||
uint32_t res;
|
||||
__ASM volatile ("LDAH %0, [%1]" : "=r" (res) : "r" (ptr) : "memory");
|
||||
return ((uint16_t)res);
|
||||
}
|
||||
|
||||
__IAR_FT uint32_t __LDA(volatile uint32_t *ptr)
|
||||
{
|
||||
uint32_t res;
|
||||
__ASM volatile ("LDA %0, [%1]" : "=r" (res) : "r" (ptr) : "memory");
|
||||
return res;
|
||||
}
|
||||
|
||||
__IAR_FT void __STLB(uint8_t value, volatile uint8_t *ptr)
|
||||
{
|
||||
__ASM volatile ("STLB %1, [%0]" :: "r" (ptr), "r" (value) : "memory");
|
||||
}
|
||||
|
||||
__IAR_FT void __STLH(uint16_t value, volatile uint16_t *ptr)
|
||||
{
|
||||
__ASM volatile ("STLH %1, [%0]" :: "r" (ptr), "r" (value) : "memory");
|
||||
}
|
||||
|
||||
__IAR_FT void __STL(uint32_t value, volatile uint32_t *ptr)
|
||||
{
|
||||
__ASM volatile ("STL %1, [%0]" :: "r" (ptr), "r" (value) : "memory");
|
||||
}
|
||||
|
||||
__IAR_FT uint8_t __LDAEXB(volatile uint8_t *ptr)
|
||||
{
|
||||
uint32_t res;
|
||||
__ASM volatile ("LDAEXB %0, [%1]" : "=r" (res) : "r" (ptr) : "memory");
|
||||
return ((uint8_t)res);
|
||||
}
|
||||
|
||||
__IAR_FT uint16_t __LDAEXH(volatile uint16_t *ptr)
|
||||
{
|
||||
uint32_t res;
|
||||
__ASM volatile ("LDAEXH %0, [%1]" : "=r" (res) : "r" (ptr) : "memory");
|
||||
return ((uint16_t)res);
|
||||
}
|
||||
|
||||
__IAR_FT uint32_t __LDAEX(volatile uint32_t *ptr)
|
||||
{
|
||||
uint32_t res;
|
||||
__ASM volatile ("LDAEX %0, [%1]" : "=r" (res) : "r" (ptr) : "memory");
|
||||
return res;
|
||||
}
|
||||
|
||||
__IAR_FT uint32_t __STLEXB(uint8_t value, volatile uint8_t *ptr)
|
||||
{
|
||||
uint32_t res;
|
||||
__ASM volatile ("STLEXB %0, %2, [%1]" : "=r" (res) : "r" (ptr), "r" (value) : "memory");
|
||||
return res;
|
||||
}
|
||||
|
||||
__IAR_FT uint32_t __STLEXH(uint16_t value, volatile uint16_t *ptr)
|
||||
{
|
||||
uint32_t res;
|
||||
__ASM volatile ("STLEXH %0, %2, [%1]" : "=r" (res) : "r" (ptr), "r" (value) : "memory");
|
||||
return res;
|
||||
}
|
||||
|
||||
__IAR_FT uint32_t __STLEX(uint32_t value, volatile uint32_t *ptr)
|
||||
{
|
||||
uint32_t res;
|
||||
__ASM volatile ("STLEX %0, %2, [%1]" : "=r" (res) : "r" (ptr), "r" (value) : "memory");
|
||||
return res;
|
||||
}
|
||||
|
||||
#endif /* __ARM_ARCH_8M_MAIN__ or __ARM_ARCH_8M_BASE__ */
|
||||
|
||||
#undef __IAR_FT
|
||||
#undef __IAR_M0_FAMILY
|
||||
#undef __ICCARM_V8
|
||||
|
||||
#pragma diag_default=Pe940
|
||||
#pragma diag_default=Pe177
|
||||
|
||||
#endif /* __CMSIS_ICCARM_H__ */
|
||||
39
Software/Drivers/CMSIS/Core/Include/cmsis_version.h
Normal file
39
Software/Drivers/CMSIS/Core/Include/cmsis_version.h
Normal file
@ -0,0 +1,39 @@
|
||||
/**************************************************************************//**
|
||||
* @file cmsis_version.h
|
||||
* @brief CMSIS Core(M) Version definitions
|
||||
* @version V5.0.2
|
||||
* @date 19. April 2017
|
||||
******************************************************************************/
|
||||
/*
|
||||
* Copyright (c) 2009-2017 ARM Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#if defined ( __ICCARM__ )
|
||||
#pragma system_include /* treat file as system include file for MISRA check */
|
||||
#elif defined (__clang__)
|
||||
#pragma clang system_header /* treat file as system include file */
|
||||
#endif
|
||||
|
||||
#ifndef __CMSIS_VERSION_H
|
||||
#define __CMSIS_VERSION_H
|
||||
|
||||
/* CMSIS Version definitions */
|
||||
#define __CM_CMSIS_VERSION_MAIN ( 5U) /*!< [31:16] CMSIS Core(M) main version */
|
||||
#define __CM_CMSIS_VERSION_SUB ( 1U) /*!< [15:0] CMSIS Core(M) sub version */
|
||||
#define __CM_CMSIS_VERSION ((__CM_CMSIS_VERSION_MAIN << 16U) | \
|
||||
__CM_CMSIS_VERSION_SUB ) /*!< CMSIS Core(M) version number */
|
||||
#endif
|
||||
1918
Software/Drivers/CMSIS/Core/Include/core_armv8mbl.h
Normal file
1918
Software/Drivers/CMSIS/Core/Include/core_armv8mbl.h
Normal file
File diff suppressed because it is too large
Load Diff
2927
Software/Drivers/CMSIS/Core/Include/core_armv8mml.h
Normal file
2927
Software/Drivers/CMSIS/Core/Include/core_armv8mml.h
Normal file
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user