├── .cproject ├── .gitignore ├── .project ├── .settings └── org.eclipse.cdt.codan.core.prefs ├── README.md ├── inc ├── core_cm3.h ├── node.h ├── stm32-template.h ├── stm32f10x_conf.h └── stm32f10x_it.h ├── modbus ├── crc.cpp ├── crc.h ├── slave-rtu.cpp ├── slave-rtu.h ├── usart-rs485-modbus.cpp └── usart-rs485-modbus.h ├── readme.txt ├── src ├── main.cpp ├── node.cpp └── stm32f10x_it.cpp ├── stm32-modbus.doxyfile ├── stm32_flash.ld ├── sys ├── core_cm3.c ├── library_hacks.cpp ├── newlib_stubs.cpp ├── startup_stm32f10x_md_vl.S └── system_stm32f10x.c └── test └── md_readbit.py /.cproject: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | Debug/ 2 | Release/ 3 | html/ 4 | 5 | stm32libs 6 | *.swp 7 | 8 | -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | demo 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.cdt.managedbuilder.core.genmakebuilder 10 | clean,full,incremental, 11 | 12 | 13 | 14 | 15 | org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder 16 | full,incremental, 17 | 18 | 19 | 20 | 21 | 22 | org.eclipse.cdt.core.cnature 23 | org.eclipse.cdt.core.ccnature 24 | org.eclipse.cdt.managedbuilder.core.managedBuildNature 25 | org.eclipse.cdt.managedbuilder.core.ScannerConfigNature 26 | 27 | 28 | 29 | StdPeriph 30 | 2 31 | PARENT-1-PROJECT_LOC/Libraries/STM32F10x_StdPeriph_Driver/src 32 | 33 | 34 | stm32libs 35 | 2 36 | PARENT-1-PROJECT_LOC/stm32libs 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /.settings/org.eclipse.cdt.codan.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.cdt.codan.checkers.errnoreturn=Warning 3 | org.eclipse.cdt.codan.checkers.errnoreturn.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},implicit\=>false} 4 | org.eclipse.cdt.codan.checkers.errreturnvalue=Error 5 | org.eclipse.cdt.codan.checkers.errreturnvalue.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} 6 | org.eclipse.cdt.codan.checkers.noreturn=Error 7 | org.eclipse.cdt.codan.checkers.noreturn.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},implicit\=>false} 8 | org.eclipse.cdt.codan.internal.checkers.AbstractClassCreation=Error 9 | org.eclipse.cdt.codan.internal.checkers.AbstractClassCreation.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} 10 | org.eclipse.cdt.codan.internal.checkers.AmbiguousProblem=Error 11 | org.eclipse.cdt.codan.internal.checkers.AmbiguousProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} 12 | org.eclipse.cdt.codan.internal.checkers.AssignmentInConditionProblem=Warning 13 | org.eclipse.cdt.codan.internal.checkers.AssignmentInConditionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} 14 | org.eclipse.cdt.codan.internal.checkers.AssignmentToItselfProblem=Error 15 | org.eclipse.cdt.codan.internal.checkers.AssignmentToItselfProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} 16 | org.eclipse.cdt.codan.internal.checkers.CaseBreakProblem=Warning 17 | org.eclipse.cdt.codan.internal.checkers.CaseBreakProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},no_break_comment\=>"no break",last_case_param\=>false,empty_case_param\=>false} 18 | org.eclipse.cdt.codan.internal.checkers.CatchByReference=Warning 19 | org.eclipse.cdt.codan.internal.checkers.CatchByReference.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},unknown\=>false,exceptions\=>()} 20 | org.eclipse.cdt.codan.internal.checkers.CircularReferenceProblem=Error 21 | org.eclipse.cdt.codan.internal.checkers.CircularReferenceProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} 22 | org.eclipse.cdt.codan.internal.checkers.ClassMembersInitialization=Warning 23 | org.eclipse.cdt.codan.internal.checkers.ClassMembersInitialization.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},skip\=>true} 24 | org.eclipse.cdt.codan.internal.checkers.FieldResolutionProblem=Error 25 | org.eclipse.cdt.codan.internal.checkers.FieldResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} 26 | org.eclipse.cdt.codan.internal.checkers.FunctionResolutionProblem=Error 27 | org.eclipse.cdt.codan.internal.checkers.FunctionResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} 28 | org.eclipse.cdt.codan.internal.checkers.InvalidArguments=Error 29 | org.eclipse.cdt.codan.internal.checkers.InvalidArguments.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} 30 | org.eclipse.cdt.codan.internal.checkers.InvalidTemplateArgumentsProblem=Error 31 | org.eclipse.cdt.codan.internal.checkers.InvalidTemplateArgumentsProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} 32 | org.eclipse.cdt.codan.internal.checkers.LabelStatementNotFoundProblem=Error 33 | org.eclipse.cdt.codan.internal.checkers.LabelStatementNotFoundProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} 34 | org.eclipse.cdt.codan.internal.checkers.MemberDeclarationNotFoundProblem=Error 35 | org.eclipse.cdt.codan.internal.checkers.MemberDeclarationNotFoundProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} 36 | org.eclipse.cdt.codan.internal.checkers.MethodResolutionProblem=Error 37 | org.eclipse.cdt.codan.internal.checkers.MethodResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} 38 | org.eclipse.cdt.codan.internal.checkers.NamingConventionFunctionChecker=-Info 39 | org.eclipse.cdt.codan.internal.checkers.NamingConventionFunctionChecker.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},pattern\=>"^[a-z]",macro\=>true,exceptions\=>()} 40 | org.eclipse.cdt.codan.internal.checkers.NonVirtualDestructorProblem=Warning 41 | org.eclipse.cdt.codan.internal.checkers.NonVirtualDestructorProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} 42 | org.eclipse.cdt.codan.internal.checkers.OverloadProblem=Error 43 | org.eclipse.cdt.codan.internal.checkers.OverloadProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} 44 | org.eclipse.cdt.codan.internal.checkers.RedeclarationProblem=Error 45 | org.eclipse.cdt.codan.internal.checkers.RedeclarationProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} 46 | org.eclipse.cdt.codan.internal.checkers.RedefinitionProblem=Error 47 | org.eclipse.cdt.codan.internal.checkers.RedefinitionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} 48 | org.eclipse.cdt.codan.internal.checkers.ReturnStyleProblem=-Warning 49 | org.eclipse.cdt.codan.internal.checkers.ReturnStyleProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} 50 | org.eclipse.cdt.codan.internal.checkers.ScanfFormatStringSecurityProblem=-Warning 51 | org.eclipse.cdt.codan.internal.checkers.ScanfFormatStringSecurityProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} 52 | org.eclipse.cdt.codan.internal.checkers.StatementHasNoEffectProblem=Warning 53 | org.eclipse.cdt.codan.internal.checkers.StatementHasNoEffectProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},macro\=>true,exceptions\=>()} 54 | org.eclipse.cdt.codan.internal.checkers.SuggestedParenthesisProblem=Warning 55 | org.eclipse.cdt.codan.internal.checkers.SuggestedParenthesisProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},paramNot\=>false} 56 | org.eclipse.cdt.codan.internal.checkers.SuspiciousSemicolonProblem=Warning 57 | org.eclipse.cdt.codan.internal.checkers.SuspiciousSemicolonProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},else\=>false,afterelse\=>false} 58 | org.eclipse.cdt.codan.internal.checkers.TypeResolutionProblem=Error 59 | org.eclipse.cdt.codan.internal.checkers.TypeResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} 60 | org.eclipse.cdt.codan.internal.checkers.UnusedFunctionDeclarationProblem=Warning 61 | org.eclipse.cdt.codan.internal.checkers.UnusedFunctionDeclarationProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},macro\=>true} 62 | org.eclipse.cdt.codan.internal.checkers.UnusedStaticFunctionProblem=Warning 63 | org.eclipse.cdt.codan.internal.checkers.UnusedStaticFunctionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},macro\=>true} 64 | org.eclipse.cdt.codan.internal.checkers.UnusedVariableDeclarationProblem=Warning 65 | org.eclipse.cdt.codan.internal.checkers.UnusedVariableDeclarationProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},macro\=>true,exceptions\=>("@(\#)","$Id")} 66 | org.eclipse.cdt.codan.internal.checkers.VariableResolutionProblem=Error 67 | org.eclipse.cdt.codan.internal.checkers.VariableResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} 68 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | stm32 development template for modbus based on ST STM32F100 STM32Discovery 2 | 3 | OS: ubuntu 4 | 5 | Toolchain: Sourcery CodeBench Lite Edition for ARM EABI hosted on IA32 GNU/Linux 6 | 7 | IDE: eclipse + cdt + gnu arm eclipe plug-in 8 | 9 | note: the startup asm source file should be copied from Libraries/CMSIS/CM3/DeviceSupport/ST/STM32F10x/startup, and rename startup_stm32f10x_hd.s to startup_stm32f10x_hd.S 10 | -------------------------------------------------------------------------------- /inc/node.h: -------------------------------------------------------------------------------- 1 | /* 2 | * node.h 3 | * 4 | * Created on: Jul 23, 2013 5 | * Author: agu 6 | */ 7 | 8 | #ifndef NODE_H_ 9 | #define NODE_H_ 10 | 11 | #include 12 | 13 | #include "modbus/slave-rtu.h" 14 | #include "gpio/gpio.h" 15 | #include "adc/adc.h" 16 | #include "dma/dma.h" 17 | 18 | class Node: public SlaveRtu { 19 | public: 20 | Node(UsartRs485Modbus & usart, uint8_t address); 21 | ~Node(); 22 | void init(); 23 | 24 | private: 25 | Gpio ** _bit_input_pins; 26 | Gpio ** _coil_pins; 27 | Gpio ** _short_input_pins; 28 | 29 | Adc * _adc; 30 | uint8_t * _adc_channels; 31 | const static uint8_t _uuid[]; 32 | const static uint8_t _lengths[]; 33 | 34 | uint8_t updateBitInputs(uint16_t index, uint16_t length); 35 | uint8_t updateShortInputs(uint16_t index, uint16_t length); 36 | uint8_t updateCoils(uint16_t index, uint16_t length); 37 | uint8_t updateHoldings(uint16_t index, uint16_t length) {return 0;} 38 | }; 39 | 40 | #endif /* NODE_H_ */ 41 | -------------------------------------------------------------------------------- /inc/stm32-template.h: -------------------------------------------------------------------------------- 1 | /* 2 | * stm32-template.h 3 | * 4 | * Created on: May 31, 2013 5 | * Author: agu 6 | */ 7 | 8 | #ifndef STM32_TEMPLATE_H_ 9 | #define STM32_TEMPLATE_H_ 10 | 11 | #include "stm32f10x.h" 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | #include "common/bit_op.h" 18 | #include "usart/usart.h" 19 | #include "gpio/gpio.h" 20 | #include "tim/tim.h" 21 | #include "nvic/nvic.h" 22 | #include "i2c/i2c.h" 23 | #include "adc/adc.h" 24 | 25 | void init(); 26 | extern void setup(); 27 | extern void loop(); 28 | extern void delay(u32 ms); 29 | extern void delayMicroseconds(vu32 us); 30 | 31 | #endif /* STM32_TEMPLATE_H_ */ 32 | -------------------------------------------------------------------------------- /inc/stm32f10x_conf.h: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file stm32f10x_conf.h 4 | * @author MCD Application Team 5 | * @version V3.5.0 6 | * @date 08-April-2011 7 | * @brief Library configuration file. 8 | ****************************************************************************** 9 | * @attention 10 | * 11 | * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS 12 | * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE 13 | * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY 14 | * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING 15 | * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE 16 | * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. 17 | * 18 | *

© COPYRIGHT 2011 STMicroelectronics

19 | ****************************************************************************** 20 | */ 21 | 22 | /* Define to prevent recursive inclusion -------------------------------------*/ 23 | #ifndef __STM32F10x_CONF_H 24 | #define __STM32F10x_CONF_H 25 | 26 | #ifdef __cplusplus 27 | extern "C" { 28 | #endif 29 | 30 | /* Includes ------------------------------------------------------------------*/ 31 | /* Uncomment/Comment the line below to enable/disable peripheral header file inclusion */ 32 | #include "stm32f10x_adc.h" 33 | #include "stm32f10x_bkp.h" 34 | #include "stm32f10x_can.h" 35 | #include "stm32f10x_cec.h" 36 | #include "stm32f10x_crc.h" 37 | #include "stm32f10x_dac.h" 38 | #include "stm32f10x_dbgmcu.h" 39 | #include "stm32f10x_dma.h" 40 | #include "stm32f10x_exti.h" 41 | #include "stm32f10x_flash.h" 42 | #include "stm32f10x_fsmc.h" 43 | #include "stm32f10x_gpio.h" 44 | #include "stm32f10x_i2c.h" 45 | #include "stm32f10x_iwdg.h" 46 | #include "stm32f10x_pwr.h" 47 | #include "stm32f10x_rcc.h" 48 | #include "stm32f10x_rtc.h" 49 | #include "stm32f10x_sdio.h" 50 | #include "stm32f10x_spi.h" 51 | #include "stm32f10x_tim.h" 52 | #include "stm32f10x_usart.h" 53 | #include "stm32f10x_wwdg.h" 54 | #include "misc.h" /* High level functions for NVIC and SysTick (add-on to CMSIS functions) */ 55 | 56 | /* Exported types ------------------------------------------------------------*/ 57 | /* Exported constants --------------------------------------------------------*/ 58 | /* Uncomment the line below to expanse the "assert_param" macro in the 59 | Standard Peripheral Library drivers code */ 60 | /* #define USE_FULL_ASSERT 1 */ 61 | 62 | /* Exported macro ------------------------------------------------------------*/ 63 | #ifdef USE_FULL_ASSERT 64 | 65 | /** 66 | * @brief The assert_param macro is used for function's parameters check. 67 | * @param expr: If expr is false, it calls assert_failed function which reports 68 | * the name of the source file and the source line number of the call 69 | * that failed. If expr is true, it returns no value. 70 | * @retval None 71 | */ 72 | #define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__)) 73 | /* Exported functions ------------------------------------------------------- */ 74 | void assert_failed(uint8_t* file, uint32_t line); 75 | #else 76 | #define assert_param(expr) ((void)0) 77 | #endif /* USE_FULL_ASSERT */ 78 | 79 | #ifdef __cplusplus 80 | } 81 | #endif 82 | 83 | #endif /* __STM32F10x_CONF_H */ 84 | 85 | /******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ 86 | -------------------------------------------------------------------------------- /inc/stm32f10x_it.h: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file stm32f10x_it.h 4 | * @author MCD Application Team 5 | * @version V3.5.0 6 | * @date 08-April-2011 7 | * @brief This file contains the headers of the interrupt handlers. 8 | ****************************************************************************** 9 | * @attention 10 | * 11 | * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS 12 | * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE 13 | * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY 14 | * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING 15 | * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE 16 | * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. 17 | * 18 | *

© COPYRIGHT 2011 STMicroelectronics

19 | ****************************************************************************** 20 | */ 21 | 22 | /* Define to prevent recursive inclusion -------------------------------------*/ 23 | #ifndef __STM32F10x_IT_H 24 | #define __STM32F10x_IT_H 25 | 26 | /* Includes ------------------------------------------------------------------*/ 27 | #include "stm32f10x.h" 28 | 29 | #ifdef __cplusplus 30 | extern "C" { 31 | #endif 32 | 33 | /* Exported types ------------------------------------------------------------*/ 34 | /* Exported constants --------------------------------------------------------*/ 35 | /* Exported macro ------------------------------------------------------------*/ 36 | /* Exported functions ------------------------------------------------------- */ 37 | 38 | void NMI_Handler(void); 39 | void HardFault_Handler(void); 40 | void MemManage_Handler(void); 41 | void BusFault_Handler(void); 42 | void UsageFault_Handler(void); 43 | void SVC_Handler(void); 44 | void DebugMon_Handler(void); 45 | void PendSV_Handler(void); 46 | void SysTick_Handler(void); 47 | void TIM2_IRQHandler(void); 48 | void USART1_IRQHandler(void); 49 | void TIM1_UP_TIM16_IRQHandler(void); 50 | 51 | #ifdef __cplusplus 52 | } 53 | #endif 54 | 55 | #endif /* __STM32F10x_IT_H */ 56 | 57 | /******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ 58 | -------------------------------------------------------------------------------- /modbus/crc.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Crc.cpp 3 | * 4 | * Created on: Jul 17, 2013 5 | * Author: agu 6 | */ 7 | 8 | #include "crc.h" 9 | 10 | const uint8_t Crc::_HI[] = { 11 | 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 12 | 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 13 | 14 | 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 15 | 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 16 | 17 | 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 18 | 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 19 | 20 | 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 21 | 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 22 | 23 | 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 24 | 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 25 | 26 | 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 27 | 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 28 | 29 | 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 30 | 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 31 | 32 | 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 33 | 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 34 | 35 | 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 36 | 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 37 | 38 | 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 39 | 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 40 | 41 | 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 42 | 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 43 | 44 | 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 45 | 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 46 | 47 | 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 48 | 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 49 | 50 | 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 51 | 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 52 | 53 | 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 54 | 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 55 | 56 | 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 57 | 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 58 | }; 59 | 60 | const uint8_t Crc::_LO[] = { 61 | 0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 62 | 0xC6, 0x06, 0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 63 | 64 | 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E, 65 | 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09, 0x08, 0xC8, 66 | 67 | 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A, 68 | 0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 69 | 70 | 0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 71 | 0xD2, 0x12, 0x13, 0xD3, 0x11, 0xD1, 0xD0, 0x10, 72 | 73 | 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32, 74 | 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4, 75 | 76 | 0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 77 | 0xFA, 0x3A, 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 78 | 79 | 0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 80 | 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED, 0xEC, 0x2C, 81 | 82 | 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26, 83 | 0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 84 | 85 | 0xA0, 0x60, 0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 86 | 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4, 87 | 88 | 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F, 0x6E, 0xAE, 89 | 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68, 90 | 91 | 0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 92 | 0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 93 | 94 | 0xB4, 0x74, 0x75, 0xB5, 0x77, 0xB7, 0xB6, 0x76, 95 | 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0, 96 | 97 | 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92, 98 | 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 99 | 100 | 0x9C, 0x5C, 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 101 | 0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 102 | 103 | 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B, 0x8A, 0x4A, 104 | 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C, 105 | 106 | 0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 107 | 0x82, 0x42, 0x43, 0x83, 0x41, 0x81, 0x80, 0x40 108 | }; 109 | 110 | uint16_t Crc::calc(const uint8_t *p, uint16_t length) { 111 | uint8_t hi = 0xFF; 112 | uint8_t lo = 0xFF; 113 | 114 | while (length--) { 115 | uint8_t i = lo ^ *p++; 116 | lo = hi ^ _HI[i]; 117 | hi = _LO[i]; 118 | } 119 | return (uint16_t) (hi << 8) | lo; 120 | } 121 | 122 | Crc crc; 123 | -------------------------------------------------------------------------------- /modbus/crc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Crc.h 3 | * 4 | * Created on: Jul 17, 2013 5 | * Author: agu 6 | */ 7 | 8 | #ifndef CRC_H_ 9 | #define CRC_H_ 10 | 11 | #include "stm32f10x.h" 12 | 13 | class Crc { 14 | public: 15 | static uint16_t calc(const uint8_t *p, uint16_t length); 16 | private: 17 | const static uint8_t _HI[]; 18 | const static uint8_t _LO[]; 19 | }; 20 | 21 | extern Crc crc; 22 | 23 | #endif /* CRC_H_ */ 24 | -------------------------------------------------------------------------------- /modbus/slave-rtu.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * slave-rtu.cpp 3 | * 4 | * Created on: Jul 17, 2013 5 | * Author: agu 6 | */ 7 | 8 | #include "slave-rtu.h" 9 | 10 | /** 11 | * 12 | * 13 | * 14 | */ 15 | 16 | SlaveRtu::SlaveRtu(UsartRs485Modbus & usart, uint8_t address) : 17 | _usart(usart), _address(address) { 18 | 19 | _bit_inputs = NULL; 20 | _bit_input_length = 0; 21 | 22 | _short_inputs = NULL; 23 | _short_input_length = 0; 24 | 25 | _coils = NULL; 26 | _coil_length = 0; 27 | 28 | _holdings = NULL; 29 | _holding_length = 0; 30 | 31 | this->initBitInputs(16); 32 | this->initShortInputs(8); 33 | this->initCoils(32); 34 | this->initHoldings(16); 35 | } 36 | 37 | SlaveRtu::~SlaveRtu() { 38 | free(_bit_inputs); 39 | free(_short_inputs); 40 | 41 | free(_coils); 42 | free(_holdings); 43 | } 44 | 45 | void SlaveRtu::initBitInputs(uint16_t length) { 46 | if (_bit_inputs) free(_bit_inputs); 47 | 48 | _bit_input_length = length; 49 | uint8_t bit_input_byte_size = (_bit_input_length + 7) >> 3; 50 | _bit_inputs = (uint8_t *) malloc(bit_input_byte_size * sizeof(uint8_t)); 51 | 52 | assert_param(_bit_inputs); 53 | memset(_bit_inputs, 0, bit_input_byte_size); 54 | } 55 | 56 | void SlaveRtu::initShortInputs(uint16_t length) { 57 | if (_short_inputs) free(_short_inputs); 58 | 59 | _short_input_length = length; 60 | _short_inputs = (uint16_t *) malloc(_short_input_length * sizeof(uint16_t)); 61 | assert_param(_short_inputs); 62 | memset(_short_inputs, 0, _short_input_length * sizeof(uint16_t)); 63 | } 64 | 65 | void SlaveRtu::initCoils(uint16_t length) { 66 | if (_coils) free(_coils); 67 | 68 | _coil_length = length; 69 | uint8_t coils_byte_size = (_coil_length + 7) >> 3; 70 | _coils = (uint8_t *) malloc(coils_byte_size * sizeof(uint8_t)); 71 | assert_param(_coils); 72 | memset(_coils, 0, coils_byte_size); 73 | } 74 | 75 | void SlaveRtu::initHoldings(uint16_t length) { 76 | if (_holdings) free(_holdings); 77 | 78 | _holding_length = length; 79 | _holdings = (uint16_t *) malloc(_holding_length * sizeof(uint16_t)); 80 | assert_param(_holdings); 81 | memset(_holdings, 0, _holding_length * sizeof(uint16_t)); 82 | } 83 | 84 | void SlaveRtu::init() { 85 | _usart.init(); 86 | } 87 | 88 | void SlaveRtu::setAddress(uint8_t address) { 89 | _address = address; 90 | } 91 | 92 | void SlaveRtu::handler() { 93 | static uint16_t length_rx = 0; 94 | 95 | if (_usart.available()) { 96 | _buff_rx[length_rx++] = _usart.read(); 97 | } 98 | 99 | if (_usart.isReceiving() == false) { 100 | memset(_buff_tx, 0, _BUFF_LENGTH); 101 | 102 | do { 103 | if (length_rx < 4 || length_rx >= _BUFF_LENGTH) break; 104 | if (_buff_rx[0] && _buff_rx[0] != _address) break; 105 | if (this->checkFrameCrc(_buff_rx, length_rx) == false) break; 106 | 107 | _buff_tx[0] = _address; 108 | _buff_tx[1] = _buff_rx[1]; // function code 109 | 110 | uint8_t length_tx = 1; 111 | uint8_t exception = 0; 112 | 113 | switch (_buff_rx[1]) { 114 | case 0x01: 115 | exception = onReadCoils(&length_tx); 116 | break; 117 | case 0x02: 118 | exception = onReadBitInputs(&length_tx); 119 | break; 120 | case 0x03: 121 | exception = onReadHoldings(&length_tx); 122 | break; 123 | case 0x04: 124 | exception = onReadShortInputs(&length_tx); 125 | break; 126 | case 0x05: 127 | exception = onWriteSingleCoil(&length_tx); 128 | break; 129 | case 0x06: 130 | exception = onWriteSingleHolding(&length_tx); 131 | break; 132 | case 0x0f: 133 | exception = onWriteMultipleCoils(length_rx, &length_tx); 134 | break; 135 | case 0x10: 136 | exception = onWriteMultipleHoldings(length_rx, &length_tx); 137 | break; 138 | default: 139 | exception = 0x01; 140 | break; 141 | } 142 | 143 | if (exception) { 144 | _buff_tx[1] += 0x80; 145 | _buff_tx[2] = exception; 146 | length_tx = 3; 147 | } 148 | 149 | if (_buff_tx[0]) this->appendCrcAndReply(length_tx); 150 | } while (false); 151 | 152 | _usart.setReady(); 153 | length_rx = 0; 154 | } 155 | } 156 | 157 | bool SlaveRtu::checkFrameCrc(const uint8_t *p, uint8_t length) { 158 | uint16_t crc0 = crc.calc(p, length - 2); 159 | uint16_t crc1 = p[length - 2] | (p[length - 1] << 8); 160 | return crc0 == crc1; 161 | } 162 | 163 | void SlaveRtu::appendCrcAndReply(uint8_t length_tx) { 164 | uint16_t v = crc.calc(_buff_tx, length_tx); 165 | _buff_tx[length_tx] = lowByte(v); 166 | _buff_tx[length_tx + 1] = highByte(v); 167 | _usart.write(_buff_tx, length_tx + 2); 168 | _usart.flush(); 169 | } 170 | 171 | void SlaveRtu::setCoil(uint16_t index, BitAction state) { 172 | assert_param(index < _coil_length); 173 | bitWrite(_coils[index >> 3], index & 0x07, state == Bit_SET); 174 | } 175 | 176 | BitAction SlaveRtu::getCoil(uint16_t index) { 177 | assert_param(index < _coil_length); 178 | return bitRead(_coils[index >> 3],index & 0x07) ? Bit_SET : Bit_RESET; 179 | } 180 | 181 | uint8_t SlaveRtu::onReadCoils(uint8_t * p_length_tx) { 182 | 183 | uint16_t length = make16(_buff_rx[4], _buff_rx[5]); 184 | if (!length || length > 0x07d0) return 0x03; 185 | 186 | uint16_t address = make16(_buff_rx[2], _buff_rx[3]); 187 | if (address + length > _coil_length) return 0x02; 188 | 189 | for (uint16_t i = 0; i < length; i++) { 190 | bitWrite(_buff_tx[3 + (i >> 3)], i & 0x07, 191 | this->getCoil(address + i) == Bit_SET); 192 | } 193 | 194 | _buff_tx[2] = (length + 7) >> 3; 195 | 196 | *p_length_tx = 3 + _buff_tx[2]; 197 | return 0; 198 | } 199 | 200 | void SlaveRtu::setBitInput(uint16_t index, BitAction state) { 201 | assert_param(index < _bit_input_length); 202 | bitWrite(_bit_inputs[index >> 3], index & 0x07, state == Bit_SET); 203 | } 204 | 205 | BitAction SlaveRtu::getBitInput(uint16_t index) { 206 | assert_param(index < _bit_input_length); 207 | return bitRead(_bit_inputs[index >> 3], index & 0x07) ? Bit_SET : Bit_RESET; 208 | } 209 | 210 | uint8_t SlaveRtu::onReadBitInputs(uint8_t * p_length_tx) { 211 | uint16_t length = make16(_buff_rx[4], _buff_rx[5]); 212 | if (!length || length > 0x07d0) return 0x03; 213 | 214 | uint16_t address = make16(_buff_rx[2], _buff_rx[3]); 215 | if (address + length > _bit_input_length) return 0x02; 216 | 217 | if (updateBitInputs(address, length)) return 0x04; 218 | 219 | for (uint16_t i = 0; i < length; i++) 220 | bitWrite(_buff_tx[3 + (i >> 3)], i & 0x07, 221 | this->getBitInput(address + i) == Bit_SET); 222 | 223 | _buff_tx[2] = (length + 7) >> 3; 224 | 225 | *p_length_tx = 3 + _buff_tx[2]; 226 | return 0; 227 | } 228 | 229 | uint8_t SlaveRtu::onWriteSingleCoil(uint8_t * p_length_tx) { 230 | uint16_t val = make16(_buff_rx[4], _buff_rx[5]); 231 | if (val && val != 0xff00) return 0x03; 232 | 233 | uint16_t address = make16(_buff_rx[2], _buff_rx[3]); 234 | if (address >= _coil_length) return 0x02; 235 | 236 | this->setCoil(address, val ? Bit_SET : Bit_RESET); 237 | 238 | if (updateCoils(address, 1)) return 0x04; 239 | 240 | memcpy(_buff_tx + 2, _buff_rx + 2, 4); 241 | *p_length_tx = 6; 242 | return 0; 243 | } 244 | 245 | uint8_t SlaveRtu::onWriteMultipleCoils(uint8_t length_rx, 246 | uint8_t * p_length_tx) { 247 | uint16_t length = make16(_buff_rx[4], _buff_rx[5]); 248 | if (!length || length > 0x07b0) return 0x03; 249 | if (length_rx - 9 != _buff_rx[6]) return 0x03; 250 | 251 | uint16_t index = make16(_buff_rx[2], _buff_rx[3]); 252 | if (index + length > _coil_length) return 0x02; 253 | 254 | for (uint16_t i = 0; i < length; i++) 255 | this->setCoil(index + i, 256 | bitRead(_buff_rx[7 + (i >> 3)], i & 0x07) ? Bit_SET : Bit_RESET); 257 | 258 | if (updateCoils(index, length)) return 0x04; 259 | 260 | memcpy(_buff_tx + 2, _buff_rx + 2, 4); 261 | *p_length_tx = 6; 262 | return 0; 263 | } 264 | 265 | uint8_t SlaveRtu::onReadShortInputs(uint8_t * p_length_tx) { 266 | uint16_t length = make16(_buff_rx[4], _buff_rx[5]); 267 | if (!length || length > 0x07d) return 0x03; 268 | 269 | uint16_t index = make16(_buff_rx[2], _buff_rx[3]); 270 | if (index + length > _short_input_length) return 0x02; 271 | 272 | if (updateShortInputs(index, length)) return 0x04; 273 | 274 | for (uint8_t i = 0; i < length; i++) { 275 | _buff_tx[3 + i + i] = highByte(_short_inputs[index + i]); 276 | _buff_tx[4 + i + i] = lowByte(_short_inputs[index + i]); 277 | } 278 | 279 | _buff_tx[2] = length * 2; 280 | *p_length_tx = _buff_tx[2] + 3; 281 | return 0; 282 | } 283 | 284 | void SlaveRtu::setShortInput(uint16_t index, uint16_t val) { 285 | assert_param(index < _short_input_length); 286 | _short_inputs[index] = val; 287 | } 288 | 289 | uint16_t SlaveRtu::getShortInput(uint16_t index) { 290 | assert_param(index < _short_input_length); 291 | return _short_inputs[index]; 292 | } 293 | 294 | uint8_t SlaveRtu::onReadHoldings(uint8_t * p_length_tx) { 295 | uint16_t length = make16(_buff_rx[4], _buff_rx[5]); 296 | if (!length || length > 0x07d) return 0x03; 297 | 298 | uint16_t index = make16(_buff_rx[2], _buff_rx[3]); 299 | if (index + length > _holding_length) return 0x02; 300 | 301 | for (uint8_t i = 0; i < length; i++) { 302 | _buff_tx[3 + i + i] = highByte(_holdings[index + i]); 303 | _buff_tx[4 + i + i] = lowByte(_holdings[index + i]); 304 | } 305 | 306 | _buff_tx[2] = length * 2; 307 | *p_length_tx = _buff_tx[2] + 3; 308 | return 0; 309 | } 310 | 311 | void SlaveRtu::setHolding(uint16_t index, uint16_t val) { 312 | assert_param(index < _holding_length); 313 | _holdings[index] = val; 314 | } 315 | 316 | uint16_t SlaveRtu::getHolding(uint16_t index) { 317 | assert_param(index < _holding_length); 318 | return _holdings[index]; 319 | } 320 | 321 | uint8_t SlaveRtu::onWriteSingleHolding(uint8_t * p_length_tx) { 322 | uint16_t val = make16(_buff_rx[4], _buff_rx[5]); 323 | 324 | uint16_t index = make16(_buff_rx[2], _buff_rx[3]); 325 | if (index >= _holding_length) return 0x02; 326 | 327 | this->setHolding(index, val); 328 | 329 | if (updateHoldings(index, 1)) return 0x04; 330 | 331 | memcpy(_buff_tx + 2, _buff_rx + 2, 4); 332 | *p_length_tx = 6; 333 | return 0; 334 | } 335 | 336 | uint8_t SlaveRtu::onWriteMultipleHoldings(uint8_t length_rx, 337 | uint8_t * p_length_tx) { 338 | uint16_t length = make16(_buff_rx[4], _buff_rx[5]); 339 | if (!length || length > 0x7b) return 0x03; 340 | if (length_rx - 9 != _buff_rx[6]) return 0x03; 341 | if (length != _buff_rx[6] >> 1) return 0x03; 342 | 343 | uint16_t index = make16(_buff_rx[2], _buff_rx[3]); 344 | if (index + length > _holding_length) return 0x02; 345 | 346 | for (uint8_t i = 0; i < length; i++) { 347 | _holdings[index + i] = 348 | make16(_buff_rx[7 + i + i], _buff_rx[8 + i + i]); 349 | } 350 | 351 | if (updateHoldings(index, length)) return 0x04; 352 | 353 | memcpy(_buff_tx + 2, _buff_rx + 2, 4); 354 | *p_length_tx = 6; 355 | return 0; 356 | } 357 | 358 | -------------------------------------------------------------------------------- /modbus/slave-rtu.h: -------------------------------------------------------------------------------- 1 | /* 2 | * slave-rtu.h 3 | * 4 | * Created on: Jul 17, 2013 5 | * Author: agu 6 | */ 7 | 8 | #ifndef SLAVE_RTU_H_ 9 | #define SLAVE_RTU_H_ 10 | 11 | #include 12 | #include 13 | 14 | #include "stm32f10x.h" 15 | 16 | #include "usart-rs485-modbus.h" 17 | #include "nvic/nvic.h" 18 | #include "gpio/gpio.h" 19 | #include "common/bit_op.h" 20 | 21 | #include "crc.h" 22 | 23 | /** 24 | * SlaveRtu class 25 | * get me 26 | */ 27 | 28 | class SlaveRtu { 29 | public: 30 | SlaveRtu(UsartRs485Modbus & usart, uint8_t address); 31 | virtual ~SlaveRtu(); 32 | 33 | void init(); 34 | void setAddress(uint8_t address); 35 | void handler(); 36 | void handleTimIrq(); 37 | 38 | void initBitInputs(uint16_t length); 39 | void initShortInputs(uint16_t length); 40 | 41 | void initCoils(uint16_t length); 42 | void initHoldings(uint16_t length); 43 | 44 | void setBitInput(uint16_t index, BitAction state); 45 | BitAction getBitInput(uint16_t index); 46 | 47 | void setShortInput(uint16_t index, uint16_t val); 48 | uint16_t getShortInput(uint16_t index); 49 | 50 | void setCoil(uint16_t index, BitAction state); 51 | BitAction getCoil(uint16_t index); 52 | 53 | void setHolding(uint16_t index, uint16_t val); 54 | uint16_t getHolding(uint16_t index); 55 | 56 | protected: 57 | 58 | int16_t _coil_length; 59 | uint16_t _bit_input_length; 60 | uint16_t _short_input_length; 61 | uint16_t _holding_length; 62 | 63 | virtual uint8_t updateBitInputs(uint16_t index, uint16_t length) {return 0;}; 64 | virtual uint8_t updateShortInputs(uint16_t index, uint16_t length) {return 0;}; 65 | virtual uint8_t updateCoils(uint16_t index, uint16_t length) {return 0;}; 66 | virtual uint8_t updateHoldings(uint16_t index, uint16_t length) {return 0;}; 67 | 68 | private: 69 | UsartRs485Modbus & _usart; 70 | 71 | static const uint16_t _BUFF_LENGTH = 256; 72 | uint8_t _buff_rx[_BUFF_LENGTH]; 73 | uint8_t _buff_tx[_BUFF_LENGTH]; 74 | 75 | uint8_t _address; 76 | 77 | uint8_t * _bit_inputs; 78 | uint16_t * _short_inputs; 79 | uint8_t * _coils; 80 | uint16_t * _holdings; 81 | 82 | bool checkFrameCrc(const uint8_t *p, uint8_t length); 83 | void appendCrcAndReply(uint8_t length_tx); 84 | 85 | uint8_t onReadBitInputs(uint8_t * p_length_tx); 86 | uint8_t onReadShortInputs(uint8_t * p_length_tx); 87 | 88 | uint8_t onReadCoils(uint8_t * p_length_tx); 89 | uint8_t onWriteSingleCoil(uint8_t * p_length_tx); 90 | uint8_t onWriteMultipleCoils(uint8_t length_rx, uint8_t * p_length_tx); 91 | 92 | uint8_t onReadHoldings(uint8_t * p_length_tx); 93 | uint8_t onWriteSingleHolding(uint8_t * p_length_tx); 94 | uint8_t onWriteMultipleHoldings(uint8_t length_rx, uint8_t * p_length_tx); 95 | }; 96 | 97 | #endif /* SLAVE_RTU_H_ */ 98 | -------------------------------------------------------------------------------- /modbus/usart-rs485-modbus.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * usart.cpp 3 | * 4 | * Created on: May 28, 2013 5 | * Author: agu 6 | */ 7 | 8 | #include "usart-rs485-modbus.h" 9 | 10 | UsartRs485Modbus::UsartRs485Modbus(USART_TypeDef * usart, uint32_t rcc_apbx_periph, 11 | void (*rcc_apbx_periph_clock_cmd)(uint32_t, FunctionalState), Gpio & de, 12 | Gpio & re, Tim & tim, uint8_t buff_size, uint16_t time_out) : 13 | UsartRs485(usart, rcc_apbx_periph, rcc_apbx_periph_clock_cmd, de, re, buff_size, 14 | time_out), _tim(tim) { 15 | _is_receiving = true; 16 | } 17 | 18 | UsartRs485Modbus::~UsartRs485Modbus() { 19 | 20 | } 21 | 22 | void UsartRs485Modbus::init(uint32_t baudrate, uint16_t word_length, 23 | uint16_t stop_bits, uint16_t parity, uint16_t mode, 24 | uint16_t hardware_flow_control) { 25 | 26 | this->UsartRs485::init(baudrate, word_length, stop_bits, parity, mode, 27 | hardware_flow_control); 28 | 29 | // t = 11 * 3.5 / baudrate / (1 / 20000) 30 | _tim.init(20000, (770000UL / baudrate)); 31 | _tim.configureIT(TIM_IT_Update); 32 | _tim.configureArrPreload(); 33 | 34 | _tim.setCounter(0x0000); 35 | //_tim.setState(ENABLE); 36 | } 37 | 38 | void UsartRs485Modbus::onRXNE() { 39 | this->UsartRs485::onRXNE(); 40 | _tim.setCounter(0x0000); 41 | _tim.setState(ENABLE); 42 | } 43 | 44 | void UsartRs485Modbus::onTimIrq() { 45 | if (_tim.getITStatus(TIM_IT_Update) == SET) { 46 | _tim.clearITPendingBit(TIM_IT_Update); 47 | _tim.setState(DISABLE); 48 | _is_receiving = false; 49 | } 50 | } 51 | 52 | bool UsartRs485Modbus::isReceiving() { 53 | return _is_receiving; 54 | } 55 | 56 | void UsartRs485Modbus::setReady() { 57 | _is_receiving = true; 58 | } 59 | -------------------------------------------------------------------------------- /modbus/usart-rs485-modbus.h: -------------------------------------------------------------------------------- 1 | /* 2 | * usart.h 3 | * 4 | * Created on: May 28, 2013 5 | * Author: agu 6 | */ 7 | 8 | #ifndef USART_RS485_MODBUS_H_ 9 | #define USART_RS485_MODBUS_H_ 10 | 11 | #include "usart-rs485/usart-rs485.h" 12 | #include "gpio/gpio.h" 13 | #include "tim/tim.h" 14 | 15 | #include 16 | 17 | class UsartRs485Modbus: public UsartRs485 { 18 | public: 19 | UsartRs485Modbus(USART_TypeDef * usart, 20 | uint32_t rcc_apbx_periph, 21 | void (*rcc_apbx_periph_clock_cmd)(uint32_t, FunctionalState), 22 | Gpio & de, Gpio & re, Tim & tim, 23 | uint8_t buff_size = 128, 24 | uint16_t time_out = 4); 25 | ~UsartRs485Modbus(); 26 | 27 | void init(uint32_t baudrate = 19200, 28 | uint16_t word_length = USART_WordLength_9b, 29 | uint16_t stop_bits = USART_StopBits_1, 30 | uint16_t parity = USART_Parity_Even, 31 | uint16_t mode = USART_Mode_Rx | USART_Mode_Tx, 32 | uint16_t hardware_flow_control = USART_HardwareFlowControl_None); 33 | 34 | void onTimIrq(); 35 | bool isReceiving(); 36 | void setReady(); 37 | 38 | protected: 39 | void onRXNE(); 40 | 41 | private: 42 | Tim & _tim; 43 | volatile bool _is_receiving; 44 | }; 45 | 46 | #endif /* USART_RS485_MODBUS_H_ */ 47 | 48 | -------------------------------------------------------------------------------- /readme.txt: -------------------------------------------------------------------------------- 1 | /** 2 | @page GPIO_IOToggle GPIO IO Toggle example 3 | 4 | @verbatim 5 | ******************** (C) COPYRIGHT 2011 STMicroelectronics ******************* 6 | * @file GPIO/IOToggle/readme.txt 7 | * @author MCD Application Team 8 | * @version V3.5.0 9 | * @date 08-April-2011 10 | * @brief Description of the GPIO IO Toggle example. 11 | ****************************************************************************** 12 | * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS 13 | * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE 14 | * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY 15 | * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING 16 | * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE 17 | * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. 18 | ****************************************************************************** 19 | @endverbatim 20 | 21 | @par Example Description 22 | 23 | GPIO ports are connected on APB2 bus, using BSRRH and BSRRL registers 2 cycles 24 | are required to set a pin and another cycle to reset it. So GPIO pins can toggle 25 | at AHB clock divided by 4. 26 | 27 | This example describes how to use BSRR and BRR (Port Bit Set/Reset Register 28 | and Port Bit Reset Register) for maximum IO toggling. 29 | 30 | PD0 and PD2 (configured in output pushpull mode) toggles in a forever loop: 31 | - Set PD0 and PD2 by setting corresponding bits in BSRR register 32 | - Reset PD0 and PD2 by setting corresponding bits in BRR register 33 | 34 | In this example, HCLK is configured at 72 MHz so PD0 and PD2 toggles at 18MHz. 35 | To achieve the maximum IO toggling frequency, you have to configure your compiler 36 | options for high speed optimization. 37 | 38 | @par Directory contents 39 | 40 | - GPIO/IOToggle/stm32f10x_conf.h Library Configuration file 41 | - GPIO/IOToggle/stm32f10x_it.c Interrupt handlers 42 | - GPIO/IOToggle/stm32f10x_it.h Header for stm32f10x_it.c 43 | - GPIO/IOToggle/main.c Main program 44 | - GPIO/IOToggle/system_stm32f10x.c STM32F10x system source file 45 | 46 | @par Hardware and Software environment 47 | 48 | - This example runs on STM32F10x Connectivity line, High-Density, High-Density 49 | Value line, Medium-Density, XL-Density, Medium-Density Value line, Low-Density 50 | and Low-Density Value line Devices. 51 | 52 | - This example has been tested with STMicroelectronics STM32100E-EVAL (High-Density 53 | Value line), STM32100B-EVAL (Medium-Density Value line), STM3210C-EVAL 54 | (Connectivity line), STM3210E-EVAL (High-Density and XL-Density) and 55 | STM3210B-EVAL (Medium-Density) evaluation boards and can be easily tailored 56 | to any other supported device and development board. 57 | To select the STMicroelectronics evaluation board used to run the example, 58 | uncomment the corresponding line in stm32_eval.h file (under Utilities\STM32_EVAL) 59 | 60 | @par How to use it ? 61 | 62 | In order to make the program work, you must do the following : 63 | - Copy all source files from this example folder to the template folder under 64 | Project\STM32F10x_StdPeriph_Template 65 | - Open your preferred toolchain 66 | - Rebuild all files and load your image into target memory 67 | - Run the example 68 | 69 | @note 70 | - Low-density Value line devices are STM32F100xx microcontrollers where the 71 | Flash memory density ranges between 16 and 32 Kbytes. 72 | - Low-density devices are STM32F101xx, STM32F102xx and STM32F103xx 73 | microcontrollers where the Flash memory density ranges between 16 and 32 Kbytes. 74 | - Medium-density Value line devices are STM32F100xx microcontrollers where 75 | the Flash memory density ranges between 64 and 128 Kbytes. 76 | - Medium-density devices are STM32F101xx, STM32F102xx and STM32F103xx 77 | microcontrollers where the Flash memory density ranges between 64 and 128 Kbytes. 78 | - High-density Value line devices are STM32F100xx microcontrollers where 79 | the Flash memory density ranges between 256 and 512 Kbytes. 80 | - High-density devices are STM32F101xx and STM32F103xx microcontrollers where 81 | the Flash memory density ranges between 256 and 512 Kbytes. 82 | - XL-density devices are STM32F101xx and STM32F103xx microcontrollers where 83 | the Flash memory density ranges between 512 and 1024 Kbytes. 84 | - Connectivity line devices are STM32F105xx and STM32F107xx microcontrollers. 85 | 86 | *

© COPYRIGHT 2011 STMicroelectronics

87 | */ 88 | -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "stm32-template.h" 2 | #include "gpio-array/gpio-array.h" 3 | #include "node.h" 4 | 5 | int main(void) __attribute__((weak)); 6 | 7 | Gpio usart_de(GPIOB, GPIO_Pin_15, RCC_APB2Periph_GPIOB); 8 | Gpio usart_re(GPIOB, GPIO_Pin_15, RCC_APB2Periph_GPIOB); 9 | 10 | Tim t1(TIM1, RCC_APB2Periph_TIM1, RCC_APB2PeriphClockCmd); 11 | UsartRs485Modbus usart(USART1, RCC_APB2Periph_USART1, RCC_APB2PeriphClockCmd, 12 | usart_de, usart_re, t1); 13 | 14 | Gpio led_green(GPIOC, GPIO_Pin_9, RCC_APB2Periph_GPIOC); 15 | Gpio led_blue(GPIOC, GPIO_Pin_8, RCC_APB2Periph_GPIOC); 16 | 17 | Node slave(usart, 0x02); 18 | 19 | Gpio dip_0(GPIOB, GPIO_Pin_14, RCC_APB2Periph_GPIOB); 20 | Gpio dip_1(GPIOB, GPIO_Pin_13, RCC_APB2Periph_GPIOB); 21 | Gpio dip_2(GPIOB, GPIO_Pin_12, RCC_APB2Periph_GPIOB); 22 | Gpio dip_3(GPIOB, GPIO_Pin_11, RCC_APB2Periph_GPIOB); 23 | Gpio dip_4(GPIOB, GPIO_Pin_10, RCC_APB2Periph_GPIOB); 24 | Gpio dip_5(GPIOB, GPIO_Pin_0, RCC_APB2Periph_GPIOB); 25 | Gpio dip_6(GPIOB, GPIO_Pin_1, RCC_APB2Periph_GPIOB); 26 | GpioArray dips(7); 27 | 28 | void setup() { 29 | dips.setGpio(0, dip_0); 30 | dips.setGpio(1, dip_1); 31 | dips.setGpio(2, dip_2); 32 | dips.setGpio(3, dip_3); 33 | dips.setGpio(4, dip_4); 34 | dips.setGpio(5, dip_5); 35 | dips.setGpio(6, dip_6); 36 | 37 | dips.init(GPIO_Mode_IPU); 38 | slave.setAddress(dips.getInput()); 39 | } 40 | 41 | int main(void) { 42 | init(); 43 | setup(); 44 | slave.init(); 45 | 46 | for (;;) 47 | slave.handler(); 48 | } 49 | 50 | void init() { 51 | SysTick_Config(SystemCoreClock / 1000); // Tick per ms 52 | 53 | Gpio usart_tx(GPIOA, GPIO_Pin_9, 54 | RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO); 55 | usart_tx.init(GPIO_Mode_AF_OD); 56 | 57 | Gpio usart_rx(GPIOA, GPIO_Pin_10, 58 | RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO); 59 | usart_rx.init(GPIO_Mode_IN_FLOATING); 60 | 61 | setvbuf(stdin, NULL, _IONBF, 0); 62 | setvbuf(stdout, NULL, _IONBF, 0); 63 | setvbuf(stderr, NULL, _IONBF, 0); 64 | 65 | nvic.configureGroup(NVIC_PriorityGroup_1); 66 | nvic.configure(TIM1_UP_TIM16_IRQn, 0, 3, ENABLE); 67 | nvic.configure(USART1_IRQn, 1, 2, ENABLE); 68 | 69 | led_green.init(GPIO_Mode_Out_PP); 70 | 71 | nvic.configure(TIM2_IRQn, 1, 3, ENABLE); 72 | Tim t2(TIM2, RCC_APB1Periph_TIM2, RCC_APB1PeriphClockCmd); 73 | t2.init(1000, 1000); 74 | t2.configureIT(TIM_IT_Update); 75 | t2.setState(); 76 | } 77 | 78 | void delay(u32 ms) { 79 | extern vu32 millis; 80 | uint32_t start = millis; 81 | 82 | while (ms) { 83 | if (millis - start) { 84 | ms--; 85 | start++; 86 | } 87 | } 88 | } 89 | 90 | // delayMicroseconds ref to libmaple 91 | void delayMicroseconds(vu32 us) { 92 | us *= SystemCoreClock / 3000000; 93 | 94 | asm volatile( 95 | " mov r0, %[us] \n\t" 96 | "1: subs r0, #1 \n\t" 97 | " bhi 1b \n\t" 98 | : 99 | : [us] "r" (us) 100 | : "r0" 101 | ); 102 | } 103 | 104 | #ifdef USE_FULL_ASSERT 105 | 106 | void assert_failed(uint8_t* file, uint32_t line) { 107 | fprintf(stderr, "assert failed on %s, line # %ld\r\n", file, line); 108 | while (1) 109 | ; 110 | } 111 | 112 | #endif 113 | -------------------------------------------------------------------------------- /src/node.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * node.cpp 3 | * 4 | * Created on: Jul 23, 2013 5 | * Author: agu 6 | */ 7 | 8 | #include "node.h" 9 | 10 | const uint8_t Node::_uuid[] = "665247461d1c11e395bc73bf3a254a5f"; 11 | 12 | const uint8_t Node::_lengths[] = { 2, 1, 2, 16 }; 13 | 14 | Node::Node(UsartRs485Modbus & usart, uint8_t address) : 15 | SlaveRtu(usart, address) { 16 | 17 | this->initBitInputs(_lengths[0]); 18 | this->initCoils(_lengths[1]); 19 | 20 | this->initShortInputs(16 + 4 + _lengths[2]); 21 | this->initHoldings(_lengths[3]); 22 | 23 | _bit_input_pins = (Gpio **) malloc(_bit_input_length * sizeof(Gpio *)); 24 | 25 | _bit_input_pins[0] = new Gpio(GPIOA, GPIO_Pin_0, RCC_APB2Periph_GPIOA); 26 | _bit_input_pins[1] = new Gpio(GPIOA, GPIO_Pin_1, RCC_APB2Periph_GPIOA); 27 | 28 | _coil_pins = (Gpio **) malloc(_coil_length * sizeof(Gpio *)); 29 | _coil_pins[0] = new Gpio(GPIOC, GPIO_Pin_8, RCC_APB2Periph_GPIOC); 30 | 31 | _short_input_pins = (Gpio **) malloc(2 * sizeof(Gpio *)); 32 | _short_input_pins[0] = new Gpio(GPIOA, GPIO_Pin_5, RCC_APB2Periph_GPIOA); 33 | _short_input_pins[1] = new Gpio(GPIOA, GPIO_Pin_6, RCC_APB2Periph_GPIOA); 34 | 35 | _adc = new Adc(ADC1, RCC_APB2Periph_ADC1); 36 | _adc_channels = new uint8_t[2]; 37 | _adc_channels[0] = ADC_Channel_5; 38 | _adc_channels[1] = ADC_Channel_6; 39 | 40 | for (uint8_t i = 0; i < 16; i++) { 41 | this->setShortInput(i, make16(_uuid[i + i], _uuid[i + i + 1])); 42 | } 43 | 44 | for (uint8_t i = 0; i < 4; i++) 45 | this->setShortInput(i + 16, _lengths[i]); 46 | } 47 | 48 | Node::~Node() { 49 | for (uint8_t i = 0; i < _bit_input_length; i++) 50 | delete _bit_input_pins[i]; 51 | delete[] _bit_input_pins; 52 | 53 | for (uint8_t i = 0; i < _coil_length; i++) 54 | delete _coil_pins[i]; 55 | delete[] _coil_pins; 56 | 57 | for (uint8_t i = 0; i < 2; i++) 58 | delete _short_input_pins[i]; 59 | delete[] _short_input_pins; 60 | 61 | delete _adc; 62 | delete _adc_channels; 63 | } 64 | 65 | void Node::init() { 66 | this->SlaveRtu::init(); 67 | 68 | for (uint8_t i = 0; i < _bit_input_length; i++) 69 | _bit_input_pins[i]->init(GPIO_Mode_IPD); 70 | 71 | for (uint8_t i = 0; i < _coil_length; i++) 72 | _coil_pins[i]->init(GPIO_Mode_Out_PP); 73 | 74 | for (uint8_t i = 0; i < 2; i++) 75 | _short_input_pins[i]->init(GPIO_Mode_AIN); 76 | 77 | _adc->init(ADC_Mode_Independent, DISABLE, DISABLE, 78 | ADC_ExternalTrigConv_None); 79 | _adc->calibrate(); 80 | 81 | _adc->configChannel(ADC_Channel_5, 1); 82 | } 83 | 84 | uint8_t Node::updateBitInputs(uint16_t index, uint16_t length) { 85 | for (uint16_t i = 0; i < length; i++) 86 | this->setBitInput(index + i, _bit_input_pins[index + i]->getInput()); 87 | return 0; 88 | } 89 | 90 | uint8_t Node::updateCoils(uint16_t index, uint16_t length) { 91 | for (uint16_t i = 0; i < length; i++) 92 | _coil_pins[index + i]->set(this->getCoil(index + i)); 93 | return 0; 94 | } 95 | 96 | uint8_t Node::updateShortInputs(uint16_t index, uint16_t length) { 97 | for (uint16_t i = 0; i < length; i++) { 98 | if (index + i >= 20) { 99 | _adc->configChannel(_adc_channels[index - 20 + i], 1); 100 | _adc->startSoftwareConvert(); 101 | this->setShortInput(index + i, _adc->getValue()); 102 | } 103 | } 104 | return 0; 105 | } 106 | 107 | -------------------------------------------------------------------------------- /src/stm32f10x_it.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file stm32f10x_it.cpp 4 | * @author MCD Application Team 5 | * @version V3.5.0 6 | * @date 08-April-2011 7 | * @brief Main Interrupt Service Routines. 8 | * This file provides template for all exceptions handler and peripherals 9 | * interrupt service routine. 10 | ****************************************************************************** 11 | * @attention 12 | * 13 | * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS 14 | * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE 15 | * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY 16 | * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING 17 | * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE 18 | * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. 19 | * 20 | *

© COPYRIGHT 2011 STMicroelectronics

21 | ****************************************************************************** 22 | */ 23 | 24 | /* Includes ------------------------------------------------------------------*/ 25 | #include "stm32f10x_it.h" 26 | #include "gpio/gpio.h" 27 | #include "modbus/slave-rtu.h" 28 | 29 | /** @addtogroup STM32F10x_StdPeriph_Examples 30 | * @{ 31 | */ 32 | 33 | /** @addtogroup GPIO_IOToggle 34 | * @{ 35 | */ 36 | 37 | /* Private typedef -----------------------------------------------------------*/ 38 | /* Private define ------------------------------------------------------------*/ 39 | /* Private macro -------------------------------------------------------------*/ 40 | /* Private variables ---------------------------------------------------------*/ 41 | /* Private function prototypes -----------------------------------------------*/ 42 | /* Private functions ---------------------------------------------------------*/ 43 | 44 | /******************************************************************************/ 45 | /* Cortex-M3 Processor Exceptions Handlers */ 46 | /******************************************************************************/ 47 | 48 | /** 49 | * @brief This function handles NMI exception. 50 | * @retval None 51 | */ 52 | void NMI_Handler(void) { 53 | } 54 | 55 | /** 56 | * @brief This function handles Hard Fault exception. 57 | * @retval None 58 | */ 59 | void HardFault_Handler(void) { 60 | /* Go to infinite loop when Hard Fault exception occurs */ 61 | while (1) { 62 | } 63 | } 64 | 65 | /** 66 | * @brief This function handles Memory Manage exception. 67 | * @retval None 68 | */ 69 | void MemManage_Handler(void) { 70 | /* Go to infinite loop when Memory Manage exception occurs */ 71 | while (1) { 72 | } 73 | } 74 | 75 | /** 76 | * @brief This function handles Bus Fault exception. 77 | * @retval None 78 | */ 79 | void BusFault_Handler(void) { 80 | /* Go to infinite loop when Bus Fault exception occurs */ 81 | while (1) { 82 | } 83 | } 84 | 85 | /** 86 | * @brief This function handles Usage Fault exception. 87 | * @retval None 88 | */ 89 | void UsageFault_Handler(void) { 90 | /* Go to infinite loop when Usage Fault exception occurs */ 91 | while (1) { 92 | } 93 | } 94 | 95 | /** 96 | * @brief This function handles SVCall exception. 97 | * @retval None 98 | */ 99 | void SVC_Handler(void) { 100 | } 101 | 102 | /** 103 | * @brief This function handles Debug Monitor exception. 104 | * @retval None 105 | */ 106 | void DebugMon_Handler(void) { 107 | } 108 | 109 | /** 110 | * @brief This function handles PendSV_Handler exception. 111 | * @retval None 112 | */ 113 | void PendSV_Handler(void) { 114 | } 115 | 116 | /** 117 | * @brief This function handles SysTick Handler. 118 | * @param None 119 | * @retval None 120 | */ 121 | 122 | //vu32 TimingDelay = 0; 123 | vu32 millis = 0; 124 | 125 | void SysTick_Handler(void) { 126 | millis++; 127 | } 128 | 129 | /******************************************************************************/ 130 | /* STM32F10x Peripherals Interrupt Handlers */ 131 | /* Add here the Interrupt Handler for the used peripheral(s) (PPP), for the */ 132 | /* available peripheral interrupt handler's name please refer to the startup */ 133 | /* file (startup_stm32f10x_xx.s). */ 134 | /******************************************************************************/ 135 | 136 | /** 137 | * @brief This function handles PPP interrupt request. 138 | * @retval None 139 | */ 140 | /*void PPP_IRQHandler(void) 141 | { 142 | }*/ 143 | 144 | void TIM2_IRQHandler(void) { 145 | extern Gpio led_green; 146 | 147 | if (TIM_GetITStatus(TIM2, TIM_IT_Update)) { 148 | TIM_ClearITPendingBit(TIM2, TIM_IT_Update); 149 | led_green.toggle(); 150 | } 151 | } 152 | 153 | void USART1_IRQHandler(void) { 154 | extern UsartRs485Modbus usart; 155 | usart.ithandler(); 156 | } 157 | 158 | void TIM1_UP_TIM16_IRQHandler(void) { 159 | extern UsartRs485Modbus usart; 160 | usart.onTimIrq(); 161 | } 162 | /** 163 | * @} 164 | */ 165 | 166 | /** 167 | * @} 168 | */ 169 | 170 | /******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ 171 | -------------------------------------------------------------------------------- /stm32_flash.ld: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aguegu/stm32-modbus/9ea4504e134e74652d6a87873a13852d730b6ca2/stm32_flash.ld -------------------------------------------------------------------------------- /sys/core_cm3.c: -------------------------------------------------------------------------------- 1 | /**************************************************************************//** 2 | * @file core_cm3.c 3 | * @brief CMSIS Cortex-M3 Core Peripheral Access Layer Source File 4 | * @version V1.30 5 | * @date 30. October 2009 6 | * 7 | * @note 8 | * Copyright (C) 2009 ARM Limited. All rights reserved. 9 | * 10 | * @par 11 | * ARM Limited (ARM) is supplying this software for use with Cortex-M 12 | * processor based microcontrollers. This file can be freely distributed 13 | * within development tools that are supporting such ARM based processors. 14 | * 15 | * @par 16 | * THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED 17 | * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF 18 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. 19 | * ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR 20 | * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER. 21 | * 22 | ******************************************************************************/ 23 | 24 | #include 25 | 26 | /* define compiler specific symbols */ 27 | #if defined ( __CC_ARM ) 28 | #define __ASM __asm /*!< asm keyword for ARM Compiler */ 29 | #define __INLINE __inline /*!< inline keyword for ARM Compiler */ 30 | 31 | #elif defined ( __ICCARM__ ) 32 | #define __ASM __asm /*!< asm keyword for IAR Compiler */ 33 | #define __INLINE inline /*!< inline keyword for IAR Compiler. Only avaiable in High optimization mode! */ 34 | 35 | #elif defined ( __GNUC__ ) 36 | #define __ASM __asm /*!< asm keyword for GNU Compiler */ 37 | #define __INLINE inline /*!< inline keyword for GNU Compiler */ 38 | 39 | #elif defined ( __TASKING__ ) 40 | #define __ASM __asm /*!< asm keyword for TASKING Compiler */ 41 | #define __INLINE inline /*!< inline keyword for TASKING Compiler */ 42 | 43 | #endif 44 | 45 | /* ################### Compiler specific Intrinsics ########################### */ 46 | 47 | #if defined ( __CC_ARM ) /*------------------RealView Compiler -----------------*/ 48 | /* ARM armcc specific functions */ 49 | 50 | /** 51 | * @brief Return the Process Stack Pointer 52 | * 53 | * @return ProcessStackPointer 54 | * 55 | * Return the actual process stack pointer 56 | */ 57 | __ASM uint32_t __get_PSP(void) 58 | { 59 | mrs r0, psp 60 | bx lr 61 | } 62 | 63 | /** 64 | * @brief Set the Process Stack Pointer 65 | * 66 | * @param topOfProcStack Process Stack Pointer 67 | * 68 | * Assign the value ProcessStackPointer to the MSP 69 | * (process stack pointer) Cortex processor register 70 | */ 71 | __ASM void __set_PSP(uint32_t topOfProcStack) 72 | { 73 | msr psp, r0 74 | bx lr 75 | } 76 | 77 | /** 78 | * @brief Return the Main Stack Pointer 79 | * 80 | * @return Main Stack Pointer 81 | * 82 | * Return the current value of the MSP (main stack pointer) 83 | * Cortex processor register 84 | */ 85 | __ASM uint32_t __get_MSP(void) 86 | { 87 | mrs r0, msp 88 | bx lr 89 | } 90 | 91 | /** 92 | * @brief Set the Main Stack Pointer 93 | * 94 | * @param topOfMainStack Main Stack Pointer 95 | * 96 | * Assign the value mainStackPointer to the MSP 97 | * (main stack pointer) Cortex processor register 98 | */ 99 | __ASM void __set_MSP(uint32_t mainStackPointer) 100 | { 101 | msr msp, r0 102 | bx lr 103 | } 104 | 105 | /** 106 | * @brief Reverse byte order in unsigned short value 107 | * 108 | * @param value value to reverse 109 | * @return reversed value 110 | * 111 | * Reverse byte order in unsigned short value 112 | */ 113 | __ASM uint32_t __REV16(uint16_t value) 114 | { 115 | rev16 r0, r0 116 | bx lr 117 | } 118 | 119 | /** 120 | * @brief Reverse byte order in signed short value with sign extension to integer 121 | * 122 | * @param value value to reverse 123 | * @return reversed value 124 | * 125 | * Reverse byte order in signed short value with sign extension to integer 126 | */ 127 | __ASM int32_t __REVSH(int16_t value) 128 | { 129 | revsh r0, r0 130 | bx lr 131 | } 132 | 133 | #if (__ARMCC_VERSION < 400000) 134 | 135 | /** 136 | * @brief Remove the exclusive lock created by ldrex 137 | * 138 | * Removes the exclusive lock which is created by ldrex. 139 | */ 140 | __ASM void __CLREX(void) 141 | { 142 | clrex 143 | } 144 | 145 | /** 146 | * @brief Return the Base Priority value 147 | * 148 | * @return BasePriority 149 | * 150 | * Return the content of the base priority register 151 | */ 152 | __ASM uint32_t __get_BASEPRI(void) 153 | { 154 | mrs r0, basepri 155 | bx lr 156 | } 157 | 158 | /** 159 | * @brief Set the Base Priority value 160 | * 161 | * @param basePri BasePriority 162 | * 163 | * Set the base priority register 164 | */ 165 | __ASM void __set_BASEPRI(uint32_t basePri) 166 | { 167 | msr basepri, r0 168 | bx lr 169 | } 170 | 171 | /** 172 | * @brief Return the Priority Mask value 173 | * 174 | * @return PriMask 175 | * 176 | * Return state of the priority mask bit from the priority mask register 177 | */ 178 | __ASM uint32_t __get_PRIMASK(void) 179 | { 180 | mrs r0, primask 181 | bx lr 182 | } 183 | 184 | /** 185 | * @brief Set the Priority Mask value 186 | * 187 | * @param priMask PriMask 188 | * 189 | * Set the priority mask bit in the priority mask register 190 | */ 191 | __ASM void __set_PRIMASK(uint32_t priMask) 192 | { 193 | msr primask, r0 194 | bx lr 195 | } 196 | 197 | /** 198 | * @brief Return the Fault Mask value 199 | * 200 | * @return FaultMask 201 | * 202 | * Return the content of the fault mask register 203 | */ 204 | __ASM uint32_t __get_FAULTMASK(void) 205 | { 206 | mrs r0, faultmask 207 | bx lr 208 | } 209 | 210 | /** 211 | * @brief Set the Fault Mask value 212 | * 213 | * @param faultMask faultMask value 214 | * 215 | * Set the fault mask register 216 | */ 217 | __ASM void __set_FAULTMASK(uint32_t faultMask) 218 | { 219 | msr faultmask, r0 220 | bx lr 221 | } 222 | 223 | /** 224 | * @brief Return the Control Register value 225 | * 226 | * @return Control value 227 | * 228 | * Return the content of the control register 229 | */ 230 | __ASM uint32_t __get_CONTROL(void) 231 | { 232 | mrs r0, control 233 | bx lr 234 | } 235 | 236 | /** 237 | * @brief Set the Control Register value 238 | * 239 | * @param control Control value 240 | * 241 | * Set the control register 242 | */ 243 | __ASM void __set_CONTROL(uint32_t control) 244 | { 245 | msr control, r0 246 | bx lr 247 | } 248 | 249 | #endif /* __ARMCC_VERSION */ 250 | 251 | #elif (defined (__ICCARM__)) /*------------------ ICC Compiler -------------------*/ 252 | /* IAR iccarm specific functions */ 253 | #pragma diag_suppress=Pe940 254 | 255 | /** 256 | * @brief Return the Process Stack Pointer 257 | * 258 | * @return ProcessStackPointer 259 | * 260 | * Return the actual process stack pointer 261 | */ 262 | uint32_t __get_PSP(void) 263 | { 264 | __ASM("mrs r0, psp"); 265 | __ASM("bx lr"); 266 | } 267 | 268 | /** 269 | * @brief Set the Process Stack Pointer 270 | * 271 | * @param topOfProcStack Process Stack Pointer 272 | * 273 | * Assign the value ProcessStackPointer to the MSP 274 | * (process stack pointer) Cortex processor register 275 | */ 276 | void __set_PSP(uint32_t topOfProcStack) 277 | { 278 | __ASM("msr psp, r0"); 279 | __ASM("bx lr"); 280 | } 281 | 282 | /** 283 | * @brief Return the Main Stack Pointer 284 | * 285 | * @return Main Stack Pointer 286 | * 287 | * Return the current value of the MSP (main stack pointer) 288 | * Cortex processor register 289 | */ 290 | uint32_t __get_MSP(void) 291 | { 292 | __ASM("mrs r0, msp"); 293 | __ASM("bx lr"); 294 | } 295 | 296 | /** 297 | * @brief Set the Main Stack Pointer 298 | * 299 | * @param topOfMainStack Main Stack Pointer 300 | * 301 | * Assign the value mainStackPointer to the MSP 302 | * (main stack pointer) Cortex processor register 303 | */ 304 | void __set_MSP(uint32_t topOfMainStack) 305 | { 306 | __ASM("msr msp, r0"); 307 | __ASM("bx lr"); 308 | } 309 | 310 | /** 311 | * @brief Reverse byte order in unsigned short value 312 | * 313 | * @param value value to reverse 314 | * @return reversed value 315 | * 316 | * Reverse byte order in unsigned short value 317 | */ 318 | uint32_t __REV16(uint16_t value) 319 | { 320 | __ASM("rev16 r0, r0"); 321 | __ASM("bx lr"); 322 | } 323 | 324 | /** 325 | * @brief Reverse bit order of value 326 | * 327 | * @param value value to reverse 328 | * @return reversed value 329 | * 330 | * Reverse bit order of value 331 | */ 332 | uint32_t __RBIT(uint32_t value) 333 | { 334 | __ASM("rbit r0, r0"); 335 | __ASM("bx lr"); 336 | } 337 | 338 | /** 339 | * @brief LDR Exclusive (8 bit) 340 | * 341 | * @param *addr address pointer 342 | * @return value of (*address) 343 | * 344 | * Exclusive LDR command for 8 bit values) 345 | */ 346 | uint8_t __LDREXB(uint8_t *addr) 347 | { 348 | __ASM("ldrexb r0, [r0]"); 349 | __ASM("bx lr"); 350 | } 351 | 352 | /** 353 | * @brief LDR Exclusive (16 bit) 354 | * 355 | * @param *addr address pointer 356 | * @return value of (*address) 357 | * 358 | * Exclusive LDR command for 16 bit values 359 | */ 360 | uint16_t __LDREXH(uint16_t *addr) 361 | { 362 | __ASM("ldrexh r0, [r0]"); 363 | __ASM("bx lr"); 364 | } 365 | 366 | /** 367 | * @brief LDR Exclusive (32 bit) 368 | * 369 | * @param *addr address pointer 370 | * @return value of (*address) 371 | * 372 | * Exclusive LDR command for 32 bit values 373 | */ 374 | uint32_t __LDREXW(uint32_t *addr) 375 | { 376 | __ASM("ldrex r0, [r0]"); 377 | __ASM("bx lr"); 378 | } 379 | 380 | /** 381 | * @brief STR Exclusive (8 bit) 382 | * 383 | * @param value value to store 384 | * @param *addr address pointer 385 | * @return successful / failed 386 | * 387 | * Exclusive STR command for 8 bit values 388 | */ 389 | uint32_t __STREXB(uint8_t value, uint8_t *addr) 390 | { 391 | __ASM("strexb r0, r0, [r1]"); 392 | __ASM("bx lr"); 393 | } 394 | 395 | /** 396 | * @brief STR Exclusive (16 bit) 397 | * 398 | * @param value value to store 399 | * @param *addr address pointer 400 | * @return successful / failed 401 | * 402 | * Exclusive STR command for 16 bit values 403 | */ 404 | uint32_t __STREXH(uint16_t value, uint16_t *addr) 405 | { 406 | __ASM("strexh r0, r0, [r1]"); 407 | __ASM("bx lr"); 408 | } 409 | 410 | /** 411 | * @brief STR Exclusive (32 bit) 412 | * 413 | * @param value value to store 414 | * @param *addr address pointer 415 | * @return successful / failed 416 | * 417 | * Exclusive STR command for 32 bit values 418 | */ 419 | uint32_t __STREXW(uint32_t value, uint32_t *addr) 420 | { 421 | __ASM("strex r0, r0, [r1]"); 422 | __ASM("bx lr"); 423 | } 424 | 425 | #pragma diag_default=Pe940 426 | 427 | #elif (defined (__GNUC__)) /*------------------ GNU Compiler ---------------------*/ 428 | /* GNU gcc specific functions */ 429 | 430 | /** 431 | * @brief Return the Process Stack Pointer 432 | * 433 | * @return ProcessStackPointer 434 | * 435 | * Return the actual process stack pointer 436 | */ 437 | uint32_t __get_PSP(void) __attribute__( ( naked ) ); 438 | uint32_t __get_PSP(void) { 439 | uint32_t result = 0; 440 | 441 | __ASM volatile ("MRS %0, psp\n\t" 442 | "MOV r0, %0 \n\t" 443 | "BX lr \n\t" : "=r" (result) ); 444 | return (result); 445 | } 446 | 447 | /** 448 | * @brief Set the Process Stack Pointer 449 | * 450 | * @param topOfProcStack Process Stack Pointer 451 | * 452 | * Assign the value ProcessStackPointer to the MSP 453 | * (process stack pointer) Cortex processor register 454 | */ 455 | void __set_PSP(uint32_t topOfProcStack) __attribute__( ( naked ) ); 456 | void __set_PSP(uint32_t topOfProcStack) { 457 | __ASM volatile ("MSR psp, %0\n\t" 458 | "BX lr \n\t" : : "r" (topOfProcStack) ); 459 | } 460 | 461 | /** 462 | * @brief Return the Main Stack Pointer 463 | * 464 | * @return Main Stack Pointer 465 | * 466 | * Return the current value of the MSP (main stack pointer) 467 | * Cortex processor register 468 | */ 469 | uint32_t __get_MSP(void) __attribute__( ( naked ) ); 470 | uint32_t __get_MSP(void) { 471 | uint32_t result = 0; 472 | 473 | __ASM volatile ("MRS %0, msp\n\t" 474 | "MOV r0, %0 \n\t" 475 | "BX lr \n\t" : "=r" (result) ); 476 | return (result); 477 | } 478 | 479 | /** 480 | * @brief Set the Main Stack Pointer 481 | * 482 | * @param topOfMainStack Main Stack Pointer 483 | * 484 | * Assign the value mainStackPointer to the MSP 485 | * (main stack pointer) Cortex processor register 486 | */ 487 | void __set_MSP(uint32_t topOfMainStack) __attribute__( ( naked ) ); 488 | void __set_MSP(uint32_t topOfMainStack) { 489 | __ASM volatile ("MSR msp, %0\n\t" 490 | "BX lr \n\t" : : "r" (topOfMainStack) ); 491 | } 492 | 493 | /** 494 | * @brief Return the Base Priority value 495 | * 496 | * @return BasePriority 497 | * 498 | * Return the content of the base priority register 499 | */ 500 | uint32_t __get_BASEPRI(void) { 501 | uint32_t result = 0; 502 | 503 | __ASM volatile ("MRS %0, basepri_max" : "=r" (result) ); 504 | return (result); 505 | } 506 | 507 | /** 508 | * @brief Set the Base Priority value 509 | * 510 | * @param basePri BasePriority 511 | * 512 | * Set the base priority register 513 | */ 514 | void __set_BASEPRI(uint32_t value) { 515 | __ASM volatile ("MSR basepri, %0" : : "r" (value) ); 516 | } 517 | 518 | /** 519 | * @brief Return the Priority Mask value 520 | * 521 | * @return PriMask 522 | * 523 | * Return state of the priority mask bit from the priority mask register 524 | */ 525 | uint32_t __get_PRIMASK(void) { 526 | uint32_t result = 0; 527 | 528 | __ASM volatile ("MRS %0, primask" : "=r" (result) ); 529 | return (result); 530 | } 531 | 532 | /** 533 | * @brief Set the Priority Mask value 534 | * 535 | * @param priMask PriMask 536 | * 537 | * Set the priority mask bit in the priority mask register 538 | */ 539 | void __set_PRIMASK(uint32_t priMask) { 540 | __ASM volatile ("MSR primask, %0" : : "r" (priMask) ); 541 | } 542 | 543 | /** 544 | * @brief Return the Fault Mask value 545 | * 546 | * @return FaultMask 547 | * 548 | * Return the content of the fault mask register 549 | */ 550 | uint32_t __get_FAULTMASK(void) { 551 | uint32_t result = 0; 552 | 553 | __ASM volatile ("MRS %0, faultmask" : "=r" (result) ); 554 | return (result); 555 | } 556 | 557 | /** 558 | * @brief Set the Fault Mask value 559 | * 560 | * @param faultMask faultMask value 561 | * 562 | * Set the fault mask register 563 | */ 564 | void __set_FAULTMASK(uint32_t faultMask) { 565 | __ASM volatile ("MSR faultmask, %0" : : "r" (faultMask) ); 566 | } 567 | 568 | /** 569 | * @brief Return the Control Register value 570 | * 571 | * @return Control value 572 | * 573 | * Return the content of the control register 574 | */ 575 | uint32_t __get_CONTROL(void) { 576 | uint32_t result = 0; 577 | 578 | __ASM volatile ("MRS %0, control" : "=r" (result) ); 579 | return (result); 580 | } 581 | 582 | /** 583 | * @brief Set the Control Register value 584 | * 585 | * @param control Control value 586 | * 587 | * Set the control register 588 | */ 589 | void __set_CONTROL(uint32_t control) { 590 | __ASM volatile ("MSR control, %0" : : "r" (control) ); 591 | } 592 | 593 | /** 594 | * @brief Reverse byte order in integer value 595 | * 596 | * @param value value to reverse 597 | * @return reversed value 598 | * 599 | * Reverse byte order in integer value 600 | */ 601 | uint32_t __REV(uint32_t value) { 602 | uint32_t result = 0; 603 | 604 | __ASM volatile ("rev %0, %1" : "=r" (result) : "r" (value) ); 605 | return (result); 606 | } 607 | 608 | /** 609 | * @brief Reverse byte order in unsigned short value 610 | * 611 | * @param value value to reverse 612 | * @return reversed value 613 | * 614 | * Reverse byte order in unsigned short value 615 | */ 616 | uint32_t __REV16(uint16_t value) { 617 | uint32_t result = 0; 618 | 619 | __ASM volatile ("rev16 %0, %1" : "=r" (result) : "r" (value) ); 620 | return (result); 621 | } 622 | 623 | /** 624 | * @brief Reverse byte order in signed short value with sign extension to integer 625 | * 626 | * @param value value to reverse 627 | * @return reversed value 628 | * 629 | * Reverse byte order in signed short value with sign extension to integer 630 | */ 631 | int32_t __REVSH(int16_t value) { 632 | uint32_t result = 0; 633 | 634 | __ASM volatile ("revsh %0, %1" : "=r" (result) : "r" (value) ); 635 | return (result); 636 | } 637 | 638 | /** 639 | * @brief Reverse bit order of value 640 | * 641 | * @param value value to reverse 642 | * @return reversed value 643 | * 644 | * Reverse bit order of value 645 | */ 646 | uint32_t __RBIT(uint32_t value) { 647 | uint32_t result = 0; 648 | 649 | __ASM volatile ("rbit %0, %1" : "=r" (result) : "r" (value) ); 650 | return (result); 651 | } 652 | 653 | /** 654 | * @brief LDR Exclusive (8 bit) 655 | * 656 | * @param *addr address pointer 657 | * @return value of (*address) 658 | * 659 | * Exclusive LDR command for 8 bit value 660 | */ 661 | uint8_t __LDREXB(uint8_t *addr) { 662 | uint8_t result = 0; 663 | 664 | __ASM volatile ("ldrexb %0, [%1]" : "=r" (result) : "r" (addr) ); 665 | return (result); 666 | } 667 | 668 | /** 669 | * @brief LDR Exclusive (16 bit) 670 | * 671 | * @param *addr address pointer 672 | * @return value of (*address) 673 | * 674 | * Exclusive LDR command for 16 bit values 675 | */ 676 | uint16_t __LDREXH(uint16_t *addr) { 677 | uint16_t result = 0; 678 | 679 | __ASM volatile ("ldrexh %0, [%1]" : "=r" (result) : "r" (addr) ); 680 | return (result); 681 | } 682 | 683 | /** 684 | * @brief LDR Exclusive (32 bit) 685 | * 686 | * @param *addr address pointer 687 | * @return value of (*address) 688 | * 689 | * Exclusive LDR command for 32 bit values 690 | */ 691 | uint32_t __LDREXW(uint32_t *addr) { 692 | uint32_t result = 0; 693 | 694 | __ASM volatile ("ldrex %0, [%1]" : "=r" (result) : "r" (addr) ); 695 | return (result); 696 | } 697 | 698 | /** 699 | * @brief STR Exclusive (8 bit) 700 | * 701 | * @param value value to store 702 | * @param *addr address pointer 703 | * @return successful / failed 704 | * 705 | * Exclusive STR command for 8 bit values 706 | */ 707 | uint32_t __STREXB(uint8_t value, uint8_t *addr) { 708 | uint32_t result = 0; 709 | 710 | /* 711 | origin: 712 | __ASM volatile ("strexb %0, %2, [%1]" : "=r" (result) : "r" (addr), "r" (value) ); 713 | 714 | modify according to 715 | http://old.nabble.com/-Bug-gas-13215--New%3A-ARM-Cortex-M3-strexh-strexb-instructions-with-same-registers-generates-error-to32516436.html#a33051551 716 | 717 | */ 718 | 719 | __ASM volatile ("strexb %0, %2, [%1]" : "=&r" (result) : "r" (addr), "r" (value) ); 720 | return (result); 721 | } 722 | 723 | /** 724 | * @brief STR Exclusive (16 bit) 725 | * 726 | * @param value value to store 727 | * @param *addr address pointer 728 | * @return successful / failed 729 | * 730 | * Exclusive STR command for 16 bit values 731 | */ 732 | uint32_t __STREXH(uint16_t value, uint16_t *addr) { 733 | uint32_t result = 0; 734 | 735 | /* 736 | origin: 737 | __ASM volatile ("strexh %0, %2, [%1]" : "=r" (result) : "r" (addr), "r" (value) ); 738 | 739 | modify according to 740 | http://old.nabble.com/-Bug-gas-13215--New%3A-ARM-Cortex-M3-strexh-strexb-instructions-with-same-registers-generates-error-to32516436.html#a33051551 741 | 742 | */ 743 | 744 | __ASM volatile ("strexh %0, %2, [%1]" : "=&r" (result) : "r" (addr), "r" (value) ); 745 | return (result); 746 | } 747 | 748 | /** 749 | * @brief STR Exclusive (32 bit) 750 | * 751 | * @param value value to store 752 | * @param *addr address pointer 753 | * @return successful / failed 754 | * 755 | * Exclusive STR command for 32 bit values 756 | */ 757 | uint32_t __STREXW(uint32_t value, uint32_t *addr) { 758 | uint32_t result = 0; 759 | 760 | __ASM volatile ("strex %0, %2, [%1]" : "=r" (result) : "r" (addr), "r" (value) ); 761 | return (result); 762 | } 763 | 764 | #elif (defined (__TASKING__)) /*------------------ TASKING Compiler ---------------------*/ 765 | /* TASKING carm specific functions */ 766 | 767 | /* 768 | * The CMSIS functions have been implemented as intrinsics in the compiler. 769 | * Please use "carm -?i" to get an up to date list of all instrinsics, 770 | * Including the CMSIS ones. 771 | */ 772 | 773 | #endif 774 | -------------------------------------------------------------------------------- /sys/library_hacks.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * LibraryHacks.cpp 3 | * 4 | * Created on: 23 Jan 2011 5 | * Author: Andy 6 | * source: : stm32plus, version 2.1.0 7 | * @ http://andybrown.me.uk/wk/downloads/ 8 | */ 9 | 10 | #include 11 | #include 12 | 13 | 14 | /* 15 | * The default pulls in 70K of garbage 16 | */ 17 | 18 | namespace __gnu_cxx { 19 | 20 | void __verbose_terminate_handler() { 21 | for(;;); 22 | } 23 | } 24 | 25 | 26 | /* 27 | * The default pulls in about 12K of garbage 28 | */ 29 | 30 | extern "C" void __cxa_pure_virtual() { 31 | for(;;); 32 | } 33 | 34 | 35 | /* 36 | * Implement C++ new/delete operators using the heap 37 | */ 38 | 39 | void *operator new(size_t size) { 40 | return malloc(size); 41 | } 42 | 43 | void *operator new(size_t,void *ptr) { 44 | return ptr; 45 | } 46 | 47 | void *operator new[](size_t size) { 48 | return malloc(size); 49 | } 50 | 51 | void *operator new[](size_t,void *ptr) { 52 | return ptr; 53 | } 54 | 55 | void operator delete(void *p) { 56 | free(p); 57 | } 58 | 59 | void operator delete[](void *p) { 60 | free(p); 61 | } 62 | 63 | 64 | /* 65 | * EABI builds can generate reams of stack unwind code for system generated exceptions 66 | * e.g. (divide-by-zero). Since we don't support exceptions we'll wrap out these 67 | * symbols and save a lot of flash space. 68 | */ 69 | 70 | extern "C" void __wrap___aeabi_unwind_cpp_pr0() {} 71 | extern "C" void __wrap___aeabi_unwind_cpp_pr1() {} 72 | extern "C" void __wrap___aeabi_unwind_cpp_pr2() {} 73 | 74 | 75 | /* 76 | * sbrk function for getting space for malloc and friends 77 | */ 78 | 79 | extern "C" { 80 | 81 | caddr_t _sbrk ( int incr ) { 82 | 83 | extern int _end; 84 | 85 | static unsigned char *heap = NULL; 86 | unsigned char *prev_heap; 87 | 88 | if (heap == NULL) { 89 | heap = (unsigned char *)&_end; 90 | } 91 | prev_heap = heap; 92 | /* check removed to show basic approach */ 93 | 94 | heap += incr; 95 | 96 | return (caddr_t) prev_heap; 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /sys/newlib_stubs.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * newlib_stubs.c 3 | * 4 | * Created on: 2 Nov 2010 5 | * Author: nanoage.co.uk 6 | * Weihong Guan (@aGuegu) 7 | * 8 | * modified on source: 9 | https://sites.google.com/site/stm32discovery/ 10 | open-source-development-with-the-stm32-discovery/ 11 | getting-newlib-to-work-with-stm32-and-code-sourcery-lite-eabi 12 | 13 | http://andybrown.me.uk/wk/2011/12/28/ 14 | stm32plus-a-c-library-for-stm32-development/ 15 | * 16 | */ 17 | 18 | #ifdef __cplusplus 19 | extern "C" { 20 | #endif 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include "usart/usart.h" 27 | #include 28 | #include 29 | 30 | #undef errno 31 | extern int errno; 32 | 33 | /* 34 | environ 35 | A pointer to a list of environment variables and their values. 36 | For a minimal environment, this empty list is adequate: 37 | */ 38 | char *__env[1] = { 0 }; 39 | char **environ = __env; 40 | 41 | int _write(int file, const char *ptr, int len); 42 | 43 | void _exit(int status) { 44 | _write(STDOUT_FILENO, "exit", 4); 45 | while (1) 46 | ; 47 | } 48 | 49 | int _close(int file) { 50 | return -1; 51 | } 52 | /* 53 | execve 54 | Transfer control to a new process. Minimal implementation (for a system without processes): 55 | */ 56 | int _execve(char *name, char **argv, char **env) { 57 | errno = ENOMEM; 58 | return -1; 59 | } 60 | /* 61 | fork 62 | Create a new process. Minimal implementation (for a system without processes): 63 | */ 64 | 65 | int _fork() { 66 | errno = EAGAIN; 67 | return -1; 68 | } 69 | /* 70 | fstat 71 | Status of an open file. For consistency with other minimal implementations in these examples, 72 | all files are regarded as character special devices. 73 | The `sys/stat.h' header file required is distributed in the `include' subdirectory for this C library. 74 | */ 75 | int _fstat(int file, struct stat *st) { 76 | st->st_mode = S_IFCHR; 77 | return 0; 78 | } 79 | 80 | /* 81 | getpid 82 | Process-ID; this is sometimes used to generate strings unlikely to conflict with other processes. Minimal implementation, for a system without processes: 83 | */ 84 | 85 | int _getpid() { 86 | return 1; 87 | } 88 | 89 | /* 90 | isatty 91 | Query whether output stream is a terminal. For consistency with the other minimal implementations, 92 | */ 93 | int _isatty(int file) { 94 | switch (file) { 95 | case STDOUT_FILENO: 96 | case STDERR_FILENO: 97 | case STDIN_FILENO: 98 | return 1; 99 | default: 100 | //errno = ENOTTY; 101 | errno = EBADF; 102 | return 0; 103 | } 104 | } 105 | 106 | /* 107 | kill 108 | Send a signal. Minimal implementation: 109 | */ 110 | int _kill(int pid, int sig) { 111 | errno = EINVAL; 112 | return (-1); 113 | } 114 | 115 | /* 116 | link 117 | Establish a new name for an existing file. Minimal implementation: 118 | */ 119 | 120 | int _link(char *s_old, char *s_new) { 121 | errno = EMLINK; 122 | return -1; 123 | } 124 | 125 | /* 126 | lseek 127 | Set position in a file. Minimal implementation: 128 | */ 129 | int _lseek(int file, int ptr, int dir) { 130 | return 0; 131 | } 132 | 133 | /* 134 | sbrk 135 | Increase program data space. 136 | Malloc and related functions depend on this 137 | */ 138 | //caddr_t _sbrk(int incr) { 139 | // 140 | // extern char _ebss; // Defined by the linker 141 | // static char *heap_end; 142 | // char *prev_heap_end; 143 | // 144 | // if (heap_end == 0) { 145 | // heap_end = &_ebss; 146 | // } 147 | // prev_heap_end = heap_end; 148 | // 149 | // char * stack = (char*) __get_MSP(); 150 | // if (heap_end + incr > stack) { 151 | // _write(STDERR_FILENO, "Heap and stack collision\n", 25); 152 | // errno = ENOMEM; 153 | // return (caddr_t) -1; 154 | // //abort (); 155 | // } 156 | // 157 | // heap_end += incr; 158 | // return (caddr_t) prev_heap_end; 159 | //} 160 | 161 | /* 162 | read 163 | Read a character to a file. `libc' subroutines will use this system routine for input from all files, including stdin 164 | Returns -1 on error or blocks until the number of characters have been read. 165 | */ 166 | 167 | int _read(int file, char *ptr, int len) { 168 | 169 | extern Usart usart; 170 | 171 | int num = 0; 172 | switch (file) { 173 | case STDIN_FILENO: 174 | for (int i = 0; i < len; i++) { 175 | *ptr++ = usart.read(); 176 | num++; 177 | } 178 | break; 179 | default: 180 | errno = EBADF; 181 | return -1; 182 | } 183 | return num; 184 | } 185 | 186 | /* 187 | stat 188 | Status of a file (by name). Minimal implementation: 189 | int _EXFUN(stat,( const char *__path, struct stat *__sbuf )); 190 | */ 191 | 192 | int _stat(const char *filepath, struct stat *st) { 193 | st->st_mode = S_IFCHR; 194 | return 0; 195 | } 196 | 197 | /* 198 | times 199 | Timing information for current process. Minimal implementation: 200 | */ 201 | 202 | clock_t _times(struct tms *buf) { 203 | return -1; 204 | } 205 | 206 | /* 207 | unlink 208 | Remove a file's directory entry. Minimal implementation: 209 | */ 210 | int _unlink(char *name) { 211 | errno = ENOENT; 212 | return -1; 213 | } 214 | 215 | /* 216 | wait 217 | Wait for a child process. Minimal implementation: 218 | */ 219 | int _wait(int *status) { 220 | errno = ECHILD; 221 | return -1; 222 | } 223 | 224 | /* 225 | write 226 | Write a character to a file. `libc' subroutines will use this system routine for output to all files, including stdout 227 | Returns -1 on error or number of bytes sent 228 | */ 229 | 230 | int _write(int file, const char *ptr, int len) { 231 | 232 | extern Usart usart; 233 | 234 | int n; 235 | switch (file) { 236 | case STDOUT_FILENO: /*stdout*/ 237 | for (n = 0; n < len; n++) { 238 | usart.write(*ptr++); 239 | } 240 | break; 241 | case STDERR_FILENO: /* stderr */ 242 | for (n = 0; n < len; n++) { 243 | usart.write(*ptr++); 244 | } 245 | break; 246 | default: 247 | errno = EBADF; 248 | return -1; 249 | } 250 | return len; 251 | } 252 | 253 | #ifdef __cplusplus 254 | } 255 | #endif 256 | -------------------------------------------------------------------------------- /sys/startup_stm32f10x_md_vl.S: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file startup_stm32f10x_md_vl.s 4 | * @author MCD Application Team 5 | * @version V3.5.0 6 | * @date 11-March-2011 7 | * @brief STM32F10x Medium Density Value Line Devices vector table for Atollic 8 | * toolchain. 9 | * This module performs: 10 | * - Set the initial SP 11 | * - Set the initial PC == Reset_Handler, 12 | * - Set the vector table entries with the exceptions ISR address 13 | * - Configure the clock system 14 | * - Branches to main in the C library (which eventually 15 | * calls main()). 16 | * After Reset the Cortex-M3 processor is in Thread mode, 17 | * priority is Privileged, and the Stack is set to Main. 18 | ****************************************************************************** 19 | * @attention 20 | * 21 | * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS 22 | * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE 23 | * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY 24 | * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING 25 | * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE 26 | * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. 27 | * 28 | *

© COPYRIGHT 2011 STMicroelectronics

29 | ****************************************************************************** 30 | */ 31 | 32 | .syntax unified 33 | .cpu cortex-m3 34 | .fpu softvfp 35 | .thumb 36 | 37 | .global g_pfnVectors 38 | .global Default_Handler 39 | 40 | /* start address for the initialization values of the .data section. 41 | defined in linker script */ 42 | .word _sidata 43 | /* start address for the .data section. defined in linker script */ 44 | .word _sdata 45 | /* end address for the .data section. defined in linker script */ 46 | .word _edata 47 | /* start address for the .bss section. defined in linker script */ 48 | .word _sbss 49 | /* end address for the .bss section. defined in linker script */ 50 | .word _ebss 51 | 52 | .equ BootRAM, 0xF108F85F 53 | /** 54 | * @brief This is the code that gets called when the processor first 55 | * starts execution following a reset event. Only the absolutely 56 | * necessary set is performed, after which the application 57 | * supplied main() routine is called. 58 | * @param None 59 | * @retval : None 60 | */ 61 | 62 | .section .text.Reset_Handler 63 | .weak Reset_Handler 64 | .type Reset_Handler, %function 65 | Reset_Handler: 66 | 67 | /* Copy the data segment initializers from flash to SRAM */ 68 | movs r1, #0 69 | b LoopCopyDataInit 70 | 71 | CopyDataInit: 72 | ldr r3, =_sidata 73 | ldr r3, [r3, r1] 74 | str r3, [r0, r1] 75 | adds r1, r1, #4 76 | 77 | LoopCopyDataInit: 78 | ldr r0, =_sdata 79 | ldr r3, =_edata 80 | adds r2, r0, r1 81 | cmp r2, r3 82 | bcc CopyDataInit 83 | ldr r2, =_sbss 84 | b LoopFillZerobss 85 | /* Zero fill the bss segment. */ 86 | FillZerobss: 87 | movs r3, #0 88 | str r3, [r2], #4 89 | 90 | LoopFillZerobss: 91 | ldr r3, = _ebss 92 | cmp r2, r3 93 | bcc FillZerobss 94 | 95 | /* Call the clock system intitialization function.*/ 96 | bl SystemInit 97 | /* Call static constructors */ 98 | bl __libc_init_array 99 | /* Call the application's entry point.*/ 100 | bl main 101 | bx lr 102 | .size Reset_Handler, .-Reset_Handler 103 | 104 | /** 105 | * @brief This is the code that gets called when the processor receives an 106 | * unexpected interrupt. This simply enters an infinite loop, preserving 107 | * the system state for examination by a debugger. 108 | * 109 | * @param None 110 | * @retval : None 111 | */ 112 | .section .text.Default_Handler,"ax",%progbits 113 | Default_Handler: 114 | Infinite_Loop: 115 | b Infinite_Loop 116 | .size Default_Handler, .-Default_Handler 117 | /****************************************************************************** 118 | * 119 | * The minimal vector table for a Cortex M3. Note that the proper constructs 120 | * must be placed on this to ensure that it ends up at physical address 121 | * 0x0000.0000. 122 | * 123 | ******************************************************************************/ 124 | .section .isr_vector,"a",%progbits 125 | .type g_pfnVectors, %object 126 | .size g_pfnVectors, .-g_pfnVectors 127 | 128 | 129 | g_pfnVectors: 130 | .word _estack 131 | .word Reset_Handler 132 | .word NMI_Handler 133 | .word HardFault_Handler 134 | .word MemManage_Handler 135 | .word BusFault_Handler 136 | .word UsageFault_Handler 137 | .word 0 138 | .word 0 139 | .word 0 140 | .word 0 141 | .word SVC_Handler 142 | .word DebugMon_Handler 143 | .word 0 144 | .word PendSV_Handler 145 | .word SysTick_Handler 146 | .word WWDG_IRQHandler 147 | .word PVD_IRQHandler 148 | .word TAMPER_IRQHandler 149 | .word RTC_IRQHandler 150 | .word FLASH_IRQHandler 151 | .word RCC_IRQHandler 152 | .word EXTI0_IRQHandler 153 | .word EXTI1_IRQHandler 154 | .word EXTI2_IRQHandler 155 | .word EXTI3_IRQHandler 156 | .word EXTI4_IRQHandler 157 | .word DMA1_Channel1_IRQHandler 158 | .word DMA1_Channel2_IRQHandler 159 | .word DMA1_Channel3_IRQHandler 160 | .word DMA1_Channel4_IRQHandler 161 | .word DMA1_Channel5_IRQHandler 162 | .word DMA1_Channel6_IRQHandler 163 | .word DMA1_Channel7_IRQHandler 164 | .word ADC1_IRQHandler 165 | .word 0 166 | .word 0 167 | .word 0 168 | .word 0 169 | .word EXTI9_5_IRQHandler 170 | .word TIM1_BRK_TIM15_IRQHandler 171 | .word TIM1_UP_TIM16_IRQHandler 172 | .word TIM1_TRG_COM_TIM17_IRQHandler 173 | .word TIM1_CC_IRQHandler 174 | .word TIM2_IRQHandler 175 | .word TIM3_IRQHandler 176 | .word TIM4_IRQHandler 177 | .word I2C1_EV_IRQHandler 178 | .word I2C1_ER_IRQHandler 179 | .word I2C2_EV_IRQHandler 180 | .word I2C2_ER_IRQHandler 181 | .word SPI1_IRQHandler 182 | .word SPI2_IRQHandler 183 | .word USART1_IRQHandler 184 | .word USART2_IRQHandler 185 | .word USART3_IRQHandler 186 | .word EXTI15_10_IRQHandler 187 | .word RTCAlarm_IRQHandler 188 | .word CEC_IRQHandler 189 | .word 0 190 | .word 0 191 | .word 0 192 | .word 0 193 | .word 0 194 | .word 0 195 | .word 0 196 | .word 0 197 | .word 0 198 | .word 0 199 | .word 0 200 | .word TIM6_DAC_IRQHandler 201 | .word TIM7_IRQHandler 202 | .word 0 203 | .word 0 204 | .word 0 205 | .word 0 206 | .word 0 207 | .word 0 208 | .word 0 209 | .word 0 210 | .word 0 211 | .word 0 212 | .word 0 213 | .word 0 214 | .word 0 215 | .word 0 216 | .word 0 217 | .word 0 218 | .word 0 219 | .word 0 220 | .word 0 221 | .word 0 222 | .word 0 223 | .word 0 224 | .word 0 225 | .word 0 226 | .word 0 227 | .word 0 228 | .word 0 229 | .word 0 230 | .word 0 231 | .word 0 232 | .word 0 233 | .word 0 234 | .word 0 235 | .word 0 236 | .word 0 237 | .word 0 238 | .word 0 239 | .word 0 240 | .word 0 241 | .word 0 242 | .word 0 243 | .word 0 244 | .word 0 245 | .word BootRAM /* @0x01CC. This is for boot in RAM mode for 246 | STM32F10x Medium Value Line Density devices. */ 247 | 248 | /******************************************************************************* 249 | * 250 | * Provide weak aliases for each Exception handler to the Default_Handler. 251 | * As they are weak aliases, any function with the same name will override 252 | * this definition. 253 | * 254 | *******************************************************************************/ 255 | 256 | 257 | .weak NMI_Handler 258 | .thumb_set NMI_Handler,Default_Handler 259 | 260 | .weak HardFault_Handler 261 | .thumb_set HardFault_Handler,Default_Handler 262 | 263 | .weak MemManage_Handler 264 | .thumb_set MemManage_Handler,Default_Handler 265 | 266 | .weak BusFault_Handler 267 | .thumb_set BusFault_Handler,Default_Handler 268 | 269 | .weak UsageFault_Handler 270 | .thumb_set UsageFault_Handler,Default_Handler 271 | 272 | .weak SVC_Handler 273 | .thumb_set SVC_Handler,Default_Handler 274 | 275 | .weak DebugMon_Handler 276 | .thumb_set DebugMon_Handler,Default_Handler 277 | 278 | .weak PendSV_Handler 279 | .thumb_set PendSV_Handler,Default_Handler 280 | 281 | .weak SysTick_Handler 282 | .thumb_set SysTick_Handler,Default_Handler 283 | 284 | .weak WWDG_IRQHandler 285 | .thumb_set WWDG_IRQHandler,Default_Handler 286 | 287 | .weak PVD_IRQHandler 288 | .thumb_set PVD_IRQHandler,Default_Handler 289 | 290 | .weak TAMPER_IRQHandler 291 | .thumb_set TAMPER_IRQHandler,Default_Handler 292 | 293 | .weak RTC_IRQHandler 294 | .thumb_set RTC_IRQHandler,Default_Handler 295 | 296 | .weak FLASH_IRQHandler 297 | .thumb_set FLASH_IRQHandler,Default_Handler 298 | 299 | .weak RCC_IRQHandler 300 | .thumb_set RCC_IRQHandler,Default_Handler 301 | 302 | .weak EXTI0_IRQHandler 303 | .thumb_set EXTI0_IRQHandler,Default_Handler 304 | 305 | .weak EXTI1_IRQHandler 306 | .thumb_set EXTI1_IRQHandler,Default_Handler 307 | 308 | .weak EXTI2_IRQHandler 309 | .thumb_set EXTI2_IRQHandler,Default_Handler 310 | 311 | .weak EXTI3_IRQHandler 312 | .thumb_set EXTI3_IRQHandler,Default_Handler 313 | 314 | .weak EXTI4_IRQHandler 315 | .thumb_set EXTI4_IRQHandler,Default_Handler 316 | 317 | .weak DMA1_Channel1_IRQHandler 318 | .thumb_set DMA1_Channel1_IRQHandler,Default_Handler 319 | 320 | .weak DMA1_Channel2_IRQHandler 321 | .thumb_set DMA1_Channel2_IRQHandler,Default_Handler 322 | 323 | .weak DMA1_Channel3_IRQHandler 324 | .thumb_set DMA1_Channel3_IRQHandler,Default_Handler 325 | 326 | .weak DMA1_Channel4_IRQHandler 327 | .thumb_set DMA1_Channel4_IRQHandler,Default_Handler 328 | 329 | .weak DMA1_Channel5_IRQHandler 330 | .thumb_set DMA1_Channel5_IRQHandler,Default_Handler 331 | 332 | .weak DMA1_Channel6_IRQHandler 333 | .thumb_set DMA1_Channel6_IRQHandler,Default_Handler 334 | 335 | .weak DMA1_Channel7_IRQHandler 336 | .thumb_set DMA1_Channel7_IRQHandler,Default_Handler 337 | 338 | .weak ADC1_IRQHandler 339 | .thumb_set ADC1_IRQHandler,Default_Handler 340 | 341 | .weak EXTI9_5_IRQHandler 342 | .thumb_set EXTI9_5_IRQHandler,Default_Handler 343 | 344 | .weak TIM1_BRK_TIM15_IRQHandler 345 | .thumb_set TIM1_BRK_TIM15_IRQHandler,Default_Handler 346 | 347 | .weak TIM1_UP_TIM16_IRQHandler 348 | .thumb_set TIM1_UP_TIM16_IRQHandler,Default_Handler 349 | 350 | .weak TIM1_TRG_COM_TIM17_IRQHandler 351 | .thumb_set TIM1_TRG_COM_TIM17_IRQHandler,Default_Handler 352 | 353 | .weak TIM1_CC_IRQHandler 354 | .thumb_set TIM1_CC_IRQHandler,Default_Handler 355 | 356 | .weak TIM2_IRQHandler 357 | .thumb_set TIM2_IRQHandler,Default_Handler 358 | 359 | .weak TIM3_IRQHandler 360 | .thumb_set TIM3_IRQHandler,Default_Handler 361 | 362 | .weak TIM4_IRQHandler 363 | .thumb_set TIM4_IRQHandler,Default_Handler 364 | 365 | .weak I2C1_EV_IRQHandler 366 | .thumb_set I2C1_EV_IRQHandler,Default_Handler 367 | 368 | .weak I2C1_ER_IRQHandler 369 | .thumb_set I2C1_ER_IRQHandler,Default_Handler 370 | 371 | .weak I2C2_EV_IRQHandler 372 | .thumb_set I2C2_EV_IRQHandler,Default_Handler 373 | 374 | .weak I2C2_ER_IRQHandler 375 | .thumb_set I2C2_ER_IRQHandler,Default_Handler 376 | 377 | .weak SPI1_IRQHandler 378 | .thumb_set SPI1_IRQHandler,Default_Handler 379 | 380 | .weak SPI2_IRQHandler 381 | .thumb_set SPI2_IRQHandler,Default_Handler 382 | 383 | .weak USART1_IRQHandler 384 | .thumb_set USART1_IRQHandler,Default_Handler 385 | 386 | .weak USART2_IRQHandler 387 | .thumb_set USART2_IRQHandler,Default_Handler 388 | 389 | .weak USART3_IRQHandler 390 | .thumb_set USART3_IRQHandler,Default_Handler 391 | 392 | .weak EXTI15_10_IRQHandler 393 | .thumb_set EXTI15_10_IRQHandler,Default_Handler 394 | 395 | .weak RTCAlarm_IRQHandler 396 | .thumb_set RTCAlarm_IRQHandler,Default_Handler 397 | 398 | .weak CEC_IRQHandler 399 | .thumb_set CEC_IRQHandler,Default_Handler 400 | 401 | .weak TIM6_DAC_IRQHandler 402 | .thumb_set TIM6_DAC_IRQHandler,Default_Handler 403 | 404 | .weak TIM7_IRQHandler 405 | .thumb_set TIM7_IRQHandler,Default_Handler 406 | 407 | /******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ 408 | 409 | -------------------------------------------------------------------------------- /sys/system_stm32f10x.c: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file system_stm32f10x.c 4 | * @author MCD Application Team 5 | * @version V3.5.0 6 | * @date 08-April-2011 7 | * @brief CMSIS Cortex-M3 Device Peripheral Access Layer System Source File. 8 | * 9 | * 1. This file provides two functions and one global variable to be called from 10 | * user application: 11 | * - SystemInit(): Setups the system clock (System clock source, PLL Multiplier 12 | * factors, AHB/APBx prescalers and Flash settings). 13 | * This function is called at startup just after reset and 14 | * before branch to main program. This call is made inside 15 | * the "startup_stm32f10x_xx.s" file. 16 | * 17 | * - SystemCoreClock variable: Contains the core clock (HCLK), it can be used 18 | * by the user application to setup the SysTick 19 | * timer or configure other parameters. 20 | * 21 | * - SystemCoreClockUpdate(): Updates the variable SystemCoreClock and must 22 | * be called whenever the core clock is changed 23 | * during program execution. 24 | * 25 | * 2. After each device reset the HSI (8 MHz) is used as system clock source. 26 | * Then SystemInit() function is called, in "startup_stm32f10x_xx.s" file, to 27 | * configure the system clock before to branch to main program. 28 | * 29 | * 3. If the system clock source selected by user fails to startup, the SystemInit() 30 | * function will do nothing and HSI still used as system clock source. User can 31 | * add some code to deal with this issue inside the SetSysClock() function. 32 | * 33 | * 4. The default value of HSE crystal is set to 8 MHz (or 25 MHz, depedning on 34 | * the product used), refer to "HSE_VALUE" define in "stm32f10x.h" file. 35 | * When HSE is used as system clock source, directly or through PLL, and you 36 | * are using different crystal you have to adapt the HSE value to your own 37 | * configuration. 38 | * 39 | ****************************************************************************** 40 | * @attention 41 | * 42 | * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS 43 | * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE 44 | * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY 45 | * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING 46 | * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE 47 | * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. 48 | * 49 | *

© COPYRIGHT 2011 STMicroelectronics

50 | ****************************************************************************** 51 | */ 52 | 53 | /** @addtogroup CMSIS 54 | * @{ 55 | */ 56 | 57 | /** @addtogroup stm32f10x_system 58 | * @{ 59 | */ 60 | 61 | /** @addtogroup STM32F10x_System_Private_Includes 62 | * @{ 63 | */ 64 | 65 | #include "stm32f10x.h" 66 | 67 | /** 68 | * @} 69 | */ 70 | 71 | /** @addtogroup STM32F10x_System_Private_TypesDefinitions 72 | * @{ 73 | */ 74 | 75 | /** 76 | * @} 77 | */ 78 | 79 | /** @addtogroup STM32F10x_System_Private_Defines 80 | * @{ 81 | */ 82 | 83 | /*!< Uncomment the line corresponding to the desired System clock (SYSCLK) 84 | frequency (after reset the HSI is used as SYSCLK source) 85 | 86 | IMPORTANT NOTE: 87 | ============== 88 | 1. After each device reset the HSI is used as System clock source. 89 | 90 | 2. Please make sure that the selected System clock doesn't exceed your device's 91 | maximum frequency. 92 | 93 | 3. If none of the define below is enabled, the HSI is used as System clock 94 | source. 95 | 96 | 4. The System clock configuration functions provided within this file assume that: 97 | - For Low, Medium and High density Value line devices an external 8MHz 98 | crystal is used to drive the System clock. 99 | - For Low, Medium and High density devices an external 8MHz crystal is 100 | used to drive the System clock. 101 | - For Connectivity line devices an external 25MHz crystal is used to drive 102 | the System clock. 103 | If you are using different crystal you have to adapt those functions accordingly. 104 | */ 105 | 106 | #if defined (STM32F10X_LD_VL) || (defined STM32F10X_MD_VL) || (defined STM32F10X_HD_VL) 107 | /* #define SYSCLK_FREQ_HSE HSE_VALUE */ 108 | #define SYSCLK_FREQ_24MHz 24000000 109 | #else 110 | /* #define SYSCLK_FREQ_HSE HSE_VALUE */ 111 | /* #define SYSCLK_FREQ_24MHz 24000000 */ 112 | /* #define SYSCLK_FREQ_36MHz 36000000 */ 113 | /* #define SYSCLK_FREQ_48MHz 48000000 */ 114 | /* #define SYSCLK_FREQ_56MHz 56000000 */ 115 | #define SYSCLK_FREQ_72MHz 72000000 116 | #endif 117 | 118 | /*!< Uncomment the following line if you need to use external SRAM mounted 119 | on STM3210E-EVAL board (STM32 High density and XL-density devices) or on 120 | STM32100E-EVAL board (STM32 High-density value line devices) as data memory */ 121 | #if defined (STM32F10X_HD) || (defined STM32F10X_XL) || (defined STM32F10X_HD_VL) 122 | /* #define DATA_IN_ExtSRAM */ 123 | #endif 124 | 125 | /*!< Uncomment the following line if you need to relocate your vector Table in 126 | Internal SRAM. */ 127 | /* #define VECT_TAB_SRAM */ 128 | #define VECT_TAB_OFFSET 0x0 /*!< Vector Table base offset field. 129 | This value must be a multiple of 0x200. */ 130 | 131 | 132 | /** 133 | * @} 134 | */ 135 | 136 | /** @addtogroup STM32F10x_System_Private_Macros 137 | * @{ 138 | */ 139 | 140 | /** 141 | * @} 142 | */ 143 | 144 | /** @addtogroup STM32F10x_System_Private_Variables 145 | * @{ 146 | */ 147 | 148 | /******************************************************************************* 149 | * Clock Definitions 150 | *******************************************************************************/ 151 | #ifdef SYSCLK_FREQ_HSE 152 | uint32_t SystemCoreClock = SYSCLK_FREQ_HSE; /*!< System Clock Frequency (Core Clock) */ 153 | #elif defined SYSCLK_FREQ_24MHz 154 | uint32_t SystemCoreClock = SYSCLK_FREQ_24MHz; /*!< System Clock Frequency (Core Clock) */ 155 | #elif defined SYSCLK_FREQ_36MHz 156 | uint32_t SystemCoreClock = SYSCLK_FREQ_36MHz; /*!< System Clock Frequency (Core Clock) */ 157 | #elif defined SYSCLK_FREQ_48MHz 158 | uint32_t SystemCoreClock = SYSCLK_FREQ_48MHz; /*!< System Clock Frequency (Core Clock) */ 159 | #elif defined SYSCLK_FREQ_56MHz 160 | uint32_t SystemCoreClock = SYSCLK_FREQ_56MHz; /*!< System Clock Frequency (Core Clock) */ 161 | #elif defined SYSCLK_FREQ_72MHz 162 | uint32_t SystemCoreClock = SYSCLK_FREQ_72MHz; /*!< System Clock Frequency (Core Clock) */ 163 | #else /*!< HSI Selected as System Clock source */ 164 | uint32_t SystemCoreClock = HSI_VALUE; /*!< System Clock Frequency (Core Clock) */ 165 | #endif 166 | 167 | __I uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9}; 168 | /** 169 | * @} 170 | */ 171 | 172 | /** @addtogroup STM32F10x_System_Private_FunctionPrototypes 173 | * @{ 174 | */ 175 | 176 | static void SetSysClock(void); 177 | 178 | #ifdef SYSCLK_FREQ_HSE 179 | static void SetSysClockToHSE(void); 180 | #elif defined SYSCLK_FREQ_24MHz 181 | static void SetSysClockTo24(void); 182 | #elif defined SYSCLK_FREQ_36MHz 183 | static void SetSysClockTo36(void); 184 | #elif defined SYSCLK_FREQ_48MHz 185 | static void SetSysClockTo48(void); 186 | #elif defined SYSCLK_FREQ_56MHz 187 | static void SetSysClockTo56(void); 188 | #elif defined SYSCLK_FREQ_72MHz 189 | static void SetSysClockTo72(void); 190 | #endif 191 | 192 | #ifdef DATA_IN_ExtSRAM 193 | static void SystemInit_ExtMemCtl(void); 194 | #endif /* DATA_IN_ExtSRAM */ 195 | 196 | /** 197 | * @} 198 | */ 199 | 200 | /** @addtogroup STM32F10x_System_Private_Functions 201 | * @{ 202 | */ 203 | 204 | /** 205 | * @brief Setup the microcontroller system 206 | * Initialize the Embedded Flash Interface, the PLL and update the 207 | * SystemCoreClock variable. 208 | * @note This function should be used only after reset. 209 | * @retval None 210 | */ 211 | void SystemInit (void) 212 | { 213 | /* Reset the RCC clock configuration to the default reset state(for debug purpose) */ 214 | /* Set HSION bit */ 215 | RCC->CR |= (uint32_t)0x00000001; 216 | 217 | /* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */ 218 | #ifndef STM32F10X_CL 219 | RCC->CFGR &= (uint32_t)0xF8FF0000; 220 | #else 221 | RCC->CFGR &= (uint32_t)0xF0FF0000; 222 | #endif /* STM32F10X_CL */ 223 | 224 | /* Reset HSEON, CSSON and PLLON bits */ 225 | RCC->CR &= (uint32_t)0xFEF6FFFF; 226 | 227 | /* Reset HSEBYP bit */ 228 | RCC->CR &= (uint32_t)0xFFFBFFFF; 229 | 230 | /* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */ 231 | RCC->CFGR &= (uint32_t)0xFF80FFFF; 232 | 233 | #ifdef STM32F10X_CL 234 | /* Reset PLL2ON and PLL3ON bits */ 235 | RCC->CR &= (uint32_t)0xEBFFFFFF; 236 | 237 | /* Disable all interrupts and clear pending bits */ 238 | RCC->CIR = 0x00FF0000; 239 | 240 | /* Reset CFGR2 register */ 241 | RCC->CFGR2 = 0x00000000; 242 | #elif defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || (defined STM32F10X_HD_VL) 243 | /* Disable all interrupts and clear pending bits */ 244 | RCC->CIR = 0x009F0000; 245 | 246 | /* Reset CFGR2 register */ 247 | RCC->CFGR2 = 0x00000000; 248 | #else 249 | /* Disable all interrupts and clear pending bits */ 250 | RCC->CIR = 0x009F0000; 251 | #endif /* STM32F10X_CL */ 252 | 253 | #if defined (STM32F10X_HD) || (defined STM32F10X_XL) || (defined STM32F10X_HD_VL) 254 | #ifdef DATA_IN_ExtSRAM 255 | SystemInit_ExtMemCtl(); 256 | #endif /* DATA_IN_ExtSRAM */ 257 | #endif 258 | 259 | /* Configure the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers */ 260 | /* Configure the Flash Latency cycles and enable prefetch buffer */ 261 | SetSysClock(); 262 | 263 | #ifdef VECT_TAB_SRAM 264 | SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM. */ 265 | #else 266 | SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH. */ 267 | #endif 268 | } 269 | 270 | /** 271 | * @brief Update SystemCoreClock variable according to Clock Register Values. 272 | * The SystemCoreClock variable contains the core clock (HCLK), it can 273 | * be used by the user application to setup the SysTick timer or configure 274 | * other parameters. 275 | * 276 | * @note Each time the core clock (HCLK) changes, this function must be called 277 | * to update SystemCoreClock variable value. Otherwise, any configuration 278 | * based on this variable will be incorrect. 279 | * 280 | * @note - The system frequency computed by this function is not the real 281 | * frequency in the chip. It is calculated based on the predefined 282 | * constant and the selected clock source: 283 | * 284 | * - If SYSCLK source is HSI, SystemCoreClock will contain the HSI_VALUE(*) 285 | * 286 | * - If SYSCLK source is HSE, SystemCoreClock will contain the HSE_VALUE(**) 287 | * 288 | * - If SYSCLK source is PLL, SystemCoreClock will contain the HSE_VALUE(**) 289 | * or HSI_VALUE(*) multiplied by the PLL factors. 290 | * 291 | * (*) HSI_VALUE is a constant defined in stm32f1xx.h file (default value 292 | * 8 MHz) but the real value may vary depending on the variations 293 | * in voltage and temperature. 294 | * 295 | * (**) HSE_VALUE is a constant defined in stm32f1xx.h file (default value 296 | * 8 MHz or 25 MHz, depedning on the product used), user has to ensure 297 | * that HSE_VALUE is same as the real frequency of the crystal used. 298 | * Otherwise, this function may have wrong result. 299 | * 300 | * - The result of this function could be not correct when using fractional 301 | * value for HSE crystal. 302 | * @retval None 303 | */ 304 | void SystemCoreClockUpdate (void) 305 | { 306 | uint32_t tmp = 0, pllmull = 0, pllsource = 0; 307 | 308 | #ifdef STM32F10X_CL 309 | uint32_t prediv1source = 0, prediv1factor = 0, prediv2factor = 0, pll2mull = 0; 310 | #endif /* STM32F10X_CL */ 311 | 312 | #if defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || (defined STM32F10X_HD_VL) 313 | uint32_t prediv1factor = 0; 314 | #endif /* STM32F10X_LD_VL or STM32F10X_MD_VL or STM32F10X_HD_VL */ 315 | 316 | /* Get SYSCLK source -------------------------------------------------------*/ 317 | tmp = RCC->CFGR & RCC_CFGR_SWS; 318 | 319 | switch (tmp) 320 | { 321 | case 0x00: /* HSI used as system clock */ 322 | SystemCoreClock = HSI_VALUE; 323 | break; 324 | case 0x04: /* HSE used as system clock */ 325 | SystemCoreClock = HSE_VALUE; 326 | break; 327 | case 0x08: /* PLL used as system clock */ 328 | 329 | /* Get PLL clock source and multiplication factor ----------------------*/ 330 | pllmull = RCC->CFGR & RCC_CFGR_PLLMULL; 331 | pllsource = RCC->CFGR & RCC_CFGR_PLLSRC; 332 | 333 | #ifndef STM32F10X_CL 334 | pllmull = ( pllmull >> 18) + 2; 335 | 336 | if (pllsource == 0x00) 337 | { 338 | /* HSI oscillator clock divided by 2 selected as PLL clock entry */ 339 | SystemCoreClock = (HSI_VALUE >> 1) * pllmull; 340 | } 341 | else 342 | { 343 | #if defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || (defined STM32F10X_HD_VL) 344 | prediv1factor = (RCC->CFGR2 & RCC_CFGR2_PREDIV1) + 1; 345 | /* HSE oscillator clock selected as PREDIV1 clock entry */ 346 | SystemCoreClock = (HSE_VALUE / prediv1factor) * pllmull; 347 | #else 348 | /* HSE selected as PLL clock entry */ 349 | if ((RCC->CFGR & RCC_CFGR_PLLXTPRE) != (uint32_t)RESET) 350 | {/* HSE oscillator clock divided by 2 */ 351 | SystemCoreClock = (HSE_VALUE >> 1) * pllmull; 352 | } 353 | else 354 | { 355 | SystemCoreClock = HSE_VALUE * pllmull; 356 | } 357 | #endif 358 | } 359 | #else 360 | pllmull = pllmull >> 18; 361 | 362 | if (pllmull != 0x0D) 363 | { 364 | pllmull += 2; 365 | } 366 | else 367 | { /* PLL multiplication factor = PLL input clock * 6.5 */ 368 | pllmull = 13 / 2; 369 | } 370 | 371 | if (pllsource == 0x00) 372 | { 373 | /* HSI oscillator clock divided by 2 selected as PLL clock entry */ 374 | SystemCoreClock = (HSI_VALUE >> 1) * pllmull; 375 | } 376 | else 377 | {/* PREDIV1 selected as PLL clock entry */ 378 | 379 | /* Get PREDIV1 clock source and division factor */ 380 | prediv1source = RCC->CFGR2 & RCC_CFGR2_PREDIV1SRC; 381 | prediv1factor = (RCC->CFGR2 & RCC_CFGR2_PREDIV1) + 1; 382 | 383 | if (prediv1source == 0) 384 | { 385 | /* HSE oscillator clock selected as PREDIV1 clock entry */ 386 | SystemCoreClock = (HSE_VALUE / prediv1factor) * pllmull; 387 | } 388 | else 389 | {/* PLL2 clock selected as PREDIV1 clock entry */ 390 | 391 | /* Get PREDIV2 division factor and PLL2 multiplication factor */ 392 | prediv2factor = ((RCC->CFGR2 & RCC_CFGR2_PREDIV2) >> 4) + 1; 393 | pll2mull = ((RCC->CFGR2 & RCC_CFGR2_PLL2MUL) >> 8 ) + 2; 394 | SystemCoreClock = (((HSE_VALUE / prediv2factor) * pll2mull) / prediv1factor) * pllmull; 395 | } 396 | } 397 | #endif /* STM32F10X_CL */ 398 | break; 399 | 400 | default: 401 | SystemCoreClock = HSI_VALUE; 402 | break; 403 | } 404 | 405 | /* Compute HCLK clock frequency ----------------*/ 406 | /* Get HCLK prescaler */ 407 | tmp = AHBPrescTable[((RCC->CFGR & RCC_CFGR_HPRE) >> 4)]; 408 | /* HCLK clock frequency */ 409 | SystemCoreClock >>= tmp; 410 | } 411 | 412 | /** 413 | * @brief Configures the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers. 414 | * @param None 415 | * @retval None 416 | */ 417 | static void SetSysClock(void) 418 | { 419 | #ifdef SYSCLK_FREQ_HSE 420 | SetSysClockToHSE(); 421 | #elif defined SYSCLK_FREQ_24MHz 422 | SetSysClockTo24(); 423 | #elif defined SYSCLK_FREQ_36MHz 424 | SetSysClockTo36(); 425 | #elif defined SYSCLK_FREQ_48MHz 426 | SetSysClockTo48(); 427 | #elif defined SYSCLK_FREQ_56MHz 428 | SetSysClockTo56(); 429 | #elif defined SYSCLK_FREQ_72MHz 430 | SetSysClockTo72(); 431 | #endif 432 | 433 | /* If none of the define above is enabled, the HSI is used as System clock 434 | source (default after reset) */ 435 | } 436 | 437 | /** 438 | * @brief Setup the external memory controller. Called in startup_stm32f10x.s 439 | * before jump to __main 440 | * @param None 441 | * @retval None 442 | */ 443 | #ifdef DATA_IN_ExtSRAM 444 | /** 445 | * @brief Setup the external memory controller. 446 | * Called in startup_stm32f10x_xx.s/.c before jump to main. 447 | * This function configures the external SRAM mounted on STM3210E-EVAL 448 | * board (STM32 High density devices). This SRAM will be used as program 449 | * data memory (including heap and stack). 450 | * @param None 451 | * @retval None 452 | */ 453 | void SystemInit_ExtMemCtl(void) 454 | { 455 | /*!< FSMC Bank1 NOR/SRAM3 is used for the STM3210E-EVAL, if another Bank is 456 | required, then adjust the Register Addresses */ 457 | 458 | /* Enable FSMC clock */ 459 | RCC->AHBENR = 0x00000114; 460 | 461 | /* Enable GPIOD, GPIOE, GPIOF and GPIOG clocks */ 462 | RCC->APB2ENR = 0x000001E0; 463 | 464 | /* --------------- SRAM Data lines, NOE and NWE configuration ---------------*/ 465 | /*---------------- SRAM Address lines configuration -------------------------*/ 466 | /*---------------- NOE and NWE configuration --------------------------------*/ 467 | /*---------------- NE3 configuration ----------------------------------------*/ 468 | /*---------------- NBL0, NBL1 configuration ---------------------------------*/ 469 | 470 | GPIOD->CRL = 0x44BB44BB; 471 | GPIOD->CRH = 0xBBBBBBBB; 472 | 473 | GPIOE->CRL = 0xB44444BB; 474 | GPIOE->CRH = 0xBBBBBBBB; 475 | 476 | GPIOF->CRL = 0x44BBBBBB; 477 | GPIOF->CRH = 0xBBBB4444; 478 | 479 | GPIOG->CRL = 0x44BBBBBB; 480 | GPIOG->CRH = 0x44444B44; 481 | 482 | /*---------------- FSMC Configuration ---------------------------------------*/ 483 | /*---------------- Enable FSMC Bank1_SRAM Bank ------------------------------*/ 484 | 485 | FSMC_Bank1->BTCR[4] = 0x00001011; 486 | FSMC_Bank1->BTCR[5] = 0x00000200; 487 | } 488 | #endif /* DATA_IN_ExtSRAM */ 489 | 490 | #ifdef SYSCLK_FREQ_HSE 491 | /** 492 | * @brief Selects HSE as System clock source and configure HCLK, PCLK2 493 | * and PCLK1 prescalers. 494 | * @note This function should be used only after reset. 495 | * @param None 496 | * @retval None 497 | */ 498 | static void SetSysClockToHSE(void) 499 | { 500 | __IO uint32_t StartUpCounter = 0, HSEStatus = 0; 501 | 502 | /* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/ 503 | /* Enable HSE */ 504 | RCC->CR |= ((uint32_t)RCC_CR_HSEON); 505 | 506 | /* Wait till HSE is ready and if Time out is reached exit */ 507 | do 508 | { 509 | HSEStatus = RCC->CR & RCC_CR_HSERDY; 510 | StartUpCounter++; 511 | } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT)); 512 | 513 | if ((RCC->CR & RCC_CR_HSERDY) != RESET) 514 | { 515 | HSEStatus = (uint32_t)0x01; 516 | } 517 | else 518 | { 519 | HSEStatus = (uint32_t)0x00; 520 | } 521 | 522 | if (HSEStatus == (uint32_t)0x01) 523 | { 524 | 525 | #if !defined STM32F10X_LD_VL && !defined STM32F10X_MD_VL && !defined STM32F10X_HD_VL 526 | /* Enable Prefetch Buffer */ 527 | FLASH->ACR |= FLASH_ACR_PRFTBE; 528 | 529 | /* Flash 0 wait state */ 530 | FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY); 531 | 532 | #ifndef STM32F10X_CL 533 | FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_0; 534 | #else 535 | if (HSE_VALUE <= 24000000) 536 | { 537 | FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_0; 538 | } 539 | else 540 | { 541 | FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_1; 542 | } 543 | #endif /* STM32F10X_CL */ 544 | #endif 545 | 546 | /* HCLK = SYSCLK */ 547 | RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1; 548 | 549 | /* PCLK2 = HCLK */ 550 | RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1; 551 | 552 | /* PCLK1 = HCLK */ 553 | RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV1; 554 | 555 | /* Select HSE as system clock source */ 556 | RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW)); 557 | RCC->CFGR |= (uint32_t)RCC_CFGR_SW_HSE; 558 | 559 | /* Wait till HSE is used as system clock source */ 560 | while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x04) 561 | { 562 | } 563 | } 564 | else 565 | { /* If HSE fails to start-up, the application will have wrong clock 566 | configuration. User can add here some code to deal with this error */ 567 | } 568 | } 569 | #elif defined SYSCLK_FREQ_24MHz 570 | /** 571 | * @brief Sets System clock frequency to 24MHz and configure HCLK, PCLK2 572 | * and PCLK1 prescalers. 573 | * @note This function should be used only after reset. 574 | * @param None 575 | * @retval None 576 | */ 577 | static void SetSysClockTo24(void) 578 | { 579 | __IO uint32_t StartUpCounter = 0, HSEStatus = 0; 580 | 581 | /* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/ 582 | /* Enable HSE */ 583 | RCC->CR |= ((uint32_t)RCC_CR_HSEON); 584 | 585 | /* Wait till HSE is ready and if Time out is reached exit */ 586 | do 587 | { 588 | HSEStatus = RCC->CR & RCC_CR_HSERDY; 589 | StartUpCounter++; 590 | } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT)); 591 | 592 | if ((RCC->CR & RCC_CR_HSERDY) != RESET) 593 | { 594 | HSEStatus = (uint32_t)0x01; 595 | } 596 | else 597 | { 598 | HSEStatus = (uint32_t)0x00; 599 | } 600 | 601 | if (HSEStatus == (uint32_t)0x01) 602 | { 603 | #if !defined STM32F10X_LD_VL && !defined STM32F10X_MD_VL && !defined STM32F10X_HD_VL 604 | /* Enable Prefetch Buffer */ 605 | FLASH->ACR |= FLASH_ACR_PRFTBE; 606 | 607 | /* Flash 0 wait state */ 608 | FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY); 609 | FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_0; 610 | #endif 611 | 612 | /* HCLK = SYSCLK */ 613 | RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1; 614 | 615 | /* PCLK2 = HCLK */ 616 | RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1; 617 | 618 | /* PCLK1 = HCLK */ 619 | RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV1; 620 | 621 | #ifdef STM32F10X_CL 622 | /* Configure PLLs ------------------------------------------------------*/ 623 | /* PLL configuration: PLLCLK = PREDIV1 * 6 = 24 MHz */ 624 | RCC->CFGR &= (uint32_t)~(RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLSRC | RCC_CFGR_PLLMULL); 625 | RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLXTPRE_PREDIV1 | RCC_CFGR_PLLSRC_PREDIV1 | 626 | RCC_CFGR_PLLMULL6); 627 | 628 | /* PLL2 configuration: PLL2CLK = (HSE / 5) * 8 = 40 MHz */ 629 | /* PREDIV1 configuration: PREDIV1CLK = PLL2 / 10 = 4 MHz */ 630 | RCC->CFGR2 &= (uint32_t)~(RCC_CFGR2_PREDIV2 | RCC_CFGR2_PLL2MUL | 631 | RCC_CFGR2_PREDIV1 | RCC_CFGR2_PREDIV1SRC); 632 | RCC->CFGR2 |= (uint32_t)(RCC_CFGR2_PREDIV2_DIV5 | RCC_CFGR2_PLL2MUL8 | 633 | RCC_CFGR2_PREDIV1SRC_PLL2 | RCC_CFGR2_PREDIV1_DIV10); 634 | 635 | /* Enable PLL2 */ 636 | RCC->CR |= RCC_CR_PLL2ON; 637 | /* Wait till PLL2 is ready */ 638 | while((RCC->CR & RCC_CR_PLL2RDY) == 0) 639 | { 640 | } 641 | #elif defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || defined (STM32F10X_HD_VL) 642 | /* PLL configuration: = (HSE / 2) * 6 = 24 MHz */ 643 | RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL)); 644 | RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_PREDIV1 | RCC_CFGR_PLLXTPRE_PREDIV1_Div2 | RCC_CFGR_PLLMULL6); 645 | #else 646 | /* PLL configuration: = (HSE / 2) * 6 = 24 MHz */ 647 | RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL)); 648 | RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLXTPRE_HSE_Div2 | RCC_CFGR_PLLMULL6); 649 | #endif /* STM32F10X_CL */ 650 | 651 | /* Enable PLL */ 652 | RCC->CR |= RCC_CR_PLLON; 653 | 654 | /* Wait till PLL is ready */ 655 | while((RCC->CR & RCC_CR_PLLRDY) == 0) 656 | { 657 | } 658 | 659 | /* Select PLL as system clock source */ 660 | RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW)); 661 | RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL; 662 | 663 | /* Wait till PLL is used as system clock source */ 664 | while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08) 665 | { 666 | } 667 | } 668 | else 669 | { /* If HSE fails to start-up, the application will have wrong clock 670 | configuration. User can add here some code to deal with this error */ 671 | } 672 | } 673 | #elif defined SYSCLK_FREQ_36MHz 674 | /** 675 | * @brief Sets System clock frequency to 36MHz and configure HCLK, PCLK2 676 | * and PCLK1 prescalers. 677 | * @note This function should be used only after reset. 678 | * @param None 679 | * @retval None 680 | */ 681 | static void SetSysClockTo36(void) 682 | { 683 | __IO uint32_t StartUpCounter = 0, HSEStatus = 0; 684 | 685 | /* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/ 686 | /* Enable HSE */ 687 | RCC->CR |= ((uint32_t)RCC_CR_HSEON); 688 | 689 | /* Wait till HSE is ready and if Time out is reached exit */ 690 | do 691 | { 692 | HSEStatus = RCC->CR & RCC_CR_HSERDY; 693 | StartUpCounter++; 694 | } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT)); 695 | 696 | if ((RCC->CR & RCC_CR_HSERDY) != RESET) 697 | { 698 | HSEStatus = (uint32_t)0x01; 699 | } 700 | else 701 | { 702 | HSEStatus = (uint32_t)0x00; 703 | } 704 | 705 | if (HSEStatus == (uint32_t)0x01) 706 | { 707 | /* Enable Prefetch Buffer */ 708 | FLASH->ACR |= FLASH_ACR_PRFTBE; 709 | 710 | /* Flash 1 wait state */ 711 | FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY); 712 | FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_1; 713 | 714 | /* HCLK = SYSCLK */ 715 | RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1; 716 | 717 | /* PCLK2 = HCLK */ 718 | RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1; 719 | 720 | /* PCLK1 = HCLK */ 721 | RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV1; 722 | 723 | #ifdef STM32F10X_CL 724 | /* Configure PLLs ------------------------------------------------------*/ 725 | 726 | /* PLL configuration: PLLCLK = PREDIV1 * 9 = 36 MHz */ 727 | RCC->CFGR &= (uint32_t)~(RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLSRC | RCC_CFGR_PLLMULL); 728 | RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLXTPRE_PREDIV1 | RCC_CFGR_PLLSRC_PREDIV1 | 729 | RCC_CFGR_PLLMULL9); 730 | 731 | /*!< PLL2 configuration: PLL2CLK = (HSE / 5) * 8 = 40 MHz */ 732 | /* PREDIV1 configuration: PREDIV1CLK = PLL2 / 10 = 4 MHz */ 733 | 734 | RCC->CFGR2 &= (uint32_t)~(RCC_CFGR2_PREDIV2 | RCC_CFGR2_PLL2MUL | 735 | RCC_CFGR2_PREDIV1 | RCC_CFGR2_PREDIV1SRC); 736 | RCC->CFGR2 |= (uint32_t)(RCC_CFGR2_PREDIV2_DIV5 | RCC_CFGR2_PLL2MUL8 | 737 | RCC_CFGR2_PREDIV1SRC_PLL2 | RCC_CFGR2_PREDIV1_DIV10); 738 | 739 | /* Enable PLL2 */ 740 | RCC->CR |= RCC_CR_PLL2ON; 741 | /* Wait till PLL2 is ready */ 742 | while((RCC->CR & RCC_CR_PLL2RDY) == 0) 743 | { 744 | } 745 | 746 | #else 747 | /* PLL configuration: PLLCLK = (HSE / 2) * 9 = 36 MHz */ 748 | RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL)); 749 | RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLXTPRE_HSE_Div2 | RCC_CFGR_PLLMULL9); 750 | #endif /* STM32F10X_CL */ 751 | 752 | /* Enable PLL */ 753 | RCC->CR |= RCC_CR_PLLON; 754 | 755 | /* Wait till PLL is ready */ 756 | while((RCC->CR & RCC_CR_PLLRDY) == 0) 757 | { 758 | } 759 | 760 | /* Select PLL as system clock source */ 761 | RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW)); 762 | RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL; 763 | 764 | /* Wait till PLL is used as system clock source */ 765 | while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08) 766 | { 767 | } 768 | } 769 | else 770 | { /* If HSE fails to start-up, the application will have wrong clock 771 | configuration. User can add here some code to deal with this error */ 772 | } 773 | } 774 | #elif defined SYSCLK_FREQ_48MHz 775 | /** 776 | * @brief Sets System clock frequency to 48MHz and configure HCLK, PCLK2 777 | * and PCLK1 prescalers. 778 | * @note This function should be used only after reset. 779 | * @param None 780 | * @retval None 781 | */ 782 | static void SetSysClockTo48(void) 783 | { 784 | __IO uint32_t StartUpCounter = 0, HSEStatus = 0; 785 | 786 | /* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/ 787 | /* Enable HSE */ 788 | RCC->CR |= ((uint32_t)RCC_CR_HSEON); 789 | 790 | /* Wait till HSE is ready and if Time out is reached exit */ 791 | do 792 | { 793 | HSEStatus = RCC->CR & RCC_CR_HSERDY; 794 | StartUpCounter++; 795 | } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT)); 796 | 797 | if ((RCC->CR & RCC_CR_HSERDY) != RESET) 798 | { 799 | HSEStatus = (uint32_t)0x01; 800 | } 801 | else 802 | { 803 | HSEStatus = (uint32_t)0x00; 804 | } 805 | 806 | if (HSEStatus == (uint32_t)0x01) 807 | { 808 | /* Enable Prefetch Buffer */ 809 | FLASH->ACR |= FLASH_ACR_PRFTBE; 810 | 811 | /* Flash 1 wait state */ 812 | FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY); 813 | FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_1; 814 | 815 | /* HCLK = SYSCLK */ 816 | RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1; 817 | 818 | /* PCLK2 = HCLK */ 819 | RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1; 820 | 821 | /* PCLK1 = HCLK */ 822 | RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2; 823 | 824 | #ifdef STM32F10X_CL 825 | /* Configure PLLs ------------------------------------------------------*/ 826 | /* PLL2 configuration: PLL2CLK = (HSE / 5) * 8 = 40 MHz */ 827 | /* PREDIV1 configuration: PREDIV1CLK = PLL2 / 5 = 8 MHz */ 828 | 829 | RCC->CFGR2 &= (uint32_t)~(RCC_CFGR2_PREDIV2 | RCC_CFGR2_PLL2MUL | 830 | RCC_CFGR2_PREDIV1 | RCC_CFGR2_PREDIV1SRC); 831 | RCC->CFGR2 |= (uint32_t)(RCC_CFGR2_PREDIV2_DIV5 | RCC_CFGR2_PLL2MUL8 | 832 | RCC_CFGR2_PREDIV1SRC_PLL2 | RCC_CFGR2_PREDIV1_DIV5); 833 | 834 | /* Enable PLL2 */ 835 | RCC->CR |= RCC_CR_PLL2ON; 836 | /* Wait till PLL2 is ready */ 837 | while((RCC->CR & RCC_CR_PLL2RDY) == 0) 838 | { 839 | } 840 | 841 | 842 | /* PLL configuration: PLLCLK = PREDIV1 * 6 = 48 MHz */ 843 | RCC->CFGR &= (uint32_t)~(RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLSRC | RCC_CFGR_PLLMULL); 844 | RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLXTPRE_PREDIV1 | RCC_CFGR_PLLSRC_PREDIV1 | 845 | RCC_CFGR_PLLMULL6); 846 | #else 847 | /* PLL configuration: PLLCLK = HSE * 6 = 48 MHz */ 848 | RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL)); 849 | RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL6); 850 | #endif /* STM32F10X_CL */ 851 | 852 | /* Enable PLL */ 853 | RCC->CR |= RCC_CR_PLLON; 854 | 855 | /* Wait till PLL is ready */ 856 | while((RCC->CR & RCC_CR_PLLRDY) == 0) 857 | { 858 | } 859 | 860 | /* Select PLL as system clock source */ 861 | RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW)); 862 | RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL; 863 | 864 | /* Wait till PLL is used as system clock source */ 865 | while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08) 866 | { 867 | } 868 | } 869 | else 870 | { /* If HSE fails to start-up, the application will have wrong clock 871 | configuration. User can add here some code to deal with this error */ 872 | } 873 | } 874 | 875 | #elif defined SYSCLK_FREQ_56MHz 876 | /** 877 | * @brief Sets System clock frequency to 56MHz and configure HCLK, PCLK2 878 | * and PCLK1 prescalers. 879 | * @note This function should be used only after reset. 880 | * @param None 881 | * @retval None 882 | */ 883 | static void SetSysClockTo56(void) 884 | { 885 | __IO uint32_t StartUpCounter = 0, HSEStatus = 0; 886 | 887 | /* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/ 888 | /* Enable HSE */ 889 | RCC->CR |= ((uint32_t)RCC_CR_HSEON); 890 | 891 | /* Wait till HSE is ready and if Time out is reached exit */ 892 | do 893 | { 894 | HSEStatus = RCC->CR & RCC_CR_HSERDY; 895 | StartUpCounter++; 896 | } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT)); 897 | 898 | if ((RCC->CR & RCC_CR_HSERDY) != RESET) 899 | { 900 | HSEStatus = (uint32_t)0x01; 901 | } 902 | else 903 | { 904 | HSEStatus = (uint32_t)0x00; 905 | } 906 | 907 | if (HSEStatus == (uint32_t)0x01) 908 | { 909 | /* Enable Prefetch Buffer */ 910 | FLASH->ACR |= FLASH_ACR_PRFTBE; 911 | 912 | /* Flash 2 wait state */ 913 | FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY); 914 | FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_2; 915 | 916 | /* HCLK = SYSCLK */ 917 | RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1; 918 | 919 | /* PCLK2 = HCLK */ 920 | RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1; 921 | 922 | /* PCLK1 = HCLK */ 923 | RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2; 924 | 925 | #ifdef STM32F10X_CL 926 | /* Configure PLLs ------------------------------------------------------*/ 927 | /* PLL2 configuration: PLL2CLK = (HSE / 5) * 8 = 40 MHz */ 928 | /* PREDIV1 configuration: PREDIV1CLK = PLL2 / 5 = 8 MHz */ 929 | 930 | RCC->CFGR2 &= (uint32_t)~(RCC_CFGR2_PREDIV2 | RCC_CFGR2_PLL2MUL | 931 | RCC_CFGR2_PREDIV1 | RCC_CFGR2_PREDIV1SRC); 932 | RCC->CFGR2 |= (uint32_t)(RCC_CFGR2_PREDIV2_DIV5 | RCC_CFGR2_PLL2MUL8 | 933 | RCC_CFGR2_PREDIV1SRC_PLL2 | RCC_CFGR2_PREDIV1_DIV5); 934 | 935 | /* Enable PLL2 */ 936 | RCC->CR |= RCC_CR_PLL2ON; 937 | /* Wait till PLL2 is ready */ 938 | while((RCC->CR & RCC_CR_PLL2RDY) == 0) 939 | { 940 | } 941 | 942 | 943 | /* PLL configuration: PLLCLK = PREDIV1 * 7 = 56 MHz */ 944 | RCC->CFGR &= (uint32_t)~(RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLSRC | RCC_CFGR_PLLMULL); 945 | RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLXTPRE_PREDIV1 | RCC_CFGR_PLLSRC_PREDIV1 | 946 | RCC_CFGR_PLLMULL7); 947 | #else 948 | /* PLL configuration: PLLCLK = HSE * 7 = 56 MHz */ 949 | RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL)); 950 | RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL7); 951 | 952 | #endif /* STM32F10X_CL */ 953 | 954 | /* Enable PLL */ 955 | RCC->CR |= RCC_CR_PLLON; 956 | 957 | /* Wait till PLL is ready */ 958 | while((RCC->CR & RCC_CR_PLLRDY) == 0) 959 | { 960 | } 961 | 962 | /* Select PLL as system clock source */ 963 | RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW)); 964 | RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL; 965 | 966 | /* Wait till PLL is used as system clock source */ 967 | while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08) 968 | { 969 | } 970 | } 971 | else 972 | { /* If HSE fails to start-up, the application will have wrong clock 973 | configuration. User can add here some code to deal with this error */ 974 | } 975 | } 976 | 977 | #elif defined SYSCLK_FREQ_72MHz 978 | /** 979 | * @brief Sets System clock frequency to 72MHz and configure HCLK, PCLK2 980 | * and PCLK1 prescalers. 981 | * @note This function should be used only after reset. 982 | * @param None 983 | * @retval None 984 | */ 985 | static void SetSysClockTo72(void) 986 | { 987 | __IO uint32_t StartUpCounter = 0, HSEStatus = 0; 988 | 989 | /* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/ 990 | /* Enable HSE */ 991 | RCC->CR |= ((uint32_t)RCC_CR_HSEON); 992 | 993 | /* Wait till HSE is ready and if Time out is reached exit */ 994 | do 995 | { 996 | HSEStatus = RCC->CR & RCC_CR_HSERDY; 997 | StartUpCounter++; 998 | } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT)); 999 | 1000 | if ((RCC->CR & RCC_CR_HSERDY) != RESET) 1001 | { 1002 | HSEStatus = (uint32_t)0x01; 1003 | } 1004 | else 1005 | { 1006 | HSEStatus = (uint32_t)0x00; 1007 | } 1008 | 1009 | if (HSEStatus == (uint32_t)0x01) 1010 | { 1011 | /* Enable Prefetch Buffer */ 1012 | FLASH->ACR |= FLASH_ACR_PRFTBE; 1013 | 1014 | /* Flash 2 wait state */ 1015 | FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY); 1016 | FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_2; 1017 | 1018 | 1019 | /* HCLK = SYSCLK */ 1020 | RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1; 1021 | 1022 | /* PCLK2 = HCLK */ 1023 | RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1; 1024 | 1025 | /* PCLK1 = HCLK */ 1026 | RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2; 1027 | 1028 | #ifdef STM32F10X_CL 1029 | /* Configure PLLs ------------------------------------------------------*/ 1030 | /* PLL2 configuration: PLL2CLK = (HSE / 5) * 8 = 40 MHz */ 1031 | /* PREDIV1 configuration: PREDIV1CLK = PLL2 / 5 = 8 MHz */ 1032 | 1033 | RCC->CFGR2 &= (uint32_t)~(RCC_CFGR2_PREDIV2 | RCC_CFGR2_PLL2MUL | 1034 | RCC_CFGR2_PREDIV1 | RCC_CFGR2_PREDIV1SRC); 1035 | RCC->CFGR2 |= (uint32_t)(RCC_CFGR2_PREDIV2_DIV5 | RCC_CFGR2_PLL2MUL8 | 1036 | RCC_CFGR2_PREDIV1SRC_PLL2 | RCC_CFGR2_PREDIV1_DIV5); 1037 | 1038 | /* Enable PLL2 */ 1039 | RCC->CR |= RCC_CR_PLL2ON; 1040 | /* Wait till PLL2 is ready */ 1041 | while((RCC->CR & RCC_CR_PLL2RDY) == 0) 1042 | { 1043 | } 1044 | 1045 | 1046 | /* PLL configuration: PLLCLK = PREDIV1 * 9 = 72 MHz */ 1047 | RCC->CFGR &= (uint32_t)~(RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLSRC | RCC_CFGR_PLLMULL); 1048 | RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLXTPRE_PREDIV1 | RCC_CFGR_PLLSRC_PREDIV1 | 1049 | RCC_CFGR_PLLMULL9); 1050 | #else 1051 | /* PLL configuration: PLLCLK = HSE * 9 = 72 MHz */ 1052 | RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | 1053 | RCC_CFGR_PLLMULL)); 1054 | RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL9); 1055 | #endif /* STM32F10X_CL */ 1056 | 1057 | /* Enable PLL */ 1058 | RCC->CR |= RCC_CR_PLLON; 1059 | 1060 | /* Wait till PLL is ready */ 1061 | while((RCC->CR & RCC_CR_PLLRDY) == 0) 1062 | { 1063 | } 1064 | 1065 | /* Select PLL as system clock source */ 1066 | RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW)); 1067 | RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL; 1068 | 1069 | /* Wait till PLL is used as system clock source */ 1070 | while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08) 1071 | { 1072 | } 1073 | } 1074 | else 1075 | { /* If HSE fails to start-up, the application will have wrong clock 1076 | configuration. User can add here some code to deal with this error */ 1077 | } 1078 | } 1079 | #endif 1080 | 1081 | /** 1082 | * @} 1083 | */ 1084 | 1085 | /** 1086 | * @} 1087 | */ 1088 | 1089 | /** 1090 | * @} 1091 | */ 1092 | /******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ 1093 | -------------------------------------------------------------------------------- /test/md_readbit.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import sys 3 | import minimalmodbus 4 | 5 | if len(sys.argv) == 2: 6 | slave = int(sys.argv[1], 0) 7 | else: 8 | slave = 0x02 9 | 10 | x = minimalmodbus.Instrument('/dev/ttyUSB0', slave) 11 | x.serial.parity = 'E' 12 | 13 | #x.debug = True 14 | 15 | print "bit_input: %d" % x.read_register(16, 0, 4, False) 16 | print "coil: %d" % x.read_register(17, 0, 4, False) 17 | print "short_input: %d" % x.read_register(18, 0, 4, False) 18 | print "holding: %d" % x.read_register(19, 0, 4, False) 19 | print 20 | 21 | print "bit_input [0]: %d" % x.read_bit(0, 2) 22 | print "bit_input [1]: %d" % x.read_bit(1, 2) 23 | print 24 | 25 | x.write_bit(0, 1, 5) 26 | print "coil [0]: " + str(x.read_bit(0, 1)) 27 | 28 | x.write_bit(0, 0, 15) 29 | print "coil [0]: " + str(x.read_bit(0, 1)) 30 | 31 | print 32 | 33 | adc = x.read_register(20 , 0, 4, False) 34 | print "short_input[0]: %4d\t%.2f%%" % (adc, adc / 40.95) 35 | adc = x.read_register(21, 0, 4, False) 36 | print "short_input[1]: %4d\t%.2f%%" % (adc, adc / 40.95) 37 | 38 | print 39 | 40 | print "uuid: %s" % x.read_string(0, 16, 4) 41 | 42 | 43 | ''' 44 | x.write_string(10, "hello", 3) 45 | print x.read_string(10, 3, 3) 46 | 47 | x.write_string(10, "world", 3) 48 | print x.read_string(10, 3, 3) 49 | ''' 50 | 51 | ''' 52 | 02050000ff008C09 53 | 020500000000CDf9 54 | 55 | 00050000ff008DEB 56 | 000500000000CC1B 57 | 58 | ''' 59 | --------------------------------------------------------------------------------